/* ===========================================================================
   assetsModule.css
   House style for the assets domain: assets, banking / bankaccount,
   loan / instrument, data sources.

   THREE RULES that keep this file small and keep it from touching anything
   it should not:

   1. SCOPED. Everything sits under .cm-scope. Put that class on a view's
      outermost element, or on the <md-dialog> element for a dialog. Nothing
      in this file can reach a module that has not opted in.

      A view that owns the whole page adds .cm-canvas, which supplies the page
      padding. An embedded view (a tab inside the product or company page)
      takes .cm-scope only and is laid out by its host.

   2. BOOTSTRAP FIRST. This file re-skins Bootstrap components and adds only
      the primitives Bootstrap genuinely lacks. Spacing, flex and text stay
      in the template as utilities: gap-3, m-0, p-3, flex-fill, ms-auto,
      small, text-muted, text-end, font-monospace. Do not re-declare them.
      This app runs Bootstrap 5.0.0-beta3, so .text-bg-*, .fw-semibold and
      .row-cols-* do NOT exist. Do not reach for them.

      The one deliberate exception is .text-muted, which Bootstrap sets to
      #6c757d, a warm grey in a palette that is otherwise entirely neutral.
      Nearly every secondary line in these views uses it, so leaving it alone
      put most of the text on screen in the wrong colour family.

   3. NO BARE ELEMENT SELECTORS. Every selector starts at .cm-scope.

   SHAPE, agreed 2026-08-27: the page is white, there is no canvas tint, and
   nothing is wrapped in a card. Separation comes from space and hairlines.
   One neutral grey scale at three fixed weights. The accent appears about
   twice per screen. Earlier revisions kept a grey page with white boxes on it
   and tuned the borders inside that shape, which is what read as dated no
   matter how it was adjusted.
   =========================================================================== */


/* --- Tokens --------------------------------------------------------------- */

.cm-scope {
    --cm-surface:       #ffffff;
    --cm-canvas:        #ffffff;   /* kept: templates and the guide name it */
    --cm-sunk:          #fafafa;   /* hover, inset wells, skeletons */
    --cm-line:          #ececef;   /* hairline between rows */
    --cm-line-2:        #e0e0e4;   /* a rule that is meant to be seen */
    --cm-ink:           #18181b;
    --cm-muted:         #52525b;   /* secondary text */
    --cm-muted-2:       #a1a1aa;   /* tertiary: sub-lines, counts, units */
    --cm-primary:       #0d9488;
    --cm-primary-hover: #0f766e;
    --cm-primary-soft:  #f0fdfa;
    --cm-danger:        #dc2626;
    --cm-warn:          #b45309;
    --cm-warn-dot:      #f59e0b;
    --cm-warn-soft:     #fffbeb;
    --cm-ok:            #15803d;
    --cm-radius:        8px;
    --cm-radius-sm:     7px;

    /* Windows 11 ships Segoe UI Variable Text; the bare system stack resolves
       to plain Segoe UI, which is the 2015 face. Asking for the current one
       first costs nothing: both are already installed, and Inter is only used
       by whoever happens to have it. No webfont, no download. */
    font-family: Inter, "Segoe UI Variable Text", -apple-system, "Segoe UI",
                 Roboto, Helvetica, Arial, sans-serif;
    font-size: 13.5px;
    line-height: 1.5;
    letter-spacing: -.006em;
    color: var(--cm-ink);
    -webkit-font-smoothing: antialiased;
}

/* Bootstrap's warm grey, corrected to the palette. See rule 2. */
.cm-scope .text-muted { color: var(--cm-muted-2) !important; }

/* A view that owns the whole page opts in for the page padding. There is no
   canvas tint any more, so this no longer paints a ground; it is kept because
   templates and the style guide both name it, and because it is still the
   honest place for page-level layout. */
.cm-scope.cm-canvas { background: var(--cm-canvas); padding: 22px 24px 28px; }

/* A dialog sits on its own surface. */
.cm-scope.cm-dialog { background: var(--cm-surface); }


/* --- Page head ------------------------------------------------------------
   A real title. Hierarchy from size and weight, not from uppercase
   letterspaced colour.
   ------------------------------------------------------------------------- */

.cm-scope .cm-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 16px; }
.cm-scope .cm-title {
    margin: 0;
    font-size: 21px;
    font-weight: 600;
    letter-spacing: -.021em;
    color: var(--cm-ink);
}
.cm-scope .cm-subtitle { margin: 3px 0 0; font-size: 13px; color: var(--cm-muted-2); }

/* Section label, for a block inside a page that already has a title. */
.cm-scope .cm-label {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--cm-ink);
}

/* Context line above a name. */
.cm-scope .cm-eyebrow {
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--cm-muted-2);
    margin-bottom: 2px;
}


/* --- Bootstrap re-skin ----------------------------------------------------
   Same markup Bootstrap ships, wearing the house style.
   ------------------------------------------------------------------------- */

/* Flat. A 1px border and a drop shadow on the same box is the 2014 card.
   New views should not reach for .card at all, since the shape is space and
   hairlines, but the views already converted still use it. */
.cm-scope .card {
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius);
    box-shadow: none;
}

.cm-scope .table {
    color: var(--cm-ink);
    margin-bottom: 0;
    border-collapse: collapse;
}

/* Bootstrap paints row striping and hover as a 9999px inset box-shadow on
   each cell, which would sit on top of anything this file sets as a
   background. Cleared here so the hover and flag treatments below are the
   ones that show; the sticky header re-declares its own shadow. */
.cm-scope .table > :not(caption) > * > * { box-shadow: none; }

/* No tint, no bold. One firm rule under the header row, hairlines between
   rows, nothing around the outside. */
.cm-scope .table > thead > tr > th {
    background: transparent;
    padding: 0 12px 8px;
    border-bottom: 1px solid var(--cm-line-2);
    color: var(--cm-muted-2);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
}

/* Air. Bootstrap's table-sm ships 4px of cell padding, which is cramped
   rather than dense, and cramped is most of what reads as old. */
.cm-scope .table > tbody > tr > td {
    padding: 11px 12px;
    border-top: 0;
    border-bottom: 1px solid var(--cm-line);
    vertical-align: middle;
}
.cm-scope .table > tbody > tr:last-child > td { border-bottom: 0; }
.cm-scope .table-hover > tbody > tr:hover > td,
.cm-scope .table > tbody > tr:focus-within > td { background: var(--cm-sunk); }

/* Grouped tables: a row and its sub-rows are ONE thing, so the rule goes
   BETWEEN groups rather than under every row. A line under each row said the
   opposite — that a dividend is a peer of the holding it was declared on, not
   something hanging off it. So the border moves onto the first row of each
   group, and the rows beneath it close up against it.

   The unattached rows at the end are one group, not one each: belonging to no
   parent is the single thing they have in common, and a rule between every
   pair of them would undo the grouping it is supposed to show. */
.cm-scope .table.cm-grouped > tbody > tr > td            { border-bottom: 0; }
/* These rows grow: a position's inputs pick up a mismatch warning and an
   edited-from-feed line, and the shared `vertical-align: middle` then drops the
   date, the currency and the totals a line and a half below the inputs they
   describe. Cells line up on their first line instead. baseline rather than
   top, so a plain-text cell sits on the inputs' text line and not 4px above it. */
.cm-scope .table.cm-grouped > tbody > tr > td            { vertical-align: baseline; }
.cm-scope .table.cm-grouped > tbody > tr.cm-group-start > td {
    border-top: 1px solid var(--cm-line);
}
.cm-scope .table.cm-grouped > tbody > tr.cm-group-start:first-child > td { border-top: 0; }
.cm-scope .table.cm-grouped > tbody > tr.cm-orphan + tr.cm-orphan > td   { border-top: 0; }

/* Indented, quieter, and unmistakably subordinate. The empty leading cell
   already sets them in; this keeps their numbers from competing with the
   position's own. Inputs stay at full strength — they are still editable. */
.cm-scope .table.cm-grouped > tbody > tr.cm-subrow > td { padding-top: 4px; padding-bottom: 4px; }
/* text-align because this cell is both the first and the LAST in its row, and
   the last-child rule above right-aligns every trailing cell for the numbers. */
.cm-scope .table.cm-grouped > tbody > tr.cm-addrow > td {
    padding-top: 2px;
    padding-bottom: 10px;
    text-align: left;
}

/* Flush with the page on both edges. */
.cm-scope .table > thead > tr > th:first-child,
.cm-scope .table > tbody > tr > td:first-child { padding-left: 2px; position: relative; }
.cm-scope .table > thead > tr > th:last-child,
.cm-scope .table > tbody > tr > td:last-child  { padding-right: 2px; text-align: right; }

/* The row that needs attention: an amber bar out in the page gutter, not a
   tinted band. A band is heavy at ten rows and fights the hover state, and as
   an inset shadow it sat one hair from the row's own text. */
.cm-scope .table > tbody > tr.cm-row-flag > td:first-child::before {
    content: "";
    position: absolute;
    left: -13px;
    top: 8px;
    bottom: 8px;
    width: 3px;
    border-radius: 3px;
    background: var(--cm-warn-dot);
}

/* A row the reader asked to see but that is not part of the working set:
   soft-deleted, deactivated, superseded. Present and readable, not competing.
   Deliberately opacity rather than a grey text colour, so the tags and the
   monospace identifiers dim with the row instead of staying at full strength. */
.cm-scope .table > tbody > tr.cm-dim > td { opacity: .5; }

/* Brief highlight when the manual-entry picker lands on a row that is
   already in the table; the controller clears the flag on a timeout and
   the transition fades the tint out. */
.cm-scope .ia-row-flash > td { background-color: var(--cm-warn-soft) !important; transition: background-color 1.2s ease-out; }

/* Long lists keep their header. Box-shadow rather than border-bottom, because
   a border on a sticky cell scrolls away with the row. */
.cm-scope .cm-scroll { max-height: 62vh; overflow: auto; margin: 0 -2px; padding: 0 2px; }
.cm-scope .cm-scroll .table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--cm-surface);
    border-bottom: 0;
    box-shadow: inset 0 -1px 0 var(--cm-line-2);
}

/* Buttons. One primary, in the accent. Everything else is a ghost: no border
   and no fill until you point at it. Grey outlined buttons were the most
   dated control on the old screen. */
.cm-scope .btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 28px;
    padding: 0 11px;
    border: 0;
    border-radius: var(--cm-radius-sm);
    font-size: 12.5px;
    font-weight: 500;
    white-space: nowrap;
}
.cm-scope .btn-primary {
    background-color: var(--cm-primary);
    border-color: var(--cm-primary);
    color: #fff;
}
.cm-scope .btn-primary:hover,
.cm-scope .btn-primary:focus,
.cm-scope .btn-primary:active {
    background-color: var(--cm-primary-hover);
    border-color: var(--cm-primary-hover);
    color: #fff;
}
/* Bordered neutral: a page-level action such as Refresh. */
.cm-scope .btn-outline-secondary {
    background: transparent;
    border: 1px solid var(--cm-line-2);
    color: var(--cm-muted);
}
.cm-scope .btn-outline-secondary:hover {
    background: var(--cm-sunk);
    border-color: var(--cm-muted-2);
    color: var(--cm-ink);
}
/* Borderless: a secondary action inside a table row. */
.cm-scope .cm-btn-ghost {
    background: transparent;
    border: 0;
    color: var(--cm-muted);
}
.cm-scope .cm-btn-ghost:hover { background: var(--cm-sunk); color: var(--cm-ink); }
/* Bordered row action: the outline stays put so the button is findable
   before anyone hovers it, and the hover is the soft primary wash rather
   than a fill — the same pairing cm-choice.selected uses. btn-outline-primary
   would go solid teal on hover, which is too loud for a per-row helper.
   Disabled keeps a hairline: it must read as "not yet", not as absent. */
.cm-scope .cm-btn-soft {
    background: transparent;
    border: 1px solid var(--cm-line-2);
    color: var(--cm-muted);
}
.cm-scope .cm-btn-soft:hover {
    background: var(--cm-primary-soft);
    border-color: var(--cm-primary);
    color: var(--cm-primary-hover);
}
.cm-scope .cm-btn-soft:disabled {
    background: transparent;
    border-color: var(--cm-line);
    color: var(--cm-muted-2);
}
.cm-scope .btn-outline-primary { background: transparent; border: 1px solid var(--cm-primary); color: var(--cm-primary); }
.cm-scope .btn-outline-primary:hover { background: var(--cm-primary); color: #fff; }
.cm-scope .btn-danger { background-color: var(--cm-danger); border-color: var(--cm-danger); }
.cm-scope .btn:focus-visible { outline: 2px solid var(--cm-primary); outline-offset: 1px; box-shadow: none; }

/* Right-aligned row actions. */
.cm-scope .cm-actions { display: inline-flex; align-items: center; gap: 2px; justify-content: flex-end; }

/* Row-action menu behind a kebab. Bootstrap's own panel is a warmer grey, a
   size larger and a shadow heavier than anything else on these screens; same
   markup it ships, retinted. Items are buttons as often as links, so the
   padding and alignment are set for both. */
.cm-scope .dropdown-menu {
    min-width: 170px;
    padding: 4px;
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius);
    background: var(--cm-surface);
    box-shadow: 0 6px 16px rgba(24, 24, 27, .09);
    font-size: 12.5px;
    color: var(--cm-ink);
}
.cm-scope .dropdown-item {
    width: 100%;
    padding: 6px 9px;
    border: 0;
    border-radius: var(--cm-radius-sm);
    background: transparent;
    color: var(--cm-muted);
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}
.cm-scope .dropdown-item:hover,
.cm-scope .dropdown-item:focus { background: var(--cm-sunk); color: var(--cm-ink); }
.cm-scope .dropdown-item:disabled { background: transparent; color: var(--cm-muted-2); }
.cm-scope .dropdown-item:focus-visible { outline: 2px solid var(--cm-primary); outline-offset: -2px; }

.cm-scope .form-control,
.cm-scope .form-select {
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius-sm);
    font-size: 12.5px;
    color: var(--cm-ink);
}
/* The shorthand above also cleared the gutter Bootstrap reserves for the select
   arrow (2.25rem). The arrow is drawn 12px from the right edge at 16px wide, so
   without this it sits on top of the text of any select narrow enough for the
   value to reach the edge — w-auto, or a fixed width. */
.cm-scope .form-select { padding-right: 30px; }

.cm-scope .form-control::placeholder { color: var(--cm-muted-2); }
.cm-scope .form-control:focus,
.cm-scope .form-select:focus {
    border-color: transparent;
    outline: 2px solid var(--cm-primary);
    outline-offset: -1px;
    box-shadow: none;
}

/* Multi-line fields keep their height; the 28px above is for one-liners. */
.cm-scope textarea.form-control { height: auto; min-height: 64px; padding: 6px 10px; }

/* Conditional fields must swap instantly. ngAnimate (via ngMaterial) hooks
   every ng-if, and reads Bootstrap's .form-control transition as a real
   animation — so a leaving input lingers ~150ms after its replacement has
   entered, briefly showing the ISIN field and the auto-generated OTHER note
   together. .ng-animate applies only mid-animation, so focus stays animated. */
.cm-scope .form-control.ng-animate { transition: none !important; }

/* Same mechanism, the wizard's footer: Back / Next / Submit are ng-if'd per
   step, and Bootstrap gives .btn (and .form-select) a ~150ms transition, so
   ngAnimate keeps the leaving button in the DOM until it has run — which reads
   as a wizard that answers a beat late on every step change. Deliberate
   animations in this scope are untouched: .ng-animate is set only while
   ngAnimate is driving that particular element. */
.cm-scope .btn.ng-animate,
.cm-scope .form-select.ng-animate { transition: none !important; }

/* The one Material form control the domain uses. */
.cm-scope md-checkbox .md-icon { border-width: 1px; border-color: var(--cm-muted-2); border-radius: 4px; }
.cm-scope md-checkbox.md-checked .md-icon { background-color: var(--cm-primary); }
.cm-scope md-checkbox[disabled] .md-icon { border-color: var(--cm-line-2); }

/* Bootstrap alerts, recolored to the palette; the markup stays Bootstrap. */
.cm-scope .alert-danger  { background: #fef2f2; border-color: #fecaca; color: var(--cm-danger); }
.cm-scope .alert-warning { background: var(--cm-warn-soft); border-color: #fde68a; color: var(--cm-warn); }

/* A search field with its icon inside. */
.cm-scope .cm-searchbox { position: relative; display: inline-flex; align-items: center; }
.cm-scope .cm-searchbox > svg {
    position: absolute;
    left: 9px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--cm-muted-2);
    pointer-events: none;
}
.cm-scope .cm-searchbox .form-control { padding-left: 29px; }

/* Tabs: an underline rail. The active tab is ink, not accent, because the
   accent belongs to the action; a teal tab plus a teal button on one screen
   is two things claiming to be the most important. */
.cm-scope .nav-tabs { border-bottom: 1px solid var(--cm-line); gap: 20px; }
.cm-scope .nav-tabs .nav-item { margin-bottom: 0; }
.cm-scope .nav-tabs .nav-link {
    padding: 0 0 9px;
    margin-bottom: -1px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: transparent;
    color: var(--cm-muted-2);
    font-size: 13.5px;
    font-weight: 500;
    cursor: pointer;
    /* The zeros above and here are stated, not inherited defaults: the product
       and company views ship an unscoped <style> block that styles .nav-tabs
       globally (radius, right margin, a .33s transition, -1px on .nav-item).
       Leave them out and that block reaches into every dialog opened from
       those pages. The transition also feeds ngAnimate — see the .form-control
       note below. */
    border-radius: 0;
    margin-right: 0;
    transition: none;
}
.cm-scope .nav-tabs .nav-link:hover { color: var(--cm-ink); background: transparent; }
.cm-scope .nav-tabs .nav-link.active {
    background: transparent;
    color: var(--cm-ink);
    border-bottom-color: var(--cm-ink);
    /* Restated, not inherited from the rule above: the product and company
       views ship an unscoped <style> block setting .nav-tabs .nav-link.active
       { padding: 10px 18px }. It sits in the body, so it beats that rule on
       source order and pushed the active tab 10px below its neighbour. */
    padding: 0 0 9px;
}
.cm-scope .cm-tab-n {
    margin-left: 6px;
    font-size: 11.5px;
    color: var(--cm-muted-2);
    font-variant-numeric: tabular-nums;
}
.cm-scope .nav-link.active .cm-tab-n { color: var(--cm-muted); }


/* --- Primitives Bootstrap does not have ----------------------------------- */

/* A custom element is inline by default. The company picker is not always the
   flex item itself — the approve dialog wraps it in a <span> that carries the
   tooltip — so without this it collapses to its content width. */
.cm-scope company-picker { display: block; }

/* Numbers that line up in a column. Pair with Bootstrap .text-end. */
.cm-scope .cm-num { font-variant-numeric: tabular-nums; }

/* The primary and secondary lines of a table cell. */
.cm-scope .cm-name    { font-weight: 500; color: var(--cm-ink); }
.cm-scope .cm-subline { margin-top: 1px; font-size: 12px; color: var(--cm-muted-2); }
.cm-scope .cm-none    { color: var(--cm-muted-2); }

/* One long compartment name should not set the width of a column. */
.cm-scope .cm-trunc { max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Inline help marker, carrying its text in a title. A field that needs a
   sentence of rationale gets it on demand instead of a line of italics beside
   it, which is read once and then read past forever. cursor: help is already
   the house tooltip cue (see stackedTransactions.css). */
.cm-scope .cm-q {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    margin-left: 5px;
    vertical-align: 1px;
    border: 1px solid var(--cm-line-2);
    border-radius: 50%;
    font-size: 10px;
    font-weight: 600;
    color: var(--cm-muted-2);
    cursor: help;
    user-select: none;
}
.cm-scope .cm-q:hover { border-color: var(--cm-muted-2); color: var(--cm-muted); }

/* An identifier the user might copy: ISIN, IBAN, provider_ref, other_code.
   No chip: one filled grey pill per row stacks into a column of grey blocks
   down the middle of the table, and monospace already says "identifier". */
.cm-scope .cm-ident {
    font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    letter-spacing: -.01em;
    color: var(--cm-muted);
}
/* Same identifier, but carrying a heading rather than sitting beside one:
   takes the heading's size and ink so a reference number can BE the name of
   a page. Must follow .cm-ident — equal specificity, source order decides. */
.cm-scope .cm-ident-strong {
    font-size:   inherit;
    font-weight: 600;
    color:       inherit;
}

/* Status: a dot and a word. A column of coloured pills is a 2016 dashboard;
   a 6px dot carries the same information at a fraction of the weight, and it
   lets the healthy rows go silent, which is what makes the bad ones findable.
   The halo exists because six pixels of colour is easy to miss on a page this
   quiet. */
.cm-scope .cm-dot {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--cm-muted);
    font-size: 12.5px;
    white-space: nowrap;
}
.cm-scope .cm-dot::before {
    content: "";
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--cm-muted-2);
}
.cm-scope .cm-dot-ok::before   { background: var(--cm-ok); }
.cm-scope .cm-dot-warn         { color: var(--cm-warn); }
.cm-scope .cm-dot-warn::before { background: var(--cm-warn-dot); box-shadow: 0 0 0 3px rgba(245, 158, 11, .16); }
.cm-scope .cm-dot-bad::before  { background: var(--cm-danger);   box-shadow: 0 0 0 3px rgba(220, 38, 38, .13); }
/* Named neutral states, so an ng-class map can stay a literal-only rename of
   the Bootstrap badge map it replaces. Both look like the plain dot. */
.cm-scope .cm-dot-running::before,
.cm-scope .cm-dot-skipped::before { background: var(--cm-muted-2); }

/* Soft label pill. Status is a dot; this is for a label that is not a state:
   a type, a scope, a classification. */
.cm-scope .cm-tag {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 5px;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.6;
    white-space: nowrap;
}
.cm-scope .cm-tag-ok     { background: #dcfce7; color: var(--cm-ok); }
.cm-scope .cm-tag-warn   { background: var(--cm-warn-soft); color: var(--cm-warn); }
.cm-scope .cm-tag-danger { background: #fee2e2; color: #b91c1c; }
.cm-scope .cm-tag-muted  { background: #f4f4f5; color: var(--cm-muted); }
.cm-scope .cm-tag-info   { background: var(--cm-primary-soft); color: var(--cm-primary-hover); }

/* Valuation date, read against asset.expected_refresh_frequency. NOT age:
   a monthly asset valued five weeks ago is overdue, a quarterly one is not.
      (no modifier) on schedule
      .cm-date-due      the cycle has come round, no value entered yet
      .cm-date-overdue  more than a cycle past due
   Degrades to a plain date when no modifier is applied, so the layout works
   with or without a controller-side helper. Distinct from asset.needs_review,
   which means an automated valuation run FAILED. */
.cm-scope .cm-date { font-variant-numeric: tabular-nums; color: var(--cm-muted); }
.cm-scope .cm-date-due     { color: var(--cm-warn);   font-weight: 600; }
.cm-scope .cm-date-overdue { color: var(--cm-danger); font-weight: 600; }

/* Empty / error. The branch improvises these differently in nearly every
   view; this is the one treatment. */
.cm-scope .cm-state {
    padding: 44px 20px;
    text-align: center;
    border: 1px dashed var(--cm-line-2);
    border-radius: 10px;
    color: var(--cm-muted-2);
    font-size: 13px;
}
.cm-scope .cm-state-title {
    display: block;
    margin-bottom: 3px;
    color: var(--cm-ink);
    font-size: 14px;
    font-weight: 600;
}
.cm-scope .cm-state-error { border-color: #fecaca; }
.cm-scope .cm-state-error .cm-state-title { color: var(--cm-danger); }

/* Loading is the table's own shape, not a spinner: the columns are already at
   their final widths, so nothing jumps when the rows land. */
.cm-scope .cm-sk {
    display: block;
    width: 70%;
    height: 9px;
    border-radius: 4px;
    background: linear-gradient(90deg, #f1f1f3, #e7e7ea, #f1f1f3);
    background-size: 200% 100%;
    animation: cm-sheen 1.3s linear infinite;
}
.cm-scope .cm-sk-sm { width: 45%; height: 7px; margin-top: 5px; opacity: .7; }
@keyframes cm-sheen { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .cm-scope .cm-sk { animation: none; } }

/* One instruction line above a list, replacing a sentence repeated per row.
   An inset well rather than floating grey text. */
.cm-scope .cm-hint {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 9px 11px;
    border-radius: var(--cm-radius);
    background: var(--cm-sunk);
    color: var(--cm-muted);
    font-size: 12.5px;
}
.cm-scope .cm-hint > svg { flex: 0 0 auto; margin-top: 2px; color: var(--cm-muted-2); }

/* Warning variant of the hint well: a caution, not an instruction. */
.cm-scope .cm-hint-warn { background: var(--cm-warn-soft); color: var(--cm-warn); }
.cm-scope .cm-hint-warn > svg { color: var(--cm-warn-dot); }

/* Field notes one step louder than text-muted. Pair with cm-subline/small. */
.cm-scope .cm-subline-warn   { color: var(--cm-warn); }
.cm-scope .cm-subline-danger { color: var(--cm-danger); }

/* Filter chips. A filter is state, not an action, so it must not borrow the
   button styles: rendering "cash is on" as a solid primary makes the loudest
   pixel on the screen a filter rather than the work, in direct competition
   with the one real primary action. */
.cm-scope .cm-filter {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 28px;
    padding: 0 10px;
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius-sm);
    background: var(--cm-surface);
    color: var(--cm-muted);
    font-size: 12.5px;
    font-weight: 500;
    cursor: pointer;
}
.cm-scope .cm-filter { justify-content: center; }
.cm-scope .cm-filter:hover  { background: var(--cm-sunk); color: var(--cm-ink); }
.cm-scope .cm-filter.active { background: var(--cm-primary-soft); border-color: var(--cm-primary); color: var(--cm-primary-hover); }
/* A chip whose "on" state means "show me the rows I normally hide" is not a
   healthy state, so it tints amber rather than teal. */
.cm-scope .cm-filter-warn.active { background: var(--cm-warn-soft); border-color: var(--cm-warn); color: var(--cm-warn); }
.cm-scope .cm-filter-n {
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 4px;
    background: rgba(24, 24, 27, .06);
    font-size: 10.5px;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.cm-scope .cm-filter.active .cm-filter-n      { background: rgba(13, 148, 136, .13); }
.cm-scope .cm-filter-warn.active .cm-filter-n { background: rgba(180, 83, 9, .14); }

/* Identity strip — the head of a detail view. What this is, its headline
   figures, and its primary action, in one element.

   Deliberately NOT a page title above a separate figures card: the name is
   the label on the number, not a display heading, because the number is what
   the page is for. A 24px name above a 22px balance had the hierarchy exactly
   backwards. Shared by loan detail, bankaccount overview, entity statement. */
.cm-scope .cm-idstrip {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    padding: 0 0 14px;
    border-bottom: 1px solid var(--cm-line-2);
}
.cm-scope .cm-idstrip-name { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.015em; color: var(--cm-ink); }
.cm-scope .cm-idstrip-fig  { display: flex; align-items: baseline; gap: 7px; }
.cm-scope .cm-idstrip-fig b {
    font-size: 26px;
    font-weight: 600;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
/* Secondary figure in the same strip: present, but not competing. */
.cm-scope .cm-idstrip-fig-sm b { font-size: 17px; }

/* Vertical divider inside a flex row. Replaces the ad-hoc
   `border-left: 2px solid ...` inline styles the branch uses for this. */
.cm-scope .cm-rule { align-self: center; width: 1px; height: 18px; background: var(--cm-line-2); }

/* Breadcrumb. Detail views are reachable by direct link and currently offer
   no way back up, so this is navigation as much as it is identity. */
.cm-scope .cm-crumbs {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 12.5px;
    color: var(--cm-muted-2);
}
.cm-scope .cm-crumbs a       { color: var(--cm-muted-2); text-decoration: none; cursor: pointer; }
.cm-scope .cm-crumbs a:hover { color: var(--cm-primary); text-decoration: underline; }
.cm-scope .cm-crumbs .sep    { color: var(--cm-line-2); }
.cm-scope .cm-crumbs .cur    { color: var(--cm-ink); font-weight: 500; }

/* Date-range filter. The row layout stays Bootstrap utilities in the
   template; the only thing Bootstrap cannot express is a consistent width
   for a native date input, which otherwise sizes differently per browser. */
.cm-scope .cm-daterange input[type="date"] { width: 150px; }

/* Label / value pairs on a detail page. */
.cm-scope .cm-def {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 6px 16px;
    align-items: baseline;
}
.cm-scope .cm-def dt { color: var(--cm-muted-2); font-weight: 400; font-size: 12.5px; }
.cm-scope .cm-def dd { margin: 0; }

/* Entity picker rail. Selected is a rounded inset block, not a full-bleed bar
   with an edge on it. */
.cm-scope .cm-rail { display: flex; flex-direction: column; gap: 1px; max-height: 62vh; overflow-y: auto; }
.cm-scope .cm-rail-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 9px;
    border-radius: var(--cm-radius-sm);
    color: var(--cm-muted);
    cursor: pointer;
}
.cm-scope .cm-rail-item:hover  { background: var(--cm-sunk); }
.cm-scope .cm-rail-item.active { background: var(--cm-primary-soft); color: var(--cm-primary-hover); font-weight: 500; }

/* Company / Product chip. Was defined THREE times in three separate
   in-template <style> blocks (assets shell, banking, entity statement). */
.cm-scope .cm-kind {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 5px;
    background: #f4f4f5;
    color: var(--cm-muted-2);
    font-size: 10px;
    font-weight: 600;
}
.cm-scope .cm-kind-p { background: #ccfbf1; color: var(--cm-primary-hover); }
.cm-scope .cm-rail-item.active .cm-kind { background: #ccfbf1; color: var(--cm-primary-hover); }

/* Wizard step rail. Structure kept from the create dialog, retinted. */
.cm-scope .cm-steps { display: flex; gap: 6px; font-size: 12px; }
.cm-scope .cm-step {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius);
    background: var(--cm-sunk);
    color: var(--cm-muted-2);
}
.cm-scope .cm-step-n {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #d4d4d8;
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 600;
}
.cm-scope .cm-step.active {
    background: var(--cm-primary-soft);
    border-color: var(--cm-primary);
    color: var(--cm-ink);
    font-weight: 500;
}
.cm-scope .cm-step.active .cm-step-n { background: var(--cm-primary); }
.cm-scope .cm-step.done { background: var(--cm-surface); border-color: var(--cm-primary); color: var(--cm-primary); }
.cm-scope .cm-step.done .cm-step-n { background: var(--cm-primary); }

/* Choice cards. Bootstrap row/col gutters fight the card borders, so this
   is a real grid. */
.cm-scope .cm-choices { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.cm-scope .cm-choice {
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius);
    background: var(--cm-surface);
    padding: 12px 14px;
    cursor: pointer;
    transition: border-color .1s, background .1s;
}
.cm-scope .cm-choice:hover    { border-color: var(--cm-muted-2); background: var(--cm-sunk); }
.cm-scope .cm-choice.selected { border-color: var(--cm-primary); background: var(--cm-primary-soft); }
.cm-scope .cm-choice-t { font-weight: 600; font-size: 14px; margin-bottom: 4px; }
.cm-scope .cm-choice-d { color: var(--cm-muted-2); font-size: 12px; line-height: 1.4; }

/* Inline stroke icons. The house style rules out emoji, which the branch
   currently uses as UI vocabulary. */
.cm-scope .cm-ico {
    width: 14px;
    height: 14px;
    vertical-align: -2px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.cm-scope .cm-ico-lg { width: 18px; height: 18px; vertical-align: -4px; }


/* Anchored picker (typeahead). One layer for the three hand-rolled copies
   the branch carried: asset create/edit feed picker, banking jump-to-entity
   picker. The anchor is the input's positioned parent; option rows keep
   ng-mousedown in the templates because blur closes the menu on a timeout. */
.cm-scope .cm-pick { position: relative; }
.cm-scope .cm-pick-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 300px;
    overflow-y: auto;
    background: var(--cm-surface);
    border: 1px solid var(--cm-line-2);
    border-radius: var(--cm-radius);
    box-shadow: 0 8px 24px rgba(24, 24, 27, .10);
    font-size: 12.5px;
}
.cm-scope .cm-pick-group {
    padding: 5px 10px;
    background: var(--cm-sunk);
    border-bottom: 1px solid var(--cm-line);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--cm-muted-2);
}
.cm-scope .cm-pick-opt {
    padding: 6px 10px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cm-scope .cm-pick-opt:hover    { background: var(--cm-sunk); }
.cm-scope .cm-pick-opt.selected { background: var(--cm-primary-soft); }
.cm-scope .cm-pick-empty,
.cm-scope .cm-pick-note {
    padding: 6px 10px;
    color: var(--cm-muted-2);
    font-style: italic;
    font-size: 12px;
}

/* The committed pick, echoed: on selection the input holds the picked label
   and is tinted, so the text in the field reads as the selection rather than
   a stale search. The × beside the input releases it. */
.cm-scope .form-control.cm-picked { border-color: var(--cm-primary); background: var(--cm-primary-soft); font-weight: 500; }

/* Inset panels: expanded detail rows, staged additions, in-place edits. */
.cm-scope .cm-well {
    padding: 10px 12px;
    border: 1px solid transparent;
    border-radius: var(--cm-radius);
    background: var(--cm-sunk);
    font-size: 12.5px;
}
.cm-scope .cm-well-new  { background: #f0fdf4; border-color: #bbf7d0; }
.cm-scope .cm-well-warn { background: var(--cm-warn-soft); border-color: #fde68a; }

/* Scrollable preformatted block (raw JSON, provenance). cm-ident is the
   inline identifier treatment; this is the block one. */
.cm-scope .cm-pre {
    margin: 0;
    padding: 10px 12px;
    max-height: 280px;
    overflow: auto;
    border-radius: var(--cm-radius);
    background: var(--cm-sunk);
    font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11.5px;
    line-height: 1.55;
    color: var(--cm-muted);
}

/* A control that reads as a link: disclosure toggles, detach, show-details. */
.cm-scope .cm-link {
    padding: 0;
    border: 0;
    background: none;
    color: var(--cm-primary);
    font-size: 12.5px;
    cursor: pointer;
}
.cm-scope .cm-link:hover { color: var(--cm-primary-hover); text-decoration: underline; }

/* Native details/summary disclosure. */
.cm-scope .cm-details > summary { cursor: pointer; color: var(--cm-muted); font-size: 12.5px; }
.cm-scope .cm-details > summary:hover { color: var(--cm-ink); }
.cm-scope .cm-details[open] > summary { margin-bottom: 6px; }

/* Collapsible JSON tree sections (data sources batch detail). The head row
   is the disclosure control; the body takes cm-pre's sunk treatment but
   hosts the rendered <details> tree, whose summaries toggle natively. */
.cm-scope .cm-json-sec { margin-top: 14px; }
.cm-scope .cm-json-sec-head {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 4px 2px;
    cursor: pointer;
    user-select: none;
    font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
    font-weight: 600;
    color: var(--cm-muted);
}
.cm-scope .cm-json-sec-head:hover { color: var(--cm-ink); }
.cm-scope .cm-json-chev { width: 10px; color: var(--cm-muted-2); }
.cm-scope .cm-json-count { font-weight: 400; color: var(--cm-muted-2); }
.cm-scope .cm-json-tree {
    margin: 4px 0 0;
    padding: 10px 12px;
    max-height: 420px;
    overflow: auto;
    border-radius: var(--cm-radius);
    background: var(--cm-sunk);
    font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11.5px;
    line-height: 1.6;
    color: var(--cm-muted);
}
.cm-scope .cm-json-tree summary { cursor: pointer; user-select: none; }
.cm-scope .cm-json-tree summary:hover { background: var(--cm-primary-soft); border-radius: 2px; }

/* Unsaved-changes marker on a tab. cm-tab-n counts; this flags. */
.cm-scope .cm-tab-dirty::after {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-left: 6px;
    border-radius: 50%;
    background: var(--cm-warn-dot);
}

/* Free text that keeps its entered line breaks. */
.cm-scope .cm-prewrap { white-space: pre-wrap; }

/* Content-width cap for sparse pages. A four-column catalog stretched
   across a wide monitor reads as empty; capping the content keeps the
   columns in one eyeful, and centering the capped column splits the spare
   width evenly so it reads as composition, not as a hole on the right.

   Put it on the page root, or on the head, tab rail and content container
   of a tabbed view. 1320px is Bootstrap's own widest .container, so the cap
   lines up with the grid the templates already use. One value for every tab:
   a container that resizes as you switch tabs draws the eye to the movement
   rather than to the table. */
.cm-scope.cm-maxw,
.cm-scope .cm-maxw {
    max-width: 1320px;
    margin-left: auto;
    margin-right: auto;
}

/* Tree connector for a child row (an auth under its connector): draws the
   corner of a branch so the parent/child relation is visible structure,
   not just an indent. */
.cm-scope .cm-branch {
    display: inline-block;
    width: 10px;
    height: 11px;
    margin: 0 7px 3px 1px;
    border-left: 1px solid var(--cm-line-2);
    border-bottom: 1px solid var(--cm-line-2);
    border-bottom-left-radius: 5px;
    vertical-align: middle;
}

/* Thin progress bar (backfill runs). Width comes from an ng-style binding. */
.cm-scope .cm-meter { height: 6px; border-radius: 3px; background: var(--cm-line); overflow: hidden; }
.cm-scope .cm-meter > i { display: block; height: 100%; background: var(--cm-primary); border-radius: 3px; transition: width .3s ease; }


/* --- Dialog chrome --------------------------------------------------------
   Angular Material renders md-dialog outside the view root, so a dialog
   template carries class="cm-scope cm-dialog" on <md-dialog> itself.
   ------------------------------------------------------------------------- */

.cm-scope.cm-dialog .cm-dialog-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--cm-line-2);
}
.cm-scope.cm-dialog .cm-dialog-head h4 {
    margin: 0;
    flex: 1;
    font-size: 19px;
    font-weight: 600;
    letter-spacing: -.02em;
}

.cm-scope.cm-dialog .cm-dialog-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--cm-line-2);
}

/* Material forces uppercase on dialog buttons; the house style does not. */
.cm-scope.cm-dialog .md-button,
.cm-scope.cm-dialog .btn { text-transform: none; }

/* Dialog sizing. The root takes cm-scope cm-dialog plus exactly one width;
   no inline sizing on md-dialog. */
.cm-scope.cm-dialog { width: 94vw; }
.cm-scope.cm-dialog.cm-dialog-sm { max-width: 520px; }
.cm-scope.cm-dialog.cm-dialog-md { max-width: 640px; }
.cm-scope.cm-dialog.cm-dialog-lg { max-width: 820px; }
.cm-scope.cm-dialog.cm-dialog-xl { max-width: 1080px; }
.cm-scope.cm-dialog.cm-dialog-2xl { max-width: 1400px; }

/* Uniform dialog padding; head and foot bring their own rules. */
.cm-scope.cm-dialog md-dialog-content { padding: 18px 20px; }
.cm-scope.cm-dialog md-dialog-actions.cm-dialog-foot { padding: 12px 20px 14px; margin: 0; }

/* An anchored picker inside a dialog would be clipped by md-dialog-content.
   Switching that scroll container to visible was the old answer and cost the
   scroll position plus a long form spilling below the dialog. Instead .cm-pick
   stops being the menu's containing block here, so the menu anchors to
   <md-dialog> — outside the scroller — and cmPickMenu
   (reusableComponents/pickMenu.js) supplies its coordinates. md-dialog is not
   the scroll container, so opening it up costs nothing; Material sets the
   overflow inline, hence the !important. */
.cm-scope.cm-dialog { overflow: visible !important; }
.cm-scope.cm-dialog .cm-pick { position: static; }
/* Until the directive writes coordinates, `auto` puts the menu at its static
   position — where it would sit in flow, directly under the input. The
   inherited `top: calc(100% + 4px)` would measure against the dialog instead
   and drop it below the whole thing for one frame. */
.cm-scope.cm-dialog .cm-pick-menu { top: auto; left: auto; right: auto; }

/* A menu anchored to the dialog would be left behind by a scrolling form, so
   the form holds still while one is open — the wheel then belongs to the list,
   which carries its own scroller. `hidden`, not `visible`: it keeps the scroll
   box and with it the position. The gutter is reserved permanently, otherwise
   the vanishing scrollbar shifts the content sideways on every open. */
.cm-scope.cm-dialog md-dialog-content { scrollbar-gutter: stable; }
.cm-scope.cm-dialog.cm-pick-locked md-dialog-content { overflow: hidden !important; }

/* Field grid used by every form dialog in the domain. */
/* start, not center: a field cell grows whenever a note, a warning or a second
   control appears under the input, and centring drags the label down with it.
   The 4px puts the label text back on the input's line — the input is 28px tall
   with its text centred, the label's own line box is 19.5px, so start on its
   own leaves every label sitting high. */
.cm-scope .cm-fields {
    display: grid;
    grid-template-columns: 160px 1fr;
    gap: 10px 14px;
    align-items: start;
}
.cm-scope .cm-fields > label { margin: 0; padding-top: 4px; color: var(--cm-muted); font-size: 13px; }
.cm-scope .cm-fields-wide { grid-column: 1 / -1; }

/* Two label/field pairs per row, for forms that would otherwise scroll.
   cm-fields-wide spans all four columns here too. */
.cm-scope .cm-fields-2 {
    display: grid;
    grid-template-columns: 160px 1fr 160px 1fr;
    gap: 10px 14px;
    align-items: start;
}
.cm-scope .cm-fields-2 > label { margin: 0; padding-top: 4px; color: var(--cm-muted); font-size: 13px; }


/* --- Banking layout -------------------------------------------------------
   Two-pane geometry preserved from the pre-conversion template; the rail
   REDESIGN is a later, mockup-first task. The row itself is d-flex gap-3
   in the template.
   ------------------------------------------------------------------------- */

.cm-scope .banking-rail {
    flex: 0 0 280px;
    position: sticky;
    top: 12px;
    align-self: flex-start;
    max-height: calc(100vh - 24px);
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.cm-scope .banking-activity { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.cm-scope .banking-main     { flex: 1; min-width: 0; }

.cm-scope .banking-activity-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--cm-radius-sm);
    cursor: pointer;
}
.cm-scope .banking-activity-row:hover  { background: var(--cm-sunk); }
.cm-scope .banking-activity-row.active { background: var(--cm-primary-soft); }

/* Group headers splitting the rail by recency; sticky while the list scrolls. */
.cm-scope .banking-group-head {
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0;
    padding: 3px 0 5px;
    background: var(--cm-surface);
}
/* The selected row's movement count picks up the selection tint. */
.cm-scope .banking-activity-row.active .cm-tag-muted { background: rgba(13, 148, 136, .13); color: var(--cm-primary-hover); }

/* Bankaccount list: the save-changes comment field keeps a usable width
   without reintroducing an inline style. */
.cm-scope .bankaccount-comment { width: 300px; max-width: 100%; }


/* --- Assets shell ---------------------------------------------------------
   Layout constants the shell needs and Bootstrap has no utility for.
   ------------------------------------------------------------------------- */

.cm-scope .assets-rail-col { flex: 0 0 250px; }
.cm-scope .assets-search   { min-width: 240px; }


@media (max-width: 720px) {
    .cm-scope .assets-rail-col { flex: 1 1 auto; }
    .cm-scope .assets-search   { min-width: 0; width: 100%; }
    .cm-scope .cm-choices { grid-template-columns: 1fr; }
    .cm-scope .cm-fields  { grid-template-columns: 1fr; }
    .cm-scope .cm-fields-2 { grid-template-columns: 1fr; }
    .cm-scope .banking-rail { position: static; max-height: none; flex: 1 1 auto; }
    /* One column here, so the label stacks above its field and the 4px that
       lines it up beside an input only adds a gap. */
    .cm-scope .cm-fields > label { margin-bottom: -6px; padding-top: 0; }
    .cm-scope .cm-trunc   { max-width: 190px; }
}
