/* ============================================================
   AKM ERP — Design system  ·  "Midnight & Signal"   (2026-10-01)
   One ERP for two companies: AKM (lubricant distribution) and
   DBP (spare parts + trucking). Midnight-ink chrome on a cool
   porcelain canvas; the ACCENT is the line of business — champagne
   amber (lubricants, spare parts) or route teal (logistics) — and
   the whole chrome shifts with it ([data-line] on <html>).
   ONE type family: IBM Plex Sans for the interface, IBM Plex Mono for what accountants read (document numbers
   and figures). A row mixes names and numbers, so the two must share a weight and a height — a light, narrow
   sans beside a wide mono read as thin text and small numbers (owner, 2026-10-04). Nothing readable is set
   below 12px, and "less important" is said with --muted, not with a smaller or fainter face (CONVENTIONS §1).
   ============================================================ */

:root {
    /* Chrome */
    --midnight:    #0e1726;
    --midnight-2:  #16233a;
    --midnight-3:  #213252;

    /* Accent = the line of business (default: amber) */
    --accent:        #c9973f;
    --accent-bright: #ddb05c;
    --accent-deep:   #a67a2a;
    --accent-ink:    #1c1405;   /* text ON the accent */
    --accent-soft:   rgba(201, 151, 63, .13);
    --accent-glow:   rgba(221, 176, 92, .34);

    /* Surfaces */
    --canvas:     #f3f5f8;
    --surface:    #ffffff;
    --surface-2:  #f8fafc;
    --border:     #e3e8ee;
    --border-soft:#edf0f4;
    --hairline:   #d3dae3;   /* a control's own edge — the secondary button's outline */

    /* Danger — what a destructive button turns to under the pointer */
    --danger:      #b42318;
    --danger-soft: #fdf1f0;

    /* Text */
    --text:       #101a2b;
    --muted:      #5b6879;
    --faint:      #6b7888;   /* 4.5:1 on white — the old #95a1b0 was 2.6:1 and carried real text */

    /* Legacy token names, kept as aliases so every existing rule follows the new palette */
    --ink:        var(--midnight);
    --ink-deep:   #0a111d;
    --ink-line:   var(--midnight-3);
    --brass:      var(--accent);
    --brass-bright: var(--accent-bright);
    --brass-soft: var(--accent-soft);
    --paper:      var(--canvas);

    /* Account-class hues (encode the COA structure) */
    --c-asset:     #0e7c86;
    --c-liability: #b4532a;
    --c-equity:    #4c4fa6;
    --c-revenue:   #3f8a3f;
    --c-cogs:      #b7842b;
    --c-expense:   #5b6b72;

    --font-sans: 'IBM Plex Sans', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

    --radius: 14px;
    --radius-sm: 9px;
    --shadow: 0 1px 2px rgba(14, 23, 38, .05), 0 18px 40px -22px rgba(14, 23, 38, .28);

    --kendo-font-family: var(--font-sans);
    --kendo-border-radius-md: 9px;
}

/* Telerik / Kendo theme — one accent, never Kendo's default coral. html:root outranks the theme's own :root,
   which loads AFTER this file and otherwise wins (that is why primary buttons stayed coral). */
html:root {
    --kendo-color-primary: var(--accent);
    --kendo-color-primary-hover: var(--accent-bright);
    --kendo-color-primary-active: var(--accent-deep);
    --kendo-color-on-primary: var(--accent-ink);
    --kendo-color-primary-subtle: var(--accent-soft);
    --kendo-color-primary-emphasis: var(--accent-deep);
    --kendo-color-primary-on-surface: var(--accent-deep);
    --kendo-font-family: var(--font-sans);
    --kendo-border-radius-md: 9px;
}

/* Logistics line (DBP): route teal. Same roles, another signal. Set on the layout's wrapper (MainLayout renders
   data-line), so popups inside TelerikRootComponent follow too. */
[data-line="L"] {
    --accent:        #0f9488;
    --accent-bright: #22b3a5;
    --accent-deep:   #0b7168;
    --accent-ink:    #ffffff;
    --accent-soft:   rgba(15, 148, 136, .12);
    --accent-glow:   rgba(34, 179, 165, .34);
}
/* A custom property is computed where it is declared: the Kendo tokens above resolved --accent on <html>, so they
   are re-declared wherever the line changes it. */
[data-line] {
    --kendo-color-primary: var(--accent);
    --kendo-color-primary-hover: var(--accent-bright);
    --kendo-color-primary-active: var(--accent-deep);
    --kendo-color-on-primary: var(--accent-ink);
    --kendo-color-primary-subtle: var(--accent-soft);
    --kendo-color-primary-emphasis: var(--accent-deep);
    --kendo-color-primary-on-surface: var(--accent-deep);
    --brass: var(--accent); --brass-bright: var(--accent-bright); --brass-soft: var(--accent-soft);
}

html, body {
    font-family: var(--font-sans);
    color: var(--text);
    background: var(--paper);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

a, .btn-link { color: var(--brass); text-decoration: none; }
a:hover { color: var(--brass-bright); }

h1, h2, h3 { letter-spacing: -.012em; }
h1:focus { outline: none; }

/* ---- Page header system (one line — see PageHeader.razor for the measurements) ------------ */
.page-head { margin: .1rem 0 .6rem; }
.page-eyebrow {
    font: 600 .78rem/1 var(--font-sans);
    letter-spacing: 0;
    color: var(--muted);
    display: inline-flex; align-items: center; gap: .45rem;
}
.page-eyebrow::before {
    content: ""; width: 7px; height: 7px; border-radius: 50%; display: inline-block;
    background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); transition: background-color .3s ease;
}
.page-head h1 {
    font: 750 1.55rem/1.1 var(--font-sans);
    letter-spacing: -.025em;
    color: var(--text); margin: 0;
}
/* Eyebrow and title on one baseline. The eyebrow keeps its brass rule, so the page still identifies its module
   at a glance — it just no longer owns a line of its own. */
.page-head__id { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; min-width: 0; }
.page-head__row { display: flex; align-items: center; gap: .8rem 1rem; flex-wrap: wrap; }
/* Actions sit at the far right whatever else is in the row (meta strip present or not). */
.page-head__actions { margin-left: auto; }

/* ---- Meta strip → a ruled "ledger tally" panel -------------- */
/* One framed panel (not loose cards): a brass header rule like a ledger's column line,
   hairline-ruled columns, mono tabular figures, and the headline total picked out in brass. */
.meta-strip { display: inline-flex; align-items: stretch; flex-wrap: wrap; margin-top: 1rem; padding: 0;
    background: var(--surface); border: 1px solid var(--border); border-top: 2px solid var(--brass);
    border-radius: 10px; box-shadow: 0 1px 2px rgba(16, 47, 56, .05), 0 10px 26px -18px rgba(16, 47, 56, .22);
    overflow: hidden; }
.meta { display: flex; flex-direction: column; gap: .32rem; padding: .68rem 1.4rem;
    border-left: 1px solid var(--border); }
.meta:first-child { border-left: none; }
.meta__num { font: 600 1.62rem/1 var(--font-mono); color: var(--ink);
    font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.meta:first-child .meta__num { color: var(--brass); }
.meta__label { font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .13em; color: var(--faint); }
/* Inside the one-line page header the tally rides ALONGSIDE the title instead of under it, so it has to be
   the height of a title, not of a dashboard card. Same panel, same figures — number and label side by side. */
.page-head__row .meta-strip { margin-top: 0; }
.page-head__row .meta { flex-direction: row; align-items: baseline; gap: .45rem; padding: .3rem .85rem; }
.page-head__row .meta__num { font-size: 1.02rem; }

/* ---- Surface card ------------------------------------------ */
.surface {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: hidden;
}

/* ---- Ledger code + class tag (the signature) --------------- */
.code { font-family: var(--font-mono); font-size: .84rem; color: var(--text); font-variant-numeric: tabular-nums; }
.num  { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---- List cell grammar — how a cell looks follows from what it IS, never from the page that drew it
   (audit 2026-10-03: document numbers came in four hand-written styles; Invoice sat next to Sales Orders
   in two of them). CONVENTIONS §4.
     identity  the locked column carries the row's name → medium weight, number or text alike;
     number    a document number or code is <DocNo> → .code; with a URL of its own it is a real link;
     figure    a right-aligned cell is a figure → mono + tabular, with or without a .num span inside. */
.k-grid td.k-grid-content-sticky { font-weight: 500; }
.k-grid td[style*="text-align: right"] { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* The link keeps the INK colour: amber on white is 3.9:1, too thin for 13px text read all day. What says
   "this opens" is the ledger rule under it, in the accent of the current line of business.
   (.k-grid is repeated in the selector because Telerik's theme loads after this file and resets grid links.) */
a.code, .k-grid a.code {
    color: var(--text);
    text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
    text-decoration-color: color-mix(in srgb, var(--accent) 60%, transparent);
}
a.code:hover, .k-grid a.code:hover { color: var(--accent-deep); text-decoration-color: currentColor; }
a.code:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* ---- Row numbers — a row's POSITION is not data: it is drawn by a CSS counter, so it cannot be sorted on,
   exported, or copied with the row, and it is always 1..n in the order the user is looking at. In a line
   table it sits in the margin of the first cell; in a grid it has a column of its own (the margin variant
   was tried on grids first and read as a number stuck to the code — and broke outright on grouped grids). Three places carry it, and only these (CONVENTIONS §4):
     document lines   <LineTable Numbered>   — the server names a line by number ("Line 3: …");
     report grids     GridPersist.Css(key, numbered: true) + GridPersist.RowNoColumn — a real "No" column;
     top-N lists      <RankList Ranked>      — the position is the information.
   Document and master lists are NOT numbered: their rows already have an identity (the number, the code). */
.line-table.is-numbered tbody { counter-reset: rowno; }
.line-table.is-numbered tbody > tr:not(:has(> td[colspan])) { counter-increment: rowno; }
/* The margin is ADDED to the first column, never taken from it: the header cell turns content-box, so its
   declared width keeps meaning "room for the content" and the column grows by exactly the 1.2rem the number
   needs (a 70px "Role" column would otherwise lose a third of itself). text-indent lines the label up with
   the cells below. */
.line-table.is-numbered thead th:first-child { position: relative; box-sizing: content-box; padding-left: 1.2rem; padding-right: 0; text-indent: .9rem; }
.line-table.is-numbered tbody > tr:not(:has(> td[colspan])) > td:first-child { position: relative; padding-left: 2.1rem; }
.line-table.is-numbered thead th:first-child::before,
.line-table.is-numbered tbody > tr:not(:has(> td[colspan])) > td:first-child::before {
    /* centred on the row, on the same line box as the text beside it — so the two share a baseline */
    position: absolute; top: 50%; transform: translateY(-50%); height: auto; text-align: right; text-indent: 0;
    font: 400 .8rem/1.4 var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0; color: var(--muted);
    pointer-events: none;
}
.line-table.is-numbered thead th:first-child::before,
.line-table.is-numbered tbody > tr:not(:has(> td[colspan])) > td:first-child::before { left: .15rem; width: 1.6rem; }
.line-table.is-numbered thead th:first-child::before { content: "No"; font: inherit; color: inherit; }
.line-table.is-numbered tbody > tr:not(:has(> td[colspan])) > td:first-child::before { content: counter(rowno); }
/* a line whose stored number is not its position (a receipt of PO lines 2 and 5) shows the stored one */
.line-table.is-numbered tbody > tr[data-n] > td:first-child::before { content: attr(data-n); }

/* report grids: a real "No" column (GridPersist.RowNoColumn) whose cells are empty — the number is the row's
   position in the CURRENT view, so sort and filter renumber it for free. --row-start is the offset of the
   current page (akm.rowStart reads it off the pager). Right-aligned like every number: 9, 10 and 100 line up
   on their units, which a centred column cannot do. */
.k-grid.is-numbered tbody { counter-reset: rowno var(--row-start, 0); }
.k-grid.is-numbered tbody > tr.k-master-row { counter-increment: rowno; }
.k-grid.is-numbered td.row-no { color: var(--muted); font-weight: 400; }
.k-grid.is-numbered td.row-no::after { content: counter(rowno); }

/* A header sits over its data: text columns read from the left, number columns end on the right — never
   centred, which leaves the label floating away from both edges. akm.headAlign marks the right-aligned ones
   (the header table and the body table are separate, so CSS alone cannot pair them). */
.k-grid th.th-r .k-cell-inner > .k-link { justify-content: flex-end; text-align: right; }

.rank.is-ranked { counter-reset: rowno; }
.rank.is-ranked > li { counter-increment: rowno; }
.rank.is-ranked .rank__label::before {
    content: counter(rowno); display: inline-block; width: 1.5rem;
    font: 400 .74rem/1 var(--font-mono); font-variant-numeric: tabular-nums; color: var(--faint);
}

.tag {
    display: inline-flex; align-items: center; gap: .4rem;
    font: 600 .75rem/1 var(--font-sans); letter-spacing: .03em;
    padding: .2rem .5rem; border-radius: 5px;
    background: color-mix(in srgb, var(--tag, var(--muted)) 12%, transparent);
    color: var(--tag, var(--muted));
}
.tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--tag, var(--muted)); }
.tag--asset     { --tag: var(--c-asset); }
.tag--liability { --tag: var(--c-liability); }
.tag--equity    { --tag: var(--c-equity); }
.tag--revenue   { --tag: var(--c-revenue); }
.tag--cogs      { --tag: var(--c-cogs); }
.tag--expense   { --tag: var(--c-expense); }

/* status pill */
/* nowrap: a pill is one label. Wrapped, it breaks into two half-rounded scraps ("One" / "approver" on a phone). */
.pill { font: 600 .75rem/1 var(--font-sans); padding: .22rem .5rem; border-radius: 999px; white-space: nowrap; }
/* semantic status pills — `--on`/`--ok` and `--neutral`/`--mid` are byte-identical aliases
   consumed under both names across pages; kept as aliases (no risky .razor rename). */
.pill--on, .pill--ok       { background: #e7f3ec; color: #2c7a4b; }
.pill--off                 { background: #f0eeea; color: #908a7e; }
.pill--neutral, .pill--mid { background: #eaeef0; color: #566b73; }
.pill--warn                { background: #fbf1de; color: #9a6b12; }

/* per-line approve/reject segmented control (Payment Proposal) */
.seg { display: inline-flex; border: 1px solid #d9d5c9; border-radius: 7px; overflow: hidden; }
.seg__btn { font: 600 .75rem/1 var(--font-sans); padding: .34rem .7rem; background: #fff; color: #908a7e;
    border: 0; border-right: 1px solid #ece9e1; cursor: pointer; transition: background .12s, color .12s; }
.seg__btn:last-child { border-right: 0; }
.seg__btn:hover { background: #f7f5ef; }
.seg__btn--on-ok { background: #e7f3ec; color: #2c7a4b; }
.seg__btn--on-no { background: #f7e3e0; color: #a84032; }
.seg__btn:focus-visible { outline: 2px solid var(--brass); outline-offset: -2px; }
tr.ppline--rejected td { opacity: .5; }
tr.ppline--rejected .num { text-decoration: line-through; }

/* ---- Telerik Grid refinements ------------------------------ */
.k-grid {
    font-family: var(--font-sans);
    background: #fff;
    border: 1px solid #d9d5c9;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(16,47,56,.05), 0 18px 40px -16px rgba(16,47,56,.18);
    font-size: .82rem;
    overflow: hidden;
}
.k-grid .k-grid-header, .k-grid .k-grid-header-wrap { background: var(--surface-2); }
.k-grid .k-grid-header { border-bottom: 1px solid var(--border); }
.k-grid .k-grid-header .k-column-title {
    font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
    font-size: .75rem; color: #4b534f;
}
.k-grid td { padding-block: .5rem; color: var(--text); border-bottom-color: #f0eee7; }
/* A grid with Size="sm" (report/data grids) must actually be compact: the global .k-grid td padding above
   out-specifies the theme's k-table-sm, so re-assert the tight padding at higher specificity. */
.k-grid .k-table-sm td, .k-grid .k-table-sm .k-table-td { padding-block: .18rem; }
/* Data-grid cells stay ONE line: truncate with an ellipsis instead of wrapping. Wrapping made rows tall and
   UNEVEN (a long Description became 2-3 lines), so few rows fit; a single line keeps every row the same
   compact height and shows more data. Pair long-text columns with a title tooltip (R11) so nothing is hidden.
   Opt out per column with .k-grid td.wrap when a cell genuinely needs to wrap.

   Applies to EVERY grid since 2026-08-03, not only the ones tagged .dense-grid: the audit found 57 of 99 grids
   carried the class and 42 did not, so the same product showed two different tables. Horizontal scroll is the
   right answer for an ERP row — wrapping a 12-column row onto three lines fits FEWER records on screen than the
   sideways scroll it was avoiding, and it makes a column of money impossible to scan. The tooltip that keeps the
   clipped value readable is attached on hover by akm.clippedTitles. */
.k-grid .k-grid-content td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.k-grid .k-grid-content td.wrap { white-space: normal; }
/* Headers never truncate. Data cells stay one line (above), but header TITLES may WRAP to a second line so the
   full column name always shows however narrow the column — the header row just gets a little taller, once, not
   per data row. Drop the width-inflating letter-spacing too. This guarantees no "OO VEN…"/"U…" clipping without
   hand-tuning every width. */
.k-grid .k-grid-header .k-column-title { letter-spacing: .01em; white-space: normal; overflow: visible; line-height: 1.15; flex: 1 1 auto; min-width: 0; }
.k-grid tr:hover td { background: var(--brass-soft); }
/* Grids whose rows open something on click (report summary -> timeline popup): show it in the cursor. */
.clickable-rows .k-grid-content tr { cursor: pointer; }
/* Icon-only action cell (e.g. the report row's timeline eye) — centred in its column. */
.cell-center { display: flex; justify-content: center; align-items: center; }
.k-grid .k-grid-pager { background: #f8f7f2; color: var(--muted); font-size: .78rem; border-top: 1px solid #e9e6dc; }
.row-actions { display: flex; gap: .25rem; justify-content: flex-end; }

/* ---- Login ------------------------------------------------- */
.login-shell { min-height: 100vh; display: grid; place-items: center; padding: 2rem;
    background: radial-gradient(1100px 560px at 50% -10%, #1a4651, var(--ink) 58%, var(--ink-deep)); }
.login-card { width: 100%; max-width: 380px; background: var(--surface); border-radius: 16px;
    box-shadow: 0 30px 60px -22px rgba(0,0,0,.55); padding: 2.2rem 2rem; }
.login-brand { display: flex; justify-content: center; margin-bottom: 1.6rem; }
.login-logo { height: 38px; width: auto; display: block; }
.login-title { font: 700 1.5rem/1.1 var(--font-sans); margin: 0; color: var(--text); letter-spacing: -.01em; }
.login-sub { color: var(--muted); font-size: .85rem; margin: .25rem 0 1.4rem; }
.login-form { display: flex; flex-direction: column; }
.login-label { font-size: .76rem; font-weight: 600; color: var(--muted); margin-top: .7rem; margin-bottom: .25rem; }
.login-input { width: 100%; padding: .6rem .7rem; border: 1px solid var(--border); border-radius: 8px;
    font: 400 .9rem var(--font-sans); background: var(--surface-2); color: var(--text); }
.login-input:focus { outline: none; border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-soft); background: #fff; }
.login-btn { margin-top: 1.5rem; padding: .68rem; border: 0; border-radius: 8px; cursor: pointer;
    background: var(--ink); color: #fff; font: 600 .92rem var(--font-sans); }
.login-btn:hover { background: var(--ink-deep); }
.login-error { background: #fee2e2; color: #b91c1c; font-size: .82rem; padding: .55rem .7rem; border-radius: 8px; margin-bottom: .6rem; }

/* ---- Topbar user ---- */
.topbar-user { font-size: .82rem; font-weight: 600; color: var(--text); }
.topbar-logout-form { display: inline; margin: 0; }
.topbar-logout { background: none; border: 1px solid var(--border); border-radius: 6px; cursor: pointer;
    font: 500 .78rem var(--font-sans); color: var(--muted); padding: .32rem .65rem; }
.topbar-logout:hover { border-color: var(--brass); color: var(--brass); }
.pw-input { width: 100%; box-sizing: border-box; padding: .45rem .6rem; }

/* ---- Menu access tree (User Management) ---- */
.access-hint { color: var(--muted); font-size: .82rem; margin: 0 0 .8rem; }
.access-tree { max-height: 440px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; padding: .5rem .75rem; }
.access-actions { display: flex; align-items: center; justify-content: space-between; margin-top: 1rem; }
.access-count { color: var(--muted); font-size: .8rem; font-weight: 600; }

/* ---- Setting screens ---- */
.setting-panel { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 1.5rem 1.6rem; box-shadow: 0 1px 3px rgba(16,47,56,.06); }
.muted-note { color: var(--muted); font-size: .85rem; }
.period-load { display: flex; gap: .6rem; align-items: flex-end; }
.period-table { width: 100%; border-collapse: collapse; }
.period-table th { text-align: left; font-size: .76rem; font-weight: 600; color: var(--muted); padding: .45rem .6rem; border-bottom: 1px solid var(--border); }
.period-table td { padding: .35rem .6rem; border-bottom: 1px solid #eef0f0; font-size: .88rem; }

/* assignment board (warehouse access, sales admin) */
.assign-board { display: flex; flex-direction: column; gap: 1.1rem; }
.assign-head { display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--border); padding-bottom: .5rem; }
.assign-title { font-weight: 700; font-size: .95rem; color: var(--text); }
.assign-bulk { display: flex; align-items: center; gap: .35rem; }
.assign-count { color: var(--muted); font-size: .78rem; font-weight: 600; margin-left: .4rem; }
.assign-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: .3rem .9rem; max-height: 460px; overflow-y: auto; padding: .2rem; }
.assign-item { display: flex; align-items: center; gap: .55rem; font-size: .88rem; padding: .28rem .2rem; cursor: pointer; }
.assign-item input { width: 16px; height: 16px; accent-color: var(--brass); }
.assign-actions { margin-top: .3rem; }

/* sales targets — year editor */
.target-toolbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .8rem; margin-bottom: 1rem; padding-bottom: .9rem; border-bottom: 1px solid var(--border); }
.target-fill { display: flex; align-items: center; gap: .55rem; }
.target-total { font-size: .9rem; color: var(--muted); }
.target-total strong { color: var(--text); font-family: var(--font-mono); font-size: 1.05rem; margin-left: .35rem; }

/* menu management rows */
.menu-grouprow { font-weight: 700; color: var(--ink); }
.menu-itemrow { padding-left: 1.1rem; color: var(--text); }

/* ===== Quotation — document editor ===== */
/* slim back link (top-left) — the document meta card below acts as the header */
.doc-back { margin: .1rem 0 .85rem; }
.linkback { display: inline-flex; align-items: center; gap: .4rem; background: none; border: 0; cursor: pointer;
    font: 600 .82rem/1 var(--font-sans); color: var(--muted); padding: .3rem .5rem .3rem 0; transition: color .15s; }
.linkback:hover { color: var(--ink); }
.linkback__arr { font-size: 1.05rem; line-height: 1; }

/* grid toolbar filter bar — From/To + Status on the left, search pushed to the right */
.k-grid-toolbar { gap: .9rem; flex-wrap: wrap; padding-block: .6rem; }
.k-grid-toolbar .grid-flt, .rpt-bar .grid-flt { display: inline-flex; align-items: center; gap: .45rem; }
.grid-flt__lbl { font: 600 .75rem/1 var(--font-sans); text-transform: uppercase; letter-spacing: .08em; color: var(--faint); }
.grid-flt__spacer { flex: 1 1 auto; }
.k-grid-toolbar .k-searchbox { width: 300px; max-width: 38vw; }

/* ---- GL report pages (Buku Besar, Neraca Saldo) ---- */
.rpt-bar { display: flex; align-items: flex-end; gap: 1rem; flex-wrap: wrap; margin: .1rem 0 1.1rem; }
.rpt-head { display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; margin: .1rem 0 .6rem; }
.rpt-open { color: var(--muted); font-size: .9rem; }
.rpt-foot { display: flex; gap: 2rem; justify-content: flex-end; flex-wrap: wrap; margin-top: .9rem;
    padding: .7rem 1.1rem; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; font-size: .9rem; }
.rpt-foot b { margin-left: .4rem; color: var(--ink); }
.rpt-foot__close b { color: var(--brass); }
.rpt-foot__off b { color: #c0392b; }
.rpt-empty { margin: 2rem 0; padding: 1.6rem; text-align: center; color: var(--muted);
    background: var(--surface); border: 1px dashed var(--border); border-radius: 10px; }
/* jurnal umum balance footer */
.ju-foot td { padding-top: .5rem; border-top: 1px solid var(--border); }
.ju-foot--off td { color: #c0392b; }
.ju-foot--ok td { color: #2f8f4e; }

/* ============================================================
   Responsive baseline — keep every screen usable on mobile.
   Most pages need NO per-page CSS once these hold.
   ============================================================ */

/* Wrap a wide table/block so IT scrolls sideways instead of the whole page. */
.x-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.x-scroll > table { min-width: max-content; }

/* ── Modals: the title bar and the buttons stay on screen, the FORM scrolls ──
   A modal is as tall as its content, and Telerik centres it with inline styles — so a long form
   (a 14-day roster, a document with many lines) grows past the viewport and takes its Save button
   with it. The rule was written once, but only inside the 640px media query, so every desktop user
   met a modal whose footer was below the fold and unreachable.
   Applies to all 39 modals at once because they share one footer class.
   The cap is in `dvh` (the `vh` line is only the fallback for a browser without it): iPhone Safari resolves
   `vh` against the screen with its toolbars RETRACTED, while a modal sits in Telerik's fixed layer, which is the
   VISIBLE area between them — a 92vh window ran ~55px past it, Save/Cancel under the bottom bar, and most
   master-data windows have no X (owner report 2026-10-07). On a desktop dvh = vh: nothing moves there. */
.k-window {
    max-width: 96vw;
    max-height: 92vh;
    max-height: 92dvh;
    display: flex;
    flex-direction: column;
}
.k-window > .k-window-titlebar { flex: none; }
.k-window > .k-window-content { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }

/* The footer lives INSIDE the scrolling content, so it is pinned with sticky rather than moved out —
   same result, no rewrite of every modal. It only detaches from the flow while there is something to
   scroll, so short forms look exactly as before.
   An audit of all 39 modals found THREE footer mechanisms, not one: 61 uses of `.quote-bar__btns`
   (transaction editors), 20 master-data modals whose buttons come from a Telerik `<FormButtons>`
   (`.k-form-buttons`), and 6 that use the real `<WindowActions>` — the last needs nothing, being a
   flex sibling of the scrolling body rather than inside it. Both of the inside-the-body kinds are
   listed here; missing the second would have left every master-data editor cut off. */
.k-window .quote-bar__btns,
.k-window .k-window-content > .k-form > .k-form-buttons {
    position: sticky;
    bottom: calc(-1 * var(--kendo-spacing-4, 1rem));
    z-index: 2;
    margin-bottom: calc(-1 * var(--kendo-spacing-4, 1rem));
    padding: .75rem 0;
    background: var(--surface);
    box-shadow: 0 -1px 0 var(--border);
}

/* ── Adaptive pickers: the sheet is never wider than the screen ──
   On a phone (AdaptiveMode.Auto) a picker opens as Telerik's action sheet, whose view is a flex item with the
   theme's `min-width: auto` — so it grows to its content's widest line. A multi-column picker's list is the sum of
   its columns (PO 550px, Customer 410px, Item 690px), so the view became 444–724px on a 390px phone: the search
   box and list began ~120px in, ran off the right edge, and the Done button sat past it (owner report 2026-10-07).
   At min-width 0 the view is the sheet's width; the list scrolls sideways inside its own box. No desktop effect:
   above the adaptive breakpoints Telerik renders a popup, not a sheet. */
.k-actionsheet .k-actionsheet-view { min-width: 0; }

@media (max-width: 640px) {
    /* Fixed-width Telerik inputs/pickers go fluid so forms, toolbars & modals fit. */
    .k-input, .k-picker, .k-textbox, .k-numerictextbox, .k-combobox, .k-dropdownlist,
    .k-datepicker, .k-datetimepicker, .k-timepicker, .k-maskedtextbox,
    .k-autocomplete, .k-multiselect { max-width: 100% !important; }

    /* CRUD modal: pin to an on-screen box and neutralise the JS centring. The scrolling body and the
       pinned footer are no longer here — they are unconditional now (see the .k-window block above),
       because a desktop modal overflows exactly the same way a phone one does. Every modal is inside
       Telerik's fixed `.k-dialog-wrapper`, so a page scrolled before opening does not move it. Top and
       cap in dvh (vh = fallback): 4 + 92 keeps the footer above Safari's bottom bar (see above). */
    .k-window {
        width: 94vw !important; max-width: 94vw !important;
        left: 3vw !important; top: 4vh !important; top: 4dvh !important;
        max-height: 92vh !important; max-height: 92dvh !important;
        transform: none !important;
    }
    .k-window .k-form-buttons, .k-window .k-actions, .k-window .k-window-actions { flex-wrap: wrap; }

    /* Data grids: keep columns readable; the grid scrolls instead of crushing them. */
    .k-grid .k-table { min-width: 560px; }

    /* Root guard: a stray wide child never scrolls/clips the whole page sideways.
       `clip` (not hidden) keeps vertical scroll working; the mobile top-bar isn't sticky. */
    html { overflow-x: clip; }

    /* Hard-cap the content containers so nothing can stretch past the viewport. */
    main, article.content, .setting-panel { max-width: 100%; min-width: 0; }

    /* Tighter panels + always-wrapping inline toolbars. */
    .setting-panel { padding: 1.1rem 1rem; }
    .period-load, .target-fill { flex-wrap: wrap; }

    /* Few-column data-entry tables (Targets, Attendance Periods) FIT the screen
       instead of forcing a wide horizontal scroll: drop their fixed column widths
       (their inputs are already fluid via the rule above) and override the
       .x-scroll max-content minimum so the table can shrink. */
    .period-table { min-width: 0 !important; }
    .period-table th, .period-table td { width: auto !important; }
    /* split the row so the two value columns are equal — Notes isn't starved by the amount field. */
    .period-table th:nth-child(2), .period-table td:nth-child(2),
    .period-table th:nth-child(3), .period-table td:nth-child(3) { width: 44% !important; }
    .x-scroll > .period-table { min-width: 0 !important; }
}

/* ===== Phone layout — shared fixes (responsive audit 2026-10-03) =====
   Measured on every route of both companies at iPhone width: EVERY page was laid out wider than the
   screen (437–612px on a 390px phone), so the browser zoomed the whole page out — which is why tables
   looked tiny and labels collided. The culprits were all shared chrome, so the fix lives here, once:
   the top bar, the grid toolbar search box, the grid pager, the toaster, segmented controls, and the
   line tables (now the LineTable component). Anything new built from these pieces inherits it. */
@media (max-width: 640px) {
    /* line tables scroll inside their own box; auto layout so fixed-width numeric columns can never
       squeeze a text column to a negative width (the Rates › Retase overlap) */
    .line-table { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }
    .line-table > .quote-lines { table-layout: auto; }
    /* WO repair/overhaul parent row: item, code, serial, qty side by side needs ~620px — wrap them */
    .wo-parent__head { flex-wrap: wrap; }
    .wo-parent__item { flex: 1 1 100%; }
    .wo-parent__f { flex: 1 1 calc(50% - .4rem); width: auto; }
    /* words never break mid-word; headers stay on one line — a column is as wide as its longest word and
       the table scrolls sideways when the sum exceeds the screen */
    .line-table > .quote-lines td { word-break: normal; overflow-wrap: normal; }
    /* …and that has to reach the LineCell's own text: it wraps `anywhere` (R17, so nothing is clipped on a desktop
       column), which in auto layout makes a column's minimum ONE CHARACTER — a Notes column read "Pe / ngi / rim / an". */
    .line-table > .quote-lines .cell-text { overflow-wrap: normal; word-break: normal; }
    .line-table > .quote-lines th { white-space: nowrap; }
    /* a date written in full ("13 Agustus 2026") does not fit half a phone: a field row with a date picker stacks */
    .qf-row:has(.k-datepicker, .k-datetimepicker) { grid-template-columns: 1fr; }

    /* segmented controls & period bars wrap instead of pushing the page wider */
    .dseg { display: flex; flex-wrap: wrap; max-width: 100%; }
    .period, .period__range { flex-wrap: wrap; max-width: 100%; }
    .page-head, .page-header, .ph-row { flex-wrap: wrap; }

    /* grid toolbar: search takes its own full row; buttons stay icon-sized */
    .k-grid-toolbar { gap: .4rem; }
    .k-grid-toolbar .k-searchbox, .k-grid-toolbar .k-grid-search { width: 100% !important; max-width: none !important; order: 99; flex: 1 1 100%; }

    /* pager: drop the "items per page" picker and the "1 - 50 of 120" text — the page buttons remain */
    .k-pager .k-pager-sizes, .k-pager .k-pager-info { display: none !important; }
    .k-pager { flex-wrap: wrap; justify-content: center; }

    /* sticky editor action bar: its two-line explanation covered a quarter of a phone screen. One small line
       keeps the status message (e.g. "Approved — reopen to change") without burying the form under it. */
    .quote-bar__hint { flex: 1 1 100%; min-width: 0; font-size: .75rem; line-height: 1.3;
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

    /* grid type: the page is no longer zoomed out, so 14px is real 14px; give rows a touch target */
    .k-grid td { padding-block: .55rem; }

    /* toaster: fixed to the visual viewport, never wider than it */
    .k-notification-group.app-toaster { max-width: calc(100% - 1.8rem); }
    .app-toaster .k-notification { width: auto !important; max-width: 100%; }
}

/* ===== Full screen for a grid — CSS, not the Fullscreen API =====
   The browser API failed twice: iPhone Safari does not implement it for anything but <video> (the
   button did nothing on a phone), and where it works, every Telerik popup — column menu, filter menu,
   dropdowns — renders on <body>, OUTSIDE the full-screen element, so filtering silently stopped working
   in full screen. Pinning the grid over the page keeps popups (z-index 10000+) above it. */
.k-grid.akm-grid--max {
    position: fixed !important; inset: 0; z-index: 1000; height: 100vh !important; height: 100dvh !important;
    max-height: none; margin: 0; border-radius: 0; border: 0; resize: none;
    background: var(--surface); padding: env(safe-area-inset-top) env(safe-area-inset-right) 0 env(safe-area-inset-left);
}
.k-grid.akm-grid--max .k-table { font-size: 1.02rem; }
html.akm-grid-max-open, html.akm-grid-max-open body { overflow: hidden; }


/* ===== Printable document ===== */
/* A document only ever renders on its OWN preview page (R15); the `--preview` modifier below is what shows
   it. The base stays hidden so a .print-doc dropped into an app page can never leak onto the screen. */
.print-doc { display: none; }
@media print { @page { size: A4; margin: 12mm 13mm; } }

/* ===== Document PREVIEW page (own route + PrintLayout) — the pattern to use for new prints ===== */
.print-shell { min-height: 100vh; background: #f2f0ea; padding: 0 0 3rem; }
.print-bar { position: sticky; top: 0; z-index: 5; display: flex; align-items: center; gap: .8rem;
    padding: .7rem 1.1rem; background: var(--surface); border-bottom: 1px solid var(--border); }
.print-bar__spacer { flex: 1; }
.print-bar__no { font-family: var(--font-mono); font-size: .82rem; color: var(--muted); }
/* On screen the document is a sheet on a desk; in print it is just the page. */
.print-doc--preview { display: block; margin: 1.4rem auto; padding: 14mm 13mm; width: 210mm; min-height: 297mm;
    background: #fff; box-shadow: 0 6px 26px rgba(16,47,56,.13); }
@media print {
    /* Nothing to hide here — this page IS the document. That is why it cannot spill a blank page. */
    .no-print { display: none !important; }
    .print-shell { background: none; padding: 0; min-height: 0; }
    .print-doc--preview { display: block; margin: 0; padding: 0; width: auto; min-height: 0; box-shadow: none; }
    /* with "Background graphics" on, the app's page colour would fill the paper below a short sheet */
    html, body { background: #fff; }
}
/* print-color-adjust: force the browser to actually print background fills (header/zebra/grand-total) */
.print-doc { color: #000; font: 9.5pt/1.45 Arial, "Helvetica Neue", sans-serif;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
/* header band */
.print-doc .pd-head { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
    padding-bottom: 9px; margin-bottom: 14px; border-bottom: 2px solid #000; }
.print-doc .pd-logo { height: 46px; display: block; }
.print-doc .pd-company { font-weight: 800; font-size: 8.5pt; margin-top: 4px; letter-spacing: .02em; color: #000; }
.print-doc .pd-title { font-weight: 800; font-size: 15pt; text-align: center; letter-spacing: .06em; color: #000; }
.print-doc .pd-place { text-align: right; font-size: 9pt; font-weight: 600; }
/* parties + info */
.print-doc .pd-to { font-size: 9pt; }
.print-doc .pd-cust { font-weight: 800; font-size: 11pt; margin: 1px 0 12px; color: #000; }
/* customer block: name + the optional "Up. <contact>" attention line (penawaran.kepada) */
.print-doc .pd-party { margin-bottom: 12px; }
.print-doc .pd-party .pd-cust { margin-bottom: 0; }
.print-doc .pd-attn { font-size: 9pt; color: #000; margin-top: 2px; }
.print-doc .pd-info { display: flex; justify-content: space-between; gap: 40px; margin-bottom: 12px; }
.print-doc .pd-info table { border-collapse: collapse; font-size: 9pt; }
.print-doc .pd-info td { padding: 1px 7px 1px 0; vertical-align: top; }
.print-doc .pd-info td:first-child { font-weight: 700; color: #000; }
.print-doc .pd-greet { margin: 0 0 9px; font-size: 9pt; }
/* items table — full grid border, petrol header, zebra rows */
.print-doc .pd-items { width: 100%; border-collapse: collapse; font-size: 8.5pt; border: 1px solid #000; }
.print-doc .pd-items thead th { background: #2b2b2b; color: #fff; font-weight: 700; text-align: left;
    padding: 6px 8px; border-right: 1px solid rgba(255, 255, 255, .16); letter-spacing: .02em; }
.print-doc .pd-items thead th:last-child { border-right: 0; }
.print-doc .pd-items thead th.r { text-align: right; }
.print-doc .pd-items tbody td { padding: 5px 8px; border: 1px solid #000; vertical-align: top; }
.print-doc .pd-items tbody tr:nth-child(even) td { background: #fff; }
.print-doc .pd-items td.r { text-align: right; white-space: nowrap; }
/* totals in the table foot — the SAME hairline grid as the body rows. Unstyled, the foot cells had no border at
   all, so only the table's dark outer frame showed around them and the totals read as one heavy box. */
.print-doc .pd-items tfoot td { padding: 4px 8px; border: 1px solid #000; }
.print-doc .pd-items tfoot .pd-grand td { background: #fff; color: #000; font-weight: 800; border-color: #000; }
.print-doc .pd-items tfoot .pd-grand td:first-child { color: #000; }
/* totals — bordered box, brass-on-petrol grand total */
.print-doc .pd-totals { margin: 8px 0 0 auto; border-collapse: collapse; font-size: 9pt; min-width: 340px; border: 1px solid #000; }
.print-doc .pd-totals td { padding: 3px 10px; border-bottom: 1px solid #000; }
.print-doc .pd-totals tr:last-child td { border-bottom: 0; }
.print-doc .pd-totals td:first-child { font-weight: 700; color: #000; }
.print-doc .pd-totals td.r { text-align: right; white-space: nowrap; }
.print-doc .pd-totals .pd-grand td { background: #fff; color: #000; font-weight: 800; font-size: 10pt; padding: 5px 10px; }
.print-doc .pd-totals .pd-grand td:first-child { color: #000; }
/* note + signature + footer */
.print-doc .pd-note { font-size: 8.5pt; margin: 22px 0 0; line-height: 1.5; }
.print-doc .pd-note b { color: #000; }
/* Quotation terms (penawaran.syarat) are a hand-typed bullet list — the line breaks ARE the formatting,
   and 319 of the 465 rows that carry terms contain them. Without pre-line they collapse into one paragraph. */
.print-doc .pd-terms { white-space: pre-line; margin-top: 18px; }
.print-doc .pd-sign { margin-top: 28px; width: 230px; text-align: center; }
.print-doc .pd-sign__title { font-size: 9pt; font-weight: 600; }
.print-doc .pd-sign__name { margin-top: 60px; font-weight: 800; font-size: 9pt; border-top: 1px solid #000; padding-top: 4px; display: inline-block; }
.print-doc .pd-sign__jabatan { font-size: 9pt; margin-top: 1px; }
.print-doc .pd-foot { text-align: center; font-size: 8pt; margin-top: 42px; color: #000; }

/* surat jalan (DO) print — Note block + 3-column signature row (DIBUAT OLEH | DISETUJUI | DITERIMA).
   The note-BLOCK styling (heading on its own line, 9pt) is shared by every doc whose note is
   `<b>Heading</b><div>…</div>` (DO, GR, PO, Pemakaian, Internal Transfer). Quotation is the ONE
   exception — its note is `<b>Note:</b><br/>text`, so a block `<b>` would double-break and it wants
   the base 8.5pt/22px. `.print-doc.quo-print` opts Quotation out; do NOT re-broaden this selector. */
.print-doc .pd-bill__addr { font-size: 9pt; margin-top: 2px; }
.print-doc:not(.quo-print) .pd-note { margin-top: 18px; font-size: 9pt; }
.print-doc:not(.quo-print) .pd-note b { display: block; margin-bottom: 2px; }
.print-doc .pd-signrow { display: flex; justify-content: space-between; gap: 24px; margin-top: 36px; }
.print-doc .pd-signcol { flex: 1; text-align: center; font-size: 9pt; }
.print-doc .pd-signcol__city { font-size: 8.5pt; margin-bottom: 2px; }
.print-doc .pd-signcol__role { font-weight: 700; letter-spacing: .03em; }
.print-doc .pd-signcol__line { margin-top: 64px; border-top: 1px solid #000; }
.print-doc .pd-signcol--named .pd-signcol__line { margin-top: 48px; }
.print-doc .pd-signcol__name { font-weight: 800; font-size: 9pt; padding-top: 3px; }

/* PURCHASE ORDER print — header boxes, boxed signature row, terms, left-aligned office footer */
.print-doc .pd-pohead { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; border: 1px solid #000;
    padding: 8px 10px; margin-bottom: 12px; }
.print-doc .pd-poaddr { border-left: 1px solid #000; padding-left: 14px; font-size: 9pt; }
.print-doc .pd-poaddr__blk { margin-bottom: 10px; }
.print-doc .pd-poaddr__blk b { display: block; margin-bottom: 2px; }
.print-doc .pd-accept { text-align: right; font-size: 9pt; margin: 14px 0 6px; }
.print-doc .pd-signrow--boxed { border: 1px solid #000; margin-top: 6px; gap: 0; }
.print-doc .pd-signrow--boxed .pd-signcol { border-right: 1px solid #000; padding: 6px 8px; display: flex; flex-direction: column; min-height: 118px; }
.print-doc .pd-signrow--boxed .pd-signcol:last-child { border-right: 0; }
/* whichever element leads the bottom block (signature image if on file, else the invisible line) soaks up the
   flex slack, so the NAME sits flush at the bottom of every column and stays aligned across all three */
.print-doc .pd-signrow--boxed .pd-signcol__line { border-top: 0; margin-top: 0; }
/* Fixed-height signature slot: every column reserves the same space whether or not it carries a TTD image,
   so the rule line and the name sit on ONE baseline across all three columns. Without it the image height
   pushed its own column's name above the others. */
/* A fixed-height slot the image sits INSIDE, so the baseline is the same in every column whether that column
   has a scanned signature or not. Was scoped to --boxed (the PO print), which is why only the PO lined up;
   the other three put the <img> straight into the column, so max-height:52px plus the line's own margin-top
   pushed "Dibuat oleh" about 50px below "Disetujui"/"Diterima". Latent while the files 404'd, live the moment
   they were seeded (PRINT-PARITY). */
.print-doc .pd-sign__slot { height: 56px; margin-top: auto; display: flex; align-items: flex-end; justify-content: center; }
.print-doc .pd-sign__slot .pd-sign__img { max-height: 56px; margin: 0; }
.print-doc .pd-signrow--boxed .pd-sign__slot { height: 56px; margin-top: auto; display: flex; align-items: flex-end; justify-content: center; }
.print-doc .pd-signrow--boxed .pd-sign__img { max-height: 56px; margin: 0; }
.print-doc .pd-signrow--boxed .pd-signcol__name { margin-top: 2px; }

/* Draft watermark — a PO printed before approval must be unmistakable to a supplier.
   The sheet is deliberately left `position: static`, so the watermark takes the PAGE as its containing block
   and covers it edge to edge. Do NOT give `.print-doc` a `position` to "scope" the watermark: that drops the
   document out of its page position and pushes it small onto page 2 (broke the PO print, 2026-07-27). */
.print-doc .pd-watermark {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    display: flex; align-items: center; justify-content: center;
    font-size: 96pt; font-weight: 800; letter-spacing: .1em;
    color: rgba(180, 35, 24, .12); transform: rotate(-30deg);
}
/* …but `absolute` covers ONE page. A long draft — 87 unposted Berita Acara and 9 draft quotations run past a
   single sheet — carried the mark on page 1 and nothing after it, so pages 2..n of an unapproved document were
   indistinguishable from a final one. `fixed` repeats per printed page, and it does NOT take the sheet out of
   flow the way giving `.print-doc` a `position` did (see the warning above). Screen preview keeps `absolute`
   so the mark scrolls with the document instead of hovering over the viewport.
   Display-standards audit 2026-07-28. */
@media print {
    .print-doc .pd-watermark { position: fixed; inset: 0; }
}
.print-doc .pd-terms { font-size: 8.5pt; margin-top: 12px; }
.print-doc .pd-terms ol { margin: 3px 0 0 16px; padding: 0; }
.print-doc .pd-foot--left { text-align: left; font-size: 7.5pt; border-top: 1px solid #000; padding-top: 6px; }
.print-doc .pd-foot--left div { margin-bottom: 1px; }
.print-doc .pd-sign__img { display: block; max-height: 52px; margin: 6px auto -8px; }
/* when a signature image is on file the name sits right under it (no empty wet-signature gap) */
.print-doc .pd-sign__img + .pd-sign__name { margin-top: 8px; }

/* ---- shared document-print bits: purchase-side + accounting prints ----
   (PO, Goods Receipt, Purchase Invoice, Pemakaian Barang, Berita Acara — logo left, title beside it) */
.print-doc .pd-head-doc { display: flex; align-items: center; gap: 18px;
    padding-bottom: 9px; margin-bottom: 12px; border-bottom: 2px solid #000; }
.print-doc .pd-head-doc .pd-logo { height: 54px; }
/* Logo sized by WIDTH (Setting › Print Settings › Logo, CompanyLogo.razor): legacy prints put the logo in a col-3 at
   width:100% ≈ 48 mm, and do.jrxml in a 180 pt title band = 63.5 mm (×1.323). A company without a width keeps the
   46 px height above (DBP). After the .pd-head-doc rule on purpose: same specificity, the later one wins. */
.print-doc .pd-logo.pd-logo--sized { height: auto; width: var(--pd-logo-w); max-width: 100%; }
.print-doc.do-print .pd-logo.pd-logo--sized { width: calc(var(--pd-logo-w) * 1.323); }
/* Quotation (penawaran.pdf): the logo on its own row, QUOTATION centred under it, the place line on the right. */
.print-doc.quo-print .pd-head { display: block; border-bottom: 0; margin-bottom: 6px; }
.print-doc.quo-print .pd-head .pd-title { margin: 6px 0 2px; font-size: 12pt; font-weight: 400; letter-spacing: 0; }
.print-doc.quo-print .pd-head .pd-place { text-align: right; font-weight: 400; }
/* Quotation items + totals (penawaran.pdf): dark header band, NO vertical lines, ONE rule under the rows, and plain
   total rows with no box around them. Invoice / DO keep their boxes; the PO's totals are plain too (below). */
.print-doc.quo-print .pd-items { border: 0; }
.print-doc.quo-print .pd-items thead th { border-right: 0; }
.print-doc.quo-print .pd-items tbody td { border: 0; }
.print-doc.quo-print .pd-items tbody tr:last-child td { border-bottom: 1px solid #000; }
.print-doc.quo-print .pd-totals { border: 0; }
.print-doc.quo-print .pd-totals td { border-bottom: 0; padding: 2px 10px; }
.print-doc.quo-print .pd-totals td:first-child { font-weight: 400; }
.print-doc.quo-print .pd-totals .pd-grand td { font-size: 9pt; font-weight: 400; padding: 2px 10px; }
/* Purchase Order (cetakan po.pdf, legacy printnew.xhtml .po-totals/.po-tnc/.po-sign): plain right-aligned total rows,
   terms with no box, and only the headings bold — header labels, totals and signature captions are regular weight. */
.print-doc.po-print .pd-terms { border: 0; border-radius: 0; padding: 0; }
.print-doc.po-print .pd-totals { border: 0; }
.print-doc.po-print .pd-totals td { border-bottom: 0; padding: 1px 5px; }
.print-doc.po-print .pd-totals td:first-child { font-weight: 400; text-align: right; }
.print-doc.po-print .pd-totals .pd-grand td { font-size: 9pt; font-weight: 400; padding: 1px 5px; }
.print-doc.po-print .pd-kv td:first-child { font-weight: 400; }
/* a header table keeps its own height in the grid row (DBP's 4-row order table beside the 5-row supplier one) */
.print-doc.po-print .pd-pohead > .pd-kv { align-self: start; }
.print-doc.po-print .pd-signcol__role { font-weight: 400; }
.print-doc.po-print .pd-signcol__name { font-weight: 400; }
.print-doc .pd-head-doc .pd-title { flex: 1; }
.print-doc .pd-doc__co { font-size: 8.5pt; color: #000; line-height: 1.45; }
.print-doc .pd-doc__co b { color: #000; display: inline-block; min-width: 42px; }
/* key/value header table (label : value), padded + nowrap so "Term Of Payment" can't wrap */
.print-doc .pd-kv { border-collapse: collapse; font-size: 9pt; }
.print-doc .pd-kv td { padding: 1px 8px 1px 0; vertical-align: top; white-space: nowrap; }
.print-doc .pd-kv td:first-child { font-weight: 700; color: #000; }
.print-doc .pd-kvrow { display: flex; justify-content: space-between; gap: 30px; margin-bottom: 12px; }
.print-doc .pd-items th.c, .print-doc .pd-items td.c { text-align: center; }
/* PO item table — legacy .po-table centres every header (No / UOM / Disc % are centred cells) */
.print-doc .po-items thead th { text-align: center; }
/* surat jalan (DO) item grid — do.pdf is a plain grid: white header, thin black borders, no zebra */
.print-doc .do-items { border: 1px solid #000; }
.print-doc .do-items thead th { background: #fff; color: #000; border: 1px solid #000; }
.print-doc .do-items tbody td { border: 1px solid #000; }
.print-doc .do-items tbody tr:nth-child(even) td { background: #fff; }
/* Delivery Order (do-print) — reference/do.pdf is a plain 8 pt black Jasper sheet (do.jrxml): 10 pt bold title, normal
   labels and values, centred NO/UOM/QTY, a normal-weight header row, no signature rules (PR-A14). */
.print-doc.do-print .pd-title { font-size: 10pt; letter-spacing: 0; margin: 6px 0 10px; }
.print-doc.do-print .pd-bill__lbl, .print-doc.do-print .pd-bill__cust, .print-doc.do-print .pd-bill__addr,
.print-doc.do-print .pd-kv, .print-doc.do-print .pd-kv td:first-child { font-size: 8pt; font-weight: 400; color: #000; }
.print-doc.do-print .pd-bill__cust { margin-top: 4px; }
.print-doc.do-print .do-items { font-size: 8pt; }
.print-doc.do-print .do-items thead th { font-weight: 400; }
.print-doc.do-print .pd-note { font-size: 8pt; }
.print-doc.do-print .pd-signcol, .print-doc.do-print .pd-signcol__city, .print-doc.do-print .pd-signcol__role { font-size: 8pt; font-weight: 400; letter-spacing: 0; }
.print-doc.do-print .pd-signrow { margin-bottom: 80px; }
/* DO footer — fixed two-line template text (do.pdf); the phone line is bold */
.print-doc .pd-foot__tel { font-weight: 700; margin-top: 2px; }

/* inline field + action button (e.g. No. Faktur + Save) */
.qf-inline { display: flex; gap: .5rem; align-items: center; }
.qf-inline > :first-child { flex: 1; }

/* signature (TTD) preview in the employee editor */
.ttd-preview { position: relative; display: inline-block; border: 1px dashed #d9d5c9; border-radius: 8px; padding: .5rem 1rem; background: #fff; }
.ttd-preview img { max-height: 64px; display: block; }
.ttd-preview .wo-att__del { position: absolute; top: -8px; right: -8px; }

/* ---- SHARED print letterhead + meta blocks ----
   These were scoped to `.inv-print` while FIVE documents attach the same class names. Delivery Order
   (do-print) and TTI (tti-print) got the markup and none of the layout: DELIVERY TO stacked above its meta
   table instead of beside it, the customer name lost its weight, and pd-meta lost border-collapse/nowrap so
   "Tgl Kirim" could wrap mid-label. Picking List had worked around it by copying the rules under its own
   modifier. Layout belongs to `.print-doc`; only what is genuinely invoice-specific stays scoped below. */
.print-doc .pd-head-inv { display: flex; align-items: center; gap: 18px; padding-bottom: 12px; margin-bottom: 6px; }
.print-doc .pd-co__name { font-weight: 800; font-size: 12pt; color: #000; letter-spacing: .02em; }
.print-doc .pd-co__line { font-size: 8.5pt; color: #000; margin-top: 2px; }
.print-doc .pd-co__line b { color: #000; font-weight: 400; display: inline-block; min-width: 44px; }
.print-doc .pd-billmeta { display: flex; justify-content: space-between; gap: 40px; margin-bottom: 16px; }
.print-doc .pd-bill__lbl { font-weight: 800; font-size: 9pt; color: #000; }
.print-doc .pd-bill__cust { font-weight: 800; font-size: 11pt; margin-top: 8px; color: #000; }
.print-doc .pd-meta { border-collapse: collapse; font-size: 9pt; }
.print-doc .pd-meta td { padding: 1px 8px 1px 0; vertical-align: top; white-space: nowrap; }
.print-doc .pd-meta td:first-child { font-weight: 700; color: #000; }
/* Tanda Terima: a long customer address wraps inside its cell instead of pushing the Courier block off the sheet. */
.print-doc.tti-print .pd-billmeta > .pd-meta:first-child { min-width: 0; flex: 1 1 auto; }
.print-doc.tti-print .pd-billmeta > .pd-meta:first-child td:last-child { white-space: normal; overflow-wrap: anywhere; }
.print-doc.tti-print .pd-billmeta > .pd-meta:last-child { flex: none; }

/* ---- Invoice print (inv-print) — matches the legacy /invoice/print_new layout ---- */
.print-doc.inv-print .pd-title { margin: 4px 0 16px; text-decoration: underline; }
.print-doc.inv-print .pd-bank { margin-top: 26px; border: 1px solid #000; border-radius: 4px; display: inline-block; padding: 8px 12px; }
.print-doc.inv-print .pd-bank table { border-collapse: collapse; font-size: 9pt; }
.print-doc.inv-print .pd-bank td { padding: 2px 8px 2px 0; }
.print-doc.inv-print .pd-bank td:first-child { font-weight: 700; color: #000; }
.print-doc.inv-print .pd-sign--inv { margin: 18px 0 0 auto; width: 230px; text-align: center; }
/* DBP logistics invoice (ERP-DWP printnew.xhtml): the rounded Notes box, the centred payment line, the signature right.
   Legacy drew the box border-secondary (grey); every print border is black (PrintStyleConventionTests). */
.print-doc .linv-notes { display: inline-block; border: 2px solid #000; border-radius: 8px; padding: 6px 12px; font-size: 8.5pt; margin-top: 12px; }
.print-doc .linv-notes__t { font-weight: 700; text-align: center; text-decoration: underline; }
.print-doc .linv-notes__p { text-align: center; margin-bottom: 4px; }
.print-doc .linv-pay { text-align: center; text-transform: uppercase; font-size: 8.5pt; margin: 28px 0; }
.print-doc .linv-sign { margin-left: auto; }
.print-doc .ship-co { text-align: center; font-size: 8.5pt; margin: -6px 0 10px; }

/* ---- Picking List print (pl-print) — replicates the legacy gudang/packinglist/printnew.xhtml ---- */
.print-doc.pl-print .pd-head-pl { display: flex; align-items: center; gap: 18px; padding-bottom: 9px; margin-bottom: 6px; }
.print-doc.pl-print .pd-title { margin: 4px 0 16px; text-decoration: underline; }
.print-doc.pl-print .pd-note { margin-top: 16px; }

/* ---- Work Order print (wo-print) — replicates legacy transaksi/workorder/printwo.xhtml ----
   A ruled work-instruction sheet, not a commercial document: boxes that the mechanic fills in by hand
   (Jabatan/NRP/Departemen, the reference number, the clock rows, the tick boxes, two of the three signatures)
   are deliberately empty, so they need visible rules or the printed sheet gives nothing to write on.
   Everything is sized to keep an ordinary order on ONE page: the legend is 6.5pt because it is a lookup, not text. */
.print-doc.wo-print { font-size: 8.5pt; line-height: 1.35; }
.print-doc.wo-print .pd-co__name { font-size: 11pt; }
.print-doc.wo-print .wo-band { display: flex; border: 1px solid #000; margin-top: 8px; }
.print-doc.wo-print .wo-band__to { flex: 1; padding: 5px 8px; border-right: 1px solid #000; }
.print-doc.wo-print .wo-band__title { flex: 1; padding: 5px 8px; text-align: center; }
.print-doc.wo-print .wo-band__hd { font-weight: 800; font-size: 12pt; color: #000; }
.print-doc.wo-print .wo-lead { margin: 7px 0 3px; }
.print-doc.wo-print .wo-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
.print-doc.wo-print .wo-grid td { border: 1px solid #000; padding: 2.5px 6px; vertical-align: top; overflow-wrap: anywhere; }
.print-doc.wo-print .wo-grid__lbl { width: 19%; color: #000; }
.print-doc.wo-print .wo-grid__lbl ~ .wo-grid__lbl { width: 24%; }   /* the right-hand labels are the longer ones */
.print-doc.wo-print .wo-grid td.wo-grid__sep { width: 12px; padding: 2.5px 0; text-align: center; border-left: 0; border-right: 0; }
.print-doc.wo-print .wo-grid__sep + td { border-left: 0; }
.print-doc.wo-print .wo-grid__text { white-space: pre-line; }
/* "Tugas ini diberikan… No : ____ Untuk melakukan pekerjaan sebagai berikut :" is ONE sentence on one line; the
   rule to write the number on takes whatever room the words leave. The sheet's date sits beside the lead above. */
.print-doc.wo-print .wo-lead--dated { display: flex; justify-content: space-between; gap: 16px; }
.print-doc.wo-print .wo-basis { display: flex; align-items: baseline; gap: 6px; margin: 9px 0 5px; white-space: nowrap; }
.print-doc.wo-print .wo-fill { flex: 1; min-width: 60px; border-bottom: 1px solid #000; align-self: flex-end; margin-bottom: 2px; }
.print-doc.wo-print .wo-items { margin-top: 6px; table-layout: fixed; font-size: 8pt; }
.print-doc.wo-print .wo-items thead th { padding: 3px 6px; text-align: center; }
.print-doc.wo-print .wo-items tbody td { padding: 2.5px 6px; text-align: center; overflow-wrap: anywhere; }
.print-doc.wo-print .wo-items tbody td.wo-items__name { text-align: left; }
.print-doc.wo-print .wo-items__empty { color: #000; }
/* Clock rows beside the assessment, the legend under both, the signatures under that — one ruled block that
   never splits across pages. Inner tables hide their own outer border so the block's rule is the only edge. */
.print-doc.wo-print .wo-foot { margin-top: 8px; break-inside: avoid; }
.print-doc.wo-print .wo-eval { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid #000; font-size: 8pt; }
.print-doc.wo-print .wo-time { width: 100%; height: 100%; border-collapse: collapse; border-style: hidden; table-layout: fixed; }
.print-doc.wo-print .wo-time th, .print-doc.wo-print .wo-time td { border: 1px solid #000; padding: 2px 6px; height: 15px; text-align: center; font-weight: 400; }
.print-doc.wo-print .wo-ticks { border-left: 1px solid #000; }
.print-doc.wo-print .wo-ticks__hd { border-bottom: 1px solid #000; padding: 2px 6px; text-align: center; }
.print-doc.wo-print .wo-ticks__body { padding: 4px 8px 2px; }
.print-doc.wo-print .wo-ticks__q { margin-bottom: 3px; }
.print-doc.wo-print .wo-ticks__row { display: flex; margin: 0 0 4px 12px; }
.print-doc.wo-print .wo-tick { display: inline-flex; align-items: center; gap: 6px; width: 118px; }
.print-doc.wo-print .wo-tick i { width: 22px; height: 11px; border: 1px solid #000; flex: none; }
.print-doc.wo-print .wo-brands { display: grid; grid-template-columns: 1fr 1fr; border: 1px solid #000; border-top: 0;
    font-size: 6.5pt; line-height: 1.3; padding: 2px 0; }
.print-doc.wo-print .wo-brands table { width: 100%; border-collapse: collapse; align-self: start; }
.print-doc.wo-print .wo-brands th { padding: 0 6px 1px; text-align: left; font-weight: 700; }
.print-doc.wo-print .wo-brands td { padding: 0 6px; vertical-align: top; }
.print-doc.wo-print .wo-brands th:first-child, .print-doc.wo-print .wo-brands td:first-child { width: 16%; white-space: nowrap; }
.print-doc.wo-print .wo-signs { width: 100%; border-collapse: collapse; table-layout: fixed; }
.print-doc.wo-print .wo-signs th { border: 1px solid #000; border-top: 0; padding: 3px 6px; text-align: center; font-weight: 400; }
.print-doc.wo-print .wo-signs td { border: 1px solid #000; height: 70px; padding: 0 6px 4px; text-align: center; vertical-align: bottom; }

/* ---- Form Advance print (adv-print) — replicates legacy transaksi/formadvance/cetak-advance.xhtml ---- */
.print-doc.adv-print .pd-co__name { font-size: 11pt; }
.print-doc.adv-print .pd-title { margin: 6px 0 14px; text-decoration: underline; text-align: center; }
.print-doc.adv-print .adv-meta { font-size: 9pt; margin-bottom: 10px; }
.print-doc.adv-print .adv-meta td { padding: 2px 6px 2px 0; }
/* The promoted .pd-meta rule bolds td:first-child, but adv-meta is a SIX-column layout
   (label,:,value,label,:,value) — so its SECOND label column lost the weight. */
.print-doc.adv-print .adv-meta td:nth-child(4) { padding-left: 26px; font-weight: 700; color: #000; }
.print-doc.adv-print .adv-items tfoot .pd-grand td { background: #102f38; color: #fff; font-weight: 800; padding: 5px 8px; }
/* Three signature columns side by side, as on the legacy sheet. */
.print-doc.adv-print .adv-signs { display: flex; justify-content: space-between; gap: 24px; margin-top: 34px; }
.print-doc.adv-print .adv-sign { flex: 1; text-align: center; }
.print-doc.adv-print .adv-sign .pd-sign__name { margin-top: 52px; border-top: 1px solid #000; padding-top: 3px; }

/* ---- Slip Gaji (slip-print) — the payslip legacy printed from View Payroll's per-row "Cetak" ---- */
/* Two side-by-side tables, because a payslip answers two questions and the eye should not have to scroll
   between them. They are independent tables rather than one six-column grid so each keeps its OWN subtotal
   row aligned to its own last line — a shared tbody would leave one column's footer floating. */
.print-doc.slip-print .slip-period { text-align: center; font-size: 10pt; font-weight: 700; color: #000;
    letter-spacing: .08em; text-transform: uppercase; margin: -6px 0 14px; }
.print-doc.slip-print .slip-meta { margin-bottom: 16px; }
.print-doc.slip-print .slip-cols { display: flex; gap: 14px; align-items: flex-start; }
.print-doc.slip-print .slip-side { flex: 1; }
.print-doc.slip-print .slip-side tfoot .pd-grand td { background: #102f38; color: #fff; font-weight: 800;
    font-size: 9pt; padding: 5px 8px; }
.print-doc.slip-print .slip-side tfoot .pd-grand td:first-child { color: #e7c573; }
.print-doc.slip-print .slip-none { color: #000; font-style: italic; }
/* The one number the employee opened this for. Bigger than the two subtotals above it, and the only gold rule
   on the sheet — the signature spends its boldness elsewhere. */
.print-doc.slip-print .slip-thp { width: 100%; border-collapse: collapse; margin-top: 14px;
    border: 2px solid #000; }
.print-doc.slip-print .slip-thp td { background: #102f38; color: #fff; font-weight: 800; font-size: 11.5pt;
    padding: 9px 12px; letter-spacing: .02em; }
.print-doc.slip-print .slip-thp td:first-child { color: #e7c573; }
.print-doc.slip-print .slip-thp td.r { text-align: right; white-space: nowrap; }
.print-doc.slip-print .slip-note { font-size: 8pt; margin: 16px 0 0; line-height: 1.5; color: #000; }
.print-doc.slip-print .slip-note b { color: #000; }
.print-doc.slip-print .slip-signs { display: flex; justify-content: space-between; gap: 24px; margin-top: 30px; }
.print-doc.slip-print .slip-sign { flex: 1; text-align: center; }
.print-doc.slip-print .slip-sign .pd-sign__name { margin-top: 52px; border-top: 1px solid #000; padding-top: 3px; }

/* ---- Financial-statement print (fs-print) — the legacy labaruginew print layout ---- */
.print-doc.fs-print .pd-title { margin: 6px 0 2px; text-align: center; text-decoration: underline; }
.print-doc.fs-print .fs-period { text-align: center; font-size: 9pt; font-weight: 600; margin-bottom: 14px; }
.print-doc.fs-print .fs-table { width: 100%; border-collapse: collapse; font-size: 9pt; }
.print-doc.fs-print .fs-table td { padding: 2px 6px; }
.print-doc.fs-print .fs-table td.r { text-align: right; white-space: nowrap; width: 170px; }
.print-doc.fs-print .fs-acc { width: 110px; color: #000; }
.print-doc.fs-print .fs-head td { padding-top: 10px; font-weight: 800; color: #000; text-transform: uppercase; }
.print-doc.fs-print .fs-total td { font-weight: 700; border-top: 1px solid #000; }

/* ---- TTI print signature blocks ---- */
.print-doc.tti-print .pd-title { text-decoration: underline; margin: 4px 0 16px; }
.print-doc.tti-print .tti-signs { display: flex; justify-content: space-between; gap: 60px; margin-top: 44px; }
.print-doc.tti-print .tti-sign { width: 45%; text-align: center; }
.print-doc.tti-print .tti-sign__t { font-size: 9pt; }
.print-doc.tti-print .tti-sign__n { margin-top: 56px; font-weight: 700; font-size: 9pt; border-top: 1px solid #000; padding-top: 4px; display: inline-block; min-width: 180px; }

.quote { display: flex; flex-direction: column; gap: 1.1rem; padding-bottom: 1rem; }
.q-eyebrow { font: 600 .75rem/1 var(--font-sans); letter-spacing: .13em; text-transform: uppercase; color: var(--faint); margin: 0 0 1rem; }
.pay-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.pay-head .q-eyebrow { margin-bottom: .6rem; }

/* meta strip */
.quote-meta { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap;
    background: linear-gradient(180deg, #fff, var(--surface-2)); border: 1px solid var(--border); border-left: 4px solid var(--brass);
    border-radius: var(--radius); padding: 1rem 1.4rem; box-shadow: var(--shadow); }
.quote-meta__id { display: flex; flex-direction: column; gap: .35rem; }
.quote-meta__id .q-eyebrow { margin: 0; }
.quote-meta__no { font: 700 1.5rem/1 var(--font-mono); color: var(--ink); letter-spacing: -.01em; }
.quote-meta__set { display: flex; align-items: flex-end; gap: 1.5rem; flex-wrap: wrap; }
.qm { display: flex; flex-direction: column; gap: .3rem; }
.qm > span { font-size: .75rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.qm > b { font-size: .98rem; font-weight: 600; color: var(--ink); line-height: 1.2; padding-bottom: .1rem; }
.qm__days { display: flex; align-items: center; gap: .4rem; }
.qm__days em { color: var(--muted); font-style: normal; font-size: .82rem; }
.qstatus { align-self: center; padding: .42rem .9rem; border-radius: 999px; font: 700 .75rem/1 var(--font-sans); letter-spacing: .04em; text-transform: uppercase; }
.qstatus--d { background: #eef0f0; color: var(--muted); }
.qstatus--a { background: rgba(63,138,63,.15); color: var(--c-revenue); }
.qstatus--r { background: rgba(180,83,42,.15); color: var(--c-liability); }
.qstatus--s { background: #fbf1de; color: #9a6b12; }
.qstatus--p { background: rgba(212,160,23,.16); color: #9a6b12; }

/* cards + fields */
.quote-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.quote-cols--foot { grid-template-columns: 1fr 380px; align-items: start; }
/* a grid track sizes to its widest child unless told otherwise — a 520px line table would widen the page */
.quote-cols > * { min-width: 0; }
.quote-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.2rem 1.35rem; box-shadow: var(--shadow); }
.qf { display: flex; flex-direction: column; gap: .3rem; margin-bottom: .9rem; }
.qf-row { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.qf-row .qf { margin-bottom: .9rem; }
/* grid tracks shrink to the screen; a long read-only value (a list of DO numbers) wraps instead of widening the page */
.qf-row > * { min-width: 0; }
.qf-ro { overflow-wrap: anywhere; }
.uom { font-size: .82rem; color: var(--muted); }
.wo-pick { display: flex; gap: .7rem; align-items: center; margin-bottom: .5rem; }
.wo-pick > :first-child { flex: 1; min-width: 0; }
.qf:last-child { margin-bottom: 0; }
.qf > label { font-size: .76rem; font-weight: 600; color: var(--muted); }
/* a read-only field value styled to sit in a .qf like the editable inputs around it */
.qf-ro { min-height: 34px; display: flex; align-items: center; padding: .3rem .1rem; font-weight: 600;
    color: var(--ink); border-bottom: 1px solid var(--border-soft); }
.qf-ro--empty { color: var(--faint); font-weight: 400; }
/* a save that will be refused, said before the user presses it (the pill--warn palette) */
.qf-warn { margin: 0 0 .8rem; padding: .45rem .6rem; border-radius: 6px; background: #fbf1de; color: #9a6b12; font-size: .85rem; }

/* line items */
.quote-lines { border-collapse: collapse; table-layout: fixed; width: 100%; }
.quote-lines thead th { font: 600 .75rem/1.15 var(--font-sans); letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
    text-align: left; padding: .46rem .55rem; background: var(--surface-2); border-bottom: 1px solid var(--border); vertical-align: middle; }
.quote-lines th.r, .quote-lines td.r { text-align: right; }
/* cells wrap instead of truncating — nothing is ever hidden; rows grow to fit the content */
.quote-lines tbody td { padding: .24rem .55rem; border-bottom: 1px solid var(--border-soft); vertical-align: middle; white-space: normal; }
.quote-lines tbody tr:hover td { background: var(--surface-2); }
/* a totals row is the table's last line: the body's own gutters (it had none, so "Total" sat flush against the
   frame and the figure against the other edge) under a heavier rule */
.quote-lines tfoot td { padding: .42rem .55rem; border-top: 1.5px solid var(--border); vertical-align: middle; }
.quote-lines .amount { font-family: var(--font-mono); font-weight: 600; color: var(--text); font-size: .95rem; }
.quote-empty { color: var(--muted); font-size: .85rem; text-align: center; padding: 1.1rem; }
.quote-addline { margin-top: .85rem; width: 100%; border: 1px dashed var(--border); background: var(--surface-2); color: var(--brass);
    font: 600 .85rem var(--font-sans); padding: .65rem; border-radius: 8px; cursor: pointer; transition: .15s; }
.quote-addline:hover { border-color: var(--brass); background: var(--brass-soft); }
.quote-addline--primary { border-style: solid; border-color: var(--brass); color: var(--brass); background: var(--brass-soft); }

/* Work Order parent→child lines (Repair/Overhaul): each customer object holds its material/service/PTA rows */
.wo-parent { border: 1px solid var(--border); border-radius: 12px; padding: .9rem; margin-bottom: .9rem; background: var(--surface); }
.wo-parent__head { display: flex; align-items: flex-start; gap: .8rem; margin-bottom: .8rem; }
.wo-parent__head > .k-button { align-self: flex-end; }
.wo-parent__item { flex: 1 1 auto; min-width: 0; }
.wo-parent__f { flex: 0 0 auto; width: 150px; }
.wo-parent__f--qty { width: 100px; }
.wo-parent__f--brand { width: 120px; }
.wo-parent__f--unit { width: 70px; }
.wo-parent__remark { margin: -.2rem 0 .8rem; }
.wo-parent__remark label { display: block; font-size: .75rem; color: var(--muted); margin-bottom: .25rem; }
.wo-parent__ro { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wo-parent__head label, .wo-parent__item label { display: block; font-size: .75rem; color: var(--muted); margin-bottom: .25rem; }
.wo-parent__ro { padding: .5rem .1rem; font-size: .88rem; color: var(--text); font-family: var(--font-mono); }
.wo-childbtns { display: flex; gap: .5rem; margin-top: .7rem; flex-wrap: wrap; }
.wo-childbtns .quote-addline { width: auto; margin-top: 0; padding: .45rem .8rem; }

/* Work Order image attachments */
.wo-att__grid { display: flex; flex-wrap: wrap; gap: .7rem; margin-bottom: .8rem; }
.wo-att__item { position: relative; margin: 0; width: 118px; height: 118px; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--surface-2); }
.wo-att__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wo-att__del { position: absolute; top: 4px; right: 4px; width: 22px; height: 22px; border: none; border-radius: 50%;
    background: rgba(20, 28, 32, .72); color: #fff; font-size: .75rem; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.wo-att__del:hover { background: #c0392b; }
.wo-att__add { display: inline-flex; align-items: center; gap: .5rem; border: 1px dashed var(--border); background: var(--surface-2);
    color: var(--brass); font: 600 .85rem var(--font-sans); padding: .55rem .9rem; border-radius: 8px; cursor: pointer; }
.wo-att__add:hover { border-color: var(--brass); background: var(--brass-soft); }
.wo-att__add input[type=file] { max-width: 190px; font-size: .78rem; }

/* summary card (dark, bold grand total) */
.quote-summary { background: var(--ink); color: #fff; border-radius: var(--radius); padding: 1.35rem 1.45rem; box-shadow: var(--shadow); }
.qs { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .44rem 0; font-size: .9rem; }
.qs > span { color: rgba(255,255,255,.68); }
.qs > b { font-family: var(--font-mono); font-weight: 600; color: #fff; }
.qs__disc { display: flex; align-items: center; gap: .35rem; }
.qs__disc em { color: rgba(255,255,255,.6); font-style: normal; }
.qs__tog { display: flex; align-items: center; gap: .5rem; color: rgba(255,255,255,.85); cursor: pointer; }
.qs--grand { margin-top: .55rem; padding-top: .85rem; border-top: 1px solid rgba(255,255,255,.18); }
.doc-meta { display: flex; gap: 1.6rem; margin: .3rem 0 .9rem; font-size: .9rem; color: var(--muted); }
.qs--grand > span { color: #fff; font-weight: 700; font-size: 1rem; }
.qs--grand > b { color: var(--brass-bright); font-size: 1.55rem; font-weight: 700; }
.qs > span small, .qs > label small { color: rgba(255,255,255,.5); font-size: .75rem; }
.qs__note { margin: .55rem 0 0; font-size: .76rem; color: rgba(255,255,255,.55); }
/* a rate typed on the summary (PPN %, PPh %, discount %) — the % sits where the reader expects it */
.qs__rate { display: flex; align-items: center; gap: .45rem; color: rgba(255,255,255,.68); }

/* lines card: title row with a secondary action on the right; a muted second line inside a cell */
.ql-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.ql-sub { font-size: .75rem; color: var(--muted); margin-top: .1rem; }
.linkbtn { border: 0; background: none; padding: 0; font: inherit; font-size: .82rem; font-weight: 600; color: var(--accent-deep); cursor: pointer; }
.linkbtn:hover { text-decoration: underline; }
.linkbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* add-a-line search (trip picker): the search sits where the next row will appear */
.ql-add { display: flex; gap: .6rem; align-items: center; margin-top: .85rem; }
.trip-opt { display: grid; grid-template-columns: 150px 1fr auto auto; gap: .9rem; align-items: baseline; width: 100%; padding: .15rem 0; }
.trip-opt__route { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.trip-opt__meta { font-size: .76rem; color: var(--muted); white-space: nowrap; }
.trip-opt__rate { min-width: 100px; text-align: right; }

/* sticky action bar — ABOVE everything of the page it floats over (z-index): without one, any positioned thing that
   scrolled under it painted on top of it — a line's sticky Delete cell sat on the "Save changes" button (owner report
   2026-10-06), a text area's inner box on the hint. Still far below popups (10000+), the header menus and dialogs. */
/* ONE bar holds every action of a document, in three zones (CONVENTIONS §7c, owner 2026-10-08 — Print had sat at the
   top of some editors and in the bar of others):
     __tools  look at the document without changing it: History → Journal → Print. A hairline divides it from…
     __hint   what this state means (why it is read-only, what the commit will do) — takes the middle;
     __btns   change it, quiet → secondary → the ONE commit, last.
   The top of an editor (.doc-back) holds the "← list" link and nothing else. A zone with nothing in it takes no room.
   It WRAPS rather than overflows: a draft Invoice's four tools and three actions need ~840px, and between the phone
   layout and a wide window (821–1300px) a one-line bar pushed Post past the edge and squeezed the hint to one word a
   line (review 2026-10-08). The hint keeps a readable floor (its flex-basis); what does not fit drops to the next line
   — the actions stay right-aligned, so the commit is always the last thing on the bar and always on screen. */
.quote-bar { position: sticky; bottom: 1rem; z-index: 20; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
    background: rgba(255,255,255,.94); backdrop-filter: blur(10px); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 9px 10px 9px 8px; box-shadow: 0 1px 2px rgba(14,23,38,.05), 0 18px 40px -22px rgba(14,23,38,.35); }
.quote-bar__tools { flex: none; display: flex; align-items: center; gap: 2px; padding-right: 12px; border-right: 1px solid var(--border); }
.quote-bar__tools:not(:has(> *)) { display: none; }
.quote-bar__hint { flex: 1 1 11rem; min-width: 0; color: var(--muted); font-size: .82rem; line-height: 1.35; }
.quote-bar__btns { display: flex; align-items: center; gap: 8px; }
.quote-bar > .quote-bar__btns { flex: none; max-width: 100%; flex-wrap: wrap; justify-content: flex-end; margin-left: auto; }
/* a bar outside the editor sheet (payroll review, the HR batch editors) keeps the sheet's own 1.1rem rhythm */
:not(.quote) > .quote-bar:not(.quote-bar--filters) { margin-top: 1.1rem; }
/* no tools (yet): the hint starts where a button's label would */
.quote-bar__tools:not(:has(> *)) + .quote-bar__hint, .quote-bar > .quote-bar__hint:first-child { padding-left: 8px; }

/* A dropdown's LIST is never narrower than it can be read. Telerik gives the list the width of the input it hangs
   from; in a line table that input is one narrow cell (the Unit picker on a Work Order line: 48px), and the list
   opened as a strip a few pixels wide with no word in it readable (owner report 2026-10-06). One rule for every
   list popup — combo, dropdown, multi-select — wherever it is; a wide input's list is already wider than this. */
.k-animation-container:has(.k-popup.k-list-container) { min-width: min(240px, calc(100vw - 16px)); }

/* Stok Opname, choosing the items to count: the filter and its options on one wrapping row */
.so-pick { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin-bottom: .75rem; }
.so-pick__opt { display: inline-flex; align-items: center; gap: .4rem; font-size: .85rem; color: var(--muted); white-space: nowrap; }

/* line table keeps its natural column widths and scrolls horizontally when the viewport is narrow,
   instead of compressing the inputs into an unreadable cram */
.quote-lines-wrap { overflow-x: auto; border: 1px solid var(--border-soft); border-radius: 10px; }
.quote-lines-wrap::-webkit-scrollbar { height: 9px; }
/* A line's own action stays in view while the frame scrolls sideways under it. On an Overhaul order the Delete button
   sat past the right edge at 1500px — "this line cannot be deleted" to whoever did not scroll the table (UAT 2026-10-06). */
.quote-lines-wrap .quote-lines tbody td:last-child:has(> .k-button),
.quote-lines-wrap .quote-lines thead th:last-child:empty { position: sticky; right: 0; z-index: 1; background: var(--surface); }
.quote-lines-wrap .quote-lines thead th:last-child:empty { background: var(--surface-2); }
.quote-lines-wrap .quote-lines tbody tr:hover td:last-child:has(> .k-button) { background: var(--surface-2); }
/* …and fits its column: a 38px button in a 40px cell with the cell's text padding stuck out 6px past the table, so
   every line table with a row action scrolled sideways by those few pixels. */
.quote-lines-wrap .quote-lines tbody td:last-child:has(> .k-button) { padding-left: 0; padding-right: 2px; text-align: right; }
.quote-lines-wrap::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
/* per-table min-width is set inline on each table (sized to its own column count); the shared rule just
   sets the compact type scale. Item is a fixed width everywhere, one text column (Remark) flexes to fill. */
.quote-lines { font-size: .84rem; }
.quote-lines thead th:first-child, .quote-lines tbody td:first-child, .quote-lines tfoot td:first-child { padding-left: .9rem; }
.quote-lines thead th:last-child, .quote-lines tbody td:last-child, .quote-lines tfoot td:last-child { padding-right: .9rem; }

/* Inline editing: line cells read as plain text — the input's border/background only appears on
   hover or focus, so values show in full and the row stays clean and precise (no boxed-in clutter). */
.quote-lines .k-input, .quote-lines .k-picker, .quote-lines .k-multiselect {
    border-color: transparent; background: transparent; box-shadow: none;
    transition: border-color .12s ease, background .12s ease; }
.quote-lines td:hover .k-input,   .quote-lines td:focus-within .k-input,
.quote-lines td:hover .k-picker,  .quote-lines td:focus-within .k-picker,
.quote-lines td:hover .k-multiselect, .quote-lines td:focus-within .k-multiselect {
    border-color: var(--border); background: #fff; }
/* hide the numeric up/down spinner buttons in the line grid — they add clutter and eat width */
.quote-lines .k-input-spinner { display: none; }
/* right-align numeric values so the decimals line up precisely down the column */
.quote-lines td.r .k-input-inner { text-align: right; }
.quote-lines .k-input-inner { padding-inline: .4rem; padding-block: .12rem; font-size: .84rem; }
/* compact editing inputs so a cell in edit mode is the same height as its text row */
.quote-lines .k-input, .quote-lines .k-picker { min-height: 28px; }
/* the read-only chips (Part No / Unit) sit flush with the input text baseline and WRAP long values
   onto the next line rather than truncating; the cell's title still shows the full value on hover */
.quote-lines .uom { display: block; padding-inline: .4rem; color: var(--muted);
    white-space: normal; overflow-wrap: anywhere; line-height: 1.35; }
/* money values stay on one line (formatted, right-aligned) — wrapping numbers reads as errors */
.quote-lines td.r .num { white-space: nowrap; }

/* click-to-edit cell: the value reads as text and wraps in full; a subtle hover panel shows it's editable,
   and clicking swaps in the input (focused via JS). Only the editing cell holds an input. */
.quote-lines td.cell { cursor: text; }
/* LineCell: a cell that cannot be edited is plain text (no hover panel, no caret); a resting editable cell is a tab
   stop, and shows where the keyboard is before it turns into its input. */
.quote-lines td.cell--ro { cursor: default; }
.quote-lines td.cell--ro:hover .cell-text { background: none; box-shadow: none; }
.quote-lines td.cell:focus { outline: none; }
.quote-lines td.cell:focus .cell-text { background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--accent-deep); }
.quote-lines .cell-text { display: block; min-height: 1.05rem; padding: .1rem .35rem; border-radius: 6px;
    white-space: normal; overflow-wrap: anywhere; line-height: 1.3; }
.quote-lines td.r .cell-text { text-align: right; }
.quote-lines .cell-text.num { font-family: var(--font-mono); font-weight: 500; }
.quote-lines .cell-text--ph { color: var(--faint); }
.quote-lines td.cell:hover .cell-text { background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border-soft); }

/* required-field validation feedback */
.req { color: #d4351c; font-weight: 700; margin-left: .1rem; }
.field-err { display: block; margin-top: .35rem; font-size: .8rem; color: #b42318; }
.qf--invalid > label { color: #d4351c; }
.qf--invalid .k-input, .qf--invalid .k-picker, .qf--invalid .k-combobox, .qf--invalid .k-dropdownlist {
    border-color: #d4351c !important; box-shadow: 0 0 0 3px rgba(212,53,28,.15) !important; }
.quote-card.qf--invalid { border-color: #d4351c; box-shadow: 0 0 0 3px rgba(212,53,28,.12); }
@keyframes akm-shake {
    10%, 90% { transform: translateX(-2px); } 20%, 80% { transform: translateX(3px); }
    30%, 50%, 70% { transform: translateX(-5px); } 40%, 60% { transform: translateX(5px); }
}
.shake { animation: akm-shake .6s cubic-bezier(.36, .07, .19, .97); }

/* ===== App toaster — Telerik notification, modernised: lower, rounded card + progress bar ===== */
.k-notification-group.app-toaster { top: 4.75rem !important; right: 1.15rem !important; }
.app-toaster .k-notification {
    position: relative; overflow: hidden;
    min-width: 290px; max-width: 400px;
    padding: .82rem 2.5rem .84rem 1rem;
    border-radius: 12px;
    font-size: .9rem; line-height: 1.42; font-weight: 500;
    box-shadow: 0 14px 34px -12px rgba(16, 47, 56, .42), 0 3px 8px -4px rgba(16, 47, 56, .22);
}
.app-toaster .k-notification-content { font-weight: 500; }
/* auto-close progress bar (drains left→right over the lifetime; pauses on hover) */
.app-toaster .k-notification::after {
    content: ''; position: absolute; left: 0; bottom: 0; height: 3px; width: 100%;
    background: rgba(255, 255, 255, .55); transform-origin: left;
    animation: toastDrain 4.5s linear forwards;
}
.app-toaster .k-notification:hover::after { animation-play-state: paused; }
@keyframes toastDrain { from { transform: scaleX(1); } to { transform: scaleX(0); } }

@media (max-width: 520px) {
    .k-notification-group.app-toaster { top: auto !important; bottom: 1rem !important; left: .9rem !important; right: .9rem !important; }
    .app-toaster .k-notification { max-width: none; width: calc(100vw - 1.8rem); }
}

/* ---- Navbar notification bell ---- */
.notif { position: relative; display: inline-flex; }
.notif__btn {
    position: relative; width: 38px; height: 38px; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); border-radius: 9px;
    background: var(--surface); color: var(--muted); cursor: pointer; transition: all .15s;
}
.notif__btn:hover { color: var(--ink); background: var(--surface-2); }
.notif__badge {
    position: absolute; top: -5px; right: -5px; min-width: 17px; height: 17px; padding: 0 4px;
    display: inline-flex; align-items: center; justify-content: center;
    background: #c0392b; color: #fff; font: 700 .62rem/1 var(--font-sans);
    border-radius: 9px; border: 2px solid var(--surface);
}
.notif__backdrop { position: fixed; inset: 0; z-index: 90; }
.notif__panel {
    position: absolute; top: calc(100% + .5rem); right: 0; z-index: 91; width: 320px; max-width: 86vw;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 18px 40px -14px rgba(16, 47, 56, .4); overflow: hidden;
}
.notif__head { padding: .7rem .9rem; font: 700 .75rem/1 var(--font-sans); text-transform: uppercase;
    letter-spacing: .08em; color: var(--faint); border-bottom: 1px solid var(--border); }
.notif__empty { padding: 1.6rem .9rem; text-align: center; color: var(--muted); font-size: .85rem; }
.notif__list { list-style: none; margin: 0; padding: .25rem; max-height: 360px; overflow-y: auto; }
.notif__item { display: flex; flex-direction: column; gap: .15rem; padding: .55rem .65rem;
    border-radius: 8px; cursor: pointer; border-left: 3px solid transparent; }
.notif__item:hover { background: var(--surface-2); }
.notif__item--approval { border-left-color: var(--brass); }
.notif__item--decision { border-left-color: #2f8f4e; }
.notif__text { font-size: .86rem; color: var(--ink); line-height: 1.35; }
.notif__time { font-size: .75rem; color: var(--faint); }
@media (max-width: 520px) {
    .notif__panel { position: fixed; top: 3.4rem; right: .6rem; left: .6rem; width: auto; }
}

/* responsive — stack the document on tablet/mobile */
@media (max-width: 820px) {
    .quote-cols, .quote-cols--foot { grid-template-columns: 1fr; }
    .quote-meta { align-items: flex-start; }
    .quote-meta__set { gap: 1rem 1.2rem; }
    /* opaque here: stacked, the bar spans the whole form, and at 92% the fields scrolling under it read through the hint.
       Stacked under the thumb (mockup 2026-10-08): the tools share one row in equal columns; the hint, one small line;
       the actions two to a row, and the commit — always last — the full width at the bottom. */
    .quote-bar { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 10px;
        background: var(--surface); backdrop-filter: none; }
    .quote-bar__tools { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 2px;
        padding: 0 0 6px; border-right: 0; border-bottom: 1px solid var(--border); }
    .quote-bar__tools > .k-button { justify-content: center; min-width: 0; }
    /* three tools or more get ~120px each on a phone — "History 248" or "Preview journal" do not fit and were clipped
       (R17). They show their icon (History keeps its count); the label stays the tooltip — every tool carries a title. */
    .quote-bar__tools:has(> button:nth-of-type(3)) > .k-button .k-button-text { display: none; }
    .quote-bar__tools:not(:has(> *)) + .quote-bar__hint, .quote-bar > .quote-bar__hint:first-child { padding-left: 0; }
    .quote-bar__hint { text-align: center; }
    .quote-bar > .quote-bar__btns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-left: 0; }
    .quote-bar > .quote-bar__btns > * { min-width: 0; justify-content: center; }
    .quote-bar > .quote-bar__btns > :last-child { grid-column: 1 / -1; }
    /* a button row that is not a bar (a modal's footer, a period run) keeps wrapping */
    .quote-bar__btns:not(.quote-bar > *) { justify-content: stretch; flex-wrap: wrap; }
    .quote-bar__btns:not(.quote-bar > *) > .k-button { flex: 1 1 auto; }
}

/* role assignment list */
.role-list { display: flex; flex-direction: column; gap: .15rem; max-height: 380px; overflow-y: auto; }

/* page access-denied */
.access-denied { max-width: 460px; margin: 4rem auto; text-align: center; background: var(--surface);
    border: 1px solid var(--border); border-radius: 14px; padding: 2.4rem 2rem; box-shadow: 0 1px 3px rgba(16,47,56,.06); }
.access-denied__mark { font-size: 2.2rem; }
.access-denied h2 { font: 700 1.4rem var(--font-sans); margin: .6rem 0 .4rem; color: var(--ink); }
.access-denied p { color: var(--muted); font-size: .9rem; margin-bottom: 1.4rem; }

/* ---- GL Imbalances (GlImbalances.razor) --------------------- */
.imb-summary { font-size: .85rem; color: var(--muted); }
.imb-summary__n { font: 700 1rem var(--font-mono); color: #9a6b12; }
.imb-summary__mut { color: var(--muted); }
.imb-summary__sep { margin: 0 .3rem; opacity: .5; }
.imb-neg { color: #b3261e; }
.imb-pos { color: #2c7a4b; }

/* ---- Journal preview panel (JournalPreviewPanel.razor) ------ */
.pill--danger { background: #fbe9e7; color: #b3261e; }
.jrn-prev__head { display: flex; align-items: center; justify-content: space-between; gap: .8rem; flex-wrap: wrap; margin-bottom: .2rem; }
.jrn-prev__head h4 { margin: 0; }
.jrn-prev__tools { display: flex; align-items: center; gap: .5rem; }
.jrn-prev .jrn-tbl { min-width: 480px; }

/* ---- Journal drill-down dialog (JournalDialog.razor) -------- */
.jrn-title { font-weight: 700; color: var(--ink); }
.jrn-title__ref { font-family: var(--font-mono); font-size: .82rem; color: var(--brass); margin-left: .55rem; }
.jrn { border: 1px solid var(--border); border-top: 2px solid var(--brass); border-radius: 4px;
    padding: .8rem .9rem; margin-bottom: .9rem; background: var(--surface); }
.jrn:last-child { margin-bottom: 0; }
.jrn--draft { border-top-color: #c9a54e; opacity: .95; }
.jrn__head { display: flex; align-items: center; justify-content: space-between; gap: .8rem; flex-wrap: wrap; }
.jrn__id { display: flex; align-items: baseline; gap: .55rem; }
.jrn__code { font: 600 .75rem/1 var(--font-sans); letter-spacing: .06em; color: var(--muted);
    background: var(--brass-soft); padding: .2rem .42rem; border-radius: 3px; }
.jrn__meta { display: flex; align-items: center; gap: .5rem; }
.jrn__date { font-family: var(--font-mono); font-size: .78rem; color: var(--muted); }
.jrn__note { font-size: .8rem; color: var(--muted); margin: .5rem 0 0; }
.jrn-tbl-wrap { overflow-x: auto; margin-top: .6rem; }
.jrn-tbl { width: 100%; border-collapse: collapse; min-width: 460px; }
.jrn-tbl th { text-align: left; font: 600 .75rem/1.2 var(--font-sans); letter-spacing: .04em;
    text-transform: uppercase; color: var(--muted); padding: .3rem .5rem; border-bottom: 1px solid var(--border); }
.jrn-tbl td { padding: .34rem .5rem; border-bottom: 1px solid var(--border-soft, #eee); font-size: .84rem; vertical-align: top; }
.jrn-tbl .r { text-align: right; }
.jrn-acc { display: block; color: var(--text); font-weight: 500; }
.jrn-desc { display: block; font-size: .75rem; color: var(--muted); margin-top: .1rem; }
.jrn-tbl tfoot td { border-top: 1.5px solid var(--ink-line); border-bottom: none; font-weight: 700; color: var(--ink); padding-top: .45rem; }
.jrn-tbl__totlbl { color: var(--muted); font-weight: 600; text-transform: uppercase; font-size: .75rem; letter-spacing: .04em; }
.jrn-tbl__unbal td { color: #9a6b12; }

/* ---- Keep: error boundary + form validation ---------------- */
.valid.modified:not([type=checkbox]) { outline: 1px solid #26b050; }
.invalid { outline: 1px solid #e50000; }
.validation-message { color: #e50000; }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}
.blazor-error-boundary::after { content: "An error has occurred."; }

/* ── Dashboards (Dashboard · Dashboard Purchase · Logistics Dashboard) ───────────────── 2026-10-02
   One system for all three. The page reads top-down from "where do we stand" to "what is behind it":
   a midnight HERO band (the one bold element — figures in mono on ink, progress against target with a PACE
   tick), a strip of KPI tiles, then panels on a 12-column grid. Every mark that has documents behind it is
   clickable and opens the DRILL drawer; the panel's caption says so. Charts: cobalt ink + the line's accent
   (ChartPalette.cs), hairline grid, no chart junk. Labels sentence case (label voice, below). */

/* toolbar row under the page head: filters left, a note right */
.dtools { display:flex; align-items:center; flex-wrap:wrap; gap:.6rem 1rem; margin:0 0 14px; }
.dtools__note { color:var(--faint); font-size:.8rem; margin-left:auto; }

/* segmented quick-pick (periods, years) */
.dseg { display:inline-flex; padding:3px; gap:2px; background:var(--surface); border:1px solid var(--border); border-radius:11px; }
.dseg button { font:600 .8rem/1 var(--font-sans); color:var(--muted); background:transparent; border:0; border-radius:8px;
    padding:.5rem .75rem; cursor:pointer; white-space:nowrap; transition:background .15s, color .15s; }
.dseg button:hover { color:var(--text); background:var(--surface-2); }
.dseg button.on { background:var(--midnight); color:#fff; }
.dseg button:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.dseg--mono button { font-family:var(--font-mono); font-weight:500; }
.period { display:flex; align-items:center; flex-wrap:wrap; gap:.6rem .8rem; }
.period__range { display:inline-flex; align-items:center; gap:.4rem; }
.period__dash { color:var(--faint); }

/* ── hero band ── */
.dhero { position:relative; display:grid; grid-template-columns:minmax(0,1.5fr) repeat(2, minmax(0,1fr)); gap:0;
    background:var(--midnight); color:#e8edf4; border-radius:var(--radius); box-shadow:var(--shadow); margin:0 0 14px; overflow:hidden; }
.dhero::after { content:""; position:absolute; inset:0 0 auto 0; height:2px; background:var(--accent); opacity:.9; }
.dhero__cell { padding:1.25rem 1.5rem 1.2rem; min-width:0; }
.dhero__cell + .dhero__cell { border-left:1px solid rgba(255,255,255,.08); }
.dhero__k { font-size:.82rem; font-weight:600; color:#9fb0c6; display:flex; justify-content:space-between; gap:.6rem; }
.dhero__pct { font-family:var(--font-mono); font-weight:500; color:#fff; }
.dhero__v { font-family:var(--font-mono); font-weight:500; font-size:1.65rem; line-height:1.15; letter-spacing:-.01em; color:#fff;
    margin:.35rem 0 .7rem; font-variant-numeric:tabular-nums; }
.dhero__cell--lead .dhero__v { font-size:2.5rem; }
.dhero__rail { position:relative; height:6px; border-radius:999px; background:rgba(255,255,255,.1); }
.dhero__rail > i { position:absolute; inset:0 auto 0 0; border-radius:999px; background:var(--accent-bright); }
.dhero__rail > b { position:absolute; top:-5px; width:2px; height:16px; margin-left:-1px; background:#fff; border-radius:1px; opacity:.85; }
.dhero__m { display:flex; justify-content:space-between; gap:.6rem; margin-top:.6rem; font-size:.78rem; color:#8496ad; font-variant-numeric:tabular-nums; }
.dhero__m em { font-style:normal; color:#c9d4e2; }
.dhero__m .is-behind { color:#f2b8a8; }
.dhero__m .is-ahead { color:#9fdcc0; }
@media (max-width:900px) {
    .dhero { grid-template-columns:1fr 1fr; }
    .dhero__cell--lead { grid-column:1/-1; }
    .dhero__cell--lead + .dhero__cell { border-left:0; }
    .dhero__cell:not(.dhero__cell--lead) { border-top:1px solid rgba(255,255,255,.08); }
}
@media (max-width:560px) { .dhero { grid-template-columns:1fr; } .dhero__cell + .dhero__cell { border-left:0; } }

/* ── KPI tiles: real anchors (keyboard + middle-click for free). Fixed counts per breakpoint so rows are full. ── */
.dash-kpis { display:grid; grid-template-columns:repeat(2,1fr); gap:12px; margin:0 0 14px; }
@media (min-width:900px)  { .dash-kpis { grid-template-columns:repeat(3,1fr); } .dash-kpis--4 { grid-template-columns:repeat(4,1fr); } }
@media (min-width:1500px) { .dash-kpis { grid-template-columns:repeat(6,1fr); } .dash-kpis--4 { grid-template-columns:repeat(4,1fr); } }
.dash-kpi { position:relative; display:flex; flex-direction:column; background:var(--surface); border:1px solid var(--border);
    border-radius:12px; padding:.85rem 1rem .75rem; color:inherit; text-decoration:none; min-width:0;
    transition:border-color .15s, box-shadow .15s; }
.dash-kpi:hover, .dash-kpi:focus-visible { border-color:color-mix(in srgb, var(--accent) 55%, var(--border)); box-shadow:var(--shadow); outline:none; color:inherit; }
.dash-kpi__label { font-size:.8rem; font-weight:600; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dash-kpi__value { font-family:var(--font-mono); font-size:1.45rem; font-weight:500; letter-spacing:-.01em; color:var(--text);
    font-variant-numeric:tabular-nums; margin:.3rem 0 .15rem; }
.dash-kpi__value.neg, .dash-kpi--alert .dash-kpi__value { color:#b3261e; }
.dash-kpi__sub { font-size:.76rem; color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.dash-kpi__spark { display:block; width:100%; height:28px; margin-top:auto; padding-top:6px; }
.dash-kpi--alert::before { content:""; position:absolute; left:-1px; top:12px; bottom:12px; width:3px; border-radius:0 3px 3px 0; background:#b3261e; }

/* "needs attention": plain sentences that link to where the work is done */
.dattn { display:flex; flex-wrap:wrap; align-items:center; gap:.45rem; margin:0 0 16px; }
.dattn__k { font-size:.8rem; font-weight:600; color:var(--muted); margin-right:.2rem; }
.dattn a { display:inline-flex; align-items:center; gap:.4rem; padding:.36rem .7rem; border-radius:999px; font-size:.8rem;
    background:var(--surface); border:1px solid var(--border); color:var(--muted); text-decoration:none; }
.dattn a b { font-family:var(--font-mono); font-weight:500; color:var(--text); }
.dattn a:hover { border-color:var(--faint); color:var(--text); }
.dattn a i { width:7px; height:7px; border-radius:50%; background:var(--faint); }
.dattn a.is-ok i { background:#2c7a4b; }
.dattn a.is-warn i { background:#c98a12; }
.dattn a.is-bad { border-color:#f0c4bf; background:#fdf3f2; color:#8f1f18; }
.dattn a.is-bad i { background:#b3261e; }

/* ── panels on a 12-column grid ── */
.dgrid { display:grid; grid-template-columns:repeat(12, minmax(0,1fr)); gap:14px; align-items:stretch; }
.dgrid > * { grid-column:span 12; }
@media (min-width:900px) {
    .dgrid > .d-6, .dgrid > .d-4, .dgrid > .d-8 { grid-column:span 6; }
    .dgrid > .d-12 { grid-column:span 12; }
}
@media (min-width:1280px) {
    .dgrid > .d-4 { grid-column:span 4; }
    .dgrid > .d-8 { grid-column:span 8; }
}
.dpanel { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:1rem 1.15rem 1.05rem; min-width:0;
    display:flex; flex-direction:column; }
.dpanel__head { display:flex; align-items:baseline; flex-wrap:wrap; gap:.25rem .6rem; }
.dpanel__title { margin:0; font-size:.98rem; font-weight:650; color:var(--text); letter-spacing:-.005em; }
.dpanel__unit { font-size:.78rem; color:var(--faint); }
.dpanel__legend { margin-left:auto; display:flex; flex-wrap:wrap; gap:.25rem .9rem; font-size:.78rem; color:var(--muted); }
.dpanel__cap { margin:.2rem 0 .5rem; font-size:.78rem; color:var(--faint); }
.dpanel__empty { margin:auto 0; padding:2.2rem 0; text-align:center; color:var(--faint); font-size:.86rem; }
.dpanel > .k-grid { margin-top:.5rem; }
/* legend key: a short line for a line series, a square for a column/area; dashed = a reference */
.lkey { display:inline-flex; align-items:center; gap:.4rem; white-space:nowrap; }
.lkey::before { content:""; width:12px; height:10px; border-radius:3px; background:var(--k); }
.lkey--line::before { height:2px; border-radius:2px; }
.lkey--dash::before { height:0; border-top:2px dashed var(--k); background:none; }

/* trend chart: the canvas is clickable when it drills */
.trend { margin:0 -.35rem -.3rem; }
.trend--pick .k-chart svg path, .trend--pick .k-chart svg circle { cursor:pointer; }
.trend-tip { display:flex; flex-direction:column; gap:.15rem; padding:.15rem .1rem; font-family:var(--font-sans); text-align:left; }
.trend-tip__k { font-size:.74rem; color:#9fb0c6; }
.trend-tip b { font-family:var(--font-mono); font-weight:500; font-size:.9rem; }
.trend-tip em { font-style:normal; font-size:.7rem; color:#8496ad; }

/* ranked bar list */
.rank { list-style:none; margin:.35rem 0 0; padding:0; display:flex; flex-direction:column; }
.rank__row { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:.8rem; row-gap:.3rem; width:100%;
    padding:.55rem .5rem; margin:0 -.5rem; border:0; border-radius:9px; background:none; text-align:left; font:inherit; color:inherit; box-sizing:content-box; }
.rank__row.is-pick { cursor:pointer; transition:background .12s; }
.rank__row.is-pick:hover { background:var(--surface-2); }
.rank__row.is-pick:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.rank__label { font-size:.86rem; color:var(--text); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.rank__val { font-family:var(--font-mono); font-size:.84rem; color:var(--text); font-variant-numeric:tabular-nums; text-align:right; }
.rank__val.neg { color:#b3261e; }
.rank__meter { grid-column:1/-1; height:5px; border-radius:999px; background:var(--border-soft); overflow:hidden; }
.rank__meter > i { display:block; height:100%; border-radius:999px; background:#2d63b4; }
.rank__sub { grid-column:1/-1; font-size: .75rem; color:var(--faint); margin-top:-.05rem; }
.rank--compact .rank__row { padding:.4rem .5rem; }
.rank__foot { display:flex; justify-content:space-between; gap:1rem; margin-top:.5rem; padding-top:.6rem; border-top:1px solid var(--border-soft);
    font-size:.8rem; color:var(--muted); }
.rank__foot b { font-family:var(--font-mono); font-weight:500; color:var(--text); }

/* split bar (composition of counts) */
.split { display:flex; gap:2px; height:12px; margin:.7rem 0 .4rem; border-radius:999px; overflow:hidden; }
.split__seg { min-width:4px; flex-basis:0; }
.split__legend { list-style:none; margin:0; padding:0; }
.split__row { display:grid; grid-template-columns:auto minmax(0,1fr) auto 3.2rem; align-items:center; gap:.65rem; width:100%;
    padding:.45rem .5rem; margin:0 -.5rem; box-sizing:content-box; border:0; border-radius:9px; background:none; font:inherit; color:inherit; text-align:left; }
.split__row.is-pick { cursor:pointer; }
.split__row.is-pick:hover { background:var(--surface-2); }
.split__row.is-pick:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.split__sw { width:10px; height:10px; border-radius:3px; }
.split__lbl { font-size:.86rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.split__lbl small { display:block; font-size: .75rem; color:var(--faint); }
.split__n { font-family:var(--font-mono); font-weight:500; font-size:.86rem; text-align:right; }
.split__pct { font-family:var(--font-mono); font-size:.78rem; color:var(--faint); text-align:right; }

/* ── drill drawer ── */
.drill-scrim { position:fixed; inset:0; z-index:1000; background:rgba(14,23,38,.32); animation:drill-fade .16s ease-out; }
.drill { position:fixed; top:0; right:0; bottom:0; z-index:1001; width:min(480px, 100vw); display:flex; flex-direction:column;
    background:var(--surface); box-shadow:-24px 0 60px -30px rgba(14,23,38,.55); outline:none; animation:drill-in .2s cubic-bezier(.2,.7,.2,1); }
.drill::before { content:""; height:3px; background:var(--accent); flex:none; }
.drill__head { display:flex; align-items:flex-start; gap:1rem; padding:1.1rem 1.3rem .9rem; border-bottom:1px solid var(--border-soft); }
.drill__id { flex:1; min-width:0; }
.drill__id h2 { margin:0; font-size:1.12rem; font-weight:650; color:var(--text); letter-spacing:-.01em; overflow-wrap:anywhere; }
.drill__id p { margin:.3rem 0 0; font-size:.8rem; color:var(--muted); }
.drill__x { flex:none; display:grid; place-items:center; width:34px; height:34px; border:0; border-radius:9px; background:var(--surface-2); color:var(--muted); cursor:pointer; }
.drill__x:hover { color:var(--text); background:var(--border-soft); }
.drill__x:focus-visible { outline:2px solid var(--accent); }
.drill__sum { display:grid; grid-template-columns:1fr auto; gap:1rem; padding:.9rem 1.3rem; background:var(--surface-2); border-bottom:1px solid var(--border-soft); }
.drill__sum span { display:block; font-size:.76rem; color:var(--muted); }
.drill__sum b { font-family:var(--font-mono); font-weight:500; font-size:1.25rem; color:var(--text); font-variant-numeric:tabular-nums; }
.drill__sum div + div { text-align:right; }
.drill__list { list-style:none; margin:0; padding:.35rem .6rem; overflow-y:auto; flex:1; }
.drill__row { display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:1rem; row-gap:.15rem; padding:.6rem .7rem; border-radius:9px; color:inherit; text-decoration:none; }
a.drill__row:hover { background:var(--surface-2); color:inherit; }
a.drill__row:hover .drill__lbl { color:var(--accent-deep); text-decoration:underline; }
a.drill__row:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.drill__lbl { font-size:.88rem; font-weight:500; color:var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drill__val { font-family:var(--font-mono); font-weight:500; font-size:.84rem; text-align:right; font-variant-numeric:tabular-nums; }
.drill__val.neg { color:#b3261e; }
.drill__sub { grid-column:1/-1; font-size:.76rem; color:var(--muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drill__more, .drill__empty { margin:0; padding:.8rem 1.3rem; font-size:.8rem; color:var(--faint); }
.drill__foot { padding:.85rem 1.3rem; border-top:1px solid var(--border-soft); display:flex; justify-content:flex-end; }
.drill__loading { display:flex; gap:6px; justify-content:center; padding:3rem 0; }
.drill__loading span { width:7px; height:7px; border-radius:50%; background:var(--accent); animation:drill-dot 1s infinite ease-in-out; }
.drill__loading span:nth-child(2) { animation-delay:.15s; } .drill__loading span:nth-child(3) { animation-delay:.3s; }
@keyframes drill-in { from { transform:translateX(24px); opacity:0; } to { transform:none; opacity:1; } }
@keyframes drill-fade { from { opacity:0; } to { opacity:1; } }
@keyframes drill-dot { 0%, 80%, 100% { opacity:.25; } 40% { opacity:1; } }
@media (prefers-reduced-motion: reduce) { .drill, .drill-scrim, .drill__loading span { animation:none; } }

/* ── document history: one button in the action bar, and the panel it opens (DocHistory, CONVENTIONS §7f) ──
   The panel is the drill drawer's look on a native <dialog>: opened as a modal it is drawn in the browser's top layer,
   so it is never trapped inside the bar its button sits in (that bar has a z-index AND a backdrop-filter). The class
   beats the browser's own `dialog:not([open]) { display:none }`, hence the rule that restores it. */
dialog.drill { inset:0 0 0 auto; margin:0; height:auto; max-height:none; max-width:100vw; border:0; padding:0; color:var(--text); overflow:hidden; }
dialog.drill:not([open]) { display:none; }
dialog.drill::backdrop { background:rgba(14,23,38,.32); animation:drill-fade .16s ease-out; }
@media (prefers-reduced-motion: reduce) { dialog.drill::backdrop { animation:none; } }

/* the button: a TOOL (its look is the tool tier, "Buttons — four tiers"), first in the bar's tools zone, never squeezed;
   its count is a figure in the documents' numerals, not a badge */
.doc-hist { flex:none; }
.doc-hist__n { font:500 .74rem/1 var(--font-mono); font-variant-numeric:tabular-nums; padding:.22rem .42rem; border-radius:999px;
    background:var(--surface-2); border:1px solid var(--border); color:var(--muted); }
/* a button row with no bar around it (a window's footer, a period run): the tools still sit on the left */
.quote-bar__btns > .doc-hist, .quote-bar__btns > .quote-bar__tools { margin-right:auto; }

.hist__body { flex:1; overflow-y:auto; overscroll-behavior:contain; padding:.2rem 1.3rem 1.8rem; }
.hist__sec + .hist__sec { margin-top:1.5rem; border-top:1px solid var(--border-soft); }
.hist__sec h3 { margin:1.05rem 0 .9rem; font:600 .78rem/1.2 var(--font-sans); color:var(--muted); }
.hist-steps, .hist-feed { list-style:none; margin:0; padding:0; }
.hist__line { display:flex; align-items:baseline; justify-content:space-between; gap:.75rem; }
.hist__line b { font-weight:600; font-size:.9rem; color:var(--text); overflow-wrap:anywhere; }
.hist__line time { flex:none; font-size:.78rem; color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; }
.hist__line .pill { flex:none; }
.hist__line--meta { margin-top:.22rem; font-size:.8rem; color:var(--muted); }
.hist__line--meta > span:first-child { min-width:0; overflow-wrap:anywhere; }
.hist__line--meta em { font-style:normal; margin-left:.45rem; color:var(--faint); }
.hist__line--meta .num { flex:none; font-size:.84rem; color:var(--text); }
/* a reason is someone's own words: set apart by a rule, shown in full, their line breaks kept */
.hist__why { margin:.5rem 0 0; padding-left:.7rem; border-left:2px solid var(--border); font-size:.84rem; line-height:1.45;
    color:var(--text); overflow-wrap:anywhere; white-space:pre-line; }

/* the approval route: its levels in order. The level being waited on is the one thing here that is loud. */
.hist-step { position:relative; padding:0 0 1.15rem 2.35rem; }
.hist-step:last-child { padding-bottom:0; }
.hist-step__no { position:absolute; left:0; top:-.16rem; box-sizing:border-box; width:1.55rem; height:1.55rem; display:grid; place-items:center;
    border-radius:50%; font:600 .74rem/1 var(--font-mono); background:var(--surface-2); border:1px solid var(--border); color:var(--muted); }
.hist-step:not(:last-child)::after { content:""; position:absolute; left:calc(.775rem - .5px); top:1.6rem; bottom:.1rem; width:1px; background:var(--border); }
.hist-step--done .hist-step__no { background:#e7f3ec; border-color:#c3dfce; color:#2c7a4b; }       /* the pills' own greens and ambers */
.hist-step--back .hist-step__no { background:#fbf1de; border-color:#ecd9ad; color:#9a6b12; }
.hist-step--now .hist-step__no { background:var(--surface); border:2px solid var(--accent); color:var(--accent-deep);
    box-shadow:0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent); }
.hist-step--moved > * { opacity:.6; }

/* what happened, newest first: a filled mark moved the document (forward green, taken back amber), a ring is a note */
.hist-ev { position:relative; padding:0 0 1.2rem 1.45rem; --hist-tone:#a9b2bd; }
.hist-ev:last-child { padding-bottom:0; }
.hist-ev::before { content:""; position:absolute; left:0; top:.36rem; box-sizing:border-box; width:9px; height:9px; border-radius:50%;
    background:var(--surface); border:2px solid var(--hist-tone); }
.hist-ev:not(:last-child)::after { content:""; position:absolute; left:4px; top:1.1rem; bottom:-.2rem; width:1px; background:var(--border); }
.hist-ev--on { --hist-tone:#2c7a4b; }
.hist-ev--back { --hist-tone:#b7811c; }
.hist-ev--on::before, .hist-ev--back::before { background:var(--hist-tone); }
.hist-ev__code { margin-left:.5rem; font:400 .74rem/1 var(--font-mono); color:var(--faint); white-space:nowrap; }

/* ── Logistics dashboard: the trip flow ─────────────────────────────────────
   Every open trip by the furthest step it reached, read left to right like the trip itself travels. One band,
   chevron joins between stages, counts in the mono numerals the documents use. The billing stage is the one the
   office acts on, so it alone carries the accent; a stage with nothing in it fades instead of shouting zero.
   Dashboard Purchase reuses it for its PR → PO → receipt → payment pipeline. */
.lflow { display:grid; grid-template-columns:repeat(var(--n, 6), minmax(0,1fr)); margin:0 0 14px; background:var(--surface);
    border:1px solid var(--border); border-radius:var(--radius); box-shadow:var(--shadow); overflow:hidden; }
.lflow__stage { position:relative; display:flex; flex-direction:column; gap:.2rem; padding:1rem 1.1rem 1rem 1.6rem;
    color:inherit; text-decoration:none; min-width:0; transition:background .15s; }
.lflow__stage:first-child { padding-left:1.2rem; }
/* the chevron: a rotated square on the stage's left edge, painted in the band colour so it reads as a notch */
.lflow__stage + .lflow__stage::before { content:""; position:absolute; left:-9px; top:50%; width:18px; height:18px;
    transform:translateY(-50%) rotate(45deg); background:var(--surface); border-top:1px solid var(--border);
    border-right:1px solid var(--border); z-index:1; }
.lflow__stage:hover, .lflow__stage:focus-visible { background:var(--surface-2); outline:none; color:inherit; }
.lflow__stage:hover + .lflow__stage::before { background:var(--surface-2); }
.lflow__stage:focus-visible { box-shadow:inset 0 0 0 2px var(--accent); }
.lflow__label { font-size:.78rem; font-weight:600; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lflow__count { font-family:var(--font-mono); font-size:clamp(1.25rem, 1.9vw, 1.85rem); font-weight:500; line-height:1.1; white-space:nowrap; color:var(--text); font-variant-numeric:tabular-nums; }
.lflow__value { font-size:.78rem; color:var(--muted); font-variant-numeric:tabular-nums; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lflow__value em { font-style:normal; color:var(--faint); }
.lflow__stage.is-empty .lflow__count { color:var(--faint); }
.lflow__stage--act { background:var(--accent-soft); }
.lflow__stage--act + .lflow__stage::before { background:var(--accent-soft); }
.lflow__stage--act .lflow__count { color:var(--accent-deep); }
.lflow__stage--act .lflow__label { color:var(--accent-deep); }
.lflow__stage--act:hover { background:var(--accent-soft); filter:brightness(.98); }
.lflow__flag { display:inline-flex; align-items:center; gap:.3rem; margin-top:.25rem; align-self:flex-start;
    padding:.12rem .5rem; border-radius:999px; font-size: .75rem; font-weight:600; background:#fbf1de; color:#9a6b12; }
@media (max-width:1100px) {
    .lflow { grid-template-columns:repeat(3, minmax(0,1fr)); }
    .lflow__stage:nth-child(3n+1)::before { display:none; }
    .lflow__stage:nth-child(n+4) { border-top:1px solid var(--border-soft); }
}
@media (max-width:560px) {
    .lflow { grid-template-columns:repeat(2, minmax(0,1fr)); }
    .lflow__stage::before { display:none; }
    .lflow__stage:nth-child(n+3) { border-top:1px solid var(--border-soft); }
}

/* the two paper chores under the KPIs: plain sentences that link to where the chore is done */
.lflow-todo { display:flex; flex-wrap:wrap; gap:.5rem 1.4rem; margin:-2px 0 14px; font-size:.84rem; }
.lflow-todo a { color:var(--muted); text-decoration:none; }
.lflow-todo a b { font-family:var(--font-mono); color:var(--text); }
.lflow-todo a span { color:var(--faint); margin-left:.2rem; }
.lflow-todo a.is-due b { color:var(--accent-deep); }
.lflow-todo a:hover { color:var(--text); text-decoration:underline; }

/* Single-line clipped cell for long unbroken tokens (invoice numbers, codes) — pair with title= (R11). */
.quote-lines td.clip { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }


/* ── Navbar user menu (profile · change password · log out) ── */
.usermenu { position:relative; display:flex; align-items:center; }
.userchip { display:inline-flex; align-items:center; gap:.5rem; min-width:0; }
.userchip__av { width:30px; height:30px; border-radius:50%; flex:none; background:var(--ink); color:#fff;
    font:700 .72rem/1 var(--font-sans); display:inline-flex; align-items:center; justify-content:center; }
.userchip__name { font-size:.82rem; font-weight:600; color:var(--text);
    max-width:150px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.usermenu__toggle { background:none; border:none; cursor:pointer; display:flex; align-items:center; gap:8px; padding:4px 6px; border-radius:8px; color:inherit; font:inherit; }
.usermenu__toggle:hover, .usermenu__toggle:focus-visible { background:var(--surface-2); box-shadow:inset 0 0 0 1px var(--border-soft); outline:none; }
.usermenu__caret { opacity:.7; }
/* Phone: the avatar alone identifies the account, and the full name is what overflowed the top bar. This
   rule MUST live here, not in MainLayout.razor.css — .userchip__name is UserMenu's element, and a scoped
   stylesheet cannot reach across a component boundary (it silently matched nothing there). */
@media (min-width: 641px) and (max-width: 1023.98px) {      /* tablet: same budget problem, the rail takes 268px */
    .userchip__name, .usermenu__caret { display: none; }
}
@media (max-width: 640.98px) {
    .userchip__name { display: none; }
    .usermenu__caret { display: none; }
    .usermenu__toggle { padding: 2px; }
    /* Anchored to a chip that now sits close to the edge, so keep the panel inside the viewport. */
    .usermenu__panel { max-width: calc(100vw - 1.5rem); }
}

.usermenu__backdrop { position:fixed; inset:0; z-index:998; }
.usermenu__panel { position:absolute; top:calc(100% + 8px); right:0; z-index:999; min-width:240px;
    background:var(--surface); border:1px solid var(--border); border-radius:10px; box-shadow:0 8px 28px rgba(0,0,0,.16); padding:6px; }
.usermenu__head { display:flex; align-items:center; gap:10px; padding:10px 10px 12px; border-bottom:1px solid var(--border-soft); margin-bottom:6px; }
.usermenu__av-lg { width:36px; height:36px; font-size:.85rem; }
.usermenu__nm { font-weight:700; color:var(--text); max-width:170px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.usermenu__un { font:500 .75rem/1.2 var(--font-mono); color:var(--muted); }
.usermenu__item { display:flex; align-items:center; gap:10px; width:100%; background:none; border:none; cursor:pointer;
    padding:9px 10px; border-radius:7px; font:500 .86rem/1 var(--font-sans); color:var(--text); text-align:left; }
.usermenu__item:hover, .usermenu__item:focus-visible { background:var(--surface-2); outline:none; }
.usermenu__item svg { color:var(--muted); flex:none; }
.usermenu__item--danger { color:#b3261e; }
.usermenu__item--danger svg { color:#b3261e; }
.usermenu__sep { height:1px; background:var(--border-soft); margin:6px 4px; }

.profile-rows { display:flex; flex-direction:column; gap:10px; }
.profile-row { display:flex; justify-content:space-between; align-items:baseline; gap:12px; font-size:.88rem; }
.profile-row > span:first-child { color:var(--muted); flex:none; }
.profile-row b { text-align:right; overflow-wrap:anywhere; }

/* Dense data grid — compact rows for big lists (Stok Barang etc.). */
/* Compact data grids use Telerik Size="sm" (official k-table-sm); this only trims the FilterRow inputs
   so the second header row doesn't tower over the data rows. */
.k-grid .k-filter-row .k-input, .k-grid .k-filter-row .k-picker { height:calc(1.5em + 6px); }
.k-grid .k-filter-row .k-table-td { padding-top:3px; padding-bottom:3px; }

/* Every multi-line note can be dragged TALLER. Telerik ships its textareas fixed, so an address or a long
   instruction had to be read through a three-row window. Vertical only — letting it grow sideways would break
   the form grid it sits in. Applies to the bare element and to both Telerik inner-input shapes. */
textarea,
.k-textarea textarea,
.k-textarea .k-input-inner { resize: vertical; }

/* A list grid fills the WINDOW instead of sitting in a fixed 640px box. With the old fixed height a page size
   of 100 still showed about twenty rows — the rest were hidden inside the grid's own scroller, which reads as
   "pagination is broken" — and the table never grew to use a tall screen. The floor stops it collapsing on a
   short window; the header stays sticky because the grid still has a height. It matches akm.gridfit's MIN, so
   the CSS floor and the JS floor cannot disagree. */
.k-grid { min-height: 240px; }

/* The page's OWN grid can be dragged taller or shorter, exactly like a textarea (which this app already makes
   resizable, above). The selector is the scope rule: a grid that IS the page's content resizes; one inside a
   card, an editor or a dialog keeps the height its markup gives it. `resize` needs a non-visible overflow —
   Telerik's .k-grid already computes overflow:hidden, verified in the browser before this shipped.
   akm.gridfit sets the initial height (measured, never a magic number), remembers what the user drags it to,
   and restores auto-fit on a double-click of the grid's own edge. */
article.content > .k-grid { resize: vertical; }

/* ═══ HR / Payroll ═══════════════════════════════════════════════════════════
   Every screen in this module answers the same two questions — WHO, and in
   WHICH MONTH. Nothing in the first build expressed that: each page grew its
   own ad-hoc filter row out of `.quote-bar__btns` (a flex row meant for
   BUTTONS), so labels and inputs landed on different baselines and the bars
   read as visibly crooked. These classes make that shared question one
   component, so the module has a spine instead of six near-misses. */

/* The scope bar. `align-items: flex-end` is the fix for the crooked baseline:
   every field is label-over-input and all inputs sit on one line. */
.hr-scope { display: flex; align-items: flex-end; gap: .9rem 1.1rem; flex-wrap: wrap;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: .9rem 1.15rem; box-shadow: var(--shadow); margin-bottom: 1.15rem; }
.hr-scope__f { display: flex; flex-direction: column; gap: .32rem; }
.hr-scope__f > label { font: 600 .75rem/1 var(--font-sans); text-transform: uppercase;
    letter-spacing: .08em; color: var(--faint); white-space: nowrap; }
.hr-scope__f--grow { flex: 1 1 280px; min-width: 210px; }
.hr-scope__spacer { flex: 1 1 auto; }
.hr-scope__btns { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
/* a long action label wraps inside the card instead of pushing the page wider than the screen (a phone, or a tablet
   whose rail leaves the card ~370px) */
.hr-scope__btns { max-width: 100%; min-width: 0; }
.hr-scope__btns .k-button { max-width: 100%; white-space: normal; height: auto; }
@media (max-width: 520px) { .hr-scope__btns { width: 100%; } }

/* A period is a COORDINATE, not prose — set it in mono like every other figure
   and code in this app, and name the month so "8" is never ambiguous. */
/* Centred by flex rather than by symmetric padding, so its height stays right whatever the label
   font resolves to. It is deliberately a little taller than the inputs beside it — it is a stamp,
   not a field — and the bar bottom-aligns them. */
.hr-stamp { font: 600 .92rem/1 var(--font-mono); color: var(--ink); background: var(--brass-soft);
    border: 1px solid rgba(212,160,23,.38); border-radius: 8px; padding: 0 .75rem;
    display: inline-flex; align-items: center; min-height: var(--kendo-line-height-em, 2.29em);
    box-sizing: border-box;
    white-space: nowrap; letter-spacing: .02em; }

/* Empty / blocked states: an empty screen is an invitation to act, not a void. */
.hr-empty { display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .5rem; padding: 3.5rem 1.5rem; background: var(--surface); border: 1px dashed var(--border);
    border-radius: var(--radius); text-align: center; }
.hr-empty__t { font-weight: 600; color: var(--text); }
.hr-empty__s { font-size: .86rem; color: var(--muted); max-width: 46ch; }

/* ── Register tables (payroll run, attendance matrix) ───────────────────────
   These are wide money/counter grids read across a row. Long employee names
   used to wrap to 3–4 lines, so every row was a different height and the whole
   table read as ragged — the "miring2" the owner saw. Names stay on ONE line
   (with a title tooltip, R11) and the identity column is frozen so it survives
   the horizontal scroll instead of scrolling away from its own numbers. */
.hr-reg-wrap { overflow: auto; border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); box-shadow: var(--shadow); max-height: calc(100vh - 20rem); }
.hr-reg { border-collapse: separate; border-spacing: 0; width: 100%; font-size: .83rem; }
.hr-reg th, .hr-reg td { white-space: nowrap; padding: .5rem .7rem; vertical-align: middle; }
.hr-reg thead th { position: sticky; top: 0; z-index: 3; background: var(--surface-2);
    font: 600 .75rem/1.2 var(--font-sans); letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted); text-align: right; border-bottom: 1px solid var(--border); }
.hr-reg thead th:first-child { text-align: left; }
.hr-reg tbody td { border-bottom: 1px solid var(--border-soft); text-align: right;
    font-family: var(--font-mono); color: var(--text); }
.hr-reg tbody tr:hover td { background: var(--surface-2); }
/* the frozen identity column — the one cell that is a NAME, not a figure */
.hr-reg__who { position: sticky; left: 0; z-index: 2; background: var(--surface);
    text-align: left !important; font-family: var(--font-sans) !important; font-weight: 600;
    max-width: 15rem; overflow: hidden; text-overflow: ellipsis;
    border-right: 1px solid var(--border); }
.hr-reg thead .hr-reg__who { z-index: 4; background: var(--surface-2); }
.hr-reg tbody tr:hover .hr-reg__who { background: var(--surface-2); }
.hr-reg tfoot td { position: sticky; bottom: 0; background: var(--ink); color: #fff;
    font-family: var(--font-mono); font-weight: 700; text-align: right; padding: .6rem .7rem; }
.hr-reg tfoot td:first-child { text-align: left; font-family: var(--font-sans); }
/* inline edit: the value reads as text until you reach for it (same idea as .quote-lines) */
.hr-reg .k-input, .hr-reg .k-picker { border-color: transparent; background: transparent; box-shadow: none; }
.hr-reg td:hover .k-input, .hr-reg td:focus-within .k-input,
.hr-reg td:hover .k-picker, .hr-reg td:focus-within .k-picker { border-color: var(--border); background: #fff; }
.hr-reg .k-numerictextbox .k-input-spinner { display: none; }
/* The three columns a reviewer actually reconciles — Bruto, Total Potongan, Net Pay — are set apart from the
   twenty components around them, so the eye finds the arithmetic in a 24-column register. */
.hr-reg th.hr-reg__tot, .hr-reg td.hr-reg__tot { background: var(--surface-2); }
.hr-reg tbody td.hr-reg__tot { border-left: 1px solid var(--border); }
.hr-reg thead th.hr-reg__tot { border-left: 1px solid var(--border); }
.hr-reg tfoot td.hr-reg__tot { background: var(--ink); border-left: 1px solid rgba(255,255,255,.25); }
.hr-reg tbody tr:hover td.hr-reg__tot { background: var(--surface-2); }
.hr-reg__slip { font-size: .78rem; font-weight: 600; text-decoration: none; white-space: nowrap; }
/* a figure that is DERIVED from another document and therefore locked here */
.hr-locked { display: inline-flex; align-items: baseline; gap: .35rem; white-space: nowrap; }
.hr-locked__i { font-size: .7rem; color: var(--faint); font-family: var(--font-sans); }

/* ── Employee record (full page, not a modal) ───────────────────────────────
   25+ fields never fit a dialog; they belong on a page with real sections. */
.emp-grid { display: grid; grid-template-columns: 260px 1fr; gap: 1.15rem; align-items: start; }
.emp-side { position: sticky; top: 1rem; display: flex; flex-direction: column; gap: .9rem; }
.emp-photo { display: flex; flex-direction: column; align-items: center; gap: .7rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 1.2rem; box-shadow: var(--shadow); }
.emp-photo__img { width: 132px; height: 132px; border-radius: 50%; object-fit: cover;
    border: 3px solid var(--surface-2); box-shadow: 0 2px 10px -4px rgba(16,47,56,.4); }
.emp-photo__ph { width: 132px; height: 132px; border-radius: 50%; display: flex; align-items: center;
    justify-content: center; background: var(--ink); color: var(--brass-bright);
    font: 700 2.4rem/1 var(--font-sans); letter-spacing: .02em; }
.emp-photo__name { font-weight: 700; text-align: center; line-height: 1.3; }
.emp-photo__meta { font-size: .8rem; color: var(--muted); text-align: center; }
.emp-sec { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: 1.15rem 1.3rem; box-shadow: var(--shadow); margin-bottom: 1.15rem; }
.emp-sec:last-child { margin-bottom: 0; }
.emp-sec__h { display: flex; align-items: baseline; gap: .6rem; margin: 0 0 1rem;
    padding-bottom: .6rem; border-bottom: 1px solid var(--border-soft); }
.emp-sec__h h3 { margin: 0; font-size: .95rem; font-weight: 700; color: var(--ink); }
.emp-sec__h em { font-style: normal; font-size: .78rem; color: var(--muted); }
.emp-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: .9rem 1rem; }
.emp-fields .qf { margin-bottom: 0; }
.emp-fields .qf--wide { grid-column: 1 / -1; }
/* A field whose blank value CHANGES BEHAVIOUR needs to say so where it is, not in a manual — the start
   date and the active flag both silently decide how someone is paid. */
.qf__hint { color: var(--muted); font-size: .78rem; line-height: 1.35; }
/* A read-only value where an input would otherwise sit: same rhythm as .qf so a page of facts lines up
   with a page of fields, without pretending to be editable. */
.profile-val { min-height: 34px; display: flex; align-items: center; color: var(--text); font-weight: 600; }

@media (max-width: 900px) {
    .emp-grid { grid-template-columns: 1fr; }
    .emp-side { position: static; }
}

/* Upload control on the employee record. The shared `.wo-att__add` deliberately shows the native file input
   (Work Order needs the file name visible); here the sidebar is 260px wide, so the native control pushed the
   label onto a second line and read as unfinished. Same affordance, no native chrome. */
.emp-upload { display: inline-flex; align-items: center; justify-content: center; gap: .4rem; width: 100%;
    border: 1px dashed var(--border); background: var(--surface-2); color: var(--brass);
    font: 600 .82rem var(--font-sans); padding: .55rem .8rem; border-radius: 8px; cursor: pointer;
    text-align: center; transition: border-color .15s, background .15s; }
.emp-upload:hover { border-color: var(--brass); background: var(--brass-soft); }
.emp-upload input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0;
    overflow: hidden; clip: rect(0 0 0 0); }
.emp-upload:focus-within { outline: 2px solid var(--brass); outline-offset: 2px; }

/* A document editor's two-column split (body + summary) only works while the body still has room. The
   summary is a fixed 380px, so below roughly 1100px the body was squeezed under ~300px — its field grid
   collapsed to a single column and half the window sat empty beside a tall, narrow card. Fold to one
   column before that happens rather than at the phone breakpoint. Measured on Insentif Sales at 1024px. */
@media (max-width: 1100px) {
    .quote-cols, .quote-cols--foot { grid-template-columns: 1fr; }
}

/* Where a payroll figure came from. Making the source visible is the point of the read-only register: every
   column except the attendance deduction is derived, so the answer to "why this amount?" is a document, and
   the way to change it is to go there — not to type over the total. */
.hr-src { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: 1.1rem;
    padding: .7rem .95rem; background: var(--surface); border: 1px solid var(--border);
    border-left: 3px solid var(--brass); border-radius: var(--radius); font-size: .82rem; }
.hr-src__lbl { color: var(--muted); }
.hr-src a { color: var(--brass); font-weight: 600; text-decoration: none; border-bottom: 1px solid transparent; }
.hr-src a:hover { border-bottom-color: var(--brass); }
.hr-src__sep { color: var(--faint); }

/* Excel-import dialog (Kas & Bank, Advance, Berita Acara). The preview is the confirmation step, so it has to
   show the WHOLE file — documents and their lines — while staying inside the window: the body scrolls, the
   action row does not, and each document is a bordered block so two adjacent ones never read as one. */
.imp-win .k-window-content { padding-bottom: .8rem; }
.imp { max-height: 58vh; overflow-y: auto; padding-right: .35rem; }
.imp__bar { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem;
    flex-wrap: wrap; padding-bottom: .8rem; border-bottom: 1px solid var(--border-soft); margin-bottom: .9rem; }
.imp__lbl { display: block; font: 600 .75rem/1.2 var(--font-sans); letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted); margin-bottom: .35rem; }
.imp__pick input[type=file] { font-size: .84rem; max-width: 380px; }
.imp__issues-box { border: 1px solid var(--danger, #b3261e); border-radius: 10px; padding: .7rem .9rem;
    margin-bottom: 1rem; background: var(--surface-2); }
.imp__issues { margin: .4rem 0 0; padding-left: 1.1rem; font-size: .84rem; }
.imp__doc { border: 1px solid var(--border-soft); border-radius: 10px; padding: .6rem .8rem; margin-bottom: .7rem; }
.imp__doc-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.imp__doc-title { font-weight: 600; }
.imp__doc-sub { color: var(--muted); font-size: .8rem; margin-bottom: .45rem; }
.imp__done .quote-lines { max-width: 560px; }

/* A day whose numbers cannot be right — present on a day off, no status on a working day, or a punch
   pair that makes no sense. Marked so HR can find it, never hidden or auto-corrected. */
.hr-reg__row--warn > td { background: #FFF7E6; }
.hr-reg__row--warn > td:first-child { box-shadow: inset 3px 0 0 #E9A118; }

/* ── Narrow screens: the filter bar and the stat tiles ────────────────────────────────────────
   Measured at 390px before this existed: a filter row was 224-245px TALL because each .qf kept its
   declared 190-220px width and stacked one per line, and the header's stat tiles came out 135, 214,
   172 and 174px wide — a ragged pile rather than a block of numbers. Both classes are shared, so
   this is every screen, not just the new ones. */
@media (max-width: 720px) {
    /* Filters go two-up and fill their column; the control inside stops keeping its desktop width. */
    .rpt-bar, .hr-scope, .quote-bar--filters {
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem .6rem;
        align-items: end;
    }
    .rpt-bar > .qf, .hr-scope > .qf, .quote-bar--filters > .qf,
    .hr-scope > .hr-scope__f { margin-bottom: 0; min-width: 0; }
    .rpt-bar .k-input, .rpt-bar .k-picker, .hr-scope .k-input, .hr-scope .k-picker,
    .quote-bar--filters .k-input, .quote-bar--filters .k-picker,
    .rpt-bar .k-dropdownlist, .hr-scope .k-dropdownlist, .quote-bar--filters .k-dropdownlist
        { width: 100% !important; }
    /* A button in a filter bar spans the row: at this width a half-width button reads as a stray chip. */
    .rpt-bar > .k-button, .hr-scope > .k-button, .quote-bar--filters > .k-button { grid-column: 1 / -1; }

    /* The locked identity column stops being sticky. On a desktop it is what keeps you on the right
       row while scrolling right (R16); on a 390px screen a 230px pinned column leaves ~160px for the
       whole rest of the table and simply covers the data. The column is still THERE and still first —
       it just scrolls with everything else. Telerik implements locking as position:sticky, so this is
       the whole mechanism. */
    .k-grid .k-grid-content-sticky,
    .k-grid .k-grid-header-sticky,
    .k-grid .k-grid-row-sticky { position: static !important; }

    /* Stat tiles: equal columns, so they read as one block instead of a ragged pile. */
    .meta-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
    .meta { border-left: none; padding: .5rem .2rem; }
    .meta__num { font-size: 1.25rem; }
}

@media (max-width: 420px) {
    /* Still TWO columns: month, year and a code picker are short, and one-per-row turned a filter
       bar into a 205px wall of chrome above the data. Only a control that is genuinely long asks
       for the full width, by carrying .filter-wide. */
    .rpt-bar > .filter-wide, .hr-scope > .filter-wide, .quote-bar--filters > .filter-wide
        { grid-column: 1 / -1; }
    .meta-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* "Login as" banner. Deliberately loud and NOT dismissible: the whole risk of impersonation is
   forgetting you are in it. */
.impersonating {
    display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
    background: #7A2E12; color: #FFF3E8; padding: .55rem 1rem; font-size: .85rem;
    border-bottom: 2px solid #E9A118;
}
.impersonating b { color: #FFD79A; }
.impersonating__dot { width: 9px; height: 9px; border-radius: 50%; background: #E9A118; flex: none; }
.impersonating__form { margin-left: .1rem; }
/* The countdown sits next to the way out, not floating on its own: it is the reason to press it.
   Tabular figures so the seconds do not jitter the layout once a second. */
.impersonating__left {
    margin-left: auto; font-variant-numeric: tabular-nums;
    font-weight: 700; color: #FFD79A; letter-spacing: .02em;
}
.impersonating__back {
    font: 600 .82rem/1 inherit; color: #7A2E12; background: #FFD79A;
    border: none; border-radius: 999px; padding: .4rem .9rem; cursor: pointer;
}
.impersonating__back:hover { background: #FFE6BF; }


/* ── Work Schedule: the cycle strip ───────────────────────────────────────────
   A roster is not fourteen unrelated rows; it is a few shifts repeated — six days on, one off,
   six nights, one off. The old form asked for 42 time values and still hid the pattern. Here the
   shifts are defined once and painted onto the cycle, and the rhythm is the thing you SEE.
   Colour carries meaning rather than decoration: brass = a day shift, petrol = a night one (it is
   literally darker), bare paper = a day off. No new palette — both are the brand's own two. */
.cyc {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 6px;
}
@media (min-width: 900px) { .cyc--long { grid-template-columns: repeat(14, minmax(0, 1fr)); } }

.cyc__day {
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    padding: .5rem .25rem .45rem;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface-2);
    font: 600 .74rem/1 var(--font-mono);
    color: var(--muted);
    cursor: pointer;
    transition: transform .12s ease, box-shadow .12s ease;
}
.cyc__day:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.cyc__day:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.cyc__num { font-size: .68rem; letter-spacing: .04em; opacity: .75; }
.cyc__time { font-size: .66rem; white-space: nowrap; }

/* Painted states. The shift's own colour, so a glance reads the rhythm without reading times. */
.cyc__day--on   { background: var(--brass); border-color: var(--brass); color: #fff; }
.cyc__day--on .cyc__num { opacity: .8; }
.cyc__day--night{ background: var(--ink); border-color: var(--ink); color: #eaf1f2; }
.cyc__day--night .cyc__num { opacity: .7; }
.cyc__day--off  { background: repeating-linear-gradient(135deg, var(--surface-2) 0 6px, var(--border-soft) 6px 12px); }

/* The pattern, said in words — the strip shows it, this proves it. */
.cyc__legend { margin-top: .5rem; font-size: .78rem; color: var(--muted); }
.cyc__legend b { color: var(--text); font-weight: 600; }

/* A shift: the definition that gets painted. Three times, once, instead of three per day. */
.shift {
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    padding: .55rem .7rem; border: 1px solid var(--border); border-radius: 10px;
    background: var(--surface); margin-bottom: .4rem;
}
.shift__dot { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.shift__name { font-weight: 600; min-width: 4.5rem; }
.shift__times { font-family: var(--font-mono); font-size: .82rem; color: var(--muted); }
.shift__pick { margin-left: auto; display: flex; gap: .4rem; align-items: center; flex-wrap: wrap; }

/* Section heading inside a form — a rule that names what follows, not decoration. */
.fsec { margin-top: 1.1rem; }
.fsec__h {
    display: flex; align-items: center; gap: .6rem;
    font: 600 .75rem/1 var(--font-sans); letter-spacing: .09em; text-transform: uppercase;
    color: var(--muted); margin-bottom: .5rem;
}
.fsec__h::after { content: ""; flex: 1; height: 1px; background: var(--border); }

/* The same rhythm, shrunk to a list cell: no numbers, no times, just the shape of the week or the
   roster. Enough to tell the office schedule from a site one without opening either. */
.cyc-mini { display: inline-flex; gap: 2px; align-items: center; }
.cyc-mini__d {
    width: 8px; height: 16px; border-radius: 2px;
    background: repeating-linear-gradient(135deg, var(--surface-2) 0 3px, var(--border-soft) 3px 6px);
    border: 1px solid var(--border);
}
.cyc-mini__d.is-on { background: var(--brass); border-color: var(--brass); }

/* A row of fields of DIFFERENT widths that wraps. `.qf-row` is a fixed two-column grid, which forces
   a 130px number box to the same width as a 250px dropdown; this keeps each field its own size and
   keeps every label stacked above its own control instead of drifting beside it. */
.qf-flow { display: flex; flex-wrap: wrap; gap: .9rem 1.1rem; margin-bottom: .9rem; align-items: flex-end; }
.qf-flow > .qf { margin-bottom: 0; }

/* ── A list grid, full screen ────────────────────────────────────────────────
   For PRESENTING a table — a projector, a review meeting — where the sidebar, the page header and
   the browser's own chrome are all eating screen the data should have. (A table that is merely
   squeezed by the sidebar has a cheaper answer: the sidebar's own collapse button.)
   The button is injected into every grid's toolbar by akm.gridFullscreen, so a grid added tomorrow
   gets it too. */
.akm-fs { margin-left: .25rem; }
/* The 4 grids with no toolbar get the button pinned to their own corner instead. */
.akm-fs-host { position: relative; }
.akm-fs-host > .akm-fs {
    position: absolute; top: .4rem; right: .4rem; z-index: 3;
    background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}

/* ── Table layout menu (akm.gridLayoutMenu) ─────────────────────────────────
   Every grid's layout is saved to the user's ACCOUNT as they drag (GridPersist). This menu is the way back
   out: Auto-fit sizes columns to their content, Reset returns to the designed layout. */
.akm-lay-btn { margin-left: .25rem; }
.akm-lay-btn[aria-expanded="true"] { background: var(--accent-soft); color: var(--accent-deep); }
.akm-fs-host > .akm-lay-btn--pinned {
    position: absolute; top: .4rem; right: 2.6rem; z-index: 3;
    background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.akm-lay {
    position: fixed; z-index: 10050; width: 268px; padding: .35rem;
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
    box-shadow: var(--shadow); animation: akm-lay-in .12s ease-out;
}
@keyframes akm-lay-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.akm-lay__head { padding: .45rem .6rem .5rem; font-size: .8rem; font-weight: 700; color: var(--text); border-bottom: 1px solid var(--border-soft); margin-bottom: .25rem; }
.akm-lay__head span { display: block; margin-top: .15rem; font-size: .75rem; font-weight: 400; color: var(--muted); line-height: 1.35; }
.akm-lay__item {
    display: flex; flex-direction: column; align-items: flex-start; gap: .05rem; width: 100%;
    padding: .45rem .6rem; border: 0; border-radius: 7px; background: none; cursor: pointer; text-align: left; font: inherit;
}
.akm-lay__item:hover, .akm-lay__item:focus-visible { background: var(--surface-2); outline: none; }
.akm-lay__item:focus-visible { box-shadow: inset 0 0 0 2px var(--accent-soft); }
.akm-lay__label { font-size: .84rem; font-weight: 600; color: var(--text); }
.akm-lay__cols { margin-top: .25rem; padding-top: .25rem; border-top: 1px solid var(--border-soft); max-height: min(46vh, 340px); overflow-y: auto; }
.akm-lay__cols:empty { display: none; }
.akm-lay__sub { padding: .3rem .6rem .2rem; font-size: .75rem; font-weight: 600; color: var(--muted); }
.akm-lay__col { display: flex; align-items: center; gap: .55rem; padding: .32rem .6rem; border-radius: 7px; font-size: .84rem; color: var(--text); cursor: pointer; }
.akm-lay__col:hover { background: var(--surface-2); }
.akm-lay__col input { width: 15px; height: 15px; accent-color: var(--accent-deep); cursor: pointer; flex: none; }
.akm-lay__col.is-locked { color: var(--muted); cursor: default; }
.akm-lay__col.is-locked input { cursor: default; }
.akm-lay__hint { font-size: .75rem; color: var(--muted); }
/* the confirmation that an invisible action happened — the layout already looks right, so say it was saved */
.k-grid.akm-grid { position: relative; }
.akm-lay__flash {
    position: absolute; top: .5rem; left: 50%; transform: translateX(-50%); z-index: 5;
    padding: .3rem .75rem; border-radius: 999px; font-size: .76rem; font-weight: 600;
    background: var(--ink); color: #fff; box-shadow: var(--shadow); transition: opacity .35s;
}
.akm-lay__flash.is-out { opacity: 0; }

.k-grid:fullscreen {
    /* The measured height (akm.gridfit) still applies, but the browser paints the backdrop black by
       default — a white grid floating on black reads as broken. */
    background: var(--surface);
    padding: .5rem .75rem 0;
    border-radius: 0;
    border: 0;
}
/* Bigger type when it is being read from across a room, not from 60cm away. */
.k-grid:fullscreen .k-table { font-size: 1.02rem; }
.k-grid:fullscreen .k-grid-header th { font-size: .92rem; }

/* ── Workload bar ────────────────────────────────────────────────────────────
   A load percentage read against a MARKED 100% line is found by the eye; the same figure in a plain
   column has to be read and compared by hand, one row at a time. The line is the person's own
   scheduled hours, so "over" is a visual fact rather than an arithmetic one.
   The bar is half-scale (200% fills it): past double, the exact figure stops mattering and a longer
   bar would only steal width from the rows still worth comparing. */
.load { display: flex; align-items: center; gap: .55rem; justify-content: flex-end; }
.load__track {
    position: relative; flex: 1 1 auto; min-width: 90px; height: 10px;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px; overflow: hidden;
}
.load__fill { height: 100%; background: var(--brass); border-radius: 999px; }
.load__fill.is-over { background: var(--c-liability); }
/* The 100% mark sits at the halfway point of a half-scale track. */
.load__line { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--ink); opacity: .45; }
.load__num { font: 600 .84rem/1 var(--font-mono); min-width: 3.4rem; text-align: right; }
.load__num.is-over { color: var(--c-liability); }

/* ===== Accessibility — reduced motion. Users whose OS asks for reduced motion get none of the
   app's own animations (akm-shake, toastDrain) or transitions. Kept at the END of the file on
   purpose (override blocks lose to later declarations — see CONVENTIONS §1b). Toast auto-close
   is driven by the Telerik CloseAfter timer, not the drain bar's animation, so dismissal still
   works; the bar simply doesn't animate. Bootstrap/Telerik ship their own guards. ===== */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── Overtime ladder (HR › Overtime Policy) ────────────────────────────────────
   The ladder drawn as a strip of hours. One accent, intensity carries the
   multiplier: the hour where the rate steps up is visible before a number is
   read, which is exactly the thing the 2026-09-16 audit found people get wrong
   (a ladder starting its 3x band one hour late costs a crew 88 equivalent hours
   a month, and in a table of numbers it looks fine).                            */
.otl__strip { display: flex; gap: 2px; margin: .1rem 0 .6rem; }
.otl__hr {
  flex: 1 1 0; min-width: 0; padding: .3rem .1rem; border-radius: 3px; text-align: center;
  background: color-mix(in srgb, var(--brass) calc(var(--otl-weight, .3) * 78%), var(--surface));
  border: 1px solid var(--border);
}
.otl__hr--rest { flex: 1.3 1 0; border-style: dashed; }
.otl__hrn { display: block; font-size: .68rem; color: var(--muted); }
.otl__hrm { display: block; font-family: var(--font-mono); font-size: .8rem; font-weight: 600; color: var(--text); }
.otl__bands { width: 100%; border-collapse: collapse; }
.otl__bands td { padding: .18rem .35rem .18rem 0; vertical-align: middle; font-size: .85rem; }
.otl__from { white-space: nowrap; width: 5.5rem; }
.otl__rowact { width: 2.5rem; text-align: right; }
.otl__acts { display: flex; gap: .4rem; margin-top: .2rem; }
.otl__preview { background: var(--paper); border-radius: 4px; }
.otl__pvrow { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-top: .4rem; }
.otl__pv { display: flex; align-items: baseline; gap: .35rem; }
.otl__pvl { font-size: .8rem; color: var(--muted); min-width: 7.5rem; }
.otl__pvn { font-size: 1.15rem; font-weight: 600; color: var(--text); }
.otl__pvu { font-size: .75rem; color: var(--faint); }
.otl__empty { max-width: 46rem; padding: 1.4rem 1.6rem; }
.otl__empty h2 { margin: 0 0 .5rem; font-size: 1.05rem; }
.otl__empty p { margin: 0 0 .6rem; font-size: .88rem; line-height: 1.55; max-width: 60ch; }

/* Roster phase strip (HR › Work Schedules): each crew's next fortnight, so an
   offset is something you SEE rather than a number you trust.                   */
.rph { display: grid; grid-template-columns: minmax(9rem, 1.4fr) auto 1fr; gap: .5rem; align-items: center; padding: .2rem 0; }
.rph__name { font-size: .85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rph__days { display: flex; gap: 2px; }
.rph__d {
  width: 1.45rem; padding: .14rem 0; border-radius: 3px; text-align: center;
  font-family: var(--font-mono); font-size: .62rem; border: 1px solid var(--border); background: var(--surface); color: var(--muted);
}
.rph__d--work { background: color-mix(in srgb, var(--brass) 42%, var(--surface)); color: var(--text); }
.rph__d--night { background: color-mix(in srgb, var(--ink) 22%, var(--surface)); color: var(--text); }
.rph__legend { display: flex; gap: .8rem; font-size: .75rem; color: var(--muted); margin-top: .3rem; }

/* ---------- Setting › Company (DBP tenant spec F0 §6) ----------
   The form on the left; on the right a PROOF — a small sheet of the company's paper showing what its documents
   will print with the values being typed, before they are saved. The sheet is the one thing on this screen that
   is allowed to look like something: white paper on the warm canvas, the initial marked in brass where it lands
   inside a number. Everything else stays plain form. */
.co-settings { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 1.4rem; align-items: start; }
.co-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem 1.2rem; padding-top: .9rem; }
.co-field { display: flex; flex-direction: column; gap: .3rem; font-size: .84rem; font-weight: 600; color: var(--text); }
.co-field--wide { grid-column: 1 / -1; }
.co-field small { font-weight: 400; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.co-field small.co-need { color: var(--c-liability); }
.co-dot { display: inline-block; width: 7px; height: 7px; margin-left: .45rem; border-radius: 50%; background: var(--c-liability); vertical-align: middle; }
.co-opt-sub { display: block; font-size: .75rem; color: var(--muted); }
.co-logo { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.co-logo img { height: 44px; width: auto; border: 1px solid var(--border); border-radius: 6px; padding: 3px; background: #fff; }
/* Setting › Print Settings (print parity P1) — the Company page's form + proof, plus rows that stack on a phone. */
.ps-logo-proof { margin: 1rem 0; padding: 1rem; background: #fff; border: 1px dashed var(--border); border-radius: 8px; overflow-x: auto; }
.ps-note { margin: 0 0 .8rem; max-width: 72ch; }
.co-grid + .ps-note { margin: .9rem 0 0; }
.ps-inherit { max-width: none; padding-top: .2rem; }
.ps-proof__address { white-space: pre-line; }
.ps-proof__place { margin-top: .7rem; text-align: right; }
.ps-offices { margin-top: 1.4rem; }
.ps-offices__pick { background: none; border: 0; padding: 0; font: inherit; font-weight: 600; cursor: pointer; text-align: left; }
.ps-offices__pick:hover { text-decoration: underline; text-underline-offset: 3px; }
.ps-offices__pick:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.ps-offices__current td { background: var(--brass-soft); }
.ps-offices .pill { margin-left: .35rem; }
.ps-offices td:nth-child(3) .pill { margin-left: 0; }
.imp-sec__h.ps-group { margin: 1.4rem 0 .1rem; }
.ps-row { display: grid; gap: .5rem 1.2rem; align-items: start; padding: .75rem 0; border-bottom: 1px solid var(--border-soft); }
.ps-row--text { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); }
.ps-row--text .ps-row__head { padding-top: 0; }
.ps-row--text .ps-row__head .pill { align-self: flex-start; margin-top: .2rem; }
.ps-row--off .k-textarea { background: var(--surface-2, #f6f5f1); color: var(--muted); }
.ps-row--delivery { grid-template-columns: 150px minmax(0, 1fr) minmax(0, 1fr); }
.ps-row--labels { padding: .2rem 0; font: 600 .75rem/1.2 var(--font-sans); color: var(--muted); }
.ps-cell { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.ps-cell__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (max-width: 760px) {
    .ps-row--text, .ps-row--delivery { grid-template-columns: minmax(0, 1fr); }
    .ps-row--labels { display: none; }
    .ps-cell__label { position: static; width: auto; height: auto; clip: auto; font-size: .78rem; color: var(--muted); }
    /* the office overview becomes one block per office: name and source, then what it prints */
    .ps-offices .jrn-tbl { min-width: 0; }
    .ps-offices thead { display: none; }
    .ps-offices .jrn-tbl tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .15rem .6rem; padding: .55rem .5rem; border-bottom: 1px solid var(--border-soft); }
    .ps-offices .jrn-tbl td { display: block; padding: 0; border: 0; }
    .ps-offices .jrn-tbl td:nth-child(2), .ps-offices .jrn-tbl td:nth-child(4), .ps-offices .jrn-tbl td:nth-child(5) { grid-column: 1 / -1; color: var(--muted); }
    .ps-offices .jrn-tbl td:nth-child(3) { grid-row: 1; grid-column: 2; }
    .ps-offices__current { background: var(--brass-soft); }
}
.co-policy { display: flex; gap: .9rem; align-items: flex-start; padding-top: 1rem; max-width: 62ch; }
.co-policy label { display: flex; flex-direction: column; gap: .25rem; font-size: .88rem; }
.co-policy label span { color: var(--muted); line-height: 1.45; }
.co-actions { display: flex; gap: 1rem; align-items: center; margin-top: 1.3rem; padding-top: 1rem; border-top: 1px solid var(--border-soft); }

.co-proof { position: sticky; top: 1rem; }
.co-proof__sheet { background: #fff; border: 1px solid var(--border); border-radius: 3px; padding: 1.1rem 1.2rem 1.2rem;
    box-shadow: 0 1px 0 var(--border), 0 18px 30px -18px rgba(16,47,56,.35); font-size: .78rem; color: var(--text); }
.co-proof__head { display: flex; gap: .8rem; align-items: flex-start; padding-bottom: .8rem; border-bottom: 2px solid var(--ink); }
.co-proof__head img { height: 40px; width: auto; }
.co-proof__nologo { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border: 1px dashed var(--faint);
    color: var(--faint); font-size: .6rem; text-align: center; line-height: 1.1; }
.co-proof__name { font-weight: 700; font-size: .86rem; }
.co-proof__line { color: var(--muted); min-height: 1em; overflow-wrap: anywhere; }
.co-proof__numbers { display: grid; grid-template-columns: auto 1fr; gap: .35rem .8rem; margin: .9rem 0; }
.co-proof__numbers dt { color: var(--muted); }
.co-proof__numbers dd { margin: 0; font-family: var(--font-mono); font-size: .76rem; word-break: break-all; }
.co-proof__numbers mark { background: var(--brass-soft); color: var(--ink); box-shadow: inset 0 -2px 0 var(--brass); padding: 0 1px; }

.setup-banner { display: flex; gap: 1rem; align-items: center; justify-content: space-between; flex-wrap: wrap;
    margin: .6rem 1.5rem 0; padding: .55rem .9rem; border-radius: 8px; background: var(--brass-soft);
    border: 1px solid rgba(183,132,43,.35); font-size: .86rem; color: var(--text); }
.setup-banner a { color: var(--ink); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.setup-banner a:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }

@media (max-width: 1100px) {
    .co-settings { grid-template-columns: minmax(0, 1fr); }
    .co-proof { position: static; max-width: 420px; }
}
@media (max-width: 640px) {
    .co-grid { grid-template-columns: minmax(0, 1fr); }
    .setup-banner { margin: .5rem .75rem 0; }
}

/* ---------- DBP logistics (spec F1 §5) ---------- */
/* Trip "lenses": one list, four ways of reading it (legacy had five screens over one table). */
.lens { display: inline-flex; gap: .2rem; padding: .2rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.lens__item { padding: .3rem .75rem; border-radius: 6px; font-size: .84rem; color: var(--muted); text-decoration: none; }
.lens__item:hover { color: var(--text); background: var(--border-soft); }
.lens__item.is-on { background: var(--ink); color: #fff; }
.lens__item:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.grid-toolbar-inline { display: flex; justify-content: flex-end; max-width: 1000px; margin-bottom: .35rem; }
.banner-note { margin: 0 0 1rem; padding: .6rem .9rem; border-radius: 8px; background: var(--brass-soft); border: 1px solid rgba(183,132,43,.35); font-size: .86rem; }
.qtotal { margin: .4rem 0 0; display: flex; justify-content: space-between; font-size: .9rem; color: var(--muted); }
.qtotal b { color: var(--text); }
.num.neg { color: #b42318; }
.quote-lines tr.is-muted td { color: var(--faint); }
.quote-totals { margin-top: .9rem; margin-left: auto; max-width: 380px; display: grid; gap: .3rem; font-size: .88rem; }
.quote-totals > div { display: flex; justify-content: space-between; gap: 1rem; color: var(--muted); }
.quote-totals > div b { color: var(--text); }
.quote-totals__grand { padding-top: .4rem; border-top: 1px solid var(--border); font-size: .95rem; }
.print-doc .pd-foot-inv { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; margin-top: 18px; }
/* logistics quotation: the cover letter under the address block, and the terms box */
.print-doc .pd-note { margin: 0 0 14px; line-height: 1.5; }
.print-doc .pd-terms { margin-top: 14px; padding: 8px 10px; border: 1px solid #000; border-radius: 4px; }
/* rich-text terms: the markup carries the line breaks, so no pre-line (it would double them) and tight paragraphs */
.print-doc .pd-terms--rich { white-space: normal; }
.print-doc .pd-terms--rich p, .rich-view p { margin: 0; }
.print-doc .pd-terms--rich ul, .print-doc .pd-terms--rich ol, .rich-view ul, .rich-view ol { margin: 2px 0 2px 18px; padding: 0; }
/* read-only render of a rich-text field inside an editor card (approved document) */
.rich-view { padding: .55rem .7rem; border: 1px solid var(--border-soft); border-radius: 8px; background: var(--surface-2); font-size: .88rem; line-height: 1.5; }
@media (max-width: 640px) { .lens { flex-wrap: wrap; } }

/* ============================================================
   Midnight & Signal — label voice (2026-10-01)
   Tracked-out capitals read as a form from 2005 and slow reading of
   short labels. Labels are sentence case, medium weight, quiet colour.
   Print documents (.print-doc) keep their own typography.
   ============================================================ */
.k-grid .k-grid-header .k-column-title { text-transform: none; letter-spacing: 0; font-weight: 650; color: var(--muted); font-size: .8rem; }
.meta__label, .grid-flt__lbl, .q-eyebrow, .qm > span, .quote-lines thead th, .notif__head,
.jrn-tbl__totlbl, .hr-scope__f > label, .jrn-tbl th, .dash-kpi__label,
.hr-reg thead th, .imp__lbl, .fsec__h {
    text-transform: none; letter-spacing: 0;
}
.meta__label { font-size: .75rem; font-weight: 600; color: var(--muted); }
.grid-flt__lbl { font-size: .76rem; color: var(--muted); }
.q-eyebrow { font-size: .78rem; color: var(--muted); }
.qm > span { font-size: .75rem; }
.quote-lines thead th { font-size: .75rem; font-weight: 650; }

/* surfaces: one radius family — sheets 14, controls 9 — and a single soft elevation */
.k-grid { border-radius: var(--radius); border-color: var(--border); box-shadow: var(--shadow); overflow: hidden; }
.k-grid .k-table-row:hover, .k-grid .k-table-row.k-hover { background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.k-grid .k-table-row.k-selected > td { background: var(--accent-soft); }
.k-button { border-radius: var(--radius-sm); }
.k-input, .k-picker { border-radius: var(--radius-sm); }
a, .btn-link { color: var(--accent-deep); }
a:hover { color: var(--accent); }

/* ===== Buttons — four tiers, one size (owner 2026-10-08, mockup approved; CONVENTIONS §1 + §7c) =====
   WHICH tier a standard action takes is decided by ActionCatalog (ActionButton emits .act--commit / --secondary /
   --tool / --quiet), never by a page. The accent no longer FILLS a button — amber under dark text read muddy ("ngga
   keliatan, jelek"); it stays the signal: the commit's glyph, the focus ring, the active nav item, chips, links.
     commit     the one loud thing: the sidebar's own midnight, a champagne glyph (teal on DBP logistics — the glyph
                follows --accent-bright, the fill stays midnight)
     secondary  white, a hairline (Save Draft, Reject)
     tool       flat, icon first, muted until touched (History, Journal, Print in an editor, Export, Refresh)
     quiet      flat and muted (Delete, Reopen, Cancel, Back…); a destructive one turns red only under the pointer
   Telerik's own classes carry the commit and secondary looks too, so a primary button written without ActionButton
   (a confirm dialog's OK, a page-specific "Load items") speaks the same language; Telerik's `error` theme is left alone
   for destructive confirm dialogs. Selectors start at `html` to outrank the theme, which loads AFTER this file; the
   theme's flat buttons carry !important (background, ::before/::after), hence the few here. */
:root { --btn-h: 38px; }
@media (max-width: 640px) { :root { --btn-h: 44px; } }      /* a thumb's height on a phone */

/* one size in every home: the document bar, list/report toolbars, print bar, modal footers. Icon-only buttons (a
   list row's actions, a grid's column menu, a picker's arrow) keep their own size — a row action is .act--row, because
   BusyButton always hands Telerik a ChildContent and Telerik then never marks it .k-icon-button. */
html .k-button.act:not(.k-icon-button):not(.act--row),
html .quote-bar .k-button:not(.k-icon-button),
html :is(.print-bar, .page-head__actions, .k-grid-toolbar, .k-toolbar-items, .rpt-bar, .hr-scope, .quote-bar__btns, .k-form-buttons, .k-dialog-actions) > .k-button:not(.k-icon-button) {
    height: var(--btn-h); padding-block: 0; padding-inline: 15px; gap: 7px;
    font: 600 .875rem/1 var(--font-sans); letter-spacing: 0;
}
/* …and the controls beside them share that height: a 30px date picker or search box next to a 38px Show read as a step
   on ~140 grid toolbars and 38 report bars (review 2026-10-08). A multi-select grows with its chips, so it only gets the
   floor; the toolbar's own icon buttons (column layout, full screen) are squares of the same height. */
html :is(.rpt-bar, .hr-scope, .quote-bar--filters, .k-grid-toolbar, .page-head__actions) :is(.k-input, .k-picker):not(.k-multiselect) { height: var(--btn-h); }
html :is(.rpt-bar, .hr-scope, .quote-bar--filters, .k-grid-toolbar, .page-head__actions) .k-multiselect { min-height: var(--btn-h); }
html .k-grid-toolbar .k-button.k-icon-button { height: var(--btn-h); width: var(--btn-h); }
html .k-button.act .k-svg-icon, html .k-button.act .k-button-icon { width: 16px; height: 16px; }
html .k-button.act { transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s; }
html .k-button.act::before, html .k-button.act::after { display: none !important; }       /* the theme's flat overlays */
html .k-button.act:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* commit */
html .k-button.k-button-solid.k-button-primary {
    color: #fff; border-color: var(--midnight); background-color: var(--midnight);
    background-image: linear-gradient(180deg, var(--midnight-2), var(--midnight));
    box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 10px 22px -12px rgba(14,23,38,.7);
}
html .k-button.k-button-solid.k-button-primary:not(.k-icon-button) { padding-inline: 18px; }
html .k-button.k-button-solid.k-button-primary .k-svg-icon { color: var(--accent-bright); }
html .k-button.k-button-solid.k-button-primary:focus { box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 10px 22px -12px rgba(14,23,38,.7); }
html .k-button.k-button-solid.k-button-primary:hover, html .k-button.k-button-solid.k-button-primary.k-hover {
    color: #fff; border-color: var(--midnight-3); background-color: var(--midnight-3); background-image: none;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.09), 0 0 0 3px var(--accent-glow), 0 12px 24px -12px rgba(14,23,38,.75);
}
html .k-button.k-button-solid.k-button-primary:active, html .k-button.k-button-solid.k-button-primary.k-active {
    color: #fff; border-color: var(--midnight); background-color: var(--midnight); background-image: none;
}
html .k-button.k-button-solid.k-button-primary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* secondary */
html .k-button.k-button-outline.k-button-primary { color: var(--text); background: var(--surface); border-color: var(--hairline); }
html .k-button.k-button-outline.k-button-primary:hover, html .k-button.k-button-outline.k-button-primary.k-hover {
    color: var(--text); background: var(--surface); border-color: var(--midnight-3); }
html .k-button.k-button-outline.k-button-primary:active, html .k-button.k-button-outline.k-button-primary.k-active {
    color: var(--text); background: var(--surface-2); border-color: var(--midnight-3); }
html .k-button.k-button-outline.k-button-primary:focus { box-shadow: none; }
html .k-button.k-button-outline.k-button-primary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
html .k-button.k-button-flat.k-button-primary { color: var(--text); }
/* Telerik's plain solid and plain outline buttons (no theme colour: a dialog's Cancel, a filter menu's Clear, a page's
   "Import calendar", "PO from Request", "Distribute cost") read as the secondary tier too — white and a hairline instead
   of the theme's grey slab, or its outline that turned into a dark fill on hover. Icon-only ones (a picker's arrow, a
   spinner) are not touched, nor a SELECTED one: a segmented control's chosen segment keeps the theme's selected look
   (CONVENTIONS §3a recommends segmented tabs).
   "Plain" = no theme colour class. Telerik 14 writes NO class for its defaults: a <TelerikButton> with neither ThemeColor
   nor FillMode renders only `.k-button`, FillMode="outline" alone `.k-button.k-button-outline` — the theme styles those
   bare classes as solid base / outline base, so the selectors name the colours a plain button does NOT have. */
html .k-button:not(.k-button-flat, .k-button-link, .k-button-clear):not(.k-button-primary, .k-button-error, .k-button-warning, .k-button-success, .k-button-info, .k-button-secondary, .k-button-tertiary, .k-button-dark, .k-button-light, .k-button-inverse):not(.k-icon-button):not(.k-selected) {
    color: var(--text); background: var(--surface); border-color: var(--hairline); }
html .k-button:not(.k-button-flat, .k-button-link, .k-button-clear):not(.k-button-primary, .k-button-error, .k-button-warning, .k-button-success, .k-button-info, .k-button-secondary, .k-button-tertiary, .k-button-dark, .k-button-light, .k-button-inverse):not(.k-icon-button):not(.k-selected):hover {
    color: var(--text); background: var(--surface); border-color: var(--midnight-3); }
html .k-button:not(.k-button-flat, .k-button-link, .k-button-clear):not(.k-button-primary, .k-button-error, .k-button-warning, .k-button-success, .k-button-info, .k-button-secondary, .k-button-tertiary, .k-button-dark, .k-button-light, .k-button-inverse):not(.k-icon-button):not(.k-selected):active {
    background: var(--surface-2); }
html .k-button.k-button-outline:not(.k-button-primary, .k-button-error, .k-button-warning):focus { box-shadow: none; }
/* A plain flat text button in one of the six homes (a bar, a toolbar, a footer, a list row, a form section) is the
   quiet tier: muted until touched. Scoped to the homes so Telerik's own flat buttons (the pager, a calendar's Today)
   keep their theme; an ActionButton (.act) already has its tier — a Delete must stay red under the pointer. */
html :is(.quote-bar, .quote-bar__btns, .page-head__actions, .k-grid-toolbar, .rpt-bar, .hr-scope, .k-form-buttons, .k-dialog-actions, .print-bar, .k-grid td, .quote-card, .setting-panel, .k-window-content) .k-button.k-button-flat:not(.k-button-primary, .k-button-error, .k-button-warning):not(.k-icon-button):not(.act) { color: var(--muted); }
html :is(.quote-bar, .quote-bar__btns, .page-head__actions, .k-grid-toolbar, .rpt-bar, .hr-scope, .k-form-buttons, .k-dialog-actions, .print-bar, .k-grid td, .quote-card, .setting-panel, .k-window-content) .k-button.k-button-flat:not(.k-button-primary, .k-button-error, .k-button-warning):not(.k-icon-button):not(.act):hover { color: var(--text); background: var(--surface-2) !important; }

/* tool — and anything placed in the bar's tools zone. Three classes + html: the theme's flat button sets its colour
   with `.k-button.k-button-flat.k-button-base` (0,3,0), so 0,2,1 lost to it. */
html .k-button.act.act--tool, html .quote-bar__tools .k-button.k-button { color: var(--muted); }
html .k-button.act.act--tool:not(.k-icon-button), html .quote-bar__tools .k-button.k-button:not(.k-icon-button) { padding-inline: 11px; }
html .k-button.act.act--tool:hover, html .quote-bar__tools .k-button.k-button:hover { color: var(--text); background: var(--surface-2) !important; }

/* quiet — and a list row's icon actions */
html .k-button.act.act--quiet, html .k-button.act.act--row { color: var(--muted); }
html .k-button.act.act--quiet:hover, html .k-button.act.act--row:hover { color: var(--text); background: var(--surface-2) !important; }
html .k-button.act.act--danger:hover { color: var(--danger); background: var(--danger-soft) !important; }

html .k-button.act.k-disabled, html .k-button.act:disabled { opacity: .5; box-shadow: none; }

/* a modal's footer ends on the right like every other home: quiet → secondary → the commit, last (tools on the left) */
.k-window .quote-bar__btns, .k-window .k-form > .k-form-buttons { justify-content: flex-end; }

/* a status shown where a button would be (CommitButton: "Awaiting approval") sits on the buttons' line */
.quote-bar__btns > .pill { align-self: center; justify-self: center; }

@media (prefers-reduced-motion: reduce) { html .k-button.act { transition: none; } }

/* Phone: a grid toolbar's tools (Refresh, Export) shorten to their icon — the label stays as the tooltip — so the
   toolbar's own search box is not squeezed to a sliver (Telerik 14 makes the toolbar a sideways scroller). */
@media (max-width: 640px) {
    html .k-grid-toolbar .k-button.act.act--tool { width: var(--btn-h); padding-inline: 0; }
    html .k-grid-toolbar .k-button.act.act--tool .k-button-text { display: none; }
}

@media (prefers-reduced-motion: reduce) { .page-eyebrow::before { transition: none; } }

/* The breadcrumb names the screen's group; the page's own eyebrow would say it twice. */
.page-eyebrow { display: none; }

/* The line-of-business carrier (MainLayout): passes the accent tokens down without a box of its own. */
.app-line { display: contents; }

/* ===== Journal control: impact confirmation, journal lines by account class, setup banner (2026-10-04) =====
   One idea carries it: every line of money is striped in its ACCOUNT CLASS colour (the --c-* tokens), so a user sees
   which side of the balance sheet an action moves before reading a single number. */
.jrn-tbl--class tbody tr td:first-child { box-shadow: inset 3px 0 0 var(--tone, transparent); }
.jrn-tbl--class .acc-asset,     .imp-tbl .acc-asset     { --tone: var(--c-asset); }
.jrn-tbl--class .acc-liability, .imp-tbl .acc-liability { --tone: var(--c-liability); }
.jrn-tbl--class .acc-equity,    .imp-tbl .acc-equity    { --tone: var(--c-equity); }
.jrn-tbl--class .acc-revenue,   .imp-tbl .acc-revenue   { --tone: var(--c-revenue); }
.jrn-tbl--class .acc-cogs,      .imp-tbl .acc-cogs      { --tone: var(--c-cogs); }
.jrn-tbl--class .acc-expense,   .imp-tbl .acc-expense   { --tone: var(--c-expense); }
.imp-tbl tbody tr td:first-child { box-shadow: inset 3px 0 0 var(--tone, transparent); }
.jrn-tbl--removed tbody td { color: var(--muted); text-decoration: line-through; text-decoration-color: rgba(179, 38, 30, .55); }
.jrn-edit td { vertical-align: middle; }
.jrn-default { margin-top: .8rem; }
.jrn-default summary { cursor: pointer; color: var(--muted); font-size: .85rem; }

.imp-sec { margin-top: 1rem; }
.imp-sec:first-child { margin-top: 0; }
.imp-sec__h { margin: 0 0 .1rem; font: 600 .9rem/1.3 var(--font-sans); color: var(--ink); }
.imp-gl { display: flex; align-items: baseline; gap: .55rem; margin-top: .45rem; }
.imp-block { border-radius: var(--radius-sm); padding: .7rem .9rem; font-size: .86rem; margin-bottom: .8rem; }
.imp-block ul { margin: .35rem 0 0 1.1rem; padding: 0; }
.imp-block--stop { background: #fbe9e7; color: #8c1d16; border: 1px solid #f2c3bd; }
.imp-neg td { background: #fdf1ef; }
.imp-in  { color: #2c7a4b; }
.imp-out { color: #b4532a; }
.imp-linked { list-style: none; margin: .3rem 0 0; padding: 0; }
.imp-linked li { display: flex; justify-content: space-between; gap: 1rem; padding: .32rem 0; border-bottom: 1px solid var(--border-soft); font-size: .85rem; }
.imp-linked__doc { color: var(--text); }
.imp-linked__chg { color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.imp-notes { margin: .8rem 0 0 1.1rem; padding: 0; color: var(--muted); font-size: .82rem; }
.imp-notes--warn { color: #8c1d16; }

.setup-banner--journal { align-items: flex-start; background: #fdf3f1; border-color: #f2c3bd; color: #6e1a14; }
.setup-banner--journal ul { margin: .3rem 0 0 1.1rem; padding: 0; font-size: .84rem; }
.setup-banner__where { font-weight: 600; }

/* .jas-cell is a <td> and must stay one: given `display: grid` it left the row, and the browser stacked a row's
   account cells in ONE column under the first header. The notes stack under the picker instead. */
.jas-cell { min-width: 230px; }
.jas-cell .muted-note { font-size: .76rem; }
.jas-bad, .jas-inherit { display: block; margin-top: .25rem; }
.jas-bad { color: #b3261e; font-size: .78rem; }
.jas-inherit { color: var(--muted); font-size: .76rem; font-style: italic; }
.audit-diff { width: 100%; border-collapse: collapse; font-size: .8rem; }
.audit-diff td { padding: .2rem .4rem; border-bottom: 1px solid var(--border-soft); vertical-align: top; }
.audit-diff .before { color: #b4532a; }
.audit-diff .after  { color: #2c7a4b; }
.audit-src--other { color: #b3261e; font-weight: 600; }
@media (max-width: 640px) {
    .imp-linked li { flex-direction: column; gap: .1rem; }
    .imp-linked__chg { text-align: left; }
}

/* ---- CRM: contacts ---- */
/* the contact list inside a master modal or a profile card: a quiet table, the row's own buttons at its right edge */
.contact-panel .jrn-tbl { min-width: 520px; }
.contact-panel .jrn-tbl td:last-child { white-space: nowrap; text-align: right; }
/* A grid host (the account profile's cards, the Customers form's columns) sizes its column to the widest content it
   holds, and a grid item's minimum width is that content's: the 520px table widened the whole page to ~590px on a
   phone instead of scrolling in its own box. Zero width + full min-width: the table no longer counts, the box still
   fills its column. */
.contact-panel .jrn-tbl-wrap { width: 0; min-width: 100%; }
.contact-panel__row--off td { color: var(--faint); }
/* Razor drops the whitespace between a name and the marks after it — the gap has to be stated */
.contact-panel .jrn-tbl .pill { margin-left: .4rem; }
/* the empty state sits where the table would, on the table's own top margin */
.contact-panel > .muted-note { margin: .6rem 0 0; }
.contact-panel__foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: .6rem; }
/* "Show inactive" keeps the right edge when Readonly leaves it alone in the foot */
.contact-panel__toggle { display: inline-flex; align-items: center; gap: .4rem; margin-left: auto; cursor: pointer; }
/* the add/edit window: the salutation is a short choice, the name gets the width */
.contact-dialog__who { grid-template-columns: 8.5rem minmax(0, 1fr); }
/* the picker's way out of an unknown name quotes what was typed — on a phone that can run to several lines,
   and a button centres its lines unless told otherwise */
.contact-picker__add { text-align: left; overflow-wrap: anywhere; }
/* Accounts list: a pending prospect's status and its "Possible duplicate" mark share a wrapping cell (td.wrap) —
   side by side when they fit, the mark on a second line when they do not */
.akm-g--crm-accounts td.wrap .pill { display: inline-block; margin: .1rem .4rem .1rem 0; }

/* ---- Settings consolidation (P2) ---- */
.jas-ro { display: flex; flex-wrap: wrap; gap: .25rem .75rem; align-items: baseline; }
/* The date line above a document's signatures (Print Settings › Documents). */
.print-doc .pd-sign__date { font-size: 8.5pt; margin-bottom: 4px; }
.print-doc .io-signs { display: flex; justify-content: space-between; gap: 2rem; }

/* Print Settings › Signatures and Documents: one document's boxes on the left, each a card of dated rows; on the right a
   strip of the sheet — the print's own classes and type, so the preview IS the signature row as it prints. That strip is
   the one thing on the tab that looks like paper; everything else stays plain form. */
.ps-sign { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 400px); gap: 1.4rem; align-items: start; }
.ps-doc-pick { max-width: 360px; margin-bottom: 1rem; }
.ps-slot { margin-bottom: 1rem; padding: 1rem 1.1rem; }
.ps-slot:last-child { margin-bottom: 0; }
.ps-slot__head { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.ps-slot__head .imp-sec__h { margin: 0 auto 0 0; }
.ps-slot__now td { background: var(--surface-2); }
.ps-slot__pill { margin-left: .4rem; }
.ps-slot__tbl td:nth-child(2) .ps-slot__pill { display: inline-block; margin: .15rem 0 0; }
.ps-slot__label { display: block; font-weight: 600; color: var(--text); }
.ps-slot__acts { white-space: nowrap; text-align: right; }
.ps-warn { color: var(--danger); font-size: .85em; }
.ps-hint { color: var(--muted); font-size: .85em; }
.ps-sign__proof > .imp-sec__h { margin-bottom: 0; }
.ps-sign__opts { padding-top: .5rem; margin-bottom: 1rem; }
.ps-sign__draft { padding-top: 0; }
.ps-sign__foot { margin: .7rem 0 0; font-size: .78rem; }
/* .print-doc is hidden on screen unless a page shows it */
.print-doc.ps-sign-preview { display: block; padding: 14px 16px 18px; background: #fff; border: 1px solid var(--border); border-radius: 3px;
    box-shadow: 0 1px 0 var(--border), 0 18px 30px -18px rgba(16,47,56,.35); overflow-x: auto; }
.ps-sign-preview__row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 14px 18px; }
.print-doc .ps-sign-preview__box { margin-top: 6px; width: auto; flex: 1 1 110px; min-width: 100px; max-width: 180px;
    display: flex; flex-direction: column; align-items: center; }
.print-doc .ps-sign-preview__box .pd-sign__slot { height: 52px; margin-top: 4px; width: 100%; }
.print-doc .ps-sign-preview__box .pd-sign__name { margin-top: 2px; min-width: 110px; max-width: 100%; overflow-wrap: anywhere; }
.print-doc .ps-sign-preview__box .ps-sign-preview__dotted { border-top: 0; font-weight: 400; }
.print-doc .ps-sign-preview__none { margin: 4px 0 0; font-style: italic; }
.ps-slot-win__grid .co-policy { padding-top: .4rem; }
/* the editor's strip of the sheet is pinned to the top of the window's scrolling body (its padding is --kendo-spacing-4) */
.ps-slot-win__proof { position: sticky; top: calc(-1 * var(--kendo-spacing-4, 1rem)); z-index: 3; margin: calc(-1 * var(--kendo-spacing-4, 1rem)) 0 0;
    padding: var(--kendo-spacing-4, 1rem) 0 .9rem; background: var(--surface); box-shadow: 0 1px 0 var(--border); }
.ps-slot-win__proofhead { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: .6rem; }
.ps-slot-win__proofhead .imp-sec__h { margin: 0; }
.ps-slot-win__draft { display: flex; align-items: center; gap: .5rem; font-size: .84rem; }
.ps-docs__place { display: flex; align-items: center; gap: .5rem; }
@media (max-width: 1100px) {
    .ps-sign { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
    /* a box's rows and the documents become one block per row: what and from when, then what it prints */
    .ps-slot, .ps-docs { padding: .9rem .8rem; }
    .ps-slot__tbl, .ps-docs__tbl { min-width: 0; }
    .ps-slot__tbl thead, .ps-docs__tbl thead { display: none; }
    .ps-slot__tbl tr, .ps-docs__tbl tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .2rem .6rem; padding: .6rem .4rem;
        border-bottom: 1px solid var(--border-soft); }
    .ps-slot__tbl td, .ps-docs__tbl td { display: block; padding: 0; border: 0; background: none; }
    .ps-slot__tbl td:nth-child(1) { font-weight: 600; }
    .ps-slot__tbl td:nth-child(2) { grid-column: 1; color: var(--muted); }
    .ps-slot__tbl td:nth-child(2) .ps-slot__pill { margin: 0 0 0 .4rem; }
    .ps-slot__tbl td:nth-child(3), .ps-docs__tbl td:nth-child(2), .ps-docs__tbl td:nth-child(3), .ps-docs__tbl td:nth-child(4) { grid-column: 1 / -1; }
    .ps-slot__tbl td:nth-child(4), .ps-docs__tbl td:nth-child(5) { grid-row: 1; grid-column: 2; }
    .ps-slot__now { background: var(--surface-2); }
    .ps-docs__tbl td > .ps-cell__label { display: block; margin-bottom: .15rem; }
    .ps-slot-win__proofhead { flex-wrap: wrap; }
    /* on a phone the window is the screen: the strip scrolls with the form instead of taking a third of it */
    .ps-slot-win__proof { position: static; margin: 0; padding: 0 0 .9rem; box-shadow: none; }
}

/* two-writer hint (ParallelRunHint.razor) */
.parallel-hint { font-size: .85rem; color: var(--muted, #6b7280); margin: -.25rem 0 .75rem; }
