:root{
  /* feature-018 slice 1 — THE 17 COLOUR TOKENS ARE GONE FROM HERE. They are ShellPalette.ErpDark now, and
     ShellPalette.ToCssVariables() is the only place any of them becomes a value (NFR-4, T-3). App.razor emits
     them on <body>, so every page still resolves var(--accent) — including the sign-in pages, which render
     outside MainLayout and therefore outside the shell's own root. Changing the accent is one line of C#.
     What remains below is what the palette does NOT own: two chart colours.

     feature-018 O-1 — THE TWO TYPE STACKS ARE GONE FROM HERE TOO. They are ShellTypography.ErpDense now
     (--shell-sans / --shell-mono), emitted beside the palette by App.razor, BECAUSE the owner's ruling is
     that configuration drives colours, fonts AND layout — and a font stack declared in a host's own
     stylesheet is a font the shell cannot configure. Same two stacks, verbatim; the ERP does not move. */
  --chart-neg:#ff9c8d;--chart-hot:#6fd6e3;
}
*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--text);font-family:var(--shell-sans);font-size:var(--shell-fs-base);line-height:var(--shell-lh);-webkit-font-smoothing:antialiased}
.num,.money{font-variant-numeric:tabular-nums}.money{font-family:var(--shell-mono);font-size:12.5px}.mono{font-family:var(--shell-mono)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* content wrapper (MudBlazor supplies the shell). Full-bleed by design: an ERP is data-dense (grids, master-detail,
   KPI cards) and lives on wide/4K monitors, so the content column fills the available width with comfortable side
   padding rather than sitting in a narrow centred band. Reading width is bounded where it matters instead — the
   master-detail DETAIL pane is capped (the split now lives in shell.css — §6.194, one rule for both hosts) so
   documents/forms stay comfortable while the list fills the rest. Small screens shed padding via the media
   queries further down. */
.view{padding:28px 40px 60px}
.head{margin-bottom:20px}.head h1{margin:0;font-size:22px;font-weight:640;letter-spacing:-.01em}.head p{margin:5px 0 0;color:var(--muted);font-size:13px}
.crumb{color:var(--faint);font-size:12px;margin-bottom:6px;cursor:pointer}
.cards{display:grid;gap:15px}.c2{grid-template-columns:1fr 1fr}.c3{grid-template-columns:repeat(3,1fr)}.c4{grid-template-columns:repeat(4,1fr)}
.card{background:var(--surface);border:1px solid var(--line-2);border-radius:12px;padding:17px 19px}.card.lg{padding:21px 23px}
.k{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:600}
.big{font-size:25px;font-weight:650;margin-top:5px}.big.sm{font-size:19px}
.sub{color:var(--muted);font-size:12.5px}.muted{color:var(--muted)}.faint{color:var(--faint)}
.stack{display:flex;flex-direction:column;gap:11px}.between{display:flex;align-items:center;justify-content:space-between;gap:12px}
.sep{border-top:1px solid var(--line-2);margin-top:15px;padding-top:13px}
.pill{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:600;border-radius:20px;padding:2px 9px;border:1px solid transparent;white-space:nowrap}
.p-good{background:#122a19;color:#82db90;border-color:#245030}.p-warn{background:#302710;color:#f0c563;border-color:#4a3c14}
.p-bad{background:#331813;color:#ff9c8d;border-color:#57271f}.p-violet{background:#211a37;color:#c7b1ff;border-color:#3a2f5c}
.p-info{background:#122240;color:#a3c0ff;border-color:#284067}.p-mute{background:#1a2230;color:var(--muted);border-color:var(--line-2)}
.p-accent{background:var(--accent-soft);color:#8fe0eb;border-color:var(--accent-dim)}
.wrap-x{overflow-x:auto}
.rawtbl table,table.rawtbl{width:100%;border-collapse:collapse;font-size:13px}
.rawtbl th{font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--faint);font-weight:600;text-align:left;padding:9px 12px;border-bottom:1px solid var(--line-2)}
.rawtbl td{padding:10px 12px;border-bottom:1px solid var(--hair);vertical-align:middle}.rawtbl tr:last-child td{border-bottom:none}
.rawtbl tbody tr:hover{background:#161e2c}.rawtbl tbody tr.clickable{cursor:pointer}.r{text-align:right}.neg{color:#ff9c8d}
.btn{display:inline-flex;align-items:center;gap:7px;background:var(--accent);color:#04222a;border:none;border-radius:9px;padding:8px 14px;font-weight:660;font-size:12.5px;cursor:pointer;font-family:inherit}
.btn.ghost{background:transparent;color:var(--text);border:1px solid var(--line-2)}.btn.sm{padding:5px 11px;font-size:11.5px;border-radius:7px}.btn.warn{background:var(--warn);color:#241c02}
.aging{display:flex;height:10px;border-radius:6px;overflow:hidden;background:var(--hair)}.aging i{display:block}.aging .a0{background:var(--good)}.aging .a1{background:var(--warn)}.aging .a2{background:var(--bad)}
.agkey{display:flex;gap:16px;margin-top:9px;font-size:11.5px;color:var(--muted)}.dot{width:8px;height:8px;border-radius:2px;display:inline-block;margin-right:5px;vertical-align:middle}
.meter{display:inline-flex;gap:2px}.meter i{width:6px;height:12px;border-radius:2px;background:#2b3850}.meter i.f{background:var(--good)}
.chip{display:inline-flex;align-items:center;gap:5px;font-size:11px;background:#1a2230;border:1px solid var(--line-2);border-radius:7px;padding:2px 8px;color:var(--muted)}.chip.ok{color:#82db90;border-color:#245030}
.note{font-size:11.5px;color:var(--faint)}.kbd{font-family:var(--shell-mono);font-size:11px;background:#0c1120;border:1px solid var(--line-2);border-bottom-width:2px;border-radius:5px;padding:1px 6px;color:var(--muted)}
.spark{width:100%;height:38px;display:block}
.ch{padding:10px 14px;border-bottom:1px solid var(--line-2);background:#131a27;font-size:12px;color:var(--muted)}
/* #79 — selected-state modifier for a clickable card (bank-account cards, master-detail); reuses the same
   left-accent-bar language as the row-selected style elsewhere (RowStyleFunc on MudTable, .navlink.active). */
.erp-card.selected{background:var(--accent-soft);box-shadow:inset 2px 0 0 var(--accent)}
.conf{font-size:10px;font-weight:700;border-radius:5px;padding:1px 6px}.conf.h{background:#122a19;color:#82db90}.conf.m{background:#302710;color:#f0c563}.conf.l{background:#1a2230;color:var(--muted)}
.in{color:#82db90}.out{color:#ff9c8d}
.basket{margin:12px;background:#111826;border:1px dashed var(--accent-dim);border-radius:10px;padding:12px 14px}
.tree{font-family:var(--shell-mono);font-size:12.5px;line-height:1.95}.tag{display:inline-block;font-size:11px;border-radius:6px;padding:1px 8px;background:var(--accent-soft);color:#8fe0eb;border:1px solid var(--accent-dim)}.tag.spare{background:#1a2230;color:var(--muted);border-color:var(--line-2)}
.form{display:grid;grid-template-columns:1fr 1fr 1fr;gap:13px}.field label{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--faint);margin-bottom:5px}.field .val{background:var(--bg);border:1px solid var(--line-2);border-radius:7px;padding:8px 11px}
.kindsel{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.kk{border:1px solid var(--line-2);border-radius:8px;padding:7px 13px;font-size:12.5px;color:var(--muted)}.kk.on{border-color:var(--accent);background:var(--accent-soft);color:var(--text)}.kk.src{color:var(--faint);font-size:11.5px}
.matrix td,.matrix th{text-align:center}.matrix td:first-child,.matrix th:first-child{text-align:left}
.yes{color:var(--good)}.ro{color:var(--info);font-size:11px}.no{color:var(--faint)}
.toggle{width:34px;height:19px;border-radius:20px;background:var(--accent);position:relative;display:inline-block}.toggle::after{content:"";position:absolute;right:2px;top:2px;width:15px;height:15px;border-radius:50%;background:#04222a}
.toggle.off{background:#2b3850}.toggle.off::after{left:2px;right:auto;background:var(--faint)}
a{color:inherit;text-decoration:none}
@media (max-width:900px){.c2,.c3,.c4,.form{grid-template-columns:1fr}}

/* ---- host content the shell PLACES but does not draw: the drawer-top company line and the "view as role"
   box (C-20's fragment), and the sign-in pages. Everything that was chrome — the app bar, the drawer, the
   brand, the nav fold, the search and identity clusters — left this file for shell.css in slice 1. ---- */
.company{display:flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--line-2);border-radius:8px;padding:7px 10px;margin:2px 8px 10px;font-size:12px;color:var(--muted)}
.company .c{width:16px;height:16px;border-radius:4px;background:#2b6ea3}
.viewas{margin:0 12px 4px;font-size:10px;color:var(--faint);text-transform:uppercase;letter-spacing:.1em}
.roleselect{margin:0 8px 10px}
.roleselect select{width:100%;background:var(--elev);color:var(--text);border:1px solid var(--line-2);border-radius:8px;padding:7px 10px;font-size:12.5px;font-family:inherit}

/* ---- MudBlazor content polish (dark, matches the surface language) ---- */
.erp-card.mud-paper{background:var(--surface);border:1px solid var(--line-2);border-radius:12px}
.erp-table.mud-table{background:transparent;border:1px solid var(--line-2);border-radius:12px;overflow:hidden}
.erp-table .mud-table-container{background:var(--surface)}
.erp-table th.mud-table-cell{font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--faint);font-weight:600;border-bottom:1px solid var(--line-2);background:var(--surface)}
.erp-table td.mud-table-cell{border-bottom:1px solid var(--hair);font-size:13px;color:var(--text)}
.erp-table tbody tr.mud-table-row:hover{background:#161e2c!important}
.money-td{font-family:var(--shell-mono);font-size:12.5px;font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.mono-td{font-family:var(--shell-mono)}
/* One-line, ellipsis-trimmed cell content (company name / line-name preview). Applied to a block SPAN inside the
   cell, never the <td>: the table layout algorithm sizes columns to their content, so a max-width on the cell
   alone is ignored. Trimming is CSS, so the full text is always intact in the element's title attribute. */
.trunc{display:block;max-width:22ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.trunc.wide{max-width:34ch}
.kpi-label{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);font-weight:600}
.kpi-value{font-size:22px;font-weight:650;margin-top:4px;font-variant-numeric:tabular-nums}
.hstack{display:flex;align-items:center;gap:8px}.hstack.wrap{flex-wrap:wrap}
.rowclick{cursor:pointer}
/* line-item tables sit FLUSH inside their card — no nested double border, span paper left→right */
.erp-table-flush.mud-table{border:none;border-radius:0;background:transparent;border-top:1px solid var(--line-2)}
.erp-table-flush .mud-table-container{background:transparent}
.erp-table-flush{margin:8px -16px 0;width:calc(100% + 32px)}
.erp-table-flush td.mud-table-cell:first-child,.erp-table-flush th.mud-table-cell:first-child{padding-left:16px}
.erp-table-flush td.mud-table-cell:last-child,.erp-table-flush th.mud-table-cell:last-child{padding-right:16px}

/* ==== UI polish 2 (2026-07-15): center · no card-in-card · clean line grid · nav sizing ==== */
/* main content column fills the width (see .view above) — no auto-centring so wide/4K screens aren't wasted */
.view{margin-left:0;margin-right:0}
/* ANY data table inside a card renders flush → removes card-in-card double borders everywhere */
.erp-card .erp-table.mud-table{border:none;border-radius:0;background:transparent}
.erp-card .erp-table .mud-table-container{background:transparent}
.erp-card .erp-table.mud-table thead th.mud-table-cell{background:transparent}
/* editable line grid: cells look like flat fields, not boxed inputs */
.erp-table-flush .mud-input.mud-input-outlined .mud-input-outlined-border{border:0 !important}
.erp-table-flush .mud-input.mud-input-outlined{background:transparent;border-bottom:1px solid var(--hair);border-radius:0}
.erp-table-flush .mud-input.mud-input-outlined.mud-focused{border-bottom:1.5px solid var(--accent)}
.erp-table-flush .mud-input-control{margin-top:0}
.erp-table-flush td.mud-table-cell{padding:3px 8px;vertical-align:middle}
/* ==== "view as role" box + its select — C-20 slot CONTENT, host-owned. The drawer's own density, icons,
   group headers, active-item rule and badge left for shell.css in slice 1; the region wrappers .drawer-top
   and .drawer-note went with them and are .shell-drawer-top / .shell-drawer-footnote there. ==== */
.viewas-box{margin:2px 8px 4px;padding:8px;border:1px dashed var(--line-2);border-radius:8px}
.viewas{font-size:9.5px;margin:0 0 4px;padding:0;color:var(--faint);text-transform:uppercase;letter-spacing:.1em}
.roleselect{margin:0}
/* P3: native select restyled to match the surface language, custom chevron */
.roleselect select{width:100%;background:var(--bg);color:var(--text);border:1px solid var(--line-2);border-radius:8px;
  padding:7px 28px 7px 10px;font-size:12.5px;font-family:inherit;appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%237e8ca6' stroke-width='2.5'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat:no-repeat;background-position:right 9px center}
.roleselect select:focus{border-color:var(--accent);outline:none}
/* KPI/summary cards in a row stretch to equal height — scoped to items that hold a card,
   so it never touches form-field grids */
.mud-grid>.mud-grid-item:has(>.erp-card){display:flex}
.mud-grid>.mud-grid-item>.erp-card{height:100%;flex:1}
.page-title{font-size:22px;font-weight:640;letter-spacing:-.01em;margin:0}
.page-title:focus,.page-title:focus-visible{outline:none}
.erp-badge.mud-chip{font-weight:600}
.erp-tag.mud-chip{font-weight:500}
.page-sub{color:var(--muted);font-size:13px;margin:5px 0 0}
/* ── epic-080 ③ — THE STAFF CHAT FRAME ─────────────────────────────────────────────────────────
   One component (ModelingEvolution.Chat's ConversationView, which ships NO stylesheet of its own) is
   rendered by both hosts, and the two hosts wrapped it in frames that agreed on nothing:

     ERP    inline style=""  border var(--mud-palette-lines-default)  radius 4px   height 26rem
     portal .chat-conversation  border var(--line-2)                  radius 6px   height 26rem

   The ERP's half was the worse one on every count. It read a MUDBLAZOR variable, so it did not follow the
   shell palette at all and would drift the moment the shell's line colour changed; and it was an INLINE
   STYLE ATTRIBUTE, which cannot be themed, cannot be overridden, and is invisible to every pin in this
   repo that reads CSS as text. Both frames now read the same shell tokens, and the radius is
   --shell-radius rather than a literal that agreed with nothing.

   ⚠ height: 26rem is STILL stated in two files, deliberately and under protest — it is the one value the
   two frames already agreed on, and unifying it means a shared stylesheet or a component parameter, which
   is the portal-wide token sweep this change is explicitly NOT (backlog: docs/backlog/). Filed, not fixed. */
/* ── M8 — THE INNER FRAME IS GONE (reviewer's ruling, and a different argument from §10's) ────────────────
   This border+radius sat INSIDE a mud-paper-outlined carrying its own border+radius, with the composer's
   rounded box inside that again: three nested frames around one conversation.

   ⚠ NOT the portal's §10 rule. §10's "Surface on Bg, one left-edge rule" describes the BUYER'S 50/50 PANEL
   and does NOT travel to an embedded staff pane (screen-staff-erp.md: "two panes with two rules"). The pane
   keeps its MudPaper frame and its definite height. What goes is only the SECOND frame drawn inside the
   first, which no contract asked for.

   `overflow:hidden` STAYS — it is what keeps the list's own scroll inside the region rather than the page,
   and the height stays definite because the package's flex chain needs something to fill. */
/* ── S1 — THE SHAPE. At 1280 the editor's columns wrap and this became 938 x 416: a ~110-character measure
   showing three messages, which is the least chat-like shape there is. Two properties, no new machinery:

   · the height BREATHES where the viewport allows but stays DEFINITE — clamp() resolves to a length, which
     is what the package's flex chain needs to fill (`.chat-panel{height:100%}` over `.chat-list{flex:1 1
     auto;min-height:0}`). A percentage or `auto` here collapses the list back to content height, which is
     the rc149 portal defect in a different frame;
   · the MEASURE is capped on the message body, not the frame. Capping the frame would leave a narrow box
     floating in a wide card; capping the text keeps the card's width for the composer and the head while
     the reading line stays a reading line. */
.offer-chat-conversation{height:clamp(22rem,55vh,40rem);overflow:hidden}
.offer-chat-conversation .chat-body{max-width:46rem}

/* ── S5 — the disabled send control read as a rendering artefact rather than a control: MudBlazor paints a
   disabled icon button at rgba(255,255,255,0.26), which against this surface is barely there. The STATE is
   correct — nothing to send, so nothing to press — and only its contrast is wrong. --faint is the token the
   rest of this pane already recedes with. */
.offer-chat-conversation [data-chat-send]:disabled,
.offer-chat-conversation [data-chat-send][disabled]{color:var(--faint)}
/* ── M9 — THE GROUPING RHYTHM, AND THIS OVERRIDE IS NOT THE CHAT PACKAGE'S FAULT ──────────────────────────
   §10 specifies 4px between messages inside a group and 16px between groups — "the ratio is what makes
   grouping legible without any rule or box". ModelingEvolution.Chat ships exactly that, and ships
   `.chat-body > :last-child { margin-bottom: 0 }` to keep it. MudBlazor.Markdown then beats it with
   `.mud-markdown-body p { margin-bottom: 1.25em !important }`, adding ~20px of dead band under every row.

   MEASURED: 24px in-group vs 36px between — a 1:1.5 ratio where the contract says 1:4. That is the main
   reason the thread reads as an undifferentiated list rather than as grouped turns, which is what the owner
   was looking at when he said it does not look nice.

   ⚠ THIS IS A THIRD OVERRIDE AND IT IS DELIBERATELY NOT COUNTED AGAINST THE CHAT PACKAGE'S CAP. The two
   standing overrides exist because a ModelingEvolution.Chat rule is wrong; here the Chat rule is RIGHT and
   is being overridden by a THIRD party's stylesheet. `!important` is required to win against `!important`,
   and the narrower selector keeps it inside the conversation.

   ⚠ APPLIED TO BOTH HOSTS IN THE SAME COMMIT (portal.css carries the twin) — same defect, same component,
   and letting one host carry it is how the two surfaces start to drift. */
.offer-chat-conversation .chat-body .mud-markdown-body p:last-child{margin-bottom:0 !important}

/* ── epic-081, owner on rc166: "The Chat doesn't look nice in ERP." ──────────────────────────────────────
   THE SAME TWO FOREIGN OVERRIDES THE PORTAL ALREADY CARRIES, applied to the second host that renders the
   same component. Not a third and a fourth: the standing cap is on the number of package rules we override,
   and these are the same two rules — the portal's copies are in portal.css with the identical reasoning, and
   docs/backlog/chat-day-separator-sticky-margin-is-the-packages.md tracks BOTH for removal in one go.

   ⚠ THE FRAME ABOVE IS NOT TOUCHED, and that is a ruling rather than an omission. screen-chat-panel.md §10's
   "Surface on Bg, one left-edge rule, no border" describes the BUYER'S 50/50 PANEL. This is an embedded pane
   inside the offer editor — screen-staff-erp.md is explicit that these are "two panes with two rules" — so a
   framed, fixed-height box is correct here. Only the CONVERSATION's rules travel between the hosts (§6.110,
   one renderer); the panel's do not.

   (1) The package's day separator is `position: sticky` carrying `margin: 16px 0 8px`. A sticky element's
       margin is not painted, so a 16px transparent strip sits above it and the row underneath shows through
       — visible on rc166 as "Klient 15:15" sliced by the 17.08.2026 band. Same spacing, painted. */
.offer-chat-conversation [data-chat-day]{margin-top:0;padding-top:16px}

/* (2) §10: "group head 14px, name `Text`/600, time `Faint`". Measured on rc166 the time came out
       rgb(233,238,246) — the same value as the sender name — so every group head read as two equally loud
       facts and nothing receded. */
.offer-chat-conversation [data-chat-time]{color:var(--faint)}

/* epic-080 — the crumb is a <button> now (see PageHeader.razor), so this rule resets the UA button styling
   it would otherwise inherit and gives it a REAL touch target. It was 46.6 x 18.6 px on a 390 px viewport,
   against --shell-target-min (ShellMetrics.TargetMinPx) of 44 — the shell's own declared floor, which the
   notice strip and the booking picker already honour and which the ERP's only mobile back-control did not.
   The negative inline margin keeps the label optically flush left: the padding that makes the target big
   enough would otherwise indent the text 10 px past the h1 beneath it, which is a visible misalignment on
   every master-detail page. Vertical padding is NOT cancelled — that is the half of the target that was
   missing. */
.page-crumb{color:var(--faint);font-size:12px;margin-bottom:6px;display:inline-flex;align-items:center;
  cursor:pointer;background:none;border:0;font-family:inherit;font-weight:inherit;letter-spacing:inherit;
  min-height:var(--shell-target-min);padding:0 10px;margin-left:-10px;border-radius:var(--shell-radius)}
.page-crumb:hover{color:var(--text)}
.page-crumb:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---- responsive (RWD) ---- */
.who-status{white-space:nowrap}
.erp-table .mud-table-container{overflow-x:auto}
.wrap-x{-webkit-overflow-scrolling:touch}
@media (max-width:1280px){ .view{max-width:100%} }
@media (max-width:960px){
  .view{padding:18px 14px 48px}
  .who-status{display:none}
  .cards.c2,.cards.c3,.cards.c4{grid-template-columns:1fr}
  .form{grid-template-columns:1fr}
  .kindsel{gap:6px}
}
@media (max-width:600px){
  /* .search and .who narrow with the shell now — see shell.css @media (max-width:600px) */
  .page-title,.head h1{font-size:19px}
  .view{padding:14px 10px 40px}
  /* stacked MudTable rows read as cards on phones */
  .erp-table .mud-table-row{display:block;border-bottom:1px solid var(--line-2);padding:6px 0}
}

/* ── F1 daily bar chart (DailyTotalsChart) — global so both the real column rects AND the MarkupString axis
   <text> labels pick it up. Theme-aware via the app CSS custom properties. ───────────────────────────────── */
.dtc-svg{width:100%;height:auto;display:block;overflow:visible;font-family:inherit}
.dtc-grid{stroke:var(--line-2);stroke-width:1}
.dtc-zero{stroke:var(--faint);stroke-width:1}
.dtc-ylabel{fill:var(--muted);font-size:13px;text-anchor:end}       /* enlarged, legible (owner: y-labels were too small) */
.dtc-xlabel{fill:var(--faint);font-size:12px;text-anchor:middle}
.dtc-bar{fill:var(--accent);pointer-events:none;transition:fill .08s ease}
.dtc-bar.neg{fill:var(--chart-neg)}
.dtc-hit{fill:transparent;cursor:pointer}
.dtc-band{fill:var(--accent-soft);opacity:0;pointer-events:none;transition:opacity .08s ease}
.dtc-col.hl .dtc-band{opacity:.6}                                    /* hovered column (shared hovered-day state) */
.dtc-col.hl .dtc-bar{fill:var(--chart-hot)}

/* ── S4 financial trend chart (FinancialTrendChart) — multi-line SVG, mirrors the .dtc- conventions above
   (real elements, not MudChart-generated paths, so var() colors resolve). ─────────────────────────────────── */
.ftc-ranges{display:flex;gap:4px}
.ftc-range{background:transparent;border:1px solid var(--line-2);color:var(--muted);border-radius:7px;padding:4px 10px;font-size:11.5px;font-family:inherit;cursor:pointer}
.ftc-range.on{border-color:var(--accent);background:var(--accent-soft);color:var(--text)}
.ftc-legend{display:flex;gap:14px;flex-wrap:wrap}
.ftc-legend-item{display:inline-flex;align-items:center;gap:6px;background:transparent;border:none;color:var(--muted);font-size:12px;font-family:inherit;cursor:pointer;padding:2px 0}
.ftc-legend-item.off{opacity:.4;text-decoration:line-through}
.ftc-dot{width:9px;height:9px;border-radius:50%;background:var(--dot);display:inline-block}
.ftc-svg{width:100%;height:auto;display:block;overflow:visible;font-family:inherit}
.ftc-grid{stroke:var(--line-2);stroke-width:1}
.ftc-zero{stroke:var(--faint);stroke-width:1}
.ftc-ylabel{fill:var(--muted);font-size:13px;text-anchor:end}
.ftc-xlabel{fill:var(--faint);font-size:11px;text-anchor:middle}
.ftc-line{fill:none;stroke-width:2;pointer-events:none}
.ftc-dot-pt{pointer-events:none}
.ftc-hit{fill:transparent;cursor:pointer}
.ftc-band{fill:var(--accent-soft);opacity:0;pointer-events:none;transition:opacity .08s ease}
.ftc-col.hl .ftc-band{opacity:.5}
/* drill-down panel (hover/focus a step → the facts that moved it that day, each linking to its source doc) */
.ftc-breakdown{display:flex;flex-wrap:wrap;gap:16px;margin-top:10px;padding:10px 12px;border:1px solid var(--line-2);border-radius:8px;background:var(--surface2)}
.ftc-breakdown-day{flex-basis:100%;font-size:12px;color:var(--muted);font-weight:600}

/* ── Exchange rates sparkline (Banking/ExchangeRates) — hand-rolled SVG for the same reason .dtc-/.ftc- are:
   MudChart's y-axis step is an Int32 in DATA units, so its tightest axis spans 1,00 PLN and an NBP mid rate
   moving in the fourth decimal draws as a flat line. Same custom-property conventions, so it is theme-aware. */
.fx-svg{width:100%;height:auto;display:block;overflow:visible;font-family:inherit}
.fx-grid{stroke:var(--line-2);stroke-width:1}
.fx-ylabel{fill:var(--muted);font-size:11px;text-anchor:end}
.fx-xlabel{fill:var(--faint);font-size:11px;text-anchor:middle}
.fx-line{stroke:var(--accent);stroke-width:2;fill:none;stroke-linecap:round}
/* a segment spanning a day with no recorded rate — dashed, so the hole is visible and not silently bridged */
.fx-line.gap{stroke-dasharray:4 3;opacity:.65}
.fx-pt{fill:var(--accent)}
.ftc-breakdown-series{min-width:190px;flex:1 1 190px}
.ftc-breakdown-head{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);margin-bottom:4px}
.ftc-breakdown-val{margin-left:auto;color:var(--text);font-weight:600}
.ftc-fact{display:flex;align-items:baseline;gap:8px;font-size:12px;padding:2px 0;border-top:1px solid var(--hair)}
.ftc-fact:first-of-type{border-top:none}
.ftc-fact-label{color:var(--text);text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.ftc-fact-label:hover{text-decoration:underline;color:var(--accent)}
.ftc-fact-amt{margin-left:auto;white-space:nowrap;font-variant-numeric:tabular-nums}
.ftc-fact-amt.pos{color:var(--good)}
.ftc-fact-amt.neg{color:var(--bad)}
.ftc-fact-empty{font-size:12px;color:var(--faint);padding:2px 0}
.ftc-fact-more{font-size:11px;color:var(--faint);padding:2px 0}
.dtc-col.sel .dtc-band{opacity:1;fill:var(--accent-dim)}             /* the day the grid is filtered to */
.dtc-col.sel .dtc-bar{fill:var(--chart-hot)}

/* ── Master-detail — the ERP's HOST GLUE only (#55) + list pager (#51) ────────────────────────
   ⚠ THE SPLIT ITSELF LIVES IN shell.css NOW (epic-081 ②, decision-log §6.194). The owner ruled that
   the portal's chat/booking panel uses this same ratio, so `.md-layout` / `.md-master` / `.md-detail`
   and the 1250px grid moved there to be ONE rule both hosts read. Do not re-add them here: two copies
   of one number is the defect that move exists to prevent.

   The two rules BELOW stayed, and stayed deliberately — both target `.view`, which is the ERP's own
   page wrapper and has no counterpart on the portal. `.md-view` also ties with the 1280px `.view`
   media query above on specificity, so it is decided by ORDER; shell.css loads FIRST, so moving it
   would have handed that tie to the media query and changed this host's paint. */
.md-view{max-width:none}   /* master-detail pages fill the width; the detail column is what's bounded, not the page */
.md-detail .view{padding:0;max-width:none;margin:0}  /* embedded detail sheds its standalone page chrome */
.list-pager{margin-top:12px;gap:12px;flex-wrap:wrap}
.list-pager .mud-pagination{margin:0}

/* ── Sign-in pages (#C1) ──────────────────────────────────────────────────────────────────────
   The Identity pages are STATICALLY rendered (see App.razor's PageRenderMode): a Blazor circuit
   cannot set an auth cookie, so the sign-in form must be a real SSR form post. That rules out
   MudBlazor's interactive inputs, hence plain elements styled to match the app's dark palette. */
.auth-shell{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:32px 16px}
.auth-card{width:100%;max-width:420px;background:var(--surface);border:1px solid var(--line-2);
  border-radius:14px;padding:28px 30px 26px}
.auth-brand{display:flex;align-items:center;gap:10px;margin-bottom:22px}
.auth-brand .mk{width:26px;height:26px;border-radius:7px;background:linear-gradient(135deg,var(--accent),var(--info))}
.auth-brand b{font-size:16px;letter-spacing:-.01em}
.auth-brand span{display:block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--faint)}
.auth-card h1{margin:0 0 4px;font-size:19px;font-weight:640;letter-spacing:-.01em}
.auth-card .sub{margin:0 0 20px;color:var(--muted);font-size:13px}
.auth-field{display:block;margin-bottom:14px}
.auth-field span{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);
  font-weight:600;margin-bottom:5px}
.auth-field input[type=text],.auth-field input[type=email],.auth-field input[type=password]{
  width:100%;padding:9px 11px;background:var(--surface2);color:var(--text);
  border:1px solid var(--line-2);border-radius:8px;font:inherit}
.auth-check{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:13px;margin-bottom:18px}
.auth-btn{width:100%;padding:10px 14px;border-radius:8px;border:1px solid transparent;font:inherit;
  font-weight:600;cursor:pointer;background:var(--accent);color:#06222a}
.auth-btn.secondary{background:transparent;color:var(--text);border-color:var(--line-2)}
.auth-btn+.auth-btn{margin-top:10px}
.auth-sep{display:flex;align-items:center;gap:12px;margin:20px 0;color:var(--faint);font-size:11px;
  text-transform:uppercase;letter-spacing:.08em}
.auth-sep:before,.auth-sep:after{content:"";flex:1;height:1px;background:var(--line-2)}
.auth-msg{border-radius:8px;padding:10px 12px;font-size:13px;margin-bottom:16px;border:1px solid}
.auth-msg.err{border-color:var(--bad);color:var(--bad);background:rgba(238,91,70,.08)}
.auth-msg.ok{border-color:var(--good);color:var(--good);background:rgba(73,178,87,.08)}
.auth-note{margin-top:18px;color:var(--faint);font-size:12px;text-align:center}
.auth-field .validation-message{color:var(--bad);font-size:12px;display:block;margin-top:4px}

/* ── "no authentication" banner (#C1) ─────────────────────────────────────────────────────────
   C-19 slot CONTENT — the ERP's own banner, rendered by Erp.Web.Shell.ErpDeploymentBanner. Shown only when
   Authentication:Disabled=true actually took effect. Fixed to the top and above MudBlazor's app bar
   (z-index 1301 > MudAppBar's 1100) so it cannot be scrolled away or covered: the pre-prod and production
   apps are otherwise pixel-identical, and telling them apart at a glance is the entire point.
   ⚠ The 26 px this occupies is COUPLED to shell.css's .has-open-mode-banner, which pushes the app bar and
   drawer down by exactly that much. Two files, one number, and both of them say so. */
.open-mode-banner{position:fixed;top:0;left:0;right:0;z-index:1301;
  background:var(--bad);color:#1a0603;font-size:12.5px;font-weight:600;letter-spacing:.01em;
  padding:5px 14px;text-align:center;line-height:1.35;
  /* ⚠ pointer-events:none — epic-080, the owner's "top left doesn't work (tested on mobile)".
     This element is z-index 1301 over an app bar at 1300, and it is TALLER than the 26 px the shell
     shifts by whenever its text wraps: MEASURED on rc140 at 43.8 px (768) and 60.6 px (390) against a
     one-line 26.9 px. So it lay on top of the drawer toggle and ATE ITS TAPS — page.tap() on the
     hamburger timed out at 390 px, which is the whole of the reported bug.
     It is a role="alert" with no controls in it and nothing in it is clickable, so it has no business
     being a hit-test target at any width. This is correct on its own terms rather than a workaround,
     and it is why the control now responds even where the banner still visually overlaps it.
     ⚠ IT DOES NOT FIX THE OVERLAP ITSELF — see shell.css's .has-open-mode-banner block. */
  pointer-events:none}
.open-mode-banner b{letter-spacing:.06em}

/* ── OWNER (2026-08-26, screenshot): the own-message accent bar sits FLUSH against the text — no margin.
   The package draws it at the gutter's RIGHT EDGE (`.chat-row-own .chat-gutter::after { right:0 }`,
   ChatMessageView preview.13) — deliberately non-displacing, but the gutter's right edge IS the text
   column's left edge, so the 2px rule touches the first glyph. One property moves it 8px into the
   gutter's 12px gap. DELIBERATE FOREIGN OVERRIDE of package CSS — dies when the package moves the bar
   itself (same family as the sticky-separator mask; see docs/backlog/chat-day-separator-sticky-margin
   note). Both hosts carry this rule in the same commit so the two surfaces cannot drift. */
.offer-chat-conversation .chat-row-own .chat-gutter::after{right:8px}
