/* ============================================================
   AKM ERP — Design system  ·  "Petrol & Brass ledger"
   Internal accounting/ERP for an oil & lubricant distributor.
   Direction: precise financial software. Petrol-ink chrome, a
   single brass accent, IBM Plex Sans for UI and IBM Plex Mono
   for the things accountants actually read — codes and figures.
   ============================================================ */

:root {
    /* Brand */
    --ink:        #102f38;   /* petrol — sidebar/chrome */
    --ink-deep:   #0b2228;
    --ink-line:   #1f4a54;
    --brass:      #b7842b;   /* the one accent */
    --brass-bright:#d29a35;
    --brass-soft: rgba(183, 132, 43, .12);

    /* Surfaces */
    --paper:      #ebe7dd;   /* content canvas (warm, a touch deeper so white cards float) */
    --surface:    #ffffff;
    --surface-2:  #faf9f5;
    --border:     #e6e3da;
    --border-soft:#eeece5;

    /* Text */
    --text:       #19211f;
    --muted:      #6c746f;
    --faint:      #99a09b;

    /* 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: 12px;
    --shadow: 0 1px 2px rgba(16,47,56,.06), 0 14px 34px -12px rgba(16,47,56,.16);

    /* Telerik / Kendo theme — bend it to the brand */
    --kendo-color-primary: var(--brass);
    --kendo-color-primary-hover: var(--brass-bright);
    --kendo-color-primary-active: #9e7124;
    --kendo-font-family: var(--font-sans);
    --kendo-border-radius-md: 8px;
}

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 .64rem/1 var(--font-sans);
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--brass);
    display: inline-flex; align-items: center; gap: .45rem;
}
.page-eyebrow::before {
    content: ""; width: 1.2rem; height: 2px; background: var(--brass); display: inline-block;
}
.page-head h1 {
    font: 700 1.35rem/1.1 var(--font-sans);
    letter-spacing: -.018em;
    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: .6rem; 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: .82rem; color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.num  { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

.tag {
    display: inline-flex; align-items: center; gap: .4rem;
    font: 600 .68rem/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 */
.pill { font: 600 .68rem/1 var(--font-sans); padding: .22rem .5rem; border-radius: 999px; }
/* 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; }
.lnk { color: var(--brass); cursor: pointer; font-weight: 600; text-decoration: none; }
.lnk:hover { text-decoration: underline; }

/* 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 .72rem/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: #f2f0e8; }
.k-grid .k-grid-header { border-bottom: 1.5px solid #e0dccf; }
.k-grid .k-grid-header .k-column-title {
    font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
    font-size: .67rem; 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.gridCellTitles. */
.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 { display: inline-flex; align-items: center; gap: .45rem; }
.grid-flt__lbl { font: 600 .68rem/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; }

/* A CRUD modal must never be wider than the screen. */
.k-window { max-width: 96vw; }

@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, neutralise JS centring, scroll long forms inside. */
    .k-window {
        width: 94vw !important; max-width: 94vw !important;
        left: 3vw !important; top: 4vh !important; max-height: 90vh !important;
        transform: none !important;
    }
    .k-window-content { max-height: 74vh; overflow-y: auto; }
    .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; }
}

/* ===== 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; }
}
/* print-color-adjust: force the browser to actually print background fills (header/zebra/grand-total) */
.print-doc { color: #14181a; 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 #102f38; }
.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: #102f38; }
.print-doc .pd-title { font-weight: 800; font-size: 15pt; text-align: center; letter-spacing: .06em; color: #102f38; }
.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: #102f38; }
/* 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: #3a4348; 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: #3a4348; }
.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 #102f38; }
.print-doc .pd-items thead th { background: #102f38; 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 #d9d4c7; vertical-align: top; }
.print-doc .pd-items tbody tr:nth-child(even) td { background: #f6f5f1; }
.print-doc .pd-items td.r { text-align: right; white-space: nowrap; }
/* 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 #cfcabb; }
.print-doc .pd-totals td { padding: 3px 10px; border-bottom: 1px solid #e8e4d8; }
.print-doc .pd-totals tr:last-child td { border-bottom: 0; }
.print-doc .pd-totals td:first-child { font-weight: 700; color: #3a4348; }
.print-doc .pd-totals td.r { text-align: right; white-space: nowrap; }
.print-doc .pd-totals .pd-grand td { background: #102f38; color: #fff; font-weight: 800; font-size: 10pt; padding: 5px 10px; }
.print-doc .pd-totals .pd-grand td:first-child { color: #e7c573; }
/* 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: #102f38; }
/* 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 #999; padding-top: 4px; display: inline-block; }
.print-doc .pd-foot { text-align: center; font-size: 8pt; margin-top: 42px; color: #444; border-top: 1px solid #d9d4c7; padding-top: 8px; }

/* 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 #999; }
.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 #333;
    padding: 8px 10px; margin-bottom: 12px; }
.print-doc .pd-poaddr { border-left: 1px solid #333; 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 #333; margin-top: 6px; gap: 0; }
.print-doc .pd-signrow--boxed .pd-signcol { border-right: 1px solid #333; 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; }
.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 #102f38; }
.print-doc .pd-head-doc .pd-logo { height: 54px; }
.print-doc .pd-head-doc .pd-title { flex: 1; }
.print-doc .pd-doc__co { font-size: 8.5pt; color: #3a4348; line-height: 1.45; }
.print-doc .pd-doc__co b { color: #102f38; 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: #3a4348; }
.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 #333; }
.print-doc .do-items thead th { background: #fff; color: #14181a; border: 1px solid #333; }
.print-doc .do-items tbody td { border: 1px solid #333; }
.print-doc .do-items tbody tr:nth-child(even) td { background: #fff; }
/* 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: #102f38; letter-spacing: .02em; }
.print-doc .pd-co__line { font-size: 8.5pt; color: #3a4348; margin-top: 2px; }
.print-doc .pd-co__line b { color: #102f38; 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: #3a4348; }
.print-doc .pd-bill__cust { font-weight: 800; font-size: 11pt; margin-top: 8px; color: #102f38; }
.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: #3a4348; }

/* ---- 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 #cfcabb; 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: #3a4348; }
.print-doc.inv-print .pd-sign--inv { margin: 18px 0 0 auto; width: 230px; text-align: center; }

/* ---- 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; border-bottom: 2px solid #102f38; }
.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 clock row, the tick boxes) are deliberately empty, so they need visible rules
   or the printed sheet gives nothing to write on. */
.print-doc.wo-print .pd-co__name { font-size: 11pt; }
.print-doc.wo-print .wo-band { display: flex; border: 1px solid #102f38; margin-top: 10px; }
.print-doc.wo-print .wo-band__to { flex: 1; padding: 6px 8px; border-right: 1px solid #102f38; font-size: 9pt; }
.print-doc.wo-print .wo-band__title { flex: 1; padding: 6px 8px; text-align: center; font-size: 9pt; }
.print-doc.wo-print .wo-band__hd { font-weight: 800; font-size: 12pt; color: #102f38; }
.print-doc.wo-print .wo-lead { font-size: 9pt; margin: 10px 0 4px; font-weight: 600; color: #102f38; }
.print-doc.wo-print .wo-desc { font-size: 9pt; margin: 0 0 6px; white-space: pre-line; }
.print-doc.wo-print .wo-grid { width: 100%; border-collapse: collapse; font-size: 9pt; }
.print-doc.wo-print .wo-grid td { border: 1px solid #102f38; padding: 3px 6px; }
.print-doc.wo-print .wo-grid__lbl { width: 15%; font-weight: 600; color: #3a4348; }
.print-doc.wo-print .wo-items { margin-bottom: 4px; }
.print-doc.wo-print .wo-items__empty { text-align: center; color: #7a848a; }
.print-doc.wo-print .wo-time { width: 60%; border-collapse: collapse; font-size: 9pt; margin-top: 10px; }
.print-doc.wo-print .wo-time th, .print-doc.wo-print .wo-time td { border: 1px solid #102f38; padding: 4px 8px; text-align: center; }
.print-doc.wo-print .wo-checks { font-size: 9pt; line-height: 1.9; }
.print-doc.wo-print .wo-box { display: inline-block; width: 11px; height: 11px; border: 1px solid #102f38; margin: 0 4px 0 12px; vertical-align: -1px; }
.print-doc.wo-print .wo-checks div > .wo-box:first-child { margin-left: 0; }
.print-doc.wo-print .pd-sign { margin-top: 26px; }
.print-doc.wo-print .wo-sign__hint { font-size: 8pt; color: #7a848a; margin-top: 2px; }

/* ---- 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: #3a4348; }
.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 #102f38; 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: #102f38;
    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: #6b7378; 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 #102f38; }
.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: #444; }
.print-doc.slip-print .slip-note b { color: #102f38; }
.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 #102f38; 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: #3a4348; }
.print-doc.fs-print .fs-head td { padding-top: 10px; font-weight: 800; color: #102f38; text-transform: uppercase; }
.print-doc.fs-print .fs-total td { font-weight: 700; border-top: 1px solid #102f38; }

/* ---- 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 #999; 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 .68rem/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: .68rem; 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 .72rem/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; }
.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; }
.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; }

/* line items */
.quote-lines { border-collapse: collapse; table-layout: fixed; width: 100%; }
.quote-lines thead th { font: 600 .62rem/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); }
.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-end; gap: .8rem; margin-bottom: .8rem; }
.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__head label, .wo-parent__item label { display: block; font-size: .72rem; 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-actions { display: flex; gap: .6rem; margin-top: 1.15rem; flex-wrap: wrap; }
.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; }

/* sticky action bar */
.quote-bar { position: sticky; bottom: 1rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    background: rgba(255,255,255,.92); backdrop-filter: blur(8px); border: 1px solid var(--border); border-radius: var(--radius);
    padding: .8rem 1.2rem; box-shadow: 0 8px 24px -10px rgba(16,47,56,.28); }
.quote-bar__hint { color: var(--muted); font-size: .82rem; }
.quote-bar__left { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.quote-bar__btns { display: flex; gap: .5rem; }

/* 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; }
.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 { padding-left: .9rem; }
.quote-lines thead th:last-child, .quote-lines tbody 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; }
.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 .72rem/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: .72rem; 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; }
    .quote-bar { flex-direction: column; align-items: stretch; }
    .quote-bar__hint { order: 2; text-align: center; }
    .quote-bar__btns { justify-content: stretch; }
    .quote-bar__btns .k-button { flex: 1; }
}

/* 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 .66rem/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 .68rem/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: .74rem; 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: .7rem; 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) ─────────────────────────────
   Page-specific names (dash-*) so nothing collides with the Home-tile classes. */

/* Target trio — the legacy revenue-vs-target progress cards (the page's signature). */
.dash-targets { display:grid; grid-template-columns:1fr; gap:12px; margin:0 0 12px; }
@media (min-width:760px) { .dash-targets { grid-template-columns:repeat(3,1fr); } }
.dash-target { background:var(--surface); border:1px solid var(--border); border-radius:10px; padding:12px 14px; }
.dash-target__row { display:flex; justify-content:space-between; align-items:baseline; gap:.5rem; }
.dash-target__label { font:600 .68rem/1 var(--font-sans); letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
.dash-target__pct { font:700 .78rem/1 var(--font-mono); }
.dash-target__value { font-size:1.3rem; font-weight:700; font-variant-numeric:tabular-nums; margin:.2rem 0 .35rem; }
.dash-target__meta { display:flex; justify-content:space-between; font-size:.72rem; color:var(--muted); font-variant-numeric:tabular-nums; }
.dash-bar { height:8px; border-radius:999px; background:var(--surface-2); border:1px solid var(--border-soft); overflow:hidden; margin-top:.4rem; }
.dash-bar > span { display:block; height:100%; border-radius:999px; }

/* KPI tiles — real anchors (keyboard + middle-click work for free).
   Fixed column counts per breakpoint, matched to the tile count (6 on Dashboard, 8 on Purchase via --4),
   so every row is always FULL — auto-fit left ragged last rows. */
.dash-kpis { display:grid; grid-template-columns:repeat(2,1fr); gap:12px; margin:0 0 12px; }
@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 { display:block; background:var(--surface); border:1px solid var(--border); border-radius:10px;
    padding:12px 14px 9px; color:inherit; text-decoration:none; transition:box-shadow .15s, border-color .15s; }
.dash-kpi:hover, .dash-kpi:focus-visible { box-shadow:0 2px 10px rgba(0,0,0,.07); border-color:var(--brass); outline:none; }
.dash-kpi__label { font-size:.68rem; letter-spacing:.08em; text-transform:uppercase; color:var(--muted); }
.dash-kpi__value { font-size:1.4rem; font-weight:700; font-variant-numeric:tabular-nums; margin:.15rem 0 .1rem; }
.dash-kpi__value.neg, .dash-kpi--alert .dash-kpi__value { color:#d03b3b; }
.dash-kpi__sub { font-size:.74rem; color:var(--muted); font-variant-numeric:tabular-nums; }
.dash-kpi__spark { display:block; width:100%; height:30px; margin-top:2px; }

.dash-chips { display:flex; flex-wrap:wrap; gap:8px; margin:0 0 16px; }
.dash-chips .pill { cursor:pointer; }

.dash-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(380px,1fr)); gap:14px; grid-auto-flow:dense; }
.dash-card { background:var(--surface); border:1px solid var(--border); border-radius:10px; padding:14px 16px; min-width:0; }
.dash-card--wide { grid-column:1/-1; }

/* 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 (max-width: 640.98px) {
    .userchip__name { display: none; }
    /* 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 .68rem/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 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. */
.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: .58rem .75rem;
    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 .62rem/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 .68rem/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; }
