/* ============================================================================
   لوحة الإدارة — the office owner's board (/management-dashboard)

   Prefix .mdash-. Loaded AFTER _dashboard.css, whose layout vocabulary this
   page reuses by CLASS NAME ONLY — .dash-grid / .dash-main / .dash-side,
   .dash-card-head, .dash-overline, .dash-status-*, .dash-cases-*, .dash-legend,
   .dash-dot, .dash-card-link. That file is not edited: «لوحة المتابعة» is a
   different product with a different audience, and the two boards share a look,
   not code.

   TOKENS ONLY. Not one colour, radius, shadow or font family is written here —
   every value comes from _variables.css or from the active design, so all five
   designs and both themes follow with no rule of their own. A chart's colour is
   a MARK; text always wears a text token.

   ONE TRAP, and it is why [data-pane] carries container-type below.
   _dashboard.css makes the two-column .dash-grid a CONTAINER query: one rule
   declares the container (`.main-content .container-fluid:has(> .dash-grid)`)
   and a bare `@container (min-width:900px)` widens the grid. On that page the
   grid is a direct child of .container-fluid, so the declaring rule matches;
   here it sits one level deeper, inside a tab pane, so nothing declares a
   container and the bare query resolves against the viewport-sized root — the
   grid silently stays one column. The pane declaring ITSELF a container is
   what restores it, and it is the same declaration the KPI grid below
   measures against.
   ============================================================================ */

/* ── The ONE filter row, above everything it scopes ────────────────────────
   Three fields and the clear button. The tracks are explicit rather than
   auto-fit: the three filters are equal in weight and must stay side by side
   on a desktop, and «مسح» is the only thing that may shrink to its content. */
.mdash-filters {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
    gap: .9rem 1rem;
    align-items: end;
    padding: 1rem 1.25rem;
    margin-bottom: 1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-xs);
}

.mdash-filters .form-label {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: .3rem;
}

/* The date-range fragment brings its own label, already styled. Align it with
   the two selects' labels so the three fields sit on one baseline. */
.mdash-filters [data-date-range] > .form-label {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-secondary);
}

.mdash-filter-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* «المعروض: …» — what the numbers above are actually about, restated in words.
   A filter row alone leaves the reader to remember what they set; this line is
   what makes a screenshot of the board self-explanatory. */
.mdash-scope {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem .6rem;
    padding-top: .75rem;
    border-top: 1px solid var(--border);
    font-size: .8125rem;
    color: var(--text-secondary);
}

.mdash-scope-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .2rem .7rem;
    border-radius: var(--radius-pill);
    background: var(--bg-secondary);
    border: 1px solid var(--border);
    color: var(--text);
    font-weight: 600;
}

.mdash-scope-chip i {
    color: var(--text-secondary);
    font-size: .75rem;
}

.mdash-scope-note {
    margin-inline-start: auto;
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .4rem;
}

/* ── Tabs ─────────────────────────────────────────────────────────────────
   .modal-form-tabs is the app's tab strip; here each tab also carries an icon,
   which is the only difference. It WRAPS rather than scrolls — six tabs at a
   phone width become two rows, and a horizontally scrolling tab strip hides
   the tabs at its end with nothing on screen saying they are there. */
.mdash-tabs .modal-form-tab {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
}

.mdash-tabs .modal-form-tab i {
    font-size: .85rem;
    opacity: .8;
}

/* ── KPI tiles ────────────────────────────────────────────────────────────
   label · value · delta-or-sub. No 48px chip like .stat-card-inline, so the
   floor is 220px rather than that family's 270px — and like there it is set by
   the widest VALUE (a money figure), never by the widest label.

   FOUR ACROSS, TWO BY TWO, OR STACKED — never 3 + 1. Every group on this page
   is a multiple of four, and rule 32's auto-fit would leave the fourth tile
   alone on its own row at a middling width. The thresholds are read from the
   PANE's width through a container query, never from the viewport: the rail
   takes 260px open and 92px collapsed, so one viewport yields two content
   widths and no breakpoint can be right for both. 940px = 4 x 220 + 3 gaps. */
.mdash-kpis {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}

@container (min-width: 460px) {
    .mdash-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@container (min-width: 940px) {
    .mdash-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.mdash-kpi {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    min-width: 0;
    padding: 1rem 1.1rem;
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-xs);
    container-type: inline-size;
    text-align: start;
    font: inherit;
    color: inherit;
}

/* A tile that OPENS something is a real <button> — this undoes only the chrome
   a button brings, so every rule above still matches it while the focus ring,
   the role and keyboard activation come for free (the .admin-stat-card rule). */
button.mdash-kpi {
    cursor: pointer;
    inline-size: 100%;
    border: 1px solid var(--border);
}

.mdash-kpi-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    min-block-size: 2rem;
}

.mdash-kpi-label {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--text-secondary);
}

.mdash-kpi-icon {
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--radius-md);
    display: grid;
    place-items: center;
    font-size: .85rem;
    background: var(--chip-primary-bg);
    color: var(--chip-primary-fg);
}

.mdash-kpi-icon.is-danger  { background: var(--chip-danger-bg);  color: var(--chip-danger-fg); }
.mdash-kpi-icon.is-warning { background: var(--chip-warning-bg); color: var(--chip-warning-fg); }
.mdash-kpi-icon.is-success { background: var(--chip-success-bg); color: var(--chip-success-fg); }
.mdash-kpi-icon.is-info    { background: var(--chip-info-bg);    color: var(--chip-info-fg); }

.mdash-kpi-value {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.2;
    color: var(--text);
}

/* The value steps down rather than the grid's floor going up: a 296px floor to
   suit one money tile would cost every panel a column at most desktop widths
   (the .stat-value precedent). Safe because the tile never sizes itself from
   its contents — its width comes from the track. */
@container (max-width: 215px) {
    .mdash-kpi-value { font-size: 1.35rem; }
}

.mdash-kpi-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    min-block-size: 1.5rem;
    font-size: .78rem;
    color: var(--text-secondary);
}

/* ▲▼ against the previous period. The colour follows whether up is GOOD, which
   the builder decides per tile — المصروفات up is red. */
.mdash-delta {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .1rem .5rem;
    border-radius: var(--radius-pill);
    font-weight: 700;
    font-size: .75rem;
}

.mdash-delta.is-good { background: var(--chip-success-bg); color: var(--chip-success-fg); }
.mdash-delta.is-bad  { background: var(--chip-danger-bg);  color: var(--chip-danger-fg); }

/* «الآن» — a STOCK number, the state right now, which does not follow the
   period (D7). It sits in the tile's FOOT and not beside the label: beside the
   label it cost the label its one line, and a wrapped KPI label is what makes a
   row of tiles ragged. Without this badge the owner changes the period, half
   the tiles do not move, and the board reads as broken. */
.mdash-now {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .05rem .5rem;
    border-radius: var(--radius-pill);
    background: var(--chip-muted-bg);
    color: var(--chip-muted-fg);
    font-size: .7rem;
    font-weight: 700;
}

.mdash-now::before {
    content: "";
    inline-size: .4rem;
    block-size: .4rem;
    border-radius: 50%;
    background: currentColor;
}

/* A dir="ltr" value must still sit on the PAGE's start edge — setting `dir` is
   what re-anchors it, so the fix rides with the cause. The same pin
   _admin.css puts on .admin-stat-card [dir] and _forms.css on .form-control. */
html[dir="rtl"] .mdash-kpi [dir] { text-align: right; }
html[dir="ltr"] .mdash-kpi [dir] { text-align: left; }

/* A group heading inside a pane — «العمل», «المال». */
.mdash-section-label {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 0 0 .75rem;
    font-size: .8125rem;
    font-weight: 700;
    color: var(--text-secondary);
}

.mdash-section-label::after {
    content: "";
    flex: 1;
    block-size: 1px;
    background: var(--border);
}

/* ── Charts ───────────────────────────────────────────────────────────────
   Thin marks, a hairline grid, 4px data-ends anchored to the baseline, 2px
   surface gaps between fills. Text never wears a series colour: a colour is
   only ever a mark BESIDE the word. */
.mdash-legend {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1rem;
    font-size: .78rem;
    color: var(--text-secondary);
}

.mdash-legend span {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
}

.mdash-key {
    inline-size: .7rem;
    block-size: .7rem;
    border-radius: 3px;
    background: var(--series);
    flex: none;
}

/* Horizontal stacked rows — حِمل العمل per bucket, five register colours. The
   hues are .agenda-cat-*, the same five the agenda and «لوحة المتابعة» use, so
   الجلسات is one colour everywhere in the app. */
.mdash-hrows {
    display: grid;
    gap: .7rem;
    margin-top: .85rem;
}

.mdash-hrow {
    display: grid;
    grid-template-columns: 8.5rem minmax(0, 1fr) 2.5rem;
    align-items: center;
    column-gap: .75rem;
    font-size: .84rem;
}

.mdash-hrow-label {
    color: var(--text);
    font-weight: 600;
    line-height: 1.25;
}

.mdash-hrow-label small {
    display: block;
    font-size: .72rem;
    font-weight: 500;
    color: var(--text-secondary);
}

.mdash-hrow.is-current .mdash-hrow-label { color: var(--primary-dark); }

.mdash-stack {
    display: flex;
    gap: 2px;
    block-size: .95rem;
    inline-size: calc(var(--w) * 1%);
    min-inline-size: .5rem;
}

.mdash-stack span {
    flex: var(--n) 1 0;
    min-inline-size: 4px;
    background: var(--event-color, var(--series));
    border-radius: 3px;
}

.mdash-hrow-total {
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    text-align: end;
}

/* Single-hue rank bars (the emphasis form): lawyers, clients, expense types.
   ONE hue, because the rows are a ranking of the same measure — a colour per
   row would claim a distinction that is not in the data. */
.mdash-rank {
    display: grid;
    gap: .85rem;
    margin-top: .6rem;
    container-type: inline-size;
}

.mdash-rank-row {
    display: grid;
    grid-template-columns: minmax(0, 13rem) minmax(0, 1fr) auto;
    align-items: center;
    column-gap: .9rem;
}

/* In a narrow card the bar drops UNDER the name. Beside a 13rem name column the
   bars of the 310px side cards collapsed to dots — a bar that cannot show a
   length is not a bar. */
@container (max-width: 440px) {
    .mdash-rank-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: .35rem; }
    .mdash-rank-row .mdash-track { grid-column: 1 / -1; grid-row: 2; }
}

.mdash-rank-who {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-width: 0;
}

/* A single avatar in a rank row. It wears .avatar-stack-cN beside this class,
   so its COLOUR comes from _admin.css and the design's own --avatar-N-* tokens
   — which is why nothing here sets background or color: the index is a hash of
   the PERSON's id (AvatarStack.colourOf), never the row's position, so one
   lawyer wears one colour in every card on the screen. Indexed by position,
   the same lawyer wore two different colours in two cards at once. */
.mdash-avatar {
    flex: none;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: .7rem;
    font-weight: 700;
}

.mdash-rank-name {
    min-width: 0;
    font-weight: 600;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mdash-rank-name small {
    display: block;
    font-size: .74rem;
    font-weight: 500;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
}

.mdash-track {
    block-size: .6rem;
    border-radius: var(--radius-pill);
    background: var(--bg-secondary);
    overflow: hidden;
}

.mdash-track span {
    display: block;
    block-size: 100%;
    inline-size: calc(var(--w) * 1%);
    /* A REAL figure is always a mark. Money spans orders of magnitude — 417
       against 94,988 is 0.44% — so a percentage width alone drew nothing at
       all for three of the four rows of «أعلى الموكلين رصيدًا», which reads as
       «this client owes nothing» beside a figure saying they do. The floor is
       the trend chart's, and `is-zero` takes it back off a true zero for the
       same reason it does there. */
    min-inline-size: 3px;
    border-radius: var(--radius-pill);
    /* The brand as a FILL, never --primary: as text that token is 1.9:1 on a
       light card in ليموني, which paints a bar nobody can see. */
    background: var(--primary-fill-solid);
}

.mdash-track span.is-zero { min-inline-size: 0; }

.mdash-rank-value {
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    min-inline-size: 2rem;
    text-align: end;
}

/* The footnote a card owes its reader — the shared-case rule under a per-lawyer
   table, the office rule under المكاتب. */
.mdash-foot-note {
    margin: .9rem 0 0;
    padding-top: .75rem;
    border-top: 1px solid var(--border);
    font-size: .78rem;
    color: var(--text-secondary);
    display: flex;
    gap: .45rem;
    align-items: baseline;
}

.mdash-foot-note i { color: var(--text-muted); }

/* ── «يحتاج إلى متابعة» — six rows, each a button opening its overlay ────── */
.mdash-attn { display: grid; margin-top: .25rem; }

.mdash-attn-row {
    display: grid;
    grid-template-columns: 2rem minmax(0, 1fr) auto auto;
    align-items: center;
    gap: .75rem;
    padding: .6rem 0;
    border: 0;
    border-bottom: 1px solid var(--border);
    background: transparent;
    font: inherit;
    color: var(--text);
    text-align: start;
    cursor: pointer;
}

.mdash-attn-row:last-child { border-bottom: 0; }
.mdash-attn-row:disabled { cursor: default; }

.mdash-attn-name { font-weight: 600; min-width: 0; }

.mdash-attn-name small {
    display: block;
    font-size: .76rem;
    font-weight: 500;
    color: var(--text-secondary);
}

.mdash-attn-count {
    font-weight: 700;
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
}

.mdash-attn-row > .mdash-attn-go { color: var(--text-muted); font-size: .75rem; }

/* The chevron points the way the reader READS, so it is mirrored rather than
   swapped: Font Awesome has no logical chevron, and a second glyph chosen in JS
   would be one more thing to keep in step with the page direction. The markup
   carries the RTL one (the default locale) and LTR flips it. */
html[dir="ltr"] .mdash-attn-go i { transform: scaleX(-1); }

.mdash-attn-row:hover:not(:disabled) { background: var(--bg-secondary); }

.mdash-attn-row:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
    border-radius: var(--radius-sm);
}

/* Nothing late is a GOOD state and must not read as a missing number. */
.mdash-attn-row.is-clear .mdash-attn-count { color: var(--text-secondary); }

/* The overlay's head says WHICH scope these rows are, because the overlay
   covers the filter row that would otherwise say so. Hidden by the module when
   no filter is set — «كل المحامين · كل المكاتب» says nothing. */
.mdash-attn-scope {
    margin: .35rem 0 0;
    font-size: .82rem;
    color: var(--text-secondary);
}

/* ── Meter — ONE ratio against a limit (نسبة التحصيل, نسبة إنجاز المهام) ─── */
.mdash-meter {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.mdash-meter-track {
    flex: 1;
    min-inline-size: 3.5rem;
    block-size: .45rem;
    border-radius: var(--radius-pill);
    background: color-mix(in srgb, var(--primary-fill-solid) 16%, var(--card));
    overflow: hidden;
}

.mdash-meter-track span {
    display: block;
    block-size: 100%;
    inline-size: calc(var(--w) * 1%);
    background: var(--primary-fill-solid);
    border-radius: var(--radius-pill);
}

.mdash-meter b {
    font-variant-numeric: tabular-nums;
    font-size: .8rem;
    color: var(--text);
}

/* The same meter INSIDE a table cell (إنجاز المهام on المحامين). A ratio is
   not a count, so the column is wider than the numeric ones and its bar takes
   whatever is left after the percentage — never a fixed px, which would make
   the bar mean a different thing per viewport. */
.mdash-table .mdash-meter-cell { min-inline-size: 5.75rem; }
.mdash-table .mdash-meter-cell .mdash-meter { justify-content: flex-start; }

/* ── Tables inside cards ──────────────────────────────────────────────────
   Not .admin-table: these are report tables with their own totals row, inside a
   card, with no row actions and no detail row — so they carry a card's type
   scale rather than a register's. */
.mdash-table {
    width: 100%;
    margin-top: .35rem;
    font-size: .875rem;
}

.mdash-table th {
    font-size: .76rem;
    font-weight: 700;
    color: var(--text-secondary);
    padding: .5rem .6rem;
    border-bottom: 1px solid var(--border-strong);
    white-space: nowrap;
    text-align: start;
}

.mdash-table td {
    padding: .6rem;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    vertical-align: middle;
}

.mdash-table tr:last-child td { border-bottom: 0; }

/* «إجمالي المكتب» — computed without duplication, never a column sum (D8). */
.mdash-table tfoot td {
    font-weight: 700;
    border-top: 1px solid var(--border-strong);
    border-bottom: 0;
    background: var(--bg-secondary);
}

.mdash-table td .link-chip { white-space: nowrap; }
.mdash-table .num { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* A short LABEL column — a case number, a branch, a status, a date.
   Without this the browser is free to satisfy a narrow viewport by breaking
   every one of them mid-word rather than letting .table-responsive scroll: at
   430px «لم تُعقد جلسة» rendered as a one-glyph-wide column four lines tall,
   and every neighbour was crushed the same way. A bounded value has no
   business yielding — the PROSE column does (CLAUDE.md's tiered floors), and
   below its floor the container is supposed to scroll. */
.mdash-table .mdash-label { white-space: nowrap; }

/* …and the prose column is the one that yields, down to a floor. `width` and
   not `max-width`: CSS 2.1 §17.5.2.2 leaves max-width on a table cell
   undefined and Blink ignores it, which is what let one long subject take the
   table's whole surplus. */
.mdash-table .mdash-prose {
    width: 18rem;
    min-width: 9rem;
}

/* A sortable header is a real button so it is reachable by keyboard. */
.mdash-sort {
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
}

.mdash-sort i { opacity: .4; font-size: .7rem; }
.mdash-sort.is-sorted i { opacity: 1; color: var(--primary); }

.mdash-late { color: var(--danger-text); font-weight: 700; }

/* A clickable row of the المحامين table — it sets the board's lawyer filter. */
.mdash-row-btn {
    border: 0;
    background: transparent;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    text-align: start;
    display: flex;
    align-items: center;
    gap: .6rem;
    min-width: 0;
}

/* ── Pane scaffolding ─────────────────────────────────────────────────────
   container-type on the ACTIVE pane is load-bearing twice over: it is what the
   KPI grid's container queries measure, and it is what makes _dashboard.css's
   .dash-grid two-column rule match at all (that rule is itself a container
   query, keyed off a .container-fluid parent this grid no longer has). */
[data-pane] { display: none; }
[data-pane].is-active { display: block; container-type: inline-size; }

.mdash-three {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
    gap: 1.5rem;
    margin-top: 1.5rem;
}

/* FOUR cards that are TWO PAIRS — the two hearing cards and the two task
   cards of المواعيد والمهام. auto-fit gives three tracks at a desktop width
   and lays them out 3 + 1, which splits the task pair across two rows and
   leaves the fourth card alone beside an empty half-screen: the same 3 + 1
   the KPI groups are forbidden from doing, for the same reason. Two tracks
   keep each pair on its own row at any width the cards fit two-up, and the
   minmax still collapses to one column on a phone. */
.mdash-pairs {
    grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr));
}
@container (min-width: 760px) {
    .mdash-pairs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A pair whose OTHER half is gated away fills the row rather than sitting in
   one of two fixed tracks. Two explicit tracks are what stop auto-fit splitting
   a pair, and the price is that they do not collapse when a card is absent —
   which is exactly what happens on الموكلين, where «أعلى الموكلين — المفوتر» is
   not rendered at all for a reader without financeReport.read. Left alone the
   survivor stood at half width beside an empty half-screen, and an empty half
   of a row reads as «something here failed to load» — the worst possible
   message on the one card a permission deliberately removed. */
.mdash-pairs > .admin-section-card:only-child { grid-column: 1 / -1; }

.mdash-three .admin-section-card,
.mdash-wide .admin-section-card { margin-bottom: 0; }

.mdash-wide { margin-top: 1.5rem; }

/* Two .dash-grid rows in a row — المالية stacks «الفواتير والتحصيل» over
   «أعمار الذمم المستحقة». _dashboard.css spaces the cards INSIDE a grid
   (gap 1.5rem) and zeroes their margin-bottom, but gives the grid itself no
   outer margin, because «لوحة المتابعة» never stacks two; here the second row
   sat flush against the first. Same 1.5rem as every other gap on the board. */
.dash-grid + .dash-grid { margin-top: 1.5rem; }

/* ── «الفواتير والتحصيل» — grouped columns, three series ──────────────────
   No chart library (D11): the bars are flex items whose height is a
   percentage of the tallest value in the window, and their colour is one of
   the three SHARED --chart-* tokens, so all five designs and both themes
   follow with no rule of their own.

   The months OUTSIDE the chosen period are dimmed rather than recoloured —
   the emphasis form. Opacity, not a second token: a muted step per series
   would be three more values to validate on five cards, and dimming preserves
   each series' own hue, which is what the legend promises. */
.mdash-trend {
    display: flex;
    align-items: flex-end;
    gap: .4rem;
    margin-top: .5rem;
}
.mdash-trend-col {
    flex: 1 1 0;
    min-inline-size: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .4rem;
}
.mdash-trend-bars {
    inline-size: 100%;
    block-size: 10rem;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 2px;
}
.mdash-trend-bars > span {
    flex: 1 1 0;
    min-inline-size: 0;
    /* A floor of 3px, so a month with a small but real figure is still a mark
       rather than nothing — an empty month and a nearly-empty one must not
       look identical. */
    block-size: max(3px, calc(var(--h) * 1%));
    border-radius: 3px 3px 0 0;
    background: var(--c);
}
.mdash-trend-bars > span.is-zero { block-size: 0; min-block-size: 0; }
.mdash-trend-col:not(.is-period) .mdash-trend-bars > span { opacity: .34; }
.mdash-trend-label {
    font-size: .72rem;
    color: var(--text-secondary);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.mdash-trend-col.is-period .mdash-trend-label { color: var(--text); font-weight: 700; }

/* The legend's swatches are the series' own hues. */
.mdash-chart-legend { display: flex; flex-wrap: wrap; gap: .35rem .9rem; margin-top: .85rem;
    padding-top: .85rem; border-top: 1px solid var(--border); font-size: .78rem;
    color: var(--text-secondary); }
.mdash-chart-legend span { display: inline-flex; align-items: center; gap: .4rem; }
.mdash-chart-legend i { inline-size: .6rem; block-size: .6rem; border-radius: 2px; background: var(--c); }

/* At a phone width twelve columns leave ~22px each: the bars still read as a
   shape, but a month name does not fit, so only the period's own months keep
   a label. The accessible twin names every month either way. */
@container (max-width: 560px) {
    .mdash-trend-bars { block-size: 7rem; }
    .mdash-trend-col:not(.is-period) .mdash-trend-label { display: none; }
}

/* A refetch HOLDS the previous render, dimmed — never a skeleton flash and
   never a jump (the list-page rule, and the dataviz one). */
.mdash-busy { opacity: .6; }

/* The empty state of a card whose query returned nothing. */
.mdash-empty {
    padding: 1.25rem .5rem;
    text-align: center;
    color: var(--text-secondary);
    font-size: .875rem;
}

/* The accessible twin of every chart: the same numbers as a real table, for a
   screen reader and for anyone who cannot use colour. Visually hidden rather
   than absent — «no value reachable by colour or hover alone».

   THIS MUST STAY ON A BLOCK WRAPPER, never on the <table>. A table is
   `display: table`, i.e. shrink-to-fit, and cannot be sized below its
   min-content — so `inline-size: 1px` left the twin at its full width, the
   `clip-path` hid only its PAINT, and `margin: -1px` pushed the document 36px
   past the start edge: a sideways scroll on a phone, caused by a table nobody
   can see. The wrapper is a div so the 1px actually applies and the table
   inside keeps the row semantics the twin exists for. */
.mdash-table-twin {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── المالية ──────────────────────────────────────────────────────────────
   أعمار الذمم المستحقة: ONE bar, five ORDERED steps of ONE hue, light → dark.
   The buckets are a sequential magnitude with a direction — «older is worse» —
   not five categories, so five hues would claim a difference in KIND that is
   not in the data.

   THE RAMP IS MIXED TOWARD --card, NOT FIVE HEX VALUES. Two things follow from
   that and neither is available to a fixed set: it tracks each DESIGN's own
   card (the five differ, and ليموني's dark `#143a44` is several steps lighter
   than the rest), and it reverses correctly with the THEME — on a light card
   step 1 is the palest tint, on a dark one the darkest, and in both it reads
   as «least ink, least concern». It is the mechanism the subtle status chips
   in _components.css already use, and for the same reason.

   The danger family rather than --chart-1..3: this is one measure being split
   by age, not three series being compared, and the card it sits on is about
   debt. --danger-fill is SHARED by every design (rule 40) — a status colour
   must read the same whichever design a colleague picked.

   MEASURED on all five designs in both themes (tools: scratchpad/ramp.js,
   which paints each step and reads the pixel — Chrome reports a resolved
   color-mix as `oklab(...)`, and parsing those three numbers as sRGB returns a
   confident near-black for every design at once). Light: L 0.907 → 0.577,
   adjacent ΔE 8.4–9.6. Dark: L 0.35–0.43 → 0.577, adjacent ΔE 5.3–6.5, tightest
   on ليموني's `#143a44` — which is why the two rules carry different
   percentages rather than one set.

   WHAT THE MEASUREMENT ALSO SAYS, and what the track below answers: the pale
   END OF A SEQUENTIAL RAMP CANNOT REACH 3:1 AGAINST ITS SURFACE. Even 100% of
   `--danger-fill` is 4.83:1 on a white card, so a five-step ramp whose first
   step cleared 3:1 would have to run 78–100% and would have no visible steps
   left. That floor is for a mark standing ALONE on the surface; these segments
   stand against each OTHER, inside a band. So the band gets a track and a
   border — its extent is drawn rather than inferred from its palest segment —
   and identity never rests on the colour anyway: the legend repeats every
   bucket with its name and its figure, and the table twin carries all five. */
.mdash-age-bar {
    --age-1: color-mix(in oklab, var(--danger-fill) 22%, var(--card));
    --age-2: color-mix(in oklab, var(--danger-fill) 40%, var(--card));
    --age-3: color-mix(in oklab, var(--danger-fill) 60%, var(--card));
    --age-4: color-mix(in oklab, var(--danger-fill) 80%, var(--card));
    --age-5: var(--danger-fill);
    display: flex;
    /* The mark spec's spacer: a surface-coloured gap between adjacent fills,
       so two neighbouring steps of one hue never touch. A ZERO bucket draws no
       segment at all (the renderer omits it) — with one it would still paint
       this gap and read as a bucket with a little in it. */
    gap: 2px;
    block-size: 1.15rem;
    border-radius: var(--radius-pill);
    overflow: hidden;
    margin-top: .85rem;
    /* The track, and the reason it is here rather than for decoration: at
       1.34:1 (light) and 1.45:1 (dark) the first step is all but invisible on
       the card, so without a drawn band «لم يحن موعدها» read as empty space
       instead of as a quarter of the money. The border defines the extent and
       the track fills the 2px spacers, so a pale segment is still inside
       something. */
    background: var(--bg-secondary);
    border: 1px solid var(--border);
}

.mdash-age-bar > span {
    display: block;
    inline-size: calc(var(--w) * 1%);
    background: var(--c);
}

/* The legend carries the swatch AND the name AND the figure, so the bar is
   never the only way to read a bucket — identity is never colour alone. */
.mdash-age-legend {
    --age-1: color-mix(in oklab, var(--danger-fill) 22%, var(--card));
    --age-2: color-mix(in oklab, var(--danger-fill) 40%, var(--card));
    --age-3: color-mix(in oklab, var(--danger-fill) 60%, var(--card));
    --age-4: color-mix(in oklab, var(--danger-fill) 80%, var(--card));
    --age-5: var(--danger-fill);
    /* FIVE EQUAL COLUMNS, not auto-fit. The five buckets are one ORDERED
       sequence and the bar above them is one band, so the legend has to read
       as the same five slices in the same order — auto-fit fitted four and
       wrapped «أكثر من 90 يومًا» alone onto a second row, which broke the
       ordering the whole card is built on. */
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: .75rem 1rem;
    margin-top: 1rem;
    container-type: inline-size;
}

/* The five do not fit side by side in a narrow card; they still wrap in ORDER,
   which is what the single row was protecting. */
@container (max-width: 640px) { .mdash-age-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (max-width: 320px) { .mdash-age-legend { grid-template-columns: minmax(0, 1fr); } }

[data-theme="dark"] .mdash-age-bar,
[data-theme="dark"] .mdash-age-legend {
    --age-1: color-mix(in oklab, var(--danger-fill) 40%, var(--card));
    --age-2: color-mix(in oklab, var(--danger-fill) 55%, var(--card));
    --age-3: color-mix(in oklab, var(--danger-fill) 70%, var(--card));
    --age-4: color-mix(in oklab, var(--danger-fill) 85%, var(--card));
}

/* Swatch and name on one line, the figure under them — so the name and its
   figure share ONE start edge. The earlier two-column grid put the swatch in a
   column of its own and left the name and the value hanging off different
   edges of the second, which read as two unrelated runs of text. */
.mdash-age-item { display: grid; gap: .15rem; min-width: 0; }

.mdash-age-head-row { display: flex; align-items: center; gap: .4rem; min-width: 0; }

.mdash-age-swatch {
    flex: none;
    inline-size: .7rem;
    block-size: .7rem;
    border-radius: 3px;
    background: var(--c);
    /* A 1px surface ring, so the palest step is still a shape on the card it
       sits on rather than a smudge — the overlapping-mark rule. */
    box-shadow: 0 0 0 1px var(--border);
}

.mdash-age-name {
    font-size: .78rem;
    color: var(--text-secondary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mdash-age-value {
    font-size: .875rem;
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* The card's headline is the الذمم المستحقة tile's own figure, so the two are
   one number rather than two that happen to agree. */
.mdash-age-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .35rem .9rem;
}

.mdash-age-total {
    font-size: 1.75rem;
    font-weight: 800;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.mdash-age-sub { font-size: .8125rem; color: var(--text-secondary); }
.mdash-age-sub b { color: var(--danger-text); font-variant-numeric: tabular-nums; }

/* A money value needs more room than a count: «96,378.26» is 4 characters
   wider than the widest count this board draws, and at the count's 2rem floor
   it wrapped under its own bar. */
.mdash-rank-money { min-inline-size: 5.5rem; }

@media (max-width: 767.98px) {
    .mdash-filters { grid-template-columns: minmax(0, 1fr); }
    .mdash-rank-row { grid-template-columns: minmax(0, 1fr) auto; }
    .mdash-rank-row .mdash-track { grid-column: 1 / -1; grid-row: 2; }
    .mdash-hrow { grid-template-columns: 6.5rem minmax(0, 1fr) 2rem; }
    .mdash-scope-note { margin-inline-start: 0; }
}
