/* =========================================================================
   NuWayMind — Source to Pay
   "Operational ledger" design system · slate + burnt-orange brand
   ========================================================================= */

:root {
    /* ---------- accessibility pass, §16 / NAV-011 (r621) ----------
     *
     * TWO SEPARATE PROBLEMS, both found by measuring rather than by looking.
     *
     * 1. --accent was never defined. Every rule the navigation shell added wrote var(--accent, #e8792a) and
     *    got its own fallback, while pre-existing rules wrote var(--orange, #FF8C1F) and got a DIFFERENT
     *    orange. One stylesheet, two brand colours, neither declared. Both now come from here.
     *
     * 2. --ok, --bad and --warn are used as TEXT on this light background and measured 1.47, 2.34 and 1.41
     *    against it. WCAG 2.2 AA wants 4.5. A status that says "overdue" in a red nobody can read is a
     *    status nobody reads — and these are the three colours the application uses to say something is
     *    wrong. Darkened to 5.53, 4.59 and 5.02; the hue is unchanged, so nothing that was green is now
     *    another colour.
     *
     * --accent-strong exists because #E8792A is 2.47 against this background: correct as a FILL behind dark
     * ink (5.87), wrong as small text. Anything that writes the accent as text uses the strong one. */
    --accent: #E8792A;          /* fills, active states, the dominant action */
    --accent-strong: #A8511A;   /* the same orange as TEXT: 4.61 on this background */
    --accent-ink: #211633;      /* what goes ON the accent: 5.87 */
    --orange: #E8792A;          /* was falling back to #FF8C1F in existing rules */

    /* Surfaces */
    --bg-app: #EEF1F4;
    --bg-sidebar: #000000;
    --bg-sidebar-hover: #1A1A1A;
    --bg-card: #FFFFFF;
    --bg-subtle: #F8FAFC;
    /* r658: the top menu (appbar) and the scene surface share one colour so the page reads as a single
       white surface, per the ask. Both are variables so a user preference can change the top-menu colour
       (and, if wanted, the scene) independently; by default they are identical white. */
    --bg-topmenu: #FFFFFF;
    --bg-scene: #FFFFFF;

    /* Ink */
    --text: #0F172A;
    --text-muted: #5A6675;
    --text-on-dark: #C4CAD4;
    --text-on-dark-strong: #FFFFFF;

    /* Brand — burnt orange for interactive surfaces (AA with white),
       marigold for the logo / live accents */
    --primary: #FF8C1F;
    --primary-hover: #F07A0A;
    --rail-w: 248px;
    --primary-soft: #FFEAD3;
    /* r1036 — the SELECTED-ROW tint, as a token. It was #FFF2E6 written out in four places, so a theme
       could not move it and the KPI colours could not either \u2014 and applying the supplier list's look
       across the estate would have spread a literal to every table. **A colour written as a number is a
       colour no theme can reach.** */
    --row-selected: #FFF2E6;
    --primary-ink: #6B3A05;
    --btn-bg: #FF8C1F;
    --btn-bg-hover: #F07A0A;
    --btn-text: #FFFFFF;
    --brand-orange: #FF8C1F;

    /* Lines */
    --line: #E2E8F0;
    --line-strong: #CBD5E1;

    /* Status */
    /* Darkened for WCAG 2.2 AA (§16). #15803D gave 4.24:1 on the application background — below the 4.5
     needed for normal text, and it is used as text in eleven places. #166534 gives 6.03. */
  --ok: #166534;        --ok-bg: #DCFCE7;
    /* Same: #B45309 was 4.25:1, used as text in four places. #92400E gives 6.00. */
  --warn: #92400E;      --warn-bg: #FEF3C7;
    /* r902 — the tokens the supplier board was using literal hex for.
     *
     * I replaced six hard-coded colours with token names and then checked whether the tokens existed.
     * **Four did not**, and shipping that would have given the KPI cards transparent backgrounds and
     * inherited text — a card whose colour silently falls back is worse than one that was never themed,
     * because nothing looks broken enough to report.
     *
     * Values carried over from the literals they replace, so the board looks identical today and is
     * themeable tomorrow. */
    --good: #047857;      --good-bg: #ECFDF5;
    --bad-bg: #FEE2E2;
    --accent-soft: var(--row-selected);
    --bad: #B91C1C;       --bad-bg: #FEE2E2;
    --neutral: #475569;   --neutral-bg: #E8EDF3;   /* r1607 — the neutral pill's grey, 20% lighter (was #E2E8F0) */
    --info: #1D4ED8;      --info-bg: #DBEAFE;

    /* Shape */
    --radius: 6px;
    /* r801 — ONE width for every centred pop-up.
     *
     * The base modal was 760px and the confirm box 460px, so two windows opening in the same place were
     * different sizes — and a user who opens several in a row sees the page jump. The width of a dialog
     * is a property of the ESTATE, not of the dialog: what it contains decides its height, never its
     * width.
     *
     * Windows that are deliberately different keep their own rule and say why (is-wide, is-docform). */
    --statusbar-h: 26px;
    --modal-w: 760px;
    --modal-w-narrow: 460px;
    --radius-sm: 4px;
    /* r1605 — the height of a dropdown, single or multi: one token, so the two cannot drift apart. The
       searchable combo had no height of its own (it fell out of its input's padding) while the chip combo
       pinned 38px, so they only happened to look alike. */
    --control-h: 36px;   /* r1606 — one height for every single-line control */
    --control-h-sm: 32px;
    --control-h-xs: 28px;
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
    --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.18);

    /* Type */
    --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-mono: "JetBrains Mono", "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    font-family: var(--font-ui);
    background: var(--bg-app);
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }

button { font-family: inherit; }

[hidden] { display: none !important; }

/* Monospace for every document number and money amount — the ledger signature */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num  { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.docno { font-family: var(--font-mono); font-weight: 500; letter-spacing: -0.02em; }

/* =========================================================================
   Sign-in screen
   ========================================================================= */
.auth-screen {
    position: fixed; inset: 0;
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    background:
        radial-gradient(1100px 520px at 14% -8%, #21323F 0%, rgba(33,50,63,0) 60%),
        linear-gradient(160deg, #16222B 0%, #0E1820 100%);
    z-index: 100;
}
.auth-card {
    width: 100%;
    max-width: 396px;
    background: var(--bg-card);
    border-radius: 10px;
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    animation: pop 0.18s ease-out;
}
.auth-top {
    padding: 30px 32px 24px;
    text-align: center;
    border-bottom: 1px solid var(--line);
    background: var(--bg-subtle);
}
.auth-logo { width: 224px; max-width: 80%; height: auto; display: block; margin: 0 auto; }
.auth-tag {
    margin-top: 14px;
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.14em;
    color: var(--text-muted); font-weight: 600;
}
.auth-body { padding: 26px 32px 30px; }
.auth-body h1 { font-size: 18px; margin-bottom: 4px; }
.auth-body .lede { color: var(--text-muted); font-size: 13px; margin: 0 0 20px; }
.auth-form { display: flex; flex-direction: column; gap: 14px; }
.auth-error {
    background: var(--bad-bg); color: var(--bad);
    border: 1px solid #FCA5A5; border-radius: var(--radius-sm);
    padding: 9px 12px; font-size: 12.5px; font-weight: 500;
}
.auth-form .btn-primary { width: 100%; justify-content: center; padding: 11px; margin-top: 4px; }
.auth-hint {
    margin-top: 20px; padding-top: 16px; border-top: 1px dashed var(--line-strong);
    font-size: 12px; color: var(--text-muted); line-height: 1.7;
}
.auth-hint code {
    font-family: var(--font-mono); font-size: 11.5px;
    background: var(--bg-subtle); border: 1px solid var(--line);
    border-radius: 3px; padding: 1px 5px; color: var(--primary-ink);
}

/* =========================================================================
   Shell
   ========================================================================= */
.app-shell {
    display: grid;
    /* r1050 — the rail's width as a TOKEN, so a full-screen overlay can start where the canvas starts.
       It was a literal here and nowhere else, so every rule that needed to clear the rail guessed \u2014 and
       two of them guessed `left: 0` and covered it. **A dimension one rule owns and others must respect
       has to be readable by them.** */
    grid-template-columns: var(--rail-w) 1fr;
    min-height: 100vh;
}

.sidebar {
    background: var(--bg-sidebar);
    color: var(--text-on-dark);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    padding: 0 14px 20px;
}

/* r666: the brand band matches the appbar's height (56px) and sits at the very top of the sidebar, so the
   SELYVO logo lines up on the same Y as the appbar buttons in the main column. The logo is sized to the
   height of those buttons (38px) with proportional width. */
.brand {
    display: flex;
    align-items: center;
    height: 56px; flex: 0 0 56px;
    padding: 0 6px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.10);
    margin-bottom: 12px;
}
.brand-logo { height: 38px; width: auto; max-width: 100%; display: block; }

.nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none; }
/* Keep the left menu scrollable when it runs out of height, but hide the scrollbar
   (Chrome/Edge/Safari use ::-webkit-scrollbar; Firefox/legacy Edge handled above). */
.nav::-webkit-scrollbar { width: 0; height: 0; display: none; }
.nav-group {
    color: #8A93A3;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 16px 10px 6px;
}
/* Primary navigation areas: the seven top-level destinations of the redesigned IA */
.nav-area {
    color: var(--text-on-dark-strong);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.10em;
    margin-top: 8px;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    background: transparent;
    border: 0;
    color: var(--text-on-dark);
    padding: 9px 10px;
    border-radius: var(--radius-sm);
    font-size: 13.5px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.nav-item:hover { background: var(--bg-sidebar-hover); color: var(--text-on-dark-strong); }
.nav-item.is-active { background: var(--bg-sidebar-hover); color: var(--text-on-dark-strong); font-weight: 600; }
.nav-dot {
    width: 6px; height: 6px; border-radius: 50%;
    background: #5B6675; flex: none;
    transition: background 0.12s ease;
}
.nav-item.is-active .nav-dot { background: var(--brand-orange); }
.nav-item:hover .nav-dot { background: #8A93A3; }
.nav-badge {
    margin-left: auto;
    min-width: 20px; height: 20px; padding: 0 6px;
    border-radius: 999px;
    background: var(--brand-orange); color: #3A2206;
    font-family: var(--font-mono); font-size: 11px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
}
.nav-badge[hidden] { display: none !important; }

/* --- Phase 0: seven-area progressive-disclosure sidebar ---
   Each primary area collapses to its header; only the active area's modules are
   shown (spec: "only one primary area is selected at a time"). People folds into
   Operations; Account and Administration sit below as utility areas. */
.nav-area { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; user-select: none; }
.nav-area::after {
    content: ""; width: 7px; height: 7px; flex: none; margin-right: 2px;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
    transform: rotate(-45deg); transition: transform 0.15s ease; opacity: 0.6;
}
.nav-area.is-expanded::after { transform: rotate(45deg); opacity: 0.9; }
.nav-area:hover { color: var(--text-on-dark-strong); }
.nav-area.is-expanded { color: var(--text-on-dark-strong); }
.nav-item.nav-collapsed { display: none !important; }
.nav-area.nav-area-util { margin-top: 14px; border-top-color: rgba(255, 255, 255, 0.16); }

/* --- Phase 0: unified My Work inbox --- */
.mw-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; border-bottom: 1px solid var(--line); }
.mw-tabs { display: flex; gap: 2px; flex-wrap: wrap; }
.mw-tab {
    position: relative; background: transparent; border: 0; cursor: pointer;
    padding: 10px 14px; margin-bottom: -1px;
    font-size: 13.5px; font-weight: 600; color: var(--text-muted);
    border-bottom: 2px solid transparent; border-radius: 6px 6px 0 0;
    display: inline-flex; align-items: center; gap: 6px;
}
.mw-tab:hover { color: var(--text); background: var(--bg-subtle); }
.mw-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }
.mw-tab.is-planned { color: var(--text-muted); opacity: 0.75; font-weight: 500; }
.mw-soon {
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-muted); background: var(--bg-subtle);
    border: 1px solid var(--line); border-radius: 999px; padding: 1px 6px;
}
.mw-sla { margin-left: auto; }
.mw-body { min-height: 120px; }

/* Role layout chip on Home (role-based defaults) */
.dh-role {
    display: inline-block; margin-top: 8px;
    font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
    color: var(--primary); background: var(--primary-soft);
    border: 1px solid var(--line); border-radius: 999px; padding: 2px 10px;
}
/* Data-freshness stamp + customize reorder list (Home personalisation) */
.dh-fresh { font-size: 11px; color: var(--text-muted); margin-left: 6px; }
.dh-ord-head { font-size: 13px; font-weight: 700; color: var(--text); margin: 2px 0 8px; display: flex; align-items: baseline; gap: 8px; }
.dh-ord-hint { font-size: 11px; font-weight: 400; color: var(--text-muted); }
.dh-ord-group { font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); margin: 10px 0 4px; }
.dh-ord-none { font-size: 12.5px; color: var(--text-muted); padding: 2px 0 4px; }
.dh-ord-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); margin-bottom: 4px; background: var(--bg-card); }
.dh-ord-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.dh-ord-name { font-size: 13px; font-weight: 600; color: var(--text); }
.dh-ord-cat { font-size: 11px; color: var(--text-muted); }
.dh-ord-btns { margin-left: auto; display: inline-flex; gap: 2px; }
.dh-ord-btn { width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; color: var(--text-muted); font-size: 13px; }
.dh-ord-btn:hover:not([disabled]) { color: var(--text); border-color: var(--line-strong); background: var(--bg-subtle); }
.dh-ord-btn[disabled] { opacity: 0.35; cursor: default; }
.dh-ord-btn.dh-ord-rm:hover { color: #b91c1c; border-color: #f0b4b4; }
.dh-lib-sep { height: 1px; background: var(--line); margin: 14px 0; }

/* Enterprise Cases */
.case-link { display: flex; align-items: center; gap: 8px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.case-link:last-child { border-bottom: 0; }
.case-link .case-x { margin-left: auto; width: 24px; height: 24px; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: var(--text-muted); cursor: pointer; }
.case-link .case-x:hover { color: #b91c1c; border-color: #f0b4b4; }
.case-dec { padding: 8px 0; border-bottom: 1px solid var(--line); }
.case-dec:last-child { border-bottom: 0; }
.case-closure { margin-top: 12px; padding: 10px 12px; background: var(--bg-subtle); border-radius: var(--radius-sm); }
.case-closure .field-label { display: block; margin-bottom: 2px; }

/* Signed-in account block */
.account {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 8px;
    margin-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.avatar {
    width: 34px; height: 34px; border-radius: 50%;
    flex: none;
    display: grid; place-items: center;
    background: var(--brand-orange); color: #3A2206;
    font-weight: 700; font-size: 13px;
    font-family: var(--font-mono);
}
.account-info { min-width: 0; flex: 1; line-height: 1.25; }
.account-name {
    color: var(--text-on-dark-strong); font-size: 13px; font-weight: 600;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.account-role {
    font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.06em;
    color: #8A93A3; font-weight: 600;
}
.logout-btn, .prefs-btn {
    border: 0; background: transparent; cursor: pointer;
    color: #8A93A3; padding: 6px; border-radius: var(--radius-sm);
    display: grid; place-items: center;
}
.logout-btn:hover, .prefs-btn:hover { background: var(--bg-sidebar-hover); color: var(--text-on-dark-strong); }
.logout-btn svg, .prefs-btn svg { width: 16px; height: 16px; display: block; }

.sidebar-foot {
    padding: 12px 10px 4px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    font-family: var(--font-mono);
    font-size: 11px;
    color: #5B7283;
    display: flex; align-items: center; gap: 8px;
}
.dot-live { width: 7px; height: 7px; border-radius: 50%; background: #22C55E; box-shadow: 0 0 0 3px rgba(34,197,94,0.18); flex: none; }

/* r655: the shell fills the viewport and does not itself scroll. The appbar and any workspace chrome
   are fixed height; the register inside a scene is the one thing that scrolls, and it does so without a
   visible scrollbar. A page that scrolls as a whole hides the decision bar below the fold, which is the
   one control a lifecycle screen exists to present. */
/* r1110 — the canvas ends where the fixed status bar begins. The bar is position:fixed over the
   bottom 26px, so a 100vh .main put every page's last line UNDER it — and the paddings added to
   compensate (r803/r1107) then pushed the board's list up, opening the gap the product owner saw.
   Shrinking .main to clear the bar makes the scene, the plain page and the scroll view all bottom
   out at the SAME line full screen uses (bottom: --statusbar-h). One reserve, at the source. */
.main { display: flex; flex-direction: column; min-width: 0;
  height: calc(100vh - var(--statusbar-h)); overflow: hidden; }
body:not(.is-authed) .main { height: 100vh; }   /* no status bar until signed in */
.view { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.view > * { min-height: 0; }

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 22px 32px;
    background: var(--bg-app);
    border-bottom: 1px solid var(--line);
    position: sticky; top: 0; z-index: 5;
}
.topbar-titles h1 { font-size: 21px; }
.topbar-titles p { margin: 2px 0 0; color: var(--text-muted); font-size: 13px; }
.topbar-actions { display: flex; gap: 10px; }

/* Ordinary (non-scene) pages keep their padding and scroll within .view. */
/* r803: the bottom padding must clear the fixed status bar, or the last rows of every scrolling view
   sit underneath it and cannot be reached. 56px was chosen before the status bar existed. */
.view.view--scroll { overflow: auto; padding: 6px 20px 24px; }   /* r1110 — bar cleared by .main */
/* r1037 — every page starts where the SUPPLIER page starts, on the same surface.
 *
 * A scene had `--bg-scene` (white) and an inset of 6/20; every other page had the app's grey showing
 * through and an inset of 28/32. So the reader crossed from Suppliers to any other register and the
 * content jumped 12px right, 22px down, and the background changed colour \u2014 three differences at once,
 * none of them meaning anything. **A layout that changes between pages is read as a different product,
 * not a different page.**
 *
 * The scene keeps its own rule below: it is full-height and does not scroll, which is a BEHAVIOUR the
 * ordinary pages must not inherit \u2014 only the surface and the inset are shared. */
.view:not(.view--scene):not(.view--scroll) {
    padding: 6px 20px 24px;   /* r1110 — the status bar is cleared by .main, so no +bar reserve here */
    overflow: auto;
    background: var(--bg-scene);
}
.view.view--scroll { background: var(--bg-scene); }

/* =========================================================================
   Buttons
   ========================================================================= */
.btn {
    min-height: var(--control-h);   /* r1606 — a button stands the same height as the field beside it */
    display: inline-flex;
    align-items: center;
    /* r1220 — a button CENTRES its label.
     *
     * `.btn` is a flex container and named no justify-content, so it inherited flex-start: harmless
     * while a button was only as wide as its text, wrong the moment one is stretched (the unsaved-
     * changes dialog gives its three buttons equal widths), where every label sat hard against the
     * left edge. **A rule that is only correct at one width is a rule that has not been written yet.** */
    justify-content: center;
    text-align: center;
    gap: 7px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 8px 14px;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
    white-space: nowrap;
    /* r1200 — a bare .btn (no variant class) rendered with NO background and a transparent border:
       plain text pretending to be a button, reported from the record detail's Edit. The spec's
       secondary button (§4.3) is the base every variant overrides: card surface, 1px border, text
       colour. Fixing the class heals every bare site at once rather than the one that was seen. */
    background: var(--bg-card);
    border-color: var(--line-strong);
    color: var(--text);
}
.btn:hover { background: var(--bg-subtle); }
.btn-primary { background: var(--btn-bg); color: var(--btn-text); font-weight: 600; }
/* r1218 — a glyph INSIDE a labelled button (the action-run mark on every Run control). The base
   .btn is already inline-flex with a gap, so the mark only needs its box: without this it inherits
   the svg's own 24px and pushes the label off the button's baseline. */
.btn > svg { width: 15px; height: 15px; flex: 0 0 auto; }
.btn.btn-icon > svg { width: 16px; height: 16px; }
.btn-primary:hover { background: var(--btn-bg-hover); }
/* r1198 — the small square action buttons (the "+" / edit / view / eye family, rendered as
   .btn-ghost.btn-icon across every register and board) carry the colour scheme's BUTTON BACKGROUND
   (--btn-bg / --btn-text), like .btn-primary; hover follows the same --btn-bg-hover convention.
   Danger-ghost icons (delete) deliberately keep their red family. */
.btn-ghost.btn-icon { background: var(--btn-bg); border-color: var(--btn-bg); color: var(--btn-text); }
.btn-ghost.btn-icon:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); color: var(--btn-text); }
.btn-ghost { background: var(--bg-card); color: var(--text); border-color: var(--line-strong); }
.btn-ghost:hover { background: var(--bg-subtle); border-color: var(--text-muted); }
.btn-subtle { background: transparent; color: var(--text-muted); border-color: transparent; padding: 6px 8px; }
.btn-subtle:hover { color: var(--text); background: var(--bg-subtle); }
.btn-danger-ghost { background: var(--bg-card); color: var(--bad); border-color: var(--line-strong); }
.btn-danger-ghost:hover { background: var(--bad-bg); border-color: var(--bad); }
.btn-sm { padding: 5px 9px; font-size: 12px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.icon-btn {
    border: 0; background: transparent; cursor: pointer;
    font-size: 22px; line-height: 1; color: var(--text-muted);
    width: 32px; height: 32px; border-radius: var(--radius-sm);
}
.icon-btn:hover { background: var(--bg-subtle); color: var(--text); }

/* =========================================================================
   Cards & metrics
   ========================================================================= */
.card {
    background: var(--bg-card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}
.card-pad { padding: 18px 20px; }
.card-head .list-new-btn { margin-left: auto; flex: 0 0 auto; padding: 7px 14px; font-size: 13px; white-space: nowrap; }
.card-head-hasnew { gap: 10px; flex-wrap: wrap; }
.card-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px; border-bottom: 1px solid var(--line);
}
.card-head h3 { font-size: 14px; }
.card-head .hint { color: var(--text-muted); font-size: 12px; }

.metric-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
    margin-bottom: 22px;
}
.metric {
    background: var(--bg-card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: 16px 18px;
    position: relative;
    overflow: hidden;
}
.metric::before {
    content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
    background: var(--primary);
}
.metric.accent-amber::before { background: var(--warn); }
.metric.accent-blue::before { background: var(--info); }
.metric.accent-slate::before { background: var(--neutral); }
.metric-label { color: var(--text-muted); font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; }
.metric-value { font-family: var(--font-mono); font-size: 26px; font-weight: 600; margin-top: 8px; letter-spacing: -0.02em; }
.metric-foot { color: var(--text-muted); font-size: 12px; margin-top: 4px; }
.metric-foot strong { color: var(--text); font-weight: 600; }

/* =========================================================================
   Pipeline (signature element)
   ========================================================================= */
.pipeline {
    display: flex;
    align-items: stretch;
    gap: 0;
    padding: 22px 20px;
    overflow-x: auto;
}
.stage {
    flex: 1 1 0;
    min-width: 116px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    position: relative;
    padding: 0 6px;
}
.stage:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 26px;
    right: -10px;
    width: 20px; height: 2px;
    background: var(--line-strong);
}
.stage:not(:last-child)::before {
    content: "";
    position: absolute;
    top: 22px;
    right: -12px;
    width: 0; height: 0;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
    border-left: 6px solid var(--line-strong);
    z-index: 1;
}
.stage-num {
    width: 54px; height: 54px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--primary-soft);
    color: var(--primary-ink);
    font-family: var(--font-mono);
    font-size: 20px; font-weight: 600;
    border: 2px solid #fff;
    box-shadow: 0 0 0 1px var(--line-strong);
}
.stage-idx {
    font-family: var(--font-mono);
    font-size: 10.5px;
    color: var(--text-muted);
    margin-top: 10px;
    letter-spacing: 0.04em;
}
.stage-name { font-size: 12.5px; font-weight: 600; margin-top: 2px; }

/* =========================================================================
   Tables
   ========================================================================= */
.table-wrap { overflow-x: auto; }
/* Document list views: header row + filter row + pager stay put; only records scroll */
/* r1053 — ONE model for how much height a list may take.
 *
 * This was `100vh - 230px`, a literal standing for "the chrome above me". On Dimensions ▸ Units that is
 * about right; on Commodity codes there are sub-tabs as well, so the chrome is taller, the list is
 * given more height than exists and it runs under the tabs it was supposed to sit below. Every screen
 * with a different amount of chrome needed a different literal, and only the first one was ever
 * measured.
 *
 * `--chrome-h` is set from the list's own top edge when it renders — the one number that is true for
 * whatever sits above it — and 230px remains only as the fallback for a list that has not been measured
 * yet. **A layout constant that stands for something variable is wrong on every screen except the one
 * it was measured on.** */
.table-wrap.is-scrollable { overflow-y: auto;
  max-height: calc(100vh - var(--chrome-h, 230px) - var(--statusbar-h)); }
.table-wrap.is-scrollable table.grid thead tr:first-child th {
    position: sticky; top: 0; z-index: 4; box-shadow: inset 0 -1px 0 var(--line);
}
.table-wrap.is-scrollable table.grid thead tr.filter-row th {
    position: sticky; top: var(--head-h, 38px); z-index: 3;
}
.table-wrap.is-scrollable table.grid tfoot .pager-cell {
    position: sticky; bottom: 0; z-index: 4; box-shadow: inset 0 1px 0 var(--line);
}
table.grid, .dv-l__t {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
table.grid thead th, .dv-l__t thead th {
    text-align: left;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-muted);
    font-weight: 600;
    /* matched to the cells below them: a header inset further than its column reads as misaligned */
    padding: 9px 12px;
    border-bottom: 1px solid var(--line);
    background: var(--bg-subtle);
    white-space: nowrap;
}
table.grid thead th.num, .dv-l__t thead th.num { text-align: right; }
table.grid tbody td, .dv-l__t tbody td {
    /* r1036 — the SUPPLIER register's density, applied to every list. It used 10px 12px while every
       other table used 12px 16px, so the estate had two row heights and the reader met a different one
       on each page. The supplier list is the one with the most controls and the most rows, and it is
       the one that was tuned \u2014 so it is the model rather than the exception. */
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
    vertical-align: middle;
}
/* r1036 — and the selected row reads the same everywhere. Only the supplier list marked one, so on
   every other page the reader had no way to see which row they were acting on. */
table.grid tbody tr.is-selected > td, .dv-l__t tbody tr.is-selected > td {
    background: var(--row-selected);
}
table.grid tbody tr:last-child td, .dv-l__t tbody tr:last-child td { border-bottom: 0; }
table.grid tbody tr:hover, .dv-l__t tbody tr:hover { background: var(--bg-subtle); }
.cell-strong { font-weight: 600; color: var(--text); }
.cell-sub { color: var(--text-muted); font-size: 12px; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: nowrap; white-space: nowrap; }
td .row-actions { min-width: max-content; }

/* =========================================================================
   Status pills
   ========================================================================= */
.pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 11.5px;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: 999px;
    white-space: nowrap;
    letter-spacing: 0.01em;
}
.pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.9; }
.pill.ok { color: var(--ok); background: var(--ok-bg); }
.pill.warn { color: var(--warn); background: var(--warn-bg); }
.pill.bad { color: var(--bad); background: var(--bad-bg); }
.pill.neutral { color: var(--neutral); background: var(--neutral-bg); }
.pill.info { color: var(--info); background: var(--info-bg); }
.pill-sm { font-size: 10.5px; padding: 2px 7px; }

/* =========================================================================
   Forms & modal
   ========================================================================= */
/* Uniform 3-line address fields across all forms (Legal Entity, vendor, customer, ...). */
.addr-multiline { min-height: 4.8em; line-height: 1.5; resize: vertical; font-family: inherit; }
/* Collapsible document history (collapsed by default; click to expand). */
.hist-details > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px; user-select: none; }
.hist-details > summary::-webkit-details-marker { display: none; }
.hist-details > summary::before { content: '\25B8'; font-size: 11px; color: var(--text-muted); transition: transform 0.12s ease; }
.hist-details[open] > summary::before { transform: rotate(90deg); }
.hist-details > summary:hover { color: var(--primary, #2b78e4); }
.modal-overlay {
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex; align-items: flex-start; justify-content: center;
    padding: 48px 16px;
    z-index: 50;
    overflow-y: auto;
}
.modal-overlay[hidden] { display: none; }
.modal {
    background: var(--bg-card);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    width: 100%;
    max-width: var(--modal-w);
    animation: pop 0.14s ease-out;
    display: flex; flex-direction: column;
    /* r1144 — item 6: the card fits within the viewport (the overlay's 48px top+bottom padding), so only
     * the body scrolls. Without this the card was head + body(78vh) + foot, which overflowed the overlay
     * and produced a second, "weird" scroll on the whole dialog. is-docright overrides this to 100vh. */
    max-height: calc(100vh - 96px);
}
@keyframes pop { from { transform: translateY(6px) scale(0.99); opacity: 0; } to { transform: none; opacity: 1; } }
.modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 18px 22px; border-bottom: 1px solid var(--line); order: 0;
}
.modal-head h2 { font-size: 16px; }
.modal-head-actions { display: flex; align-items: center; gap: 10px; }
/* r1196 — a document form's pop-up hides the corner ×: Cancel / Close / Save / Submit in the header are
   the form's ways out, and a second, unlabeled close path invited losing an edited form to a stray
   click. Non-form modals keep their ×. */
.modal--docform #modal-close { display: none; }
/* r1171 — a document form's Cancel / Save / Submit sit in the header row (beside the form name), not in
   a footer strip. Keep them compact so a long title still fits, and lay out the inline form's header the
   same way the modal header does (title left, actions right). */
.modal-head-formbtns { display: inline-flex; align-items: center; gap: 8px; }
/* r1196 — Cancel / Save / Submit sit on the RIGHT of the form header in BOTH open modes.
   r1197 — and they are the LAST thing there: the icon rail (star · log · comments) sits immediately
   BEFORE them. The first right-side element carries the auto margin; a rail preceding the button slot
   cancels the slot's own, so the two never split apart. */
.card-head .modal-head-formbtns { margin-left: auto; }
.card-head .doc-panel-rail-inline { margin-left: auto; }
/* r1544 — only the FIRST of the right-hand group pushes. `place()` marks everything it places with this
   class — the icon rail AND the Approve / Reject / chevron row — and two `margin-left: auto` siblings in
   one flex row SPLIT the free space between them, so the first sat in the middle of the header. A later
   sibling joins the group instead of pushing again. **An auto margin means "take the rest", and two of
   them each take half.** */
.card-head .doc-panel-rail-inline ~ .doc-panel-rail-inline { margin-left: 0; }
.card-head .doc-panel-rail-inline + .modal-head-formbtns { margin-left: 0; }
.modal-head-formbtns:empty { display: none; }
.modal-head-formbtns .btn { padding: 6px 12px; }
.inline-form .card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }

/* ===== Document side panel (approval flow / related documents / log / comments) ===== */
.doc-actions-wrap { position: relative; display: inline-flex; }
.doc-actions-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; min-width: 178px; background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); box-shadow: 0 12px 32px rgba(15,23,42,0.18); padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.doc-actions-menu[hidden] { display: none; }
.doc-actions-menu button { display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 10px; border: 0; background: transparent; border-radius: 8px; cursor: pointer; font-size: 13.5px; color: var(--text); text-align: left; }
.doc-actions-menu button svg { width: 16px; height: 16px; flex: 0 0 auto; opacity: 0.8; }
.doc-actions-menu button:hover { background: var(--bg-soft, rgba(15,23,42,0.05)); }
.doc-actions-menu button.da-danger { color: var(--bad); }
.doc-actions-menu button.da-danger:hover { background: var(--bad-bg); }
.doc-panel-rail { display: inline-flex; align-items: center; gap: 2px; margin-right: 6px; padding-right: 8px; border-right: 1px solid var(--line); }
/* #7 Check-requisition banner + header icon */
.pr-check-banner { position: relative; display: flex; align-items: flex-start; gap: 10px; margin: 0 0 14px; padding: 12px 36px 12px 14px; border-radius: var(--radius-sm); font-size: 13px; line-height: 1.45; border: 1px solid var(--line); }
.pr-check-banner .pr-check-msg { flex: 1; }
.pr-check-banner ul { margin: 6px 0 0; padding-left: 18px; }
.pr-check-banner li { margin: 2px 0; }
.pr-check-ok { background: #ecfdf3; border-color: #abefc6; color: #067647; }
.pr-check-bad { background: #fef3f2; border-color: #fecdca; color: #b42318; }
.pr-check-x { position: absolute; top: 6px; right: 8px; border: 0; background: none; font-size: 18px; line-height: 1; cursor: pointer; color: inherit; opacity: .65; }
.pr-check-x:hover { opacity: 1; }
.pr-check-icon-inline { margin-left: 4px; }
.pr-check-ico { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; height: 1.45em; }
.pr-check-ico svg { width: 16px; height: 16px; }
/* In an inline (full-page) form the rail sits at the right of the card-head with nothing after it, so the divider border/padding is dropped. */
.doc-panel-rail-inline { margin-right: 0; padding-right: 0; border-right: 0; }
.doc-panel-icon { width: 30px; height: 30px; padding: 5px; color: var(--text-muted); border-radius: var(--radius-sm); }
.doc-panel-icon:hover { color: var(--primary); background: rgba(255, 139, 31, 0.10); }
.doc-panel-icon svg { width: 18px; height: 18px; }
.doc-panel-rail .doc-pdf-btn { width: auto; height: 30px; padding: 0 9px; font-size: 11px; font-weight: 700; letter-spacing: 0.03em; color: var(--text-muted); }
.doc-panel-rail .doc-pdf-btn:hover { color: var(--primary); background: rgba(255, 139, 31, 0.10); }

.doc-drawer {
    position: fixed; right: 0; left: auto; top: 0; bottom: 0; width: 384px; max-width: 92vw; z-index: 60;
    background: var(--bg-card); border-left: 1px solid var(--line); box-shadow: -2px 0 24px rgba(15, 23, 42, 0.18);
    display: flex; flex-direction: column; transform: translateX(100%); transition: transform 0.2s ease;
}
.doc-drawer.open { transform: translateX(0); }
.doc-drawer[hidden] { display: none; }
.doc-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.doc-drawer-tabs { display: inline-flex; gap: 2px; }
.doc-drawer-tab { width: 34px; height: 34px; padding: 7px; color: var(--text-muted); background: transparent; border: 0; border-radius: var(--radius-sm); cursor: pointer; }
.doc-drawer-tab svg { width: 18px; height: 18px; }
.doc-drawer-tab:hover { color: var(--primary); background: rgba(255, 139, 31, 0.10); }
.doc-drawer-tab.active { color: var(--primary); background: rgba(255, 139, 31, 0.14); }
.doc-drawer-title2 { padding: 10px 16px 4px; font-size: 13px; font-weight: 600; color: var(--text); letter-spacing: 0.01em; }
.doc-drawer-body { flex: 1 1 auto; overflow-y: auto; }
.doc-drawer-pad { padding: 8px 16px 18px; }

/* Activity log, grouped by day */
.dlog-day { margin-bottom: 14px; }
.dlog-daylabel { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin: 6px 0 6px; }

/* Related documents */
.drel-group { margin-bottom: 14px; }
.drel-gtitle { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin: 4px 0 6px; }
.drel-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; margin-bottom: 4px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 13px; }
.drel-num { font-weight: 600; color: var(--text); }
.drel-status { font-size: 11px; color: var(--text-muted); }

/* Comments */
.dcom-wrap { display: flex; flex-direction: column; min-height: 100%; }
.dcom-list { flex: 1 1 auto; }
.dcom-item { padding: 8px 0; border-top: 1px solid var(--line); }
.dcom-item:first-child { border-top: 0; }
.dcom-meta { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 2px; }
.dcom-author { font-weight: 600; font-size: 13px; color: var(--text); }
.dcom-when { font-size: 11px; color: var(--text-muted); }
.dcom-text { font-size: 13px; color: var(--text); white-space: normal; word-break: break-word; }
.dcom-at { color: var(--primary); font-weight: 600; }
.dcom-compose { position: relative; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
.dcom-input { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; font-size: 13px; padding: 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); }
.dcom-input:focus { outline: none; border-color: var(--primary); }
.dcom-mention-pop { position: absolute; left: 8px; right: 8px; bottom: 64px; max-height: 168px; overflow-y: auto; background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); box-shadow: 0 6px 20px rgba(15, 23, 42, 0.16); z-index: 2; }
.dcom-mention-pop[hidden] { display: none; }
.dcom-mention-opt { padding: 7px 10px; font-size: 13px; cursor: pointer; }
.dcom-mention-opt:hover { background: rgba(255, 139, 31, 0.10); color: var(--primary); }
.dcom-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 8px; }
.dcom-hint { font-size: 11px; color: var(--text-muted); }
.modal-body { padding: 22px; overflow-y: auto; order: 2; flex: 1 1 auto; min-height: 0; }
/* action buttons (Save / Submit / Flip / Cancel …) sit at the TOP, just under the title */
.modal-foot {
    display: flex; justify-content: flex-end; gap: 10px;
    padding: 14px 22px; border-bottom: 1px solid var(--line); order: 1;
    background: var(--bg-subtle);
}
.modal-foot:empty { display: none; }
.inline-form .card-pad { display: flex; flex-direction: column; }
.inline-form #__inl-foot { order: 0; }
.inline-form #__inl-body { order: 1; }

.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px 16px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field.col-span { grid-column: 1 / -1; }
.field label { font-size: 12px; font-weight: 600; color: var(--text); }
.field label .req { color: var(--bad); margin-left: 2px; }
/* highlight a required field that blocked submission, until it gets a value */
.field.is-invalid > input, .field.is-invalid > select, .field.is-invalid > textarea,
.field.is-invalid .combo-control, .field.is-invalid .mcombo-control, .field.is-invalid .rt-wrap,
.field.is-invalid .cf-choice, .field.is-invalid .cf-att,
.cf-field.is-invalid input, .cf-field.is-invalid select, .cf-field.is-invalid textarea,
.cf-field.is-invalid .combo-control, .cf-field.is-invalid .mcombo-control, .cf-field.is-invalid .rt-wrap,
.cf-field.is-invalid .cf-choice, .cf-field.is-invalid .cf-att {
    border-color: var(--bad) !important;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--bad) 22%, transparent);
}
.field.is-invalid > label, .cf-field.is-invalid > label { color: var(--bad); }
.field .help { font-size: 11.5px; color: var(--text-muted); }
.field input, .field select, .field textarea {
    min-height: var(--control-h);   /* r1606 — a field stands the same height as a dropdown beside it */
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
    background: var(--bg-card);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
    width: 100%;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.field input.mono, .field input[inputmode="decimal"] { font-family: var(--font-mono); }
.field input[readonly], .field textarea[readonly] { background: var(--bg-app); color: var(--text-soft, var(--text)); cursor: default; }
.field input[readonly]:focus, .field textarea[readonly]:focus { border-color: var(--line-strong); box-shadow: none; }
.field textarea { resize: vertical; min-height: 70px; }
.field input:focus, .field select:focus, .field textarea:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-soft);
}

.section-label {
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-muted); font-weight: 600;
    margin: 24px 0 10px;
    display: flex; align-items: center; justify-content: space-between;
}

/* r1134 — standard document-form structure: HEADER / BODY / SECURITY / APPROVAL / BOTTOM */
.form-std .fsec { margin: 0 0 22px; }
.form-std .fsec:last-child { margin-bottom: 0; }
.form-std .fsec__h {
    font-size: 12px; text-transform: uppercase; letter-spacing: 0.07em;
    color: var(--text-muted); font-weight: 700;
    border-bottom: 1px solid var(--border); padding-bottom: 7px; margin: 0 0 14px;
}
.form-std .fsec__sub {
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-muted); font-weight: 600; margin: 16px 0 8px;
}
.form-std .fsec .section-label:first-child { margin-top: 0; }

/* Line item editor */
.lines { display: flex; flex-direction: column; gap: 8px; }
.line-row {
    display: grid;
    gap: 8px;
    align-items: end;
    padding: 10px;
    background: var(--bg-subtle);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
}
.line-row .field label { font-size: 11px; color: var(--text-muted); }
.line-del svg { width: 15px; height: 15px; }
.line-row .line-del {
    border: 1px solid var(--line-strong);
    background: var(--bg-card);
    color: var(--bad);
    border-radius: var(--radius-sm);
    height: 36px; cursor: pointer;
    font-size: 16px;
}
.line-row .line-del:hover { background: var(--bad-bg); border-color: var(--bad); }
.line-acts { display: flex; gap: 4px; align-items: end; }
.line-row .line-copy, .line-row .line-exp {
    border: 1px solid var(--line-strong);
    background: var(--bg-card);
    color: var(--text-muted);
    border-radius: var(--radius-sm);
    height: 36px; min-width: 30px; cursor: pointer; font-size: 15px;
}
.line-row .line-copy:hover, .line-row .line-exp:hover { background: var(--bg-subtle); color: var(--text); border-color: var(--brand); }
.line-block { display: flex; flex-direction: column; }
.line-detail {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding: 12px;
    background: var(--bg-card);
    border: 1px solid var(--line);
    border-top: 1px dashed var(--line-strong);
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.line-detail .field { flex: 0 1 calc(25% - 8px); min-width: 150px; box-sizing: border-box; }
.line-detail .field label { font-size: 11px; color: var(--text-muted); }
.line-detail .field input, .line-detail .field select { width: 100%; box-sizing: border-box; }
.field-muted .na { color: var(--text-muted); font-size: 12px; padding: 9px 0; opacity: 0.55; }
.line-total {
    font-family: var(--font-mono);
    font-size: 13px;
    text-align: right;
    color: var(--text);
    padding-bottom: 9px;
    font-weight: 500;
}
.lines-foot {
    display: flex; align-items: center; justify-content: space-between;
    margin-top: 12px;
}
.totals { font-family: var(--font-mono); font-size: 13px; color: var(--text-muted); text-align: right; }
.totals .grand { color: var(--text); font-size: 16px; font-weight: 600; }

/* =========================================================================
   Match result panel
   ========================================================================= */
.match-panel { font-family: var(--font-mono); font-size: 12.5px; line-height: 1.7; white-space: pre-wrap; }
.match-pass { color: var(--ok); }
.match-fail { color: var(--bad); }

.detail-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px 24px; }
.detail-grid.col-3 { grid-template-columns: repeat(3, 1fr); }
.detail-item { display: flex; flex-direction: column; gap: 3px; }
.detail-item .k { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); font-weight: 600; }
.detail-item .v { font-size: 13.5px; }

/* =========================================================================
   Approval workflow
   ========================================================================= */
.appr-summary {
    display: flex; flex-wrap: wrap; gap: 10px 24px; align-items: center;
    padding: 14px 16px; margin-bottom: 18px;
    background: var(--bg-subtle); border: 1px solid var(--line);
    border-radius: var(--radius-sm);
}

.timeline { display: flex; flex-direction: column; }

/* =========================================================================
   Attachments
   ========================================================================= */
.attach-list { display: flex; flex-direction: column; gap: 8px; }
.attach-row {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    background: var(--bg-card);
}
.attach-ico {
    width: 34px; height: 34px; border-radius: var(--radius-sm); flex: none;
    display: grid; place-items: center;
    background: var(--primary-soft); color: var(--primary-ink);
    font-family: var(--font-mono); font-size: 10px; font-weight: 700;
}
.attach-meta { flex: 1; min-width: 0; }
.attach-name { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.attach-sub { font-size: 11.5px; color: var(--text-muted); }

.attach-chip {
    display: inline-flex; align-items: center; gap: 3px;
    font-family: var(--font-mono); font-size: 11px; font-weight: 600;
    color: var(--primary-ink); background: var(--primary-soft);
    border-radius: 999px; padding: 1px 8px; margin-left: 6px; vertical-align: middle;
}
.attach-upload { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.attach-upload input[type="file"] { font-size: 12.5px; color: var(--text-muted); max-width: 100%; }

/* =========================================================================
   Approval flows — editor + history
   ========================================================================= */

/* Editor row */
.flow-step-edit {
    display: grid; grid-template-columns: 26px 1.2fr 1.4fr 36px; gap: 10px; align-items: center;
    padding: 8px; background: var(--bg-subtle);
    border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.flow-step-num {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    display: grid; place-items: center;
    background: var(--primary-soft); color: var(--primary-ink);
    font-family: var(--font-mono); font-size: 12px; font-weight: 700;
}
.flow-name, .flow-appr {
    font-family: var(--font-ui); font-size: 13px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 8px 10px; width: 100%;
}
.flow-step-edit .line-del {
    border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--bad);
    border-radius: var(--radius-sm); height: 34px; cursor: pointer; font-size: 16px;
}
.flow-step-edit .line-del:hover { background: var(--bad-bg); border-color: var(--bad); }

/* History row (approval timeline in the modal) */
.flow-step {
    display: flex; align-items: flex-start; gap: 12px;
    padding: 10px 12px; background: var(--bg-subtle);
    border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.flow-step.is-active { background: var(--primary-soft); border-color: var(--primary); }
.flow-step-comment {
    font-size: 12.5px; margin-top: 5px; color: var(--text);
    background: var(--bg-card); border-left: 2px solid var(--line-strong);
    padding: 5px 10px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* Connection test result (Setup → database) */
.test-result {
    margin-top: 14px; padding: 11px 14px; border-radius: var(--radius-sm);
    font-size: 12.5px; font-family: var(--font-mono);
    display: flex; align-items: center; gap: 8px;
    background: var(--bg-subtle); border: 1px solid var(--line); color: var(--text-muted);
}
.test-result[hidden] { display: none; }
.test-result.ok { background: var(--ok-bg); color: var(--ok); border-color: #86EFAC; }
.test-result.bad { background: var(--bad-bg); color: var(--bad); border-color: #FCA5A5; }

/* Small inline utilities used across Setup / Users / approvals */
.muted { font-size: 12.5px; color: var(--text-muted); padding: 6px 2px; }
.tag {
    display: inline-block; font-family: var(--font-mono); font-size: 11px; font-weight: 600;
    color: var(--neutral); background: var(--neutral-bg);
    border-radius: var(--radius-sm); padding: 2px 8px;
}
.form-actions { display: flex; gap: 8px; margin-top: 16px; }

/* =========================================================================
   States
   ========================================================================= */
.empty {
    text-align: center;
    padding: 56px 20px;
    color: var(--text-muted);
}
.empty .empty-mark {
    width: 46px; height: 46px; border-radius: var(--radius);
    background: var(--bg-subtle); border: 1px solid var(--line);
    display: grid; place-items: center; margin: 0 auto 14px;
    font-family: var(--font-mono); color: var(--text-muted); font-size: 18px;
}
.empty h3 { color: var(--text); font-size: 15px; margin-bottom: 4px; }

.loading { padding: 48px; text-align: center; color: var(--text-muted); font-size: 13px; }
.spinner {
    width: 22px; height: 22px; border-radius: 50%;
    border: 2.5px solid var(--line); border-top-color: var(--primary);
    margin: 0 auto 12px; animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.inline-note {
    font-size: 12.5px; color: var(--text-muted);
    background: var(--bg-subtle); border: 1px solid var(--line);
    border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 16px;
}

/* r1261 — 8px between the last field and the note that explains the panel. The note sat flush against
   the field grid, so it read as another row of the form rather than as a remark about it. The rule is on
   the note that FOLLOWS a grid rather than on the note itself: an inline-note used as a warning inside a
   list should keep whatever spacing that list gives it. */
.form-grid + .inline-note { margin-top: 8px; }

/* =========================================================================
   Toasts
   ========================================================================= */
.toast-host {
    position: fixed; right: 20px; bottom: 20px;
    display: flex; flex-direction: column; gap: 10px;
    z-index: 80;
}
.toast {
    background: #16222B;
    color: #fff;
    padding: 12px 16px;
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    font-size: 13px;
    max-width: 360px;
    border-left: 3px solid var(--primary);
    animation: slidein 0.16s ease-out;
}
.toast.err { border-left-color: #F87171; }
.toast.ok { border-left-color: #4ADE80; }
/* Centred confirmation shown briefly when a document is submitted for approval. */
.center-confirm {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 4000;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.center-confirm.show { opacity: 1; }
/* r801: a confirmation is deliberately narrower than a form — it asks one question. It uses the NARROW
   token rather than a number of its own, so the two sizes stay two sizes rather than becoming five. */
.center-confirm-box {
    background: rgba(22, 34, 43, 0.94);
    color: #fff;
    padding: 18px 30px;
    border-radius: 14px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
    max-width: var(--modal-w-narrow);
    text-align: center;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.4);
    border-top: 3px solid #4ADE80;
    transform: scale(0.96);
    transition: transform 0.2s ease;
}
.center-confirm.show .center-confirm-box { transform: scale(1); }
/* interactive variant of center-confirm: a blocking prompt with action buttons (e.g. save before leaving) */
/* r1221 — the decision buttons in a document form's header: the same spacing the header's other
   controls use, and they sit before the rail so Approve is the first thing the eye meets. */
.doc-decide-acts { display: inline-flex; align-items: center; gap: 8px; margin-right: 10px; }
/* r1222 — the header overflow: a chevron and the menu it opens, anchored to the button. */
.doc-more { position: relative; display: inline-flex; }
.doc-more-btn { padding: 6px 8px; }
.doc-more-menu { position: absolute; top: calc(100% + 4px); right: 0; z-index: 60; min-width: 210px;
    /* r1331 — `var(--card)` is not a variable this estate defines: the name is `--bg-card`, and the
       whole stylesheet uses that everywhere else. An undefined custom property with no fallback resolves
       to nothing, so the menu had NO background at all and the list underneath read straight through it.
       **A typo in a variable name is invisible in CSS: nothing errors, the rule simply does not exist.** */
    background: var(--bg-card, #fff); border: 1px solid var(--line); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,.14); padding: 4px; }
.doc-more-item { display: block; width: 100%; text-align: left; padding: 8px 10px; border: 0; background: none;
    border-radius: 6px; cursor: pointer; font: inherit; color: var(--text); }
.doc-more-item:hover { background: var(--bg-subtle); }
.doc-decide-acts .btn { padding: 6px 12px; }
.center-ask-ov { pointer-events: auto; background: rgba(0, 0, 0, 0.4); }
.center-ask { border-top-color: #F5A623; }
.center-ask-msg { margin-bottom: 16px; text-align: center; }   /* r1149 — issue 3b: centre the message */
.center-ask-row { display: flex; gap: 10px; justify-content: stretch; flex-wrap: nowrap; }
/* r1148 — the three choices are equal width, so no one option looks like the default by being wider. */
.center-ask-row .btn { flex: 1 1 0; min-width: 0; white-space: nowrap; }
/* r1148 — the approver picker pop-up (tabs: Users / Groups / Roles / AI). Its own overlay, above the form
   modal, so it does not replace the form the way a second openModal would. */
.ah-pick-ov { position: fixed; inset: 0; z-index: 1500; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(15, 23, 42, .42); opacity: 0; transition: opacity .16s ease; }
.ah-pick-ov.show { opacity: 1; }
@media (max-width: 1100px) { .ah-pick-box { width: 92%; } }
/* r1265 — the Add-approver picker is the size of the Field-properties dialog it sits beside. It was
   min(420px) and grew or shrank with its tab's contents, so choosing a user and choosing a role were two
   differently shaped windows and the list jumped as you switched. A picker whose size depends on what is
   in it makes the reader re-find the same control on every tab. */
.ah-pick-box { width: 75%; max-width: none; height: 76vh; max-height: 76vh; display: flex; flex-direction: column;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(15, 23, 42, .28); overflow: hidden; transform: translateY(8px); transition: transform .16s ease; }
.ah-pick-ov.show .ah-pick-box { transform: none; }
.ah-pick-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--line); }
.ah-pick-title { font-weight: 600; font-size: 14px; }
.ah-pick-x { appearance: none; border: 0; background: var(--bg-subtle); color: var(--text-muted);
  width: 28px; height: 28px; border-radius: 8px; font-size: 19px; line-height: 26px; cursor: pointer; }
.ah-pick-x:hover { background: var(--line); color: var(--text); }
.ah-pick-tabs { display: flex; gap: 2px; padding: 8px 10px 0; border-bottom: 1px solid var(--line); }
.ah-pick-tab { appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 6px 10px; font: inherit; font-size: 13px; font-weight: 500; color: var(--text-muted); cursor: pointer; white-space: nowrap; }
.ah-pick-tab:hover { color: var(--text); }
.ah-pick-tab.is-active { color: var(--text); border-bottom-color: var(--brand-orange); }
.ah-pick-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.ah-pick-item { appearance: none; text-align: left; background: none; border: 0; border-radius: 8px;
  padding: 8px 10px; font: inherit; font-size: 13.5px; color: var(--text); cursor: pointer; }
.ah-pick-item:hover { background: var(--bg-subtle); }
.ah-pick-note { padding: 14px 10px; color: var(--text-muted); font-size: 13px; }
/* r1172 — the picker's search field (typeahead) and its "Load more" control, for paged lists that can run
   to thousands of rows. */
.ah-pick-searchwrap { padding: 8px 10px 0; }
.ah-pick-search { width: 100%; box-sizing: border-box; padding: 7px 10px; font: inherit; font-size: 13.5px;
  border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card); color: var(--text); }
.ah-pick-search:focus { outline: none; border-color: var(--primary); }
.ah-pick-more { appearance: none; margin: 4px 2px 2px; padding: 7px 10px; font: inherit; font-size: 12.5px;
  border: 1px dashed var(--line-strong); border-radius: 8px; background: none; color: var(--text-muted); cursor: pointer; }
.ah-pick-more:hover { background: var(--bg-subtle); color: var(--text); }
.ah-pick-more:disabled { opacity: .6; cursor: default; }
@keyframes slidein { from { transform: translateX(12px); opacity: 0; } to { transform: none; opacity: 1; } }

/* =========================================================================
   Section spacing
   ========================================================================= */
.stack { display: flex; flex-direction: column; gap: 22px; }
.two-col { display: grid; grid-template-columns: 1.4fr 1fr; gap: 22px; }

/* =========================================================================
   Responsive
   ========================================================================= */
@media (max-width: 920px) {
    .app-shell { grid-template-columns: 1fr; }
    .sidebar {
        position: relative; height: auto; flex-direction: row;
        align-items: center; flex-wrap: wrap; gap: 8px;
        padding: 12px 16px;
    }
    .brand { border: 0; margin: 0; padding: 0 12px 0 0; }
    .brand-logo { max-width: 150px; }
    .nav { flex-direction: row; flex-wrap: wrap; flex: 1; gap: 4px; overflow: visible; }
    .nav-group { display: none; }
    /* On mobile the area headers are hidden and items wrap horizontally, so the
       accordion collapse is overridden — every module stays reachable. */
    .nav-item.nav-collapsed { display: flex !important; }
    .nav-badge { margin-left: 4px; }
    .account { border: 0; margin: 0; padding: 0; }
    .account-info { display: none; }
    .sidebar-foot { display: none; }
    .two-col { grid-template-columns: 1fr; }
    .view, .topbar { padding-left: 18px; padding-right: 18px; }
}
@media (max-width: 680px) {
    .form-grid, .detail-grid, .detail-grid.col-3 { grid-template-columns: 1fr; }
    .flow-step-edit { grid-template-columns: 22px 1fr 1fr 32px; }
    .topbar { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* Accessibility */
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* =========================================================================
   Drill-through links, commodity selectors, multi-flow & condition editor
   ========================================================================= */
.doclink { color: var(--primary); text-decoration: none; font-weight: 500; cursor: pointer; }
.doclink:hover { text-decoration: underline; }
/* First-column code/name in Setup & dimension lists opens that row's editor (parity with doc links) */
.setup-panel table.grid tbody tr td:first-child .docno,
.setup-panel table.grid tbody tr td:first-child .cell-strong { cursor: pointer; }
.setup-panel table.grid tbody tr td:first-child .docno { color: var(--primary); }
.setup-panel table.grid tbody tr td:first-child .docno:hover,
.setup-panel table.grid tbody tr td:first-child .cell-strong:hover { text-decoration: underline; }

.commodity-cell { min-width: 0; }
.commodity-mount { display: flex; flex-direction: column; gap: 4px; }
.commodity-sel {
    font-family: var(--font-ui); font-size: 12.5px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 6px 8px; width: 100%;
}

.flow-card {
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--bg-card); padding: 14px; margin-bottom: 12px;
}
.flow-card-name {
    flex: 1; min-width: 160px;
    font-family: var(--font-ui); font-size: 13.5px; font-weight: 600; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 8px 10px;
}
.flow-card-head .prio { font-size: 12px; color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.flow-card-prio {
    width: 64px; font-family: var(--font-mono); font-size: 12.5px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 6px 8px;
}

.cond-group { border: 1px solid var(--line); border-radius: var(--radius-sm, 8px); padding: 8px; margin-bottom: 8px; background: rgba(0,0,0,.012); }
.cond-group-root { border-style: solid; }
.cond-group .cond-group { background: rgba(255,139,31,.05); border-color: rgba(255,139,31,.35); }
.cond-group-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.cond-group-match { font-size: 12px; color: var(--text-muted); }
.cond-group-match select { font-size: 12px; padding: 2px 6px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-family: var(--font-ui); background: var(--bg-card); color: var(--text); margin: 0 4px; }
.cond-group-body { display: flex; flex-direction: column; gap: 8px; }
.cond-group-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.cond-group-del { width: 26px; height: 26px; }
.cond-empty { font-size: 12px; padding: 2px 0; }
.cond-row {
    display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start;
    padding: 8px; background: var(--bg-subtle);
    border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.cond-cell { min-width: 0; }
.cnd-field { flex: 0 0 calc(25% - 8px); }
.cnd-op    { flex: 0 0 calc(12.5% - 8px); }
.cnd-src   { flex: 0 0 calc(25% - 8px); }
.cnd-val   { flex: 1 1 calc(25% - 8px); display: flex; gap: 6px; align-items: center; flex-wrap: wrap; min-width: 0; }
.cnd-field > .combo, .cnd-field > select, .cnd-op > .combo, .cnd-op > select, .cnd-src > .combo, .cnd-src > select { width: 100%; }
.cnd-val > .cnd-mode-inline { flex: 0 0 132px; min-width: 0; }
.cnd-val > .cnd-mode-inline > .combo, .cnd-val > .cnd-mode-inline > select { width: 100%; }
.cnd-val > .cond-val, .cnd-val > .combo, .cnd-val > input.cond-val, .cnd-val > select.cond-val,
.cnd-val > .cond-dyn-date-wrap, .cnd-val > .cond-novalue { flex: 1 1 60px; min-width: 0; }
.cond-row > .line-del { flex: 0 0 auto; margin-left: auto; }
.cond-field, .cond-op, .cond-val {
    font-family: var(--font-ui); font-size: 12.5px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 7px 8px; width: 100%;
}
.cond-dyn-date-wrap { display: flex; gap: 6px; align-items: center; min-width: 0; padding: 0; border: 0; background: none; }
.cond-dyn-date-wrap > * { min-width: 0; }
.cond-dyn-base, .cond-dyn-date, .cond-dyn-offset {
    font-family: var(--font-ui); font-size: 12.5px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 7px 8px;
}
.cond-dyn-base { flex: 1 1 auto; }
.cond-dyn-date { flex: 1 1 auto; }
.cond-dyn-offset { flex: 0 0 auto; width: 88px; text-align: right; font-variant-numeric: tabular-nums; }

.step-list { display: flex; flex-direction: column; gap: 8px; }
.step-row {
    display: grid; grid-template-columns: 24px minmax(110px,1fr) 88px minmax(120px,1.1fr) 82px 74px 32px; gap: 8px; align-items: center;
    padding: 8px; background: var(--bg-subtle);
    border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.step-name, .step-appr, .step-atype, .step-grp, .step-role, .step-dyn, .step-maxamt, .step-maxcur {
    font-family: var(--font-ui); font-size: 13px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 8px 10px; width: 100%;
}
.step-maxamt { text-align: right; font-variant-numeric: tabular-nums; }
.step-picker { min-width: 0; }
.step-picker select { width: 100%; }
.hier-step {
    display: grid; grid-template-columns: 1fr 1.4fr; gap: 10px; align-items: center;
    padding: 8px; background: var(--bg-subtle); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.cond-row .line-del, .step-row .line-del {
    border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--bad);
    border-radius: var(--radius-sm); height: 34px; cursor: pointer; font-size: 16px;
}
.cond-row .line-del:hover, .step-row .line-del:hover { background: var(--bad-bg); border-color: var(--bad); }

@media (max-width: 680px) {
    .cnd-field, .cnd-op, .cnd-src { flex: 1 1 100%; }
    .cnd-val { flex: 1 1 100%; }
    .cond-row > .line-del { flex: 0 0 auto; margin-left: auto; width: 36px; }
    .step-row { grid-template-columns: 22px 1fr 32px; }
    .step-row .step-appr, .step-row .step-atype, .step-row .step-picker, .step-row .step-maxamt, .step-row .step-maxcur { grid-column: 2 / 3; }
    .hier-step { grid-template-columns: 1fr; }
}
.next-appr { display: inline-flex; flex-direction: column; line-height: 1.3; }
.next-appr-step { font-weight: 600; color: var(--text); }
.next-appr-who { font-size: 12px; color: var(--text-muted); }

/* =========================================================================
   Searchable combobox (DDLB)
   ========================================================================= */
.combo { position: relative; }
/* r672: the searchable dropdown adopts the licenser's look — a control that reads as a DROPDOWN (a
   button-like field with a clear caret) rather than a bare text box, and option rows in the same shape.
   Typing still works: the control is a superset of the licenser's, which opens a separate search box. */
.combo-control {
    display: flex; align-items: center; gap: 8px; min-height: var(--control-h);   /* r1605 */
    background: var(--bg-card); border: 1px solid var(--line-strong);
    /* r1603 — the SAME corner as a text field (`.field input`, var(--radius-sm)). It was hard-coded to 8px, so a
       searchable dropdown sat beside a text field with twice its rounding. */
    border-radius: var(--radius-sm); padding: 0 11px; cursor: pointer;
}
.combo-control:hover { border-color: var(--text-muted); }
/* r679: the open/focused dropdown changes its BORDER COLOUR only. It also carried a 3px soft ring,
   which around an already-bordered control read as a second frame - the double outline you saw. */
.combo-control:focus-within { border-color: var(--primary); box-shadow: none; }
.combo-control.is-disabled { background: var(--bg-subtle); opacity: 0.7; }
.combo-input {
    flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
    font-family: var(--font-ui); font-size: 14px; color: var(--text); padding: 9px 0;
    cursor: pointer; text-overflow: ellipsis;
}
/* once it has focus it behaves as the search field it is */
.combo-input:focus { cursor: text; }
/* r680: the text inside the control is NOT a field in its own right. A generic form-input rule was giving
   it its own 1px border at the smaller input radius, drawn inside the control's 8px one - the second,
   less-rounded frame. Reset it with enough specificity to win, for both the single and multi controls. */
.combo .combo-input, .mcombo .mcombo-input, .opick .combo-input {
    border: 0; border-radius: 0; background: transparent; box-shadow: none; outline: none;
}
.combo .combo-input:focus, .mcombo .mcombo-input:focus, .opick .combo-input:focus {
    border: 0; box-shadow: none; outline: none;
}

.combo-input:disabled { cursor: not-allowed; }
.combo-clear {
    border: 0; background: transparent; color: var(--text-muted);
    cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px;
}
.combo-clear:hover { color: var(--bad); }
.combo-caret { color: var(--text-muted); font-size: 12px; pointer-events: none; flex: 0 0 auto; }
.combo:has(> .combo-panel:not([hidden])) .combo-control,
.mcombo:has(> .combo-panel:not([hidden])) .mcombo-control { border-color: var(--primary); }
/* r671: fixed, like the licenser's dropdown — a panel taken out of the flow cannot be clipped by a
   modal, drawer or scrolling card. Its left/width/top are set on open by placeComboPanel(). */
.combo-panel {
    position: fixed; z-index: 1000;
    max-height: 264px; overflow-y: auto;
    overscroll-behavior: contain;   /* r1754 — scrolling the list never runs on into the page */
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); padding: 4px;   /* r1603 — as the control above it */
}
/* When a searchable dropdown is open, lift its container into a high stacking context so the
   options panel paints above sibling fields/sections instead of being covered by them. */
.combo:has(> .combo-panel:not([hidden])),
.mcombo:has(> .combo-panel:not([hidden])),
.opick-add:has(> .combo-panel:not([hidden])) { z-index: 90; }

/* Integration actions table: External action + Path are plain inputs outside a .field,
   so they fell back to browser-default height/font — match the standard field input. */
.intg-act-table input[type="text"] {
    font-family: var(--font-ui); font-size: 13px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); padding: 9px 11px; width: 100%; box-sizing: border-box;
}
.intg-act-table input[type="text"]:focus {
    outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
.combo-opt {
    display: flex; flex-direction: column; gap: 1px;
    padding: 9px 11px; border-radius: var(--radius-sm); cursor: pointer;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.combo-opt:hover { background: var(--primary-soft); }
.combo-opt-active { background: var(--primary-soft); }
.combo-opt-disabled { opacity: .45; cursor: not-allowed; }
.combo-opt-disabled:hover { background: transparent; }
/* r673: the licenser's popup shape - a search row above the list, roomier rows, and the current pick in
   the accent colour so it is obvious which one is chosen. */
.combo-list { display: block; }
.combo-opt-selected .combo-opt-label { color: var(--primary); font-weight: 600; }
.combo-clear-opt { padding: 9px 11px; }

/* r677: every dropdown uses the STANDARD option font. The three-line treatment below is only for
   hierarchical dimensions and lookups (commodity codes and the like), where an option needs to say
   which item it is, which family it belongs to, and where it sits in the tree. */
.combo-opt-label { font-size: 13.5px; color: var(--text); }
.combo-opt-sub2 { font-size: 11.5px; color: var(--text-muted); line-height: 1.3; opacity: .8; }
/* hierarchical option: the item line is bold, the two lines under it stay quiet */
.combo-opt--hier .combo-opt-label { font-weight: 700; }
/* r678: a column filter sits in a table header cell, so the standard control is rendered compactly there
   - same dropdown, same searchable popup, just sized for the row it lives in. */
.col-filter-cell .combo { width: 100%; }
.col-filter-cell .combo-control { padding: 0 6px; border-radius: var(--radius-sm); min-height: 0; height: var(--control-h-xs); }   /* r1603 / r1605 */
/* r1605 — and the chip combo matches it in the same place, which it never did */
.col-filter-cell .mcombo-control { padding: 0 6px; border-radius: var(--radius-sm); min-height: var(--control-h-xs); }
.col-filter-cell .combo-input { font-size: 12px; padding: 4px 0; }
.col-filter-cell .combo-caret { font-size: 10px; }

.combo-opt-sub { font-size: 11.5px; color: var(--text-muted); font-family: var(--font-mono); }
.combo-more {
    width: 100%; text-align: center; border: 0; background: transparent;
    color: var(--primary); cursor: pointer; padding: 8px; font-size: 12.5px; font-weight: 600;
}
.combo-more:hover { background: var(--primary-soft); border-radius: var(--radius-sm); }
.combo-empty { padding: 10px; text-align: center; color: var(--text-muted); font-size: 12.5px; }

/* Searchable multi-select combobox (chips + dropdown) */
.mcombo { position: relative; }
.mcombo-control { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: var(--control-h);   /* r1605 */ background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); padding: 5px 8px; cursor: text; }
.mcombo-control:focus-within { border-color: var(--primary); box-shadow: none; }
.mcombo-chips { display: contents; }
.mcombo-chip { display: inline-flex; align-items: center; gap: 5px; background: var(--primary-soft); color: var(--primary-ink); border-radius: 999px; padding: 3px 6px 3px 11px; font-size: 12.5px; font-weight: 600; }
.mcombo-chip-x { border: 0; background: transparent; color: var(--primary-ink); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 1px; opacity: 0.65; }
.mcombo-chip-x:hover { opacity: 1; }
.mcombo-input { flex: 1; min-width: 90px; border: 0; background: transparent; outline: none; font-family: var(--font-ui); font-size: 13.5px; color: var(--text); padding: 4px 0; }

/* Custom Fields — compact 32px size (Width in row) selector */
.cf-size-ddlb .combo-control { min-height: var(--control-h-sm); padding: 0 8px; }   /* r1605 */
.cf-size-ddlb .mcombo-control { min-height: var(--control-h-sm); padding: 2px 8px; }
.cf-size-ddlb .combo-input { padding: 0; height: 30px; line-height: 30px; }

/* ============================================================
   Round 6 — wide modals, expandable rows, Setup tabs
   ============================================================ */

/* Wide modal (PO / delivery note / invoice) — offset past the sidebar so
   the left menu stays fully visible, and widen to ~90% of the main area. */
/* r1126 — the offset FOLLOWS the rail's actual width. It was a hard-coded 248px (the expanded rail),
   so when the rail is collapsed to 68px the scrim still began at 248px and left a ~180px strip beside
   the collapsed rail that was neither the menu nor covered — clickable background the pop-up was meant
   to block. --rail-w is 248px normally and 68px under body.rail-collapsed, so the scrim now meets the
   rail's edge in both states. The two facts — where the rail ends and where the scrim begins — are one
   value now, and cannot drift apart. */
.modal-overlay.is-wide { left: var(--rail-w, 248px); padding: 40px 24px; }
.modal.is-wide { max-width: 1400px; width: 90%; }
@media (max-width: 920px) { .modal-overlay.is-wide { left: 0; } }
/* Document create/edit/view pop-up. Centred pop-ups keep their standard size (75% of content width);
   the right-docked pop-up (preference) is a narrow full-height panel that reflows its fields to fit. */
/* r855 — EVERY document form is the width of a Purchase Requisition.
 *
 * The rule required BOTH is-wide and is-docform, so a form whose caller forgot `wide: true` fell back to
 * the 760px default and sat visibly narrower than the one beside it. Two flags for one idea, and the
 * forms that opened narrow were the ones nobody had opened next to a wide one.
 *
 * A document form is now wide because it is a document form. If a form is genuinely meant to be narrow it
 * is not a document form, and saying so is the caller's job — not an omitted flag. */
.modal.is-docform { width: 75%; max-width: none; }
.modal.is-wide.is-docform { width: 75%; max-width: none; }
@media (max-width: 1100px) { .modal.is-docform, .modal.is-wide.is-docform { width: 92%; } }
/* Right side: dock to the right edge, full height. */
.modal-overlay.is-docright { align-items: stretch; justify-content: flex-end; padding: 0; left: 0; }
.modal-overlay.is-docright .modal.is-docform,
.modal-overlay.is-docright .modal.is-wide.is-docform {
    /* r1149 — 2/3 of the previous 75%: the right-side pop-up covered most of the screen. Its fields
       re-flow for the reduced width below. */
    width: 50%; max-width: none; height: 100vh; max-height: 100vh;
    border-radius: 0; animation: dockin 0.16s ease-out;
}
.modal-overlay.is-docright .modal.is-docform .modal-body { max-height: none; flex: 1 1 auto; }

/* =====================================================================================================
   r1260 — FIELD WIDTHS IN THE RIGHT-HAND PANEL.
   ==================================================================================================== */
/* The panel is roughly a third of the width the centred window has, so the widths an operator chose for
   a full-width form do not survive it: a 1/4 field is a label with no room for its value, and eight of
   them in a row is unreadable. The designer's widths are still the truth — they are what the page and the
   centred pop-up use — and this REMAPS them for the narrow case rather than overriding the setting:

       1/1, 1/2, 1/3        →  a full row
       1/4, 1/5, 1/6, 1/8   →  half a row

   In CSS rather than JavaScript deliberately. The widths are inline styles written at render, and the
   panel can be opened and closed without re-rendering; a rule that reads the class the overlay already
   carries follows the window instead of following a render. **A layout that has to be recomputed to stay
   correct will eventually be looked at before it is recomputed.** */
.modal-overlay.is-docright .modal.is-docform [data-w="1/1"],
.modal-overlay.is-docright .modal.is-docform [data-w="1/2"],
.modal-overlay.is-docright .modal.is-docform [data-w="1/3"] {
  flex: 0 0 calc(100% - 12px) !important; max-width: calc(100% - 12px) !important;
}
.modal-overlay.is-docright .modal.is-docform [data-w="1/4"],
.modal-overlay.is-docright .modal.is-docform [data-w="1/5"],
.modal-overlay.is-docright .modal.is-docform [data-w="1/6"],
.modal-overlay.is-docright .modal.is-docform [data-w="1/8"] {
  flex: 0 0 calc(50% - 12px) !important; max-width: calc(50% - 12px) !important;
}
/* A blank space exists to leave a gap in a layout that has been remapped out from under it — the gap it
   was placed to make is not the gap it would make here. A line break still breaks the line, because that
   is a decision about grouping rather than about width. */
.modal-overlay.is-docright .modal.is-docform .cf-blank { display: none !important; }
@keyframes dockin { from { transform: translateX(28px); opacity: 0; } to { transform: none; opacity: 1; } }
@media (max-width: 1100px) { .modal-overlay.is-docright .modal.is-docform { width: 92%; } }
@media (max-width: 760px) { .modal-overlay.is-docright .modal.is-docform { width: 100vw; } }
/* r1149 — field re-flow for the narrower right-side pop-up: no blank spacers; 1/1·1/2·1/3 take a full
   row; the small widths (1/4·1/5·1/6·1/8) pair two to a row. The inline width lives in a style attribute,
   so these override it. */
.modal-overlay.is-docright .cf-blank { display: none !important; }
.modal-overlay.is-docright .field[data-w="1/1"], .modal-overlay.is-docright .cf-field[data-w="1/1"],
.modal-overlay.is-docright .field[data-w="1/2"], .modal-overlay.is-docright .cf-field[data-w="1/2"],
.modal-overlay.is-docright .field[data-w="1/3"], .modal-overlay.is-docright .cf-field[data-w="1/3"] {
    flex: 0 0 100% !important; max-width: 100% !important; }
.modal-overlay.is-docright .field[data-w="1/4"], .modal-overlay.is-docright .cf-field[data-w="1/4"],
.modal-overlay.is-docright .field[data-w="1/5"], .modal-overlay.is-docright .cf-field[data-w="1/5"],
.modal-overlay.is-docright .field[data-w="1/6"], .modal-overlay.is-docright .cf-field[data-w="1/6"],
.modal-overlay.is-docright .field[data-w="1/8"], .modal-overlay.is-docright .cf-field[data-w="1/8"] {
    flex: 0 0 calc(50% - 12px) !important; max-width: calc(50% - 12px) !important; }

/* Expandable record rows */
.expand-col { width: 34px; }
.expand-cell { width: 34px; text-align: center; padding-right: 0; }
.row-expand {
    border: 0; background: transparent; cursor: pointer;
    color: var(--text-muted); font-size: 12px; line-height: 1;
    padding: 4px 6px; border-radius: var(--radius-sm);
    transition: color 0.12s, background 0.12s;
}
.row-expand:hover { color: var(--primary); background: var(--primary-soft); }
.row-expand.is-open { color: var(--primary); }
.detail-row > td { background: var(--bg-subtle); padding: 0; }
.detail-panel { padding: 16px 20px 20px; }
.detail-section { margin-top: 16px; }
.detail-sub {
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--text-muted); font-weight: 600; margin-bottom: 8px;
}
.detail-text { font-size: 13px; color: var(--text); white-space: pre-wrap; line-height: 1.5; }
.tkt-comment { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; margin-bottom: 8px; }
.tkt-comment.is-internal { background: var(--warn-bg); border-color: var(--warn); }
.tkt-comment-head { display: flex; align-items: center; gap: 8px; font-size: 12.5px; margin-bottom: 4px; }
.tkt-comment-body { font-size: 13.5px; line-height: 1.5; }
.trail-comment { margin-left: 8px; margin-top: 3px; font-size: 12.5px; color: var(--text-muted); font-style: italic; }
/* Per-document history log (When · What · Who) */
.hist-head { display: grid; grid-template-columns: 132px 1fr 130px; gap: 12px; padding: 0 2px 4px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.hist-log { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.hist-row { display: grid; grid-template-columns: 132px 1fr 130px; gap: 12px; align-items: baseline; padding: 7px 10px; border-top: 1px solid var(--line); background: var(--bg-card); font-size: 12.5px; }
.hist-row:first-child { border-top: 0; }
.hist-row:nth-child(even) { background: var(--bg-subtle); }
.hist-when { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.hist-action { font-weight: 600; color: var(--text); }
.hist-detail { color: var(--text-muted); }
.hist-who { color: var(--text-muted); text-align: right; }
@media (max-width: 640px) {
    .hist-head { display: none; }
    .hist-row { grid-template-columns: 1fr; gap: 2px; }
    .hist-who { text-align: left; }
}
/* Role permissions grid */
.perm-section { margin-top: 6px; }
.perm-full { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-subtle); margin-bottom: 12px; cursor: pointer; }
.perm-full input { width: 16px; height: 16px; }
.perm-head { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin: 0 2px 6px; }
@media (max-width: 640px) {
    .perm-row { grid-template-columns: 1fr; gap: 4px; }
}
table.grid.mini { width: 100%; background: var(--bg-card); border-radius: var(--radius-sm); overflow: hidden; }
table.grid.mini th, table.grid.mini td { font-size: 12px; padding: 6px 10px; }

/* Setup tabs */
.setup-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 22px; }
.setup-tab {
    border: 0; background: transparent; cursor: pointer;
    padding: 10px 16px; font-size: 13.5px; font-weight: 600; color: var(--text-muted);
    border-bottom: 2px solid transparent; margin-bottom: -1px;
    font-family: var(--font-ui); transition: color 0.12s, border-color 0.12s;
    /* r654: 40px of padding and text is under §16's 44px touch target. It was under it in Setup too,
       where nobody had measured it — adopting this component as the lifecycle strip is what surfaced it,
       and the fix belongs on the component rather than on the one screen that noticed. */
    min-height: 44px; display: inline-flex; align-items: center;
}
.setup-tab:hover { color: var(--text); }
.setup-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }
.setup-panel[hidden] { display: none; }

/* Round 7 — keep record-detail fields equal width regardless of content */
.detail-item { min-width: 0; }
.detail-item .v { overflow-wrap: anywhere; word-break: break-word; }
/* A read-only text value that exceeds the field width is truncated with an ellipsis; the full text is
   available via the title tooltip on hover. Links/HTML values are not truncated (no v-truncate class). */
.detail-item .v.v-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; word-break: normal; overflow-wrap: normal; }
.detail-item .v a.doclink { overflow-wrap: anywhere; }

/* ============================================================
   Round 8 — icon actions, sortable/filterable lists, flows list
   ============================================================ */

/* Icon-only action buttons */
.btn-icon { padding: 6px; width: var(--control-h); height: var(--control-h);   /* r1606 — square, at the family height */ display: inline-grid; place-items: center; line-height: 0; }
.btn-icon svg { width: 16px; height: 16px; display: block; }

/* Equal-width line-item columns in record-detail panels */
table.grid.mini { table-layout: fixed; }
table.grid.mini th, table.grid.mini td { overflow-wrap: anywhere; word-break: break-word; }

/* Sortable headers + per-column filter row (list views) */
table.grid thead th.sortable { cursor: pointer; user-select: none; position: relative; padding-right: 20px; }
table.grid thead th.sortable:hover { color: var(--primary); }
table.grid thead th.sortable::after { content: "\2195"; position: absolute; right: 6px; opacity: 0.35; font-size: 11px; }
table.grid thead th.sort-asc::after { content: "\2191"; opacity: 1; color: var(--primary); }
table.grid thead th.sort-desc::after { content: "\2193"; opacity: 1; color: var(--primary); }
table.grid thead tr.filter-row th { padding: 4px 8px 8px; background: var(--bg-card); font-weight: 400; }
.col-filter {
    width: 100%; box-sizing: border-box; font-size: 12px; padding: 4px 6px;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    font-family: var(--font-ui); color: var(--text); background: var(--bg-card); font-weight: 400;
}
.col-filter:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }

/* Approval-flows list toolbar */
.flows-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.flows-toolbar .help { flex: 1; }

/* ============================================================
   Round 9 — legal entities, allocation switch, nested line detail
   ============================================================ */

/* Allocation toggle switch (PO form) */
.alloc-switch { display: flex; align-items: flex-start; gap: 12px; margin: 6px 0 16px; }
.switch { position: relative; display: inline-block; width: 42px; height: 24px; flex: none; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track { position: absolute; inset: 0; background: var(--line-strong); border-radius: 999px; transition: background 0.15s; }
.switch-track::before { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; background: var(--bg-card); border-radius: 50%; transition: transform 0.15s; box-shadow: 0 1px 2px rgba(0,0,0,0.3); }
.switch input:checked + .switch-track { background: var(--primary); }
.switch input:checked + .switch-track::before { transform: translateX(18px); }
.switch-text strong { display: block; font-size: 13px; }

/* Delivery-address rows in the legal-entity modal */
.addr-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.addr-row { display: grid; grid-template-columns: 1.2fr 1.6fr 1fr 0.7fr 1fr 32px; gap: 8px; align-items: center; }
.round-row { display: grid; grid-template-columns: 1.1fr 1.6fr 1fr 0.9fr 32px; gap: 8px; align-items: center; margin-bottom: 8px; }
.round-row .input { width: 100%; box-sizing: border-box; font-size: 13px; padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.round-row .input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.addr-row input { width: 100%; box-sizing: border-box; font-size: 13px; padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.addr-row input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Nested line-item detail (inside a record detail panel) */
.line-expand { border: 0; background: transparent; cursor: pointer; color: var(--text-muted); font-size: 11px; line-height: 1; padding: 3px 5px; border-radius: var(--radius-sm); transition: color 0.12s, background 0.12s; }
.line-expand:hover { color: var(--primary); background: var(--primary-soft); }
.line-expand.is-open { color: var(--primary); }
.line-detail-row > td { background: var(--bg-card); padding: 0; box-shadow: inset 2px 0 0 var(--primary); }
.line-detail-row .detail-panel { padding: 12px 16px; }

/* Per-line select inputs in the line editor */
.line-row select[data-sel-kind] { width: 100%; box-sizing: border-box; font-size: 12.5px; padding: 6px 6px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-family: var(--font-ui); background: var(--bg-card); color: var(--text); }
.line-row select[data-sel-kind]:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }

/* ============================================================
   Round 11 — list paging
   ============================================================ */
.pager-cell { background: var(--bg-card); border-top: 1px solid var(--line); padding: 8px 12px; }
.pager { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; font-size: 12.5px; color: var(--text-muted); }
.pager-size { display: inline-flex; align-items: center; gap: 6px; }
.pager-size-sel { font-size: 12.5px; padding: 3px 6px; border: 1px solid var(--line); border-radius: var(--radius-sm); font-family: var(--font-ui); color: var(--text); background: var(--bg-card); }
.pager-info { flex: 1; }
.pager-nav { display: inline-flex; align-items: center; gap: 4px; }
.pager-page { min-width: 92px; text-align: center; }
.pager-btn { border: 1px solid var(--line); background: var(--bg-card); color: var(--text); border-radius: var(--radius-sm); width: 28px; height: 26px; cursor: pointer; font-size: 14px; line-height: 1; }
.pager-btn:hover { border-color: var(--primary); color: var(--primary); }

/* Round 11 — line action buttons (copy + delete) */
.line-acts { display: inline-flex; gap: 4px; align-items: center; justify-content: flex-end; }
.line-copy { border: 1px solid var(--line); background: var(--bg-card); color: var(--text-muted); border-radius: var(--radius-sm); width: 26px; height: 30px; cursor: pointer; font-size: 13px; line-height: 1; }
.line-copy:hover { border-color: var(--primary); color: var(--primary); background: var(--primary-soft); }

/* Round 11 — approval AND/OR selector in the flow editor */

/* Round 11 — approval-flow AND/OR selector */

/* ===================================================== COLOUR SCHEMES (per-user preference) */
:root[data-theme="dark"] {
    /* r1108 — the selected-row tint. --row-selected was declared once in :root as a pale
       peach; on this dark theme a selected row went near-white under light ink and the text
       vanished. A dark theme needs a dark selection surface, keyed to its own family. */
    --row-selected: #243447;
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #0F141A; --bg-topmenu: #0F141A;
    /* Status colours for a DARK background (§16). They are declared once in :root for the light
       themes, where a deep green reads well; on this background the same value gives 2.4-2.6:1,
       which fails AA badly. One value cannot serve nine backgrounds, so the dark themes carry
       their own. */
    --ok: #0F7A3D;
    --warn: #8A5A00;
    --bad: #B3261E;
    --bg-app: #0F141A; --bg-card: #1A2027; --bg-subtle: #151B22;
    --text: #E6EAF0; --text-muted: #9AA6B3;
    --line: #2A323D; --line-strong: #3A4450;
    --ok-bg: #13361F; --warn-bg: #3A2B0B; --bad-bg: #3A1717; --neutral-bg: #252D38; --info-bg: #16243F;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.40);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.45);
    --shadow-lg: 0 12px 32px rgba(0,0,0,0.55);
    /* Status colours restated for this background (§16, AC-08).
     * They were declared once for nine themes, so a green chosen against paper gave 3.4:1 here and
     * a red 2.8:1 — both below AA, and both invisible as a problem because the colour still LOOKS
     * like a status. Lightened until each measures at least 4.5:1 against this theme's own
     * background, which is the only surface they are ever drawn on. */
    --ok: #3F9463;
    --warn: #A17B33;
    --bad: #C96761;
}
:root[data-theme="slate"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #E3E8EE; --bg-topmenu: #E3E8EE;
    --bg-app: #E3E8EE; --bg-card: #FBFCFE; --bg-subtle: #EBEFF4;
    --text: #1B2430; --text-muted: #586475; --line: #CDD6E0; --line-strong: #B6C2D0;
}
:root[data-theme="sand"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #F2EDE4; --bg-topmenu: #F2EDE4;
    --bg-app: #F2EDE4; --bg-card: #FFFDF8; --bg-subtle: #F7F2E9;
    --text: #2B2519; --text-muted: #6B6250; --line: #E6DDCB; --line-strong: #D6C9AE;
}
:root[data-theme="ocean"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #EAF1F7; --bg-topmenu: #EAF1F7;
    --bg-app: #EAF1F7; --bg-card: #FFFFFF; --bg-subtle: #F1F6FB;
    --text: #0E2233; --text-muted: #4F6375; --line: #D4E2EE; --line-strong: #BBD0E0;
    --primary: #0E7FB8; --primary-hover: #0A6C9E; --primary-soft: #D6ECF8; --primary-ink: #0A3954; --brand-orange: #0E7FB8;
    --btn-bg: #0E7FB8; --btn-bg-hover: #0A6C9E; --btn-text: #FFFFFF;
    --info: #0E7FB8; --info-bg: #D6ECF8;
}
:root[data-theme="forest"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #ECF2EC; --bg-topmenu: #ECF2EC;
    --bg-app: #ECF2EC; --bg-card: #FFFFFF; --bg-subtle: #F2F7F2;
    --text: #14271A; --text-muted: #5C7060; --line: #D6E4D8; --line-strong: #BCD0BF;
    --primary: #2E7D4F; --primary-hover: #266B43; --primary-soft: #D8EFE0; --primary-ink: #173E27; --brand-orange: #2E7D4F;
    --btn-bg: #2E7D4F; --btn-bg-hover: #266B43; --btn-text: #FFFFFF;
}
:root[data-theme="rose"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #F7EEF1; --bg-topmenu: #F7EEF1;
    --bg-app: #F7EEF1; --bg-card: #FFFFFF; --bg-subtle: #FBF2F5;
    --text: #2B1620; --text-muted: #7A5A65; --line: #EBD7DE; --line-strong: #DCC0CA;
    --primary: #C23B6B; --primary-hover: #A82F5B; --primary-soft: #F8DCE7; --primary-ink: #611E36; --brand-orange: #C23B6B;
    --btn-bg: #C23B6B; --btn-bg-hover: #A82F5B; --btn-text: #FFFFFF;
}
:root[data-theme="graphite"] {
    /* r1108 — the selected-row tint. --row-selected was declared once in :root as a pale
       peach; on this dark theme a selected row went near-white under light ink and the text
       vanished. A dark theme needs a dark selection surface, keyed to its own family. */
    --row-selected: #333A45;
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #1C1C1E; --bg-topmenu: #1C1C1E;
    /* Status colours for a DARK background (§16). They are declared once in :root for the light
       themes, where a deep green reads well; on this background the same value gives 2.4-2.6:1,
       which fails AA badly. One value cannot serve nine backgrounds, so the dark themes carry
       their own. */
    --ok: #0F7A3D;
    --warn: #8A5A00;
    --bad: #B3261E;
    --bg-app: #1C1C1E; --bg-card: #2A2A2D; --bg-subtle: #232325;
    --text: #ECECEE; --text-muted: #A0A0A6; --line: #3A3A3E; --line-strong: #4A4A4F;
    --primary: #E8853A; --primary-hover: #D6742A; --primary-soft: #4A3422; --primary-ink: #FFD9B5; --brand-orange: #E8853A;
    --btn-bg: #E8853A; --btn-bg-hover: #D6742A; --btn-text: #FFFFFF;
    --ok-bg: #1E3A26; --warn-bg: #3A2E12; --bad-bg: #3A1E1E; --neutral-bg: #303034; --info-bg: #1E2E40;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.40); --shadow-md: 0 4px 12px rgba(0,0,0,0.45); --shadow-lg: 0 12px 32px rgba(0,0,0,0.55);
    /* Status colours restated for this background (§16, AC-08).
     * They were declared once for nine themes, so a green chosen against paper gave 3.4:1 here and
     * a red 2.8:1 — both below AA, and both invisible as a problem because the colour still LOOKS
     * like a status. Lightened until each measures at least 4.5:1 against this theme's own
     * background, which is the only surface they are ever drawn on. */
    --ok: #3F9463;
    --warn: #A7833F;
    --bad: #C96761;
}
:root[data-theme="grape"] {
    /* r1106 — the LAYOUT'S own surfaces. .view paints --bg-scene and the appbar --bg-topmenu;
       both were :root white and no theme touched them, so every scheme rendered a white page.
       The two variables the layout actually paints must live inside every theme. */
    --bg-scene: #EFEAF6; --bg-topmenu: #EFEAF6;
    --bg-app: #EFEAF6; --bg-card: #FFFFFF; --bg-subtle: #F4F0FA;
    --text: #211633; --text-muted: #685a7d; --line: #E0D6EF; --line-strong: #CBBCE2;
    --primary: #7C3AED; --primary-hover: #6D29DE; --primary-soft: #E9DDFB; --primary-ink: #3C1D72; --brand-orange: #7C3AED;
    --btn-bg: #7C3AED; --btn-bg-hover: #6D29DE; --btn-text: #FFFFFF;
}
:root[data-theme="pharma-red"] {
    /* r1127 — "Red": a red accent on a NEUTRAL LIGHT-GREY UI (was a pale-red tint). Only the accent
       family is red; the page, surfaces, borders and text are neutral grey, shared with Sky blue. */
    --bg-scene: #F1F2F4; --bg-topmenu: #F1F2F4;
    --bg-app: #F1F2F4; --bg-card: #FFFFFF; --bg-subtle: #F7F8FA;
    --text: #1A1D21; --text-muted: #5B6470; --line: #E2E5E9; --line-strong: #CDD2D8;
    --primary: #D5202A; --primary-hover: #B81A23; --primary-soft: #FADDDE; --primary-ink: #6E1116; --brand-orange: #D5202A;
    --btn-bg: #D5202A; --btn-bg-hover: #B81A23; --btn-text: #FFFFFF;
}
:root[data-theme="pharma-blue"] {
    /* r1127 — "Sky blue": a blue accent on the same NEUTRAL LIGHT-GREY UI (was a sky-blue tint). --info
       follows the accent so informational chrome matches the scheme rather than staying orange. */
    --bg-scene: #F1F2F4; --bg-topmenu: #F1F2F4;
    --bg-app: #F1F2F4; --bg-card: #FFFFFF; --bg-subtle: #F7F8FA;
    --text: #1A1D21; --text-muted: #5B6470; --line: #E2E5E9; --line-strong: #CDD2D8;
    --primary: #0077C8; --primary-hover: #0066AD; --primary-soft: #D5EAF8; --primary-ink: #073E68; --brand-orange: #0077C8;
    --btn-bg: #0077C8; --btn-bg-hover: #0066AD; --btn-text: #FFFFFF;
    --info: #0077C8; --info-bg: #D5EAF8;
}
/* r1149 — issue 7: three more dark schemes. Each carries its own dark selection surface (--row-selected),
   the layout's own --bg-scene/--bg-topmenu, and status colours lightened to clear AA on a dark ground,
   exactly as the Midnight/Graphite blocks do — a single value cannot serve both a light and a dark page. */
:root[data-theme="obsidian"] {
    --row-selected: #123536;
    --bg-scene: #0B0F12; --bg-topmenu: #0B0F12;
    --bg-app: #0B0F12; --bg-card: #14191E; --bg-subtle: #10151A;
    --text: #E6EAF0; --text-muted: #93A0AB;
    --line: #232B32; --line-strong: #354049;
    --ok-bg: #0F3324; --warn-bg: #33280A; --bad-bg: #351717; --neutral-bg: #1F272E; --info-bg: #123A38;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.45); --shadow-md: 0 4px 12px rgba(0,0,0,0.50); --shadow-lg: 0 12px 32px rgba(0,0,0,0.60);
    --ok: #3FBF8F; --warn: #C79A3A; --bad: #E07A6E;
    --primary: #2DD4BF; --primary-hover: #14B8A6; --primary-soft: #123A38; --primary-ink: #8CE8DA; --brand-orange: #2DD4BF;
    --btn-bg: #2DD4BF; --btn-bg-hover: #14B8A6; --btn-text: #06201D;
    --info: #2DD4BF;
}
:root[data-theme="deep-sea"] {
    --row-selected: #123049;
    --bg-scene: #0B1622; --bg-topmenu: #0B1622;
    --bg-app: #0B1622; --bg-card: #132234; --bg-subtle: #0F1C2B;
    --text: #E4EBF3; --text-muted: #93A3B5;
    --line: #22344A; --line-strong: #33485F;
    --ok-bg: #0F3324; --warn-bg: #33280A; --bad-bg: #351717; --neutral-bg: #1E2D3F; --info-bg: #10314B;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.45); --shadow-md: 0 4px 12px rgba(0,0,0,0.50); --shadow-lg: 0 12px 32px rgba(0,0,0,0.60);
    --ok: #3FBF8F; --warn: #C79A3A; --bad: #E07A6E;
    --primary: #38BDF8; --primary-hover: #0EA5E0; --primary-soft: #10314B; --primary-ink: #9BD9F5; --brand-orange: #38BDF8;
    --btn-bg: #38BDF8; --btn-bg-hover: #0EA5E0; --btn-text: #04283A;
    --info: #38BDF8;
}
:root[data-theme="aubergine"] {
    --row-selected: #2C1F45;
    --bg-scene: #160E1F; --bg-topmenu: #160E1F;
    --bg-app: #160E1F; --bg-card: #211630; --bg-subtle: #1B1228;
    --text: #ECE7F3; --text-muted: #A79BB5;
    --line: #322445; --line-strong: #45355C;
    --ok-bg: #123324; --warn-bg: #33280A; --bad-bg: #351717; --neutral-bg: #281E39; --info-bg: #24234B;
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.45); --shadow-md: 0 4px 12px rgba(0,0,0,0.50); --shadow-lg: 0 12px 32px rgba(0,0,0,0.60);
    --ok: #3FBF8F; --warn: #C79A3A; --bad: #E07A6E;
    --primary: #A78BFA; --primary-hover: #8B5CF6; --primary-soft: #2C2148; --primary-ink: #CDBBFB; --brand-orange: #A78BFA;
    --btn-bg: #8B5CF6; --btn-bg-hover: #7C4DEE; --btn-text: #FFFFFF;
    --info: #A78BFA;
}

/* Preferences — colour scheme picker */
/* r662: the colour-scheme cards had their selection ring (an outset box-shadow) and the "Active" check
   clipped against the grid edge \u2014 the "no room to show the full frame" report. A little padding around the
   grid gives the ring room, the cards get a touch more min-width, and the check badge can't overflow. */
/* r664: the Preferences page \u2014 a flex column of cards with a guaranteed gap between them, so the
   sections can never overlap regardless of their content or the viewport height. Each card is a static
   block (no absolute/negative-margin positioning), and the container caps its width for readability. */
.prefs-page { display: flex; flex-direction: column; gap: 16px; align-items: stretch;
  max-width: 960px; padding-bottom: 8px; }
.prefs-page > .card { margin: 0; flex: 0 0 auto; }
.theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px;
  padding: 3px; }
.theme-card {
    position: relative; display: flex; flex-direction: column; gap: 10px; align-items: flex-start;
    padding: 14px; cursor: pointer; text-align: left; min-width: 0;
    background: var(--bg-card); border: 1.5px solid var(--line); border-radius: var(--radius);
    transition: border-color .12s, box-shadow .12s;
}
.theme-card:hover { border-color: var(--primary); box-shadow: var(--shadow-sm); }
.theme-card.is-selected { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }
.theme-swatch { display: flex; width: 100%; height: 44px; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--line); }
.theme-swatch span { flex: 1; }
.theme-name { font-weight: 600; font-size: 13px; color: var(--text); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.theme-check { font-size: 11px; font-weight: 600; color: var(--primary-ink); background: var(--primary-soft); padding: 2px 8px; border-radius: 999px; }

/* Lookup value editor rows */
.lk-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.lk-row input { flex: 1; }
#lk-values { margin-bottom: 10px; }

/* Custom-field grid (width-based layout) */
.cf-grid { display: flex; flex-wrap: wrap; gap: 18px 12px; align-items: flex-start; }
/* System-field tiles (.field) and custom-field tiles (.cf-field) share a zone; match their flex
   behaviour so built-in and custom fields size identically when laid out together. */
.cf-grid > .field { flex-grow: 0; flex-shrink: 1; min-width: 120px; }
/* In the flex cf-grid, a full-width field (col-span) needs a flex-basis, not grid-column; give the raw
   fld-1-1 / fld-1-2 chip wrappers matching widths so status/notes tiles align to the same column grid. */
.cf-grid > .field.col-span { flex-basis: 100%; }
/* When a form stacks two field grids — a primary field or read-only pills above the customizable header
   zone, as on the delivery note and goods receipt — the second grid butts tight against the first, because
   `gap` only spaces items within a grid, not between sibling grids. Give any grid that follows another grid
   the standard row gap above it, so field blocks are spaced consistently across every document form. */
.cf-grid + .cf-grid { margin-top: 18px; }
.cf-grid > .fld-1-1 { flex-basis: 100%; min-width: 120px; box-sizing: border-box; }
.cf-grid > .fld-1-2 { flex-basis: calc(50% - 12px); min-width: 120px; box-sizing: border-box; }
.cf-field { display: flex; flex-direction: column; gap: 6px; flex-grow: 0; flex-shrink: 1; min-width: 120px; }
.cf-field > label { font-size: 12px; color: var(--text); font-weight: 600; }
.cf-field > label .req { color: var(--bad); margin-left: 2px; }
.cf-field .rt-wrap, .cf-field .cf-choice { width: 100%; box-sizing: border-box; }
.cf-field > input, .cf-field > select, .cf-field > textarea {
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
    background: var(--bg-card);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
    width: 100%;
    box-sizing: border-box;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.cf-field > input.mono, .cf-field > input[inputmode="decimal"] { font-family: var(--font-mono); }
.cf-field > textarea { resize: vertical; min-height: 70px; }
.cf-field > input:focus, .cf-field > select:focus, .cf-field > textarea:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-soft);
}

/* Converted-PO chip row on requisition detail */
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }

/* Supplier onboarding + questionnaire (detail panel) */
.qa-row { padding: 8px 0; border-bottom: 1px solid var(--border); }
.qa-row:last-child { border-bottom: none; }
.qa-q { font-weight: 600; font-size: 13px; }
.qa-a { color: var(--text-muted); font-size: 13px; margin-top: 2px; }
.link-row { margin-top: 6px; }
.onb-link { display: inline-block; word-break: break-all; background: rgba(0,0,0,.05); padding: 6px 8px; border-radius: 6px; font-size: 12px; }
.pill.info { background: rgba(43,120,228,.14); color: #1f5fb0; }

/* Line-item leading expander cell */
.line-exp-cell { display: flex; align-items: center; justify-content: center; }

/* Row-actions overflow → 3-dots (kebab) menu */
.kebab-menu { position: fixed; z-index: 200; display: none; flex-direction: row; align-items: center; gap: 4px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0,0,0,.18); padding: 5px; min-width: 0; width: max-content; max-width: calc(100vw - 16px); flex-wrap: nowrap; }
.row-actions.kebab-open .kebab-menu { display: flex; }
.kebab-menu .btn { width: 32px; height: 32px; min-width: 32px; padding: 0; justify-content: center; align-items: center; gap: 0; border-radius: 8px; flex: 0 0 auto; }
.kebab-menu .btn svg { width: 16px; height: 16px; flex: 0 0 auto; }

/* Custom-field radio / checkbox groups */
.cf-choice { display: flex; flex-wrap: wrap; gap: 6px 16px; padding: 6px 0; }
.cf-opt { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 400; }
.cf-opt input { width: auto; }

/* Rich-text custom field */
.rt-wrap { border: 1px solid var(--border); border-radius: 9px; overflow: hidden; }
.rt-toolbar { display: flex; gap: 2px; padding: 4px; border-bottom: 1px solid var(--border); background: rgba(0,0,0,.03); }
.rt-btn { border: 1px solid transparent; background: transparent; border-radius: 6px; min-width: 28px; height: 26px; cursor: pointer; color: var(--text); }
.rt-btn:hover { background: rgba(0,0,0,.06); }
.rt-edit { min-height: 120px; padding: 9px 11px; outline: none; font-size: 14px; line-height: 1.5; height: auto; overflow-wrap: anywhere; }
.rt-edit:focus { box-shadow: inset 0 0 0 2px rgba(255,139,31,.35); }
.rt-view { font-size: 14px; }
.rt-view ul { margin: 4px 0; padding-left: 20px; }

/* Rich-text custom field inside a line-item detail spans the full width */
.line-detail .field.cf-rich { flex-basis: 100%; }
.line-detail .rt-edit { min-height: 96px; }

/* "Clear selection" action row inside a searchable dropdown panel */
.combo-clear-opt { padding: 8px 12px; font-size: 12.5px; font-weight: 600; color: var(--bad); cursor: pointer; border-bottom: 1px solid var(--border); }
.combo-clear-opt:hover { background: rgba(0,0,0,.04); }

/* System (built-in) fields shown weak/locked in the custom-field manager */

/* ---- Form builder (Setup → Custom fields) ---- */
.fb-tabs { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 16px; border-bottom: 1px solid var(--border); }
.fb-doc-picker { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.fb-doc-picker-label { font-weight: 600; font-size: 13px; color: var(--text-muted); white-space: nowrap; }
.fb-doc-picker-combo { flex: 1; max-width: 360px; }
.fb-tab { border: none; background: transparent; padding: 9px 12px; font-size: 13px; font-weight: 600; color: var(--text-muted); cursor: pointer; border-bottom: 2px solid transparent; }
.fb-tab:hover { color: var(--text); }
.fb-tab.active { color: var(--text); border-bottom-color: var(--orange, #FF8C1F); }
.fb-section { margin-top: 16px; }
.fb-section-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: 8px; }
.fb-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 10px 0 6px; }
.fb-zone-label { font-size: 12px; color: var(--text-muted); }
.fb-sys { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.fb-tile-sys { display: inline-flex; align-items: center; gap: 6px; padding: 5px 9px; border: 1px dashed var(--border); border-radius: 8px; font-size: 12px; opacity: .55; background: var(--bg-card); }
.fb-tile-sys .fb-lock { font-size: 10px; }
.fb-canvas { display: flex; flex-wrap: wrap; gap: 10px; min-height: 56px; padding: 10px; border: 1px dashed var(--border); border-radius: 10px; background: rgba(0,0,0,.015); }
.fb-empty { color: var(--text-muted); font-size: 13px; padding: 8px; }
.fb-tile { box-sizing: border-box; min-width: 150px; flex-grow: 0; background: var(--bg-card); border: 1px solid var(--line-strong, var(--border)); border-radius: 10px; padding: 8px 10px; cursor: grab; box-shadow: 0 1px 2px rgba(0,0,0,.05); }
.fb-tile:active { cursor: grabbing; }
.fb-tile.fb-dragging { opacity: .4; outline: 2px dashed var(--orange, #FF8C1F); }
/* r1276 — the drop indicator is a LINE in the gap, not a tile-sized hole. A hole the width of the
   dragged field pushes its neighbours aside on every move, so the reader watches the row reflow and
   infers a destination from it. A 3px bar displaces nothing and states the destination outright. */
.fb-drop-ph { box-sizing: border-box; flex: 0 0 3px; min-width: 3px; align-self: stretch; min-height: 44px;
  border: 0; border-radius: 2px; background: var(--orange, #FF8C1F); margin: 0 4px; }
.fb-tile-blank { border-style: dashed; background: repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(0,0,0,.03) 6px, rgba(0,0,0,.03) 12px); }
.fb-tile-top { display: flex; align-items: center; gap: 6px; }
.fb-grip { color: var(--text-muted); cursor: grab; font-size: 13px; }
.fb-tile-label { font-weight: 600; font-size: 13px; cursor: pointer; }
.fb-tile-label:hover { text-decoration: underline; }
.fb-tile-meta { font-size: 11px; color: var(--text-muted); margin: 2px 0 6px; }
.fb-tile-acts { display: flex; align-items: center; gap: 4px; }
/* r789: sized to its content. It was as wide as the longest label, which was a sentence. */
.fb-width { width: auto; min-width: 0; font-size: 12px; padding: 2px 4px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card); color: var(--text); }

/* Blank custom-field spacer in a rendered form */
.cf-blank .cf-spacer { height: 1px; }
.cf-blank-line .cf-spacer { height: 1px; }

/* Form builder — header layout mode (system fields reorderable) */
.fb-tile-locked { background: var(--bg-card); border-style: solid; }
.fb-tile-locked .fb-tile-label { cursor: default; }
.fb-tile-locked .fb-tile-label:hover { text-decoration: none; }
.fb-tile .fb-lock { font-size: 11px; opacity: .6; margin-left: auto; }
.fb-live { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: #fff; background: var(--orange, #FF8C1F); vertical-align: middle; }

/* Column filter dropdown (limited-value columns) */
.col-filter-sel { cursor: pointer; appearance: auto; -webkit-appearance: auto; padding-right: 4px; }

/* Grand-total row in read-only line tables */
.grid.mini tfoot .lines-total td { border-top: 2px solid var(--line-strong); font-weight: 600; padding-top: 8px; }
.grid.mini tfoot .lines-total td.num { color: var(--text); }

/* Workflows: document sub-tabs + System panel */
.flow-doc-tabs { margin-bottom: 0; }
.fb-tab-count { display: inline-block; min-width: 16px; padding: 0 5px; margin-left: 4px; font-size: 11px; line-height: 16px;
    text-align: center; border-radius: 9px; background: var(--primary-soft); color: var(--primary); font-weight: 600; }
.flow-doc-panel { padding-left: 0; padding-right: 0; }
.sys-wf-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
    padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.sys-wf-row .help { margin-top: 3px; }

/* Custom colour editor */
.theme-card-custom .theme-name { font-style: italic; }
.custom-colors { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.cc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.cc-field { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--line);
    border-radius: var(--radius-sm); background: var(--bg-card); cursor: pointer; }
.cc-input { width: 34px; height: 34px; padding: 0; border: 1px solid var(--line-strong); border-radius: 6px;
    background: none; cursor: pointer; flex: 0 0 auto; }
.cc-input::-webkit-color-swatch-wrapper { padding: 2px; }
.cc-input::-webkit-color-swatch { border: none; border-radius: 4px; }
.cc-label { flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--text); font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-hex { flex: 0 0 auto; font-family: var(--font-mono, monospace); font-size: 11px; color: var(--text-muted); }
.cc-actions { margin-top: 12px; }

/* Per-document List View column picker */
.col-picker-btn { margin-left: auto; }
.card-head .col-picker-btn { align-self: center; }
/* r1544 — inside the header's right-hand group, settings sits right after the New button rather than
   being pushed away from it, and it reads as a STANDARD button. Nothing in the code marks it active, so
   whatever painted it in the primary colour was a cascade; the look is stated here outright rather than
   left to whichever rule wins. The primary colour is for the one action a screen is for — New — and a
   second coloured button beside it says there are two. */
.card-head__acts .col-picker-btn {
    margin-left: 0;
    background: var(--bg-card); color: var(--text); border-color: var(--line-strong);
}
.card-head__acts .col-picker-btn:hover { background: var(--bg-soft, var(--bg-card)); }
.col-picker-pop {
    position: fixed; z-index: 1200; min-width: 190px; max-height: 60vh; overflow: auto;
    background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius);
    box-shadow: var(--shadow-lg); padding: 8px;
}
.col-picker-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-muted); padding: 2px 6px 6px; }
.col-picker-row { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: var(--radius-sm);
    font-size: 13px; color: var(--text); cursor: pointer; }
.col-picker-row:hover { background: var(--bg-subtle); }
.col-picker-row input { cursor: pointer; }

/* Dimensions sub-tabs + Payment terms editor */
.dim-tabs { margin-bottom: 14px; }

/* =================================================================================================
   r1402 — ONE PAGE TEMPLATE FOR EVERY SETUP PANEL.

   A Setup panel began with whatever its author put first, and each of those brings its own spacing:
   `.fb-tabs` has `padding: 0 16px` and no top margin, `.inline-note` has no padding and a 16px
   bottom margin, and Memory's `.mm-head` has neither. So Configuration, Custom fields and Memory
   each started at a different height and a different left edge, which is the discrepancy reported.

   The panel now owns its own frame: the same padding on every one, and the first child's own top
   margin collapsed away so nothing can push the page down by being the thing that happens to be
   first. Sub-tab rows lose their private horizontal padding here, because the panel supplies it.

   **When every screen brings its own spacing, the page has no layout — it has as many layouts as it
   has screens.**
   ================================================================================================= */
.setup-panel { padding: 16px; }
.setup-panel > :first-child { margin-top: 0; }
.setup-panel > .fb-tabs { padding-left: 0; padding-right: 0; }

/* r1402 — and one level down. Every Setup sub-tab renders into one of these, and they carry no rule
   at all today: a sub-panel that opens with a note sits lower than one that opens with a card, on the
   same tab row. Same normalisation, so the first thing on a sub-tab starts where the first thing on
   every other sub-tab starts. */
[data-config-panel] > :first-child,
[data-dim-panel] > :first-child,
[data-sec-panel] > :first-child,
[data-flowsub-panel] > :first-child,
[data-fields-panel] > :first-child { margin-top: 0; }
.dim-panel { margin-top: 4px; }

/* Status filter tabs above document lists */
.status-tabs { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 4px 14px; }
.status-tab { border: 1px solid var(--line); background: var(--bg-card); color: var(--text-muted);
    font-size: 12.5px; font-weight: 600; padding: 5px 12px; border-radius: 999px; cursor: pointer; }
.status-tab:hover { border-color: var(--line-strong); color: var(--text); }
.status-tab.active { background: var(--primary); border-color: var(--primary); color: #fff; }

/* Bank account rows (vendor + legal entity forms) */
.bank-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.bank-row { display: grid; grid-template-columns: 1fr 1.3fr 1.6fr 1.2fr 1fr 0.8fr 32px; gap: 8px; align-items: center; }
.bank-row input { width: 100%; box-sizing: border-box; font-size: 13px; padding: 9px 11px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.bank-row input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* Configuration templates (Setup → Configuration → Templates) */
.tpl-sections { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-bottom: 14px; }
.tpl-chk { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text); }
.tpl-import { margin: 10px 0; }
.tpl-json { width: 100%; box-sizing: border-box; min-height: 160px; font-family: var(--font-mono, monospace); font-size: 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-subtle); color: var(--text); resize: vertical; }
.tpl-json:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }

/* Inline (full-page) new-document form when the pop-up preference is off */
.inline-form { max-width: 960px; margin-left: auto; margin-right: auto; }
/* r1149 — issue 8: with the pop-up preference off, a new record opens inline in this card, which is a
   flex item in the scrolling .view. Keep it from shrinking below its content (flex-shrink) so its
   background covers the whole form — the approval flow at the bottom was ending up outside the frame —
   and keep the inline flex children shrinkable on the cross axis so wide content wraps within the card
   rather than pushing it out.
   r1153 — give the card a DEFINITE width (100%, capped by max-width). Its auto left/right margins (the
   centring) otherwise suppress the flex stretch, leaving the card sized to its content — so as the form's
   content arrived (reference data, the approval flow, line tables) the card grew toward its max width
   with no page resize. A definite width fixes the width to the container, changing only when the page
   width does. */
.inline-form { flex: 0 0 auto; width: 100%; }
.inline-form .card-pad, .inline-form #__inl-body, .inline-form #__docedit, .inline-form .form-std { min-width: 0; }
.inline-form.is-wide { max-width: 100%; }
/* On-page (in-the-view) document forms: at most 75% of the content width on wide screens
   (viewport >= 1366px), and up to full width below 1366px where 75% would be too cramped. */
@media (min-width: 1366px) { .inline-form.is-wide { max-width: 75%; } }
.inline-form .modal-foot { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }

.combo-disabled, .lines-disabled { opacity: .55; pointer-events: none; }

/* Live approval-flow preview at the bottom of forms */
.flow-preview { margin-top: 18px; }
/* r1135 — the "+ Add approver" affordance on a form's approval flow */
.flow-adhoc { margin-top: 14px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.flow-adhoc .ah-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.ah-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-card); font-size: 12px; }
.ah-chip .ah-chip-t { color: var(--text-muted); font-weight: 600; }
.ah-chip .ah-chip-x { display: inline-flex; border: 0; background: transparent; cursor: pointer; color: var(--text-muted); padding: 2px; border-radius: 999px; }
.ah-chip .ah-chip-x:hover { background: var(--bg-hover, rgba(16,24,40,0.06)); color: var(--text); }
.ah-chip .ah-chip-x svg { width: 13px; height: 13px; }
.ah-add { display: inline-flex; align-items: center; gap: 5px; border: 1px dashed var(--line); background: transparent; color: var(--text-muted); border-radius: 8px; padding: 5px 10px; font-size: 12px; font-weight: 600; cursor: pointer; }
.ah-add:hover { border-color: var(--brand, #4f46e5); color: var(--brand, #4f46e5); }
.ah-add svg { width: 14px; height: 14px; }
/* r1146 — positional insertion: a "+" between each pair of flow steps, and the inline node for an
   approver the user has added at a position.
   r1151 — the "+" is lifted to the DISC level so it rides on the connector line rather than sitting
   below it. Its z-index sits above the connector so the line meets the button rather than crossing it.
   r1152 — rows are LEFT-aligned (justify-content removed) so every row's first stage sits at the same X
   as the row above; the "+" margin-top follows the now-66px disc (centre 2px pad + 33px = 35px, so a
   24px button at margin-top 23px is centred on the line). */
.rqp__line--edit { align-items: center; }
.rqp__ins { display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
  align-self: flex-start; margin-top: 23px; position: relative; z-index: 1; }
/* the editable flow puts a 24px "+" between the 250px nodes, so the previous disc centre is 24+125=149px
   left of this node's left edge; extend the connector that far so it meets both disc centres. */
.rqp__line--edit .rqp__seg { left: -149px; }
.rqp-ins-btn { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border: 1px solid var(--btn-bg); background: var(--btn-bg); color: var(--btn-text); border-radius: 999px; cursor: pointer; padding: 0; }
.rqp-ins-btn:hover { border-color: var(--btn-bg-hover); background: var(--btn-bg-hover); color: var(--btn-text); }
.rqp-ins-btn svg { width: 14px; height: 14px; }
.rqp__node--adhoc .rqp__ic.supb-kpi__ic { box-shadow: 0 0 0 3px var(--bg-subtle), 0 0 0 4px var(--brand, #4f46e5); }
.rqp__node--adhoc .rqp__lbl { color: var(--brand, #4f46e5); }
.rqp__node--adhoc .ah-node-x { display: inline-flex; align-items: center; margin-top: 4px; border: 1px solid var(--line); background: var(--bg-card); cursor: pointer; color: var(--text-muted); padding: 2px 6px; border-radius: 999px; }
.rqp__node--adhoc .ah-node-x:hover { border-color: var(--danger, #dc2626); color: var(--danger, #dc2626); }
.rqp__node--adhoc .ah-node-x svg { width: 12px; height: 12px; }
.ah-picker-at { font-size: 12px; color: var(--text-muted); font-weight: 600; margin-right: 4px; align-self: center; }
.supb-kpi__ic--accent { background: var(--brand-bg, rgba(79,70,229,0.12)); color: var(--brand, #4f46e5); }
.ah-picker { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ah-picker .ah-type { width: auto; min-width: 96px; }
.ah-picker .ah-value { width: auto; min-width: 200px; }
.flow-preview .flow-badge { font-size: 11px; font-weight: 600; color: var(--primary-ink); background: var(--primary-soft); border-radius: 999px; padding: 2px 9px; margin-left: 8px; }
.flow-preview .flow-cond { font-size: 12px; margin: 2px 0 12px; }
.flow-preview .flow-cond em { font-style: normal; color: var(--text-muted); font-weight: 600; }

/* Horizontal "business" approval flow — wraps to new lines, connected across wraps */
.wf-flow { display: flex; flex-wrap: wrap; align-items: stretch; row-gap: 8px; }
.wf-seg { display: flex; align-items: center; min-width: 0; }
.wf-node { display: flex; align-items: center; gap: 9px; background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: 10px; padding: 7px 11px; min-width: 0; }
.wf-node-num { width: 24px; height: 24px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 50%; background: var(--primary-soft); color: var(--primary-ink); font-size: 12px; font-weight: 700; }
.wf-node-info { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.wf-node-name { font-size: 12.5px; font-weight: 650; color: var(--text); white-space: nowrap; }
.wf-node-who { display: flex; align-items: center; gap: 5px; margin-top: 1px; }
.wf-who-ic { display: inline-flex; align-items: center; color: var(--text-muted); }
.wf-who-ic svg { width: 13px; height: 13px; }
.wf-who-name { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.wf-node-type { font-size: 9.5px; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-muted); background: var(--bg-subtle); border: 1px solid var(--line); border-radius: 999px; padding: 0 6px; }
.wf-node-cap { display: inline-block; align-self: flex-start; margin-top: 3px; font-size: 10.5px; font-weight: 600; color: var(--primary-ink); background: var(--primary-soft); border-radius: 5px; padding: 1px 6px; }
/* connector between steps */
.wf-conn { flex: 0 0 auto; align-self: center; width: 20px; height: 2px; margin: 0 4px; background: var(--line-strong); position: relative; }
.wf-conn::after { content: ""; position: absolute; right: -1px; top: 50%; transform: translateY(-50%); border-left: 5px solid var(--line-strong); border-top: 4px solid transparent; border-bottom: 4px solid transparent; }
/* status colours on the node marker (runtime trail) */
.wf-node.is-approved .wf-node-num { background: var(--good-bg, #e7f6ec); color: var(--good, #1a7f37); }
.wf-node.is-rejected .wf-node-num { background: var(--bad-bg, #fdeaea); color: var(--bad, #c2362f); }
.wf-node.is-current { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-soft); }
.wf-node.is-current .wf-node-num { background: var(--primary); color: #fff; }
.wf-node.is-waiting .wf-node-num { background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--line-strong); }
/* round "+" add-an-approver affordance */
.wf-add { flex: 0 0 auto; align-self: center; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 50%; cursor: pointer; background: var(--btn-bg); color: var(--btn-text); border: 1px solid var(--btn-bg); padding: 0; transition: background 0.12s, color 0.12s; }
.wf-add:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); color: var(--btn-text); }
.wf-add svg { width: 15px; height: 15px; }
.trail-comment-who { font-weight: 600; color: var(--text); }

/* Multiple-flow preview groups + system tag */
.flow-meta { font-size: 11.5px; font-weight: 500; color: var(--text-muted); margin-left: 8px; }
.flow-groups { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; }
.flow-group { margin: 0; flex: 1 1 250px; min-width: 230px; border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; background: var(--bg-card); box-shadow: var(--shadow-xs, 0 1px 2px rgba(16, 24, 40, 0.04)); }
.flow-group-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; padding-bottom: 10px; border-bottom: 1px solid var(--line); }
.flow-group-head .flow-badge { margin-left: 0; }
.flow-group-head .flow-cond { width: 100%; font-size: 11.5px; margin: 2px 0 0; color: var(--text-muted); }
.flow-sys-tag { font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); background: var(--bg-subtle); border: 1px solid var(--line); border-radius: 999px; padding: 1px 8px; }

/* Custom field: Attachment control + Line break separator */
.cf-att { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cf-att-btn { cursor: pointer; margin: 0; }
.cf-att-current { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; min-width: 0; }
.cf-att-empty { color: var(--text-muted); }
.cf-att-link { color: var(--brand); text-decoration: none; word-break: break-all; }
.cf-att-link:hover { text-decoration: underline; }
.cf-att-size { color: var(--text-muted); font-size: 11.5px; }
.cf-att-clear { border: none; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px; }
.cf-att-clear:hover { color: var(--danger, #c0392b); }
.cf-linebreak { display: flex; flex-direction: column; gap: 6px; padding: 2px 0; }
.cf-break-label { font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.cf-rule { width: 100%; border: none; border-top: 1px solid var(--line); margin: 0; }

/* System workflow setting toggle + de-duplicated step note */
.sys-setting-card { margin-bottom: 14px; }
.sys-setting-row { display: flex; align-items: flex-start; gap: 18px; justify-content: space-between; }
.sys-setting-text { min-width: 0; }
.flow-dupe-note { margin: 0; }

/* Security: user group/role checkbox pickers in the user form */

/* Workflow list: type badge + expandable detail */
.wf-type-tag { display: inline-block; font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px;
    background: var(--accent-soft, var(--bg-subtle)); color: var(--accent, var(--text)); border: 1px solid var(--line-strong); }
.wf-type-tag.hier { background: var(--warn-bg, var(--bg-subtle)); color: var(--warn, var(--text)); }
.appr-type-tag { display: inline-block; font-size: 11px; font-weight: 600; padding: 1px 8px; border-radius: 6px;
    background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--line); }
.flow-detail-cond { font-size: 13px; color: var(--text); margin: 2px 0 6px; }
.flow-detail-cond em { color: var(--text-muted); font-style: normal; font-weight: 600; padding: 0 3px; }

/* Contract recognition + AI config note variants */
.inline-note.warn { border-color: var(--warn, #b78103); background: var(--warn-bg, rgba(183,129,3,.08)); color: var(--text); }
.inline-note.err { border-color: var(--bad, #c0392b); background: var(--bad-bg, rgba(192,57,43,.08)); color: var(--text); }

/* ===================== PO Monitor ===================== */
.metric.accent-teal::before { background: #14b8a6; }
.metric.accent-rose::before { background: #f43f5e; }

.two-col.mon-charts { grid-template-columns: 1fr 1fr; margin-bottom: 22px; }

/* status donut */
.donut-wrap { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.donut { width: 150px; height: 150px; flex: none; }
.donut-num { font-family: var(--font-mono); font-size: 30px; font-weight: 700; fill: var(--text); }
.donut-cap { font-size: 11px; fill: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.donut-legend { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 190px; }
.lg-row { display: flex; align-items: center; gap: 9px; background: none; border: 0; padding: 4px 6px; border-radius: 7px; cursor: pointer; font: inherit; color: var(--text); text-align: left; width: 100%; }
.lg-row:hover { background: var(--bg-subtle); }
.lg-dot { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.lg-name { flex: 1; font-size: 13px; }
.lg-val { font-family: var(--font-mono); font-weight: 600; font-size: 13px; }

/* spend pipeline */
.pipe { display: flex; flex-direction: column; gap: 13px; }
.pipe-row { display: grid; grid-template-columns: 78px 1fr auto; align-items: center; gap: 12px; }
.pipe-label { font-size: 12.5px; color: var(--text-muted); font-weight: 600; }
.pipe-track { height: 22px; background: var(--bg-subtle); border-radius: 6px; overflow: hidden; }
.pipe-fill { height: 100%; border-radius: 6px; min-width: 2px; transition: width 0.3s ease; }
.pipe-val { font-family: var(--font-mono); font-size: 13px; font-weight: 600; white-space: nowrap; }
.pipe-pct { color: var(--text-muted); font-weight: 500; font-size: 11.5px; margin-left: 3px; }
.pipe-foot { color: var(--text-muted); font-size: 11.5px; margin-top: 4px; }

/* stage tag */
.stag { display: inline-block; padding: 3px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }

/* filter chips */
.mon-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 14px 20px 6px; }
.mon-chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; border: 1px solid var(--line); background: var(--bg-card); border-radius: 999px; cursor: pointer; font: inherit; font-size: 12.5px; color: var(--text); }
.mon-chip:hover { background: var(--bg-subtle); }
.mon-chip.is-active { background: var(--primary-soft); color: var(--primary-ink); border-color: var(--primary); font-weight: 600; }
.mon-chip .chip-n { font-family: var(--font-mono); font-weight: 700; font-size: 11.5px; opacity: 0.85; }
.mon-chip .lg-dot { width: 9px; height: 9px; }

/* PO table with expandable item detail */
.mon-table th.exp-c, .mon-table td.exp-c { width: 34px; text-align: center; padding-left: 10px; padding-right: 0; }
.mon-caret { display: inline-block; color: var(--text-muted); font-size: 11px; }
.mon-po-row { cursor: pointer; }
.mon-po-row:hover, .mon-po-row.is-open { background: var(--bg-subtle); }
.mon-po-row.is-open .mon-caret { color: var(--text); }
.mon-table tbody.mon-po { border-bottom: 1px solid var(--line); }
.mon-table tbody.mon-po:last-child { border-bottom: 0; }
.mon-lines > td { padding: 0; background: var(--bg-subtle); border-bottom: 1px solid var(--line); }
.mon-line-wrap { padding: 8px 16px 16px 44px; }
.mon-line-tbl { width: 100%; border-collapse: collapse; background: var(--bg-card); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.mon-line-tbl th { text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); font-weight: 600; padding: 9px 12px; border-bottom: 1px solid var(--line); background: var(--bg-subtle); white-space: nowrap; }
.mon-line-tbl th.num, .mon-line-tbl td.num { text-align: right; }
.mon-line-tbl td { padding: 9px 12px; border-bottom: 1px solid var(--line); font-size: 13px; vertical-align: middle; }
.mon-line-tbl tbody tr:last-child td { border-bottom: 0; }

/* item progress mini-bar (received vs invoiced over ordered) */
.mbar-cell { min-width: 96px; }
.mbar { position: relative; height: 16px; background: var(--bg-subtle); border-radius: 4px; overflow: hidden; min-width: 84px; }
.mbar-recv { position: absolute; left: 0; top: 0; height: 100%; background: #5eead4; border-radius: 4px; }
.mbar-inv { position: absolute; left: 0; top: 0; height: 100%; background: #14b8a6; border-radius: 4px; }

@media (max-width: 900px) { .two-col.mon-charts { grid-template-columns: 1fr; } }

/* config import mode selector */

/* ===================== Field-mapping builder (list + tile editor) ===================== */
.map-list-row { cursor: pointer; }
.map-edit-title { flex: 1; text-align: center; }

/* Mapping name centred on the page */
.map-active { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); cursor: pointer; white-space: nowrap; }

.map-flow-hint { font-size: 12px; padding: 8px 11px; border-radius: var(--radius-sm); line-height: 1.45; border: 1px solid var(--line); margin-bottom: 12px; }
.map-flow-hint.ok { background: var(--ok-bg); border-color: var(--ok-bg); color: var(--text); }
.map-flow-hint.warn { background: var(--warn-bg); border-color: var(--warn-bg); color: var(--text); }

.map-help { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.map-help strong { color: var(--text); }

/* Two columns of fields (source | flip | target); the document selector sits on top of each list. */
.map-col-cap { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); text-align: center; }

.map-row { display: grid; grid-template-columns: minmax(170px, 1fr) 120px minmax(170px, 1fr) 38px; align-items: center; column-gap: 12px; row-gap: 10px; padding: 9px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.map-row.has-tf { border-color: var(--primary); }
.map-lvl { font-size: 11px; height: 28px; padding: 0 6px; color: var(--text-muted); }
.map-src-end .map-lvl, .map-tgt-end .map-lvl { align-self: flex-start; width: auto; min-width: 84px; }

/* connecting line with the 3-dot transformation control in the centre */
.map-row.has-tf .map-link::before { background: var(--primary); }
.map-dots { position: relative; z-index: 1; min-width: 40px; height: 24px; padding: 0 8px; border-radius: 12px; border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--text-muted); cursor: pointer; font-size: 15px; line-height: 1; letter-spacing: 2px; display: inline-flex; align-items: center; justify-content: center; }
.map-dots:hover { border-color: var(--primary); color: var(--primary); }
.map-dots.is-set { background: var(--primary); color: #fff; border-color: var(--primary); }
.map-dots.is-open { box-shadow: 0 0 0 3px var(--primary-soft); }

/* expandable transformation panel for a mapping line */
.map-tf-panel { grid-column: 1 / -1; padding: 12px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-subtle); }
.map-tf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; }
.map-tf-grid .field { gap: 5px; }
.map-tf-hint { margin-top: 9px; font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.map-tf-hint code { background: var(--bg-card); padding: 1px 5px; border-radius: 4px; font-family: var(--font-mono); font-size: 11.5px; }

.map-empty { padding: 18px 14px; font-size: 13px; color: var(--text-muted); line-height: 1.5; background: var(--bg-card); border: 1px dashed var(--line); border-radius: var(--radius-sm); }
.map-row-warn { grid-column: 1 / -1; font-size: 11.5px; color: var(--warn); background: var(--warn-bg); border-radius: var(--radius-sm); padding: 6px 9px; }

@media (max-width: 720px) {
    .map-cols-head, .map-row { grid-template-columns: 1fr 46px 1fr 26px; column-gap: 6px; }
    .map-rows-head { display: none; }
}

@media (max-width: 720px) {
    .map-tile { flex-basis: calc(50% - 10px) !important; }
    .map-rows-head { display: none; }
    .map-row { grid-template-columns: 1fr; row-gap: 7px; }
    .map-row-arrow { display: none; }
    .map-row-del { justify-self: start; }
    .map-row-a1, .map-row-a2 { width: 100%; }
}

/* ============================================================
   Round 72 — visual field-mapping editor (drag & drop rectangles)
   ============================================================ */
.map-doc-row { display: flex; gap: 16px; margin: 4px 0 12px; flex-wrap: wrap; }
.map-doc-pick { flex: 1 1 220px; display: flex; flex-direction: column; gap: 4px; }
.map-doc-pick .map-col-cap { font-size: 12px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.map-canvas { display: flex; align-items: stretch; gap: 12px; margin: 8px 0 4px; }
.map-canvas-mid { display: flex; align-items: center; justify-content: center; font-size: 22px; color: var(--primary); flex: 0 0 28px; }
.map-panel { flex: 1 1 0; min-width: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-subtle); padding: 10px; }
.map-panel-head { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 8px; }
.map-group-cap { font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; margin: 8px 0 4px; }
.map-tilewrap { display: flex; flex-direction: column; gap: 6px; min-height: 34px; align-content: flex-start; padding: 2px; border-radius: var(--radius-sm); }
.map-tile.fb-tile { flex: 0 0 auto; width: 100%; max-width: 100%; margin: 0; cursor: grab; }
.map-tile.fb-tile:hover { border-color: var(--primary); }
.map-tile .fb-tile-top { gap: 6px; }
.map-tile .fb-tile-label { font-size: 12px; }
.map-tile-meta { display: flex; align-items: center; gap: 6px; }
.map-tile-size { font-size: 10px; font-weight: 700; color: var(--primary-ink); background: var(--primary-soft); border: 1px solid var(--primary); border-radius: 999px; padding: 1px 8px; letter-spacing: .02em; }
.map-head-form { margin: 4px 0 10px; }
.map-switch { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; align-self: center; }
.map-cf-head { font-weight: 700; font-size: 13px; margin: 10px 0 6px; }
.map-tile-key { color: var(--text-muted); font-family: var(--font-mono); font-size: 11px; }
.map-tile-cf { color: var(--primary-ink); font-weight: 700; font-style: italic; }
.map-tile-custom.fb-tile { background: var(--primary-soft); border-color: var(--primary); }
.map-tile.is-linked.fb-tile { border-color: var(--ok); box-shadow: inset 0 0 0 1px var(--ok); }
.map-tile.is-armed.fb-tile { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary); background: var(--primary-soft); }
.map-conn-head { display: flex; align-items: baseline; justify-content: space-between; margin: 16px 0 6px; font-weight: 700; font-size: 14px; }
.map-conns { display: flex; flex-direction: column; gap: 6px; }
.map-conn { border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); padding: 7px 10px; }
.map-conn.has-tf { border-color: var(--primary); }
.map-conn-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.map-conn-src, .map-conn-tgt { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; flex: 0 1 auto; }
.map-conn-tgt { font-weight: 600; }
.map-conn-mid { display: inline-flex; align-items: center; gap: 0; flex: 1 1 60px; min-width: 60px; background: none; border: none; padding: 0; cursor: pointer; }
.map-conn-line { flex: 1 1 auto; height: 2px; background: var(--line-strong); min-width: 10px; }
.map-dots-ico { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--text-muted); font-size: 16px; line-height: 1; flex: 0 0 auto; }
.map-conn-mid.is-set .map-dots-ico { border-color: var(--primary); background: var(--primary); color: #fff; }
.map-conn-mid.is-open .map-dots-ico { border-color: var(--primary); color: var(--primary); }
.map-conn-mid.is-set .map-conn-line, .map-conn-mid.is-open .map-conn-line { background: var(--primary); }
.map-conn-del { flex: 0 0 auto; }
.map-lvl-badge { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted); background: var(--bg-subtle); border: 1px solid var(--line); border-radius: 999px; padding: 1px 7px; }

/* ---- List-view multi-select + bulk-action toolbar (R81) ---- */
.grid th.sel-col, .grid td.sel-cell { width: 34px; text-align: center; padding-left: 8px; padding-right: 4px; }
.grid td.sel-cell input[type="checkbox"], .grid th.sel-col input[type="checkbox"] { cursor: pointer; width: 15px; height: 15px; accent-color: var(--primary); }
.bulk-bar { display: flex; align-items: center; gap: 12px; padding: 8px 14px; margin: 0 0 10px; background: var(--primary-soft); border: 1px solid var(--line-strong); border-radius: var(--radius); }
.bulk-bar .bulk-count { font-weight: 600; color: var(--primary-ink); }
.bulk-bar .bulk-actions { display: flex; gap: 8px; margin-left: auto; }

/* Per-user document access grid (Users ▸ Groups & Roles & Documents) */
.doc-access-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 18px; margin-top: 6px; }
.doc-access-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 8px; margin: 0; cursor: default; }
.doc-access-row > span:first-child { font-size: 13px; color: var(--text); }
@media (max-width: 640px) { .doc-access-grid { grid-template-columns: 1fr; } }

/* Database connections (Setup ▸ Configuration ▸ Database) — the list uses the standard table.grid */
.card-head .head-actions { display: flex; gap: 8px; align-items: center; }
@media (max-width: 640px) { .card-head { flex-wrap: wrap; gap: 8px; } .card-head .head-actions { width: 100%; } }

/* ===================== Layout toggle (Classic / Shop) under the logo ===================== */
.view-toggle { display: flex; gap: 4px; margin: 0 16px 14px; padding: 3px; background: var(--bg-sidebar-hover); border-radius: 999px; }
.vt-btn { flex: 1; border: 0; background: transparent; color: var(--text-on-dark); font: inherit; font-size: 12.5px; font-weight: 600; padding: 6px 10px; border-radius: 999px; cursor: pointer; transition: background .15s, color .15s; }
.vt-btn:hover { color: var(--text-on-dark-strong); }
.vt-btn.is-active { background: var(--primary); color: #fff; }

/* ===================== Catalog picker overlay ===================== */
.cat-pick-ov { position: fixed; inset: 0; background: rgba(15,23,42,.45); z-index: 9999; display: flex; align-items: center; justify-content: center; padding: 24px; }
.cat-pick { width: min(680px, 96vw); max-height: 86vh; display: flex; flex-direction: column; background: var(--bg-card); border-radius: var(--radius); box-shadow: var(--shadow-lg); overflow: hidden; }
.cat-pick-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--line); font-size: 15px; }
.cat-pick-x { border: 0; background: transparent; font-size: 22px; line-height: 1; color: var(--text-muted); cursor: pointer; }
.cat-pick-tools { padding: 12px 18px; border-bottom: 1px solid var(--line); }
.cat-pick-list { overflow: auto; padding: 6px 10px; flex: 1; }
.cat-row { display: grid; grid-template-columns: 30px 1fr 76px; align-items: center; gap: 10px; padding: 8px; border-radius: var(--radius-sm); }
.cat-row:hover { background: var(--bg-subtle); }
.cat-row.on { background: var(--primary-soft); }
.cat-row-name { font-weight: 600; font-size: 13.5px; }
.cat-row-sub { color: var(--text-muted); font-size: 12px; margin-top: 1px; }
.cat-pick-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 18px; border-top: 1px solid var(--line); }
.cat-pick-foot-btns { display: flex; gap: 8px; }
.shop-qty, .cat-row-qty { width: 100%; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); padding: 6px 8px; font: inherit; background: var(--bg-card); color: var(--text); }

/* ===================== E-shop ===================== */
.shop { display: grid; grid-template-columns: 1fr 320px; gap: 18px; align-items: start; }
.shop-toolbar { display: flex; gap: 10px; margin-bottom: 14px; }
.shop-toolbar #shop-q { flex: 1; }
.shop-cat-sel { width: 230px; }
.shop-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; }
.shop-card { display: flex; flex-direction: column; gap: 4px; background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; box-shadow: var(--shadow-sm); }
.shop-card-cat { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--primary); font-weight: 700; }
.shop-card-name { font-weight: 600; font-size: 14px; line-height: 1.25; }
.shop-card-code { font-size: 12px; color: var(--text-muted); }
.shop-card-price { font-size: 15px; font-weight: 700; margin-top: 4px; }
.shop-unit { font-size: 12px; font-weight: 500; color: var(--text-muted); }
.shop-quote { font-size: 13px; font-weight: 600; color: var(--text-muted); }
.shop-card-sup { font-size: 12px; color: var(--text-muted); min-height: 16px; }
.shop-card-foot { display: flex; gap: 8px; margin-top: 10px; }
.shop-card-foot .shop-qty { width: 64px; }
.shop-add { flex: 1; }
.shop-cart { position: sticky; top: 16px; background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); padding: 16px; }
.shop-cart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; font-size: 15px; }
.shop-cart-empty { color: var(--text-muted); font-size: 13px; }
.shop-cart-list { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow: auto; }
.shop-cart-row { display: grid; grid-template-columns: 1fr auto 22px; align-items: center; gap: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.scr-name { font-weight: 600; font-size: 13px; }
.scr-sub { font-size: 11.5px; color: var(--text-muted); }
.scr-qty { display: flex; align-items: center; gap: 6px; }
.scr-step { width: 22px; height: 22px; border: 1px solid var(--line-strong); background: var(--bg-subtle); color: var(--text); border-radius: var(--radius-sm); cursor: pointer; font-size: 14px; line-height: 1; }
.scr-rm { border: 0; background: transparent; color: var(--text-muted); font-size: 16px; cursor: pointer; }
.shop-cart-total { display: flex; align-items: center; justify-content: space-between; margin: 12px 0 4px; font-size: 14px; }
.shop-cart-note { font-size: 11.5px; margin-bottom: 10px; }
.shop-checkout { width: 100%; }
.shop-clear { width: 100%; margin-top: 6px; }
.line-tools { margin-top: 8px; }
.pr-pc-toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; font-weight: 600; color: var(--text-muted); user-select: none; vertical-align: middle; }
.foot-add { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pc-proposal { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.pc-exp-cell { width: 28px; text-align: center; padding-left: 4px; padding-right: 4px; }
.pc-exp { background: none; border: none; cursor: pointer; color: var(--text-muted); font-size: 12px; line-height: 1; padding: 4px; border-radius: 4px; transition: transform 0.15s ease; }
.pc-exp:hover { background: var(--bg-subtle); }
.pc-exp.open { transform: rotate(180deg); }
.pc-detail-row > td { background: var(--bg-subtle); }
.pc-sup { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; padding: 5px 2px; }
.pc-sup + .pc-sup { border-top: 1px solid var(--line); }
.pc-exist { font-size: 12px; color: var(--text-muted); font-weight: 600; white-space: nowrap; }
.addr-country-host { min-width: 0; }
/* Process designer (node-graph canvas) */
.pd-wrap { display: flex; flex-direction: column; }
.pd-bar { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm) var(--radius-sm) 0 0; background: var(--bg-card); flex-wrap: wrap; }
.pd-bar-name { font-size: 15px; }
.pd-hint { font-size: 12px; color: var(--text-muted); }
.pd-bar-spacer { flex: 1; }
.pd-dirty { font-size: 12px; color: var(--primary); font-weight: 600; }
.pd-body { display: grid; grid-template-columns: 178px 1fr; border: 1px solid var(--line); border-top: none; overflow: hidden; }
.pd-palette { padding: 12px; border-right: 1px solid var(--line); background: var(--bg-subtle); display: flex; flex-direction: column; gap: 6px; }
.pd-pal-btn { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 9px 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer; font-family: var(--font-ui); }
.pd-pal-btn:hover { border-color: var(--primary); }
.pd-pal-ico { width: 18px; text-align: center; color: var(--text-muted); }
.pd-pal-note { margin-top: 10px; font-size: 11px; color: var(--text-muted); line-height: 1.45; }
.pd-canvas { position: relative; height: 46vh; min-height: 300px; overflow: auto; background: var(--bg-app); background-image: radial-gradient(var(--line) 1px, transparent 1px); background-size: 22px 22px; }
.pd-edges { position: absolute; top: 0; left: 0; }
.pd-edge { pointer-events: stroke; }
.pd-node { position: absolute; background: var(--bg-card); border: 1px solid var(--line-strong); border-left-width: 4px; border-radius: var(--radius-sm); box-shadow: 0 1px 4px rgba(15,23,42,.12); user-select: none; }
.pd-node.selected { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.pd-node.connecting { outline: 2px dashed var(--primary); outline-offset: 2px; }
.pd-node-ico { color: var(--text-muted); font-size: 12px; }
.pd-node-del { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; }
.pd-node-del:hover { color: #c0392b; }
.pd-port { position: absolute; top: 18px; width: 13px; height: 13px; border-radius: 50%; background: var(--bg-card); border: 2px solid var(--text-muted); display: flex; align-items: center; justify-content: center; font-size: 9px; color: var(--text-muted); line-height: 1; }
.pd-port-in { left: -7px; }
.pd-port-out { right: -7px; cursor: crosshair; }
.pd-port-out:hover { border-color: var(--primary); color: var(--primary); }
.pd-def-kind.pd-node-START { color: #2e9e5b; } .pd-def-kind.pd-node-DOCUMENT { color: var(--primary); }
.pd-def-kind.pd-node-ACTION { color: #2d7ff9; } .pd-def-kind.pd-node-CONTROL { color: #8e44ad; }
.pd-def-kind.pd-node-DECISION { color: #b9890a; } .pd-def-kind.pd-node-END { color: #c0392b; }
/* popup (pop-out) host */
.pd-overlay { position: fixed; inset: 0; background: rgba(15,23,42,.45); z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 22px; }
.pd-popup { width: min(1180px, 96vw); max-height: 94vh; overflow: auto; background: var(--bg-card); border-radius: var(--radius); box-shadow: 0 18px 60px rgba(0,0,0,.35); }
.pd-popup .pd-bar { border-radius: var(--radius) var(--radius) 0 0; position: sticky; top: 0; z-index: 5; }
/* definition panel below the canvas */
.pd-def-kind { font-size: 13px; font-weight: 700; white-space: nowrap; }
.pd-def-name { flex: 0 0 auto; width: 100%; box-sizing: border-box; font-size: 13px; font-weight: 600; padding: 7px 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.pd-def-label { font-size: 12px; font-weight: 700; color: var(--text); }
.pd-def-hint { font-weight: 400; color: var(--text-muted); margin-left: 6px; font-size: 11px; }
.pd-def-col select, .pd-c-op { width: 100%; box-sizing: border-box; font-size: 13px; padding: 7px 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.pd-stack { display: flex; flex-direction: column; gap: 28px; }
.pd-none { font-size: 12px; }
.pd-cond { display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 6px; align-items: center; }
.pd-param input, .pd-cond input { width: 100%; box-sizing: border-box; font-size: 12px; padding: 6px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.pd-param .pd-c-op, .pd-cond .pd-c-op { padding: 6px 8px; font-size: 12px; }
.pd-x { border: none; background: none; color: var(--text-muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 3px; }
.pd-x:hover { color: #c0392b; }
.pd-assign { display: flex; align-items: center; gap: 6px; font-size: 12px; padding: 5px 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.pd-assign-n { color: var(--text-muted); font-weight: 700; }
.pd-assign-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-mini { border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--text-muted); cursor: pointer; font-size: 11px; line-height: 1; border-radius: 4px; padding: 2px 5px; }
.pd-mini:disabled { opacity: .4; cursor: default; }
.pd-add-row { margin-top: 2px; }
/* designer v3: editable process metadata strip + derived I/O field rows */
.pd-meta { display: flex; gap: 8px; align-items: center; padding: 8px 10px; border: 1px solid var(--line); border-top: none; background: var(--bg-card); }
.pd-meta-name { flex: 0 1 300px; font-size: 14px; font-weight: 600; }
.pd-meta-desc { flex: 1 1 auto; font-size: 13px; }
.pd-meta input, .pd-meta select { box-sizing: border-box; padding: 7px 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.pd-meta-status { flex: 0 0 130px; }
.pd-io-row { gap: 7px; }
.pd-io-src { flex: 0 0 auto; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; border-radius: 4px; padding: 1px 5px; }
.pd-io-custom { background: rgba(245,130,31,.16); color: var(--primary); }
.pd-io-req { color: #c0392b; font-weight: 700; }
.pd-io-lock { color: var(--line-strong); font-size: 11px; padding: 0 4px; }
.pd-cf-add { display: flex; gap: 6px; align-items: center; }
.pd-cf-add .pd-cf-label { flex: 1 1 auto; min-width: 0; box-sizing: border-box; font-size: 12px; padding: 6px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font-family: var(--font-ui); }
.pd-cf-add .pd-cf-type { flex: 0 0 auto; font-size: 12px; padding: 6px 8px; }
/* designer refinements (r157): resizable splitter + standard field formatting */
.pd-edge-temp { pointer-events: none; }
/* align designer inputs/selects with the standard field box (matches .field input) */
.pd-meta input, .pd-meta select,
.pd-define input:not([type="checkbox"]), .pd-define select, .pd-define textarea {
    font-family: var(--font-ui); font-size: 13px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); box-sizing: border-box;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.pd-meta input, .pd-meta select, .pd-def-name, .pd-cf-add .pd-cf-label,
.pd-def-col select, .pd-c-op, .pd-c-field, .pd-c-val,
.pd-io-add .pd-iof-label { padding: 9px 11px; }
.pd-meta input:focus, .pd-meta select:focus,
.pd-define input:focus, .pd-define select:focus, .pd-define textarea:focus {
    outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
/* the searchable combo that replaces each designer <select> already uses the standard box;
   keep it flush to the field width */
.pd-meta .combo, .pd-define .combo { width: 100%; min-width: 0; }
.pd-cf-add .pd-cf-type { flex: 0 0 150px; }
/* Per-node input/output field editor (add a field, upload an example JSON) */
.pd-io-add { display: flex; gap: 6px; align-items: center; margin-top: 6px; flex-wrap: wrap; }
.pd-io-add .pd-iof-label { flex: 1 1 120px; min-width: 0; }
.pd-io-add select { flex: 0 0 132px; }
.pd-io-defined { margin-top: 6px; }
.pd-io-json-btn { margin-top: 4px; }
.pd-io-hint { margin-top: 4px; }
/* JSON shown when testing an email (received message transformed into an object) */
.pd-json { margin-top: 6px; max-height: 240px; overflow: auto; background: var(--bg-app); border: 1px solid var(--line);
    border-radius: var(--radius-sm); padding: 10px 12px; font-family: var(--font-mono); font-size: 12px; line-height: 1.5; color: var(--text); white-space: pre; }
.pd-em-actions { display: flex; gap: 8px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.pd-cond { grid-template-columns: 1fr 1fr 1fr auto; }
@media (max-width: 760px) { .pd-define-grid { grid-template-columns: 1fr; } }
@media (max-width: 900px) { .pd-body { grid-template-columns: 1fr; } .pd-palette, .pd-inspector { border: none; border-top: 1px solid var(--line); } }

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

/* ===================== Open PR/PO monitor ===================== */
.appr-chip { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; white-space: nowrap; }
.appr-ok { background: #DCFCE7; color: #166534; }
.om-bar-row { display: grid; grid-template-columns: 160px 1fr 34px; align-items: center; gap: 10px; margin: 7px 0; }
.om-bar-label { font-size: 12.5px; color: var(--text); }
.om-bar-track { height: 8px; background: var(--bg-subtle); border-radius: 999px; overflow: hidden; }
.om-bar-fill { display: block; height: 100%; background: var(--primary); border-radius: 999px; }
.om-bar-n { text-align: right; font-size: 12.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.om-table td { vertical-align: middle; }
.om-row.is-aging { background: rgba(244, 63, 94, 0.05); }
.om-row.is-pending td:first-child { box-shadow: inset 3px 0 0 var(--primary); }

/* Shop cart: transport selector */
.shop-transport-label { display: block; font-size: 12px; color: var(--text-muted); margin: 10px 0 8px; }
.shop-transport-label select { display: block; width: 100%; margin-top: 4px; }

/* ===================== Sourcing & Questionnaires (R161) ===================== */
.muted-sm { color: var(--text-muted); font-size: 12px; }
.tagchip { display: inline-block; padding: 1px 8px; margin: 1px 2px; border-radius: 999px; background: var(--bg-subtle); border: 1px solid var(--line); font-size: 11px; color: var(--text-muted); }
.resp-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; padding: 4px 2px 12px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }

/* questionnaire fill / preview */
.q-fill { display: flex; flex-direction: column; gap: 4px; }
.q-sec { border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 14px; margin: 8px 0; background: var(--bg-card); }
.q-sec-title { font-weight: 700; font-size: 13px; margin-bottom: 8px; color: var(--text); }
.q-field { margin: 10px 0; }
.q-field > .q-prompt { display: block; font-size: 13px; font-weight: 600; margin-bottom: 5px; color: var(--text); }
.q-help { font-size: 11px; color: var(--text-muted); margin-top: 4px; }
.q-choice { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.q-choice.wrap { gap: 6px 14px; }
.q-opt { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); cursor: pointer; }
.q-rating { display: inline-flex; align-items: center; gap: 4px; }
.q-star { background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: var(--line-strong); padding: 0 1px; }
.q-star.on { color: var(--brand-orange, #E8833A); }
.q-star:disabled { cursor: default; }
.q-rating-val { font-size: 12px; color: var(--text-muted); margin-left: 8px; }

/* questionnaire builder */
.q-build-sec { border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 12px; margin: 8px 0; background: var(--bg-subtle); }
.q-build-sechead { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.q-sec-input { flex: 1; font-weight: 600; }
.q-build-qs { display: flex; flex-direction: column; gap: 8px; }
.q-build-row { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; background: var(--bg-card); }
.q-build-main { display: flex; flex-direction: column; gap: 6px; }
.q-build-prompt { width: 100%; }
.q-build-meta { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center; }
.q-build-meta select { max-width: 180px; }
.q-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.q-w { max-width: 84px; }
.q-build-opts { width: 100%; font-size: 12px; }
/* system console */
.sc-tools { display: flex; align-items: center; gap: 12px; }
.sc-tools label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); cursor: pointer; }
.sc-pill { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.sc-pill.ok { background: rgba(34, 139, 84, 0.12); color: #1d7a4c; }
.sc-pill.err { background: rgba(192, 57, 43, 0.12); color: var(--danger, #c0392b); }
.sc-row-err td { background: rgba(192, 57, 43, 0.06); }
.sc-msg { color: var(--danger, #c0392b); }
.sc-tabs { display: inline-flex; gap: 4px; }
.sc-tab { border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--text-muted); border-radius: 8px; padding: 5px 12px; font-size: 12px; font-weight: 600; cursor: pointer; }
.sc-tab:hover { color: var(--text); }
.sc-tab.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.sc-subtools { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 12px 16px 8px; }
.sc-subtools-r { display: inline-flex; align-items: center; gap: 12px; }
.sc-subtools-r label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); cursor: pointer; }
/* role permissions — master access switch + expandable per-document actions */
.perm2-list { display: flex; flex-direction: column; gap: 5px; }
.perm2-mod { border: 1px solid var(--line); border-radius: var(--radius-sm); }
.perm2-row { display: flex; align-items: center; gap: 10px; padding: 7px 10px; }
.perm2-exp { background: none; border: 0; cursor: pointer; color: var(--text-muted); font-size: 13px; line-height: 1; padding: 2px 4px; }
.perm2-exp:disabled { opacity: 0.3; cursor: default; }
.perm2-name { font-weight: 500; flex: 0 0 190px; }
.perm2-summary { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-muted); font-size: 12px; }
.perm2-access { flex: 0 0 auto; }
.perm2-detail { display: grid; grid-template-columns: 1fr 1fr; column-gap: 24px; padding: 4px 12px 10px 30px; border-top: 1px solid var(--line); }
.perm2-act-row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.perm2-access.perm2-partial input:checked + .switch-track { background: color-mix(in srgb, var(--primary) 50%, transparent); }
.perm2-act-body { flex: 1 1 auto; min-width: 0; }
.perm2-act-label { font-weight: 500; font-size: 13px; }
.perm2-act-desc { font-size: 12px; color: var(--text-muted); margin-top: 1px; }
.iban-check.ok { color: var(--success, #1b7f3b); }
.iban-check.warn { color: var(--danger, #c0392b); }
.iban-flag { font-size: 11px; font-weight: 700; margin-left: 4px; }
.iban-flag.ok { color: var(--success, #1b7f3b); }
.iban-flag.bad { color: var(--danger, #c0392b); }
.field-flag { font-size: 11px; font-weight: 700; margin-left: 6px; }
.field-flag.ok { color: var(--success, #1b7f3b); }
.field-flag.bad { color: var(--danger, #c0392b); }
.sv-q-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.sv-q-item { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.sv-q-item .sv-q-name { flex: 1 1 auto; min-width: 0; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* auction console */
.auc-board { display: flex; gap: 14px; flex-wrap: wrap; margin: 6px 0 12px; }
.auc-metric { display: flex; flex-direction: column; gap: 2px; padding: 12px 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-subtle); min-width: 180px; }
.auc-metric-label { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.auc-metric-val { font-size: 26px; font-weight: 800; font-family: var(--font-mono); color: var(--text); }
.auc-controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0; }
.auc-controls select, .auc-controls input { max-width: 220px; }
.auc-stay-grid { display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 10px; background: var(--bg-card); }
.auc-stay-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 13px; }
.auc-stay-row + .auc-stay-row { border-top: 1px solid var(--line); padding-top: 6px; }

/* survey results aggregation */
.agg-row { display: flex; align-items: center; gap: 10px; margin: 4px 0; }
.agg-label { flex: 0 0 120px; font-size: 12px; color: var(--text); text-align: right; }
.agg-bar { flex: 1; height: 14px; background: var(--bg-subtle); border-radius: 999px; overflow: hidden; }
.agg-fill { display: block; height: 100%; background: var(--primary); border-radius: 999px; }
.agg-n { flex: 0 0 32px; font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.agg-list { margin: 4px 0 0; padding-left: 18px; font-size: 13px; color: var(--text); display: flex; flex-direction: column; gap: 2px; }

/* R162 — sourcing event read-only detail rows (reuse .detail-grid container) + chip remove */
.src-drow { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.src-drow.full { grid-column: 1 / -1; }
.src-dk { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.src-dv { font-size: 14px; color: var(--text); word-break: break-word; }
.chip-x { cursor: pointer; color: var(--text-muted); margin-left: 2px; font-weight: 700; text-decoration: none; }
.chip-x:hover { color: var(--danger, #c0392b); }

/* R163 — drag & drop reordering (sections, questions, line items, criteria, ordered questionnaire picker) */
.drag-handle { flex: 0 0 auto; cursor: grab; color: var(--text-muted); user-select: none; padding: 2px 3px; font-size: 13px; line-height: 1.4; border-radius: var(--radius-sm); }
.drag-handle:hover { background: var(--bg-subtle); color: var(--text); }
.drag-handle:active { cursor: grabbing; }
.q-build-row { display: flex; gap: 8px; align-items: flex-start; }
.q-build-row > .q-build-main { flex: 1; min-width: 0; }
.q-build-row > .q-build-prompt { flex: 1; min-width: 0; }
.q-build-sechead > .q-sec-input { flex: 1; min-width: 0; }
.q-build-row.dragging, .q-build-sec.dragging, .opick-item.dragging { opacity: .45; }
.q-build-row.drag-over, .q-build-sec.drag-over, .opick-item.drag-over { outline: 2px dashed var(--brand-orange); outline-offset: -1px; }
/* Ordered multi-select picker (questionnaires on an event) */
.opick { display: block; }
.opick-add { position: relative; }
.opick-list { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.opick-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.opick-num { flex: 0 0 auto; min-width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; color: var(--text-muted); background: var(--bg-subtle); border-radius: 999px; }
.opick-label { flex: 1; min-width: 0; word-break: break-word; font-size: 13px; }
.opick-x { flex: 0 0 auto; border: none; background: none; cursor: pointer; color: var(--text-muted); font-size: 16px; line-height: 1; padding: 0 4px; }
.opick-x:hover { color: var(--bad); }

/* GRC/warehouse fix (r137) — storage-location table inputs (.tinp) and Lookup value inputs
   (.lk-row input) follow the standard field box (border, padding, height) instead of raw browser inputs. */
.tinp, .lk-row input {
    min-height: var(--control-h);   /* r1608 — a fixed control stands at the family height */
    font-family: var(--font-ui);
    font-size: 13px;
    color: var(--text);
    background: var(--bg-card);
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
    padding: 9px 11px;
    width: 100%;
    box-sizing: border-box;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.tinp:focus, .lk-row input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }

/* r138 — Field-settings sub-tabs (Field / Security) */
.fb-subtabs { display: flex; gap: 4px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.fb-subtab { background: none; border: none; padding: 8px 14px; font: inherit; font-size: 13px; color: var(--text-muted); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.fb-subtab.active { color: var(--text); border-bottom-color: var(--primary); font-weight: 600; }

/* r270 — Visibility tab split into two labelled sections with a divider line between them */
.cf-vis-sec { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); margin-top: 2px; }
.cf-vis-sec + .field, .cf-vis-sec + * { margin-top: 0; }
.cf-vis-divider { height: 0; border-top: 1px solid var(--line); margin: 10px 0 4px; }

/* r139 — bank-account Currency rendered as a searchable combo: fit the grid cell */
.bank-row .combo { width: 100%; min-width: 0; }

/* PR catalog-locked line fields (#6): fields fixed by the catalog item render read-only with a lock */
.pr-locked-cell { display: flex; align-items: center; gap: 4px; color: var(--text); background: var(--bg-subtle); border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); padding: 8px 10px; }
.pr-locked-cell .pr-lock { font-size: 11px; opacity: .6; margin-left: auto; }

/* ===== Process designer: action palette + node icons; Actions catalog (r211) ===== */
/* The step library shares the canvas row; cap it at the canvas height (.pd-canvas-full) so the
   grid stretches it to the same bottom edge as the canvas (scrolls internally if its content is
   taller). Previously capped at 46vh while the canvas is 64vh, so the library stopped short. */
.pd-palette { overflow-y: auto; min-height: 0; max-height: max(64vh, 360px); }
.pd-pal-group { margin-bottom: 2px; }
.pd-pal-grouphead { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); font-weight: 700; margin: 8px 2px 4px; }
.pd-pal-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.pd-pal-btn { flex-direction: column; align-items: center; text-align: center; gap: 5px; padding: 9px 6px; width: auto; font-size: 11px; line-height: 1.15; }
.pd-pal-ico { width: auto; display: inline-flex; }
.pd-pal-ico svg { width: 18px; height: 18px; }
.pd-pal-lbl { display: block; }
.pd-node-ico { display: inline-flex; vertical-align: middle; }
.pd-node-ico svg { width: 15px; height: 15px; }
.pd-def-kind svg { width: 15px; height: 15px; vertical-align: middle; margin-right: 3px; }
.pd-action-desc { font-size: 12px; color: var(--text-muted); line-height: 1.4; margin-top: 4px; }
.pd-split-field { width: 100%; box-sizing: border-box; padding: 7px 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); font-size: 13px; font-family: var(--font-ui); margin-top: 4px; }

/* ===== Process designer: 4-column inspector + zoned field structure (r212) ===== */
.pd-zone { margin-bottom: 8px; }
.pd-zone-head { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text); margin: 2px 0 5px; }
.pd-zone-hint { font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--text-muted); font-size: 10px; }
.pd-zone-sub { margin: 6px 0 0 8px; padding-left: 8px; border-left: 2px solid var(--line); }
.pd-zone-subhead { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--text-muted); margin: 2px 0 4px; }
@media (max-width: 1180px) { .pd-grid4 { grid-template-columns: repeat(2, minmax(0,1fr)); } .pd-col-node { border-right: none; padding-right: 0; } }
@media (max-width: 680px) { .pd-grid4 { grid-template-columns: 1fr; } }

/* ===== Process designer: drag-and-drop field mapping (r213) ===== */
.pd-io-row { display: flex; align-items: center; gap: 6px; }
.pd-io-draggable { cursor: grab; }
.pd-io-draggable:active { cursor: grabbing; }
.pd-io-over { outline: 2px dashed var(--primary); outline-offset: -2px; background: var(--bg-subtle); }
.pd-io-map { display: inline-flex; align-items: center; gap: 1px; margin-left: auto; font-size: 10px; color: var(--primary); background: var(--bg-subtle); border: 1px solid var(--line); border-radius: 999px; padding: 1px 3px 1px 7px; white-space: nowrap; max-width: 62%; overflow: hidden; }
.pd-map-x { font-size: 12px; line-height: 1; padding: 0 1px; color: var(--text-muted); }

/* Field-level security (CF designer "Security" tab): a field the signed-in user is not permitted to
   edit is shown but locked. The `inert` attribute disables interaction/focus in modern browsers;
   these rules provide the visual treatment and a pointer-events fallback for older engines. */
.cf-field.cf-locked { opacity: .72; }
.cf-field.cf-locked > input, .cf-field.cf-locked > select, .cf-field.cf-locked > textarea,
.cf-field.cf-locked .combo-control, .cf-field.cf-locked .mcombo-control, .cf-field.cf-locked .cf-choice,
.cf-field.cf-locked .rt-wrap, .cf-field.cf-locked .cf-att { pointer-events: none; background: var(--bg-subtle); cursor: not-allowed; }
.cf-lock-badge { display: inline-block; margin-left: 6px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--warn); background: var(--warn-bg); border-radius: 999px; padding: 1px 7px; vertical-align: middle; }

/* Multi-condition "Visible if" editor (CF designer ▸ Visibility tab) */
.vis-cond { display: flex; flex-direction: column; gap: 8px; }
.vis-cond-match { font-size: 12px; color: var(--text-muted); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.vis-cond-match select { width: auto; }
.vis-cond-rows { display: flex; flex-direction: column; gap: 8px; }
/* r1222 — the default-value row, in the same four-column rhythm as the condition row above it. */
.cf-defrow { display: flex; flex-wrap: nowrap; gap: 6px; align-items: flex-end; }
.cf-defrow > .field { margin: 0; }
.cf-defrow > .field:nth-child(1) { flex: 0 0 calc(33.333% - 12px); min-width: 0; }
.cf-defrow > .cf-defgap { flex: 0 0 calc(16.666% - 8px); }
.cf-defrow > .field:nth-child(3) { flex: 0 0 calc(16.666% - 8px); min-width: 0; }
.cf-defrow > .cf-defval { flex: 0 0 calc(33.333% - 12px); min-width: 0; }
.cf-defrow select, .cf-defrow input { width: 100%; box-sizing: border-box; }
@media (max-width: 900px) { .cf-defrow { flex-wrap: wrap; }
  .cf-defrow > .cf-defgap { display: none; }
  .cf-defrow > .field { flex: 1 1 160px; } }

/* r1222 — "Show this field when" reads as ONE row in the estate's own rhythm: field 1/3 · operator
   1/6 · source 1/6 · value 1/3, with the delete button after them. It wrapped into three ragged
   lines before, so the same condition looked different in every dialog width. */
.vis-cond-row { display: flex; flex-wrap: nowrap; gap: 6px; align-items: center; }
.vis-cond-row .vc-field { flex: 0 0 calc(33.333% - 12px); min-width: 0; }
.vis-cond-row .vc-op { flex: 0 0 calc(16.666% - 8px); width: auto; min-width: 0; }
.vis-cond-row .vc-src { flex: 0 0 calc(16.666% - 8px); width: auto; min-width: 0; }
.vis-cond-row .vc-val { flex: 0 0 calc(33.333% - 12px); min-width: 0; }
.vis-cond-row > * { max-width: 100%; }
.vis-cond-row select, .vis-cond-row input { width: 100%; box-sizing: border-box; }
@media (max-width: 900px) { .vis-cond-row { flex-wrap: wrap; }
  .vis-cond-row .vc-field, .vis-cond-row .vc-op, .vis-cond-row .vc-src, .vis-cond-row .vc-val { flex: 1 1 160px; } }
.vis-cond-row .vc-del { flex: 0 0 auto; border: 1px solid var(--line); background: var(--bg-subtle); border-radius: 6px; cursor: pointer; color: var(--text-muted); width: 30px; height: 30px; line-height: 1; font-size: 16px; }
.vis-cond-row .vc-del:hover { color: var(--bad); border-color: var(--bad); }
.vis-cond-add { align-self: flex-start; }

/* ============================================================
   Process Designer — DataStage-inspired look & feel (r243)
   Neutral graph-paper canvas, icon-headed "stage" boxes, steel-
   blue directional links, and a categorised stage palette.
   Scoped to .pd-wrap (covers docked + pop-out) so the rest of
   the app keeps the NuWayMind brand.
   ============================================================ */
.pd-wrap {
    --ds-blue: #336699;
    --ds-blue-dark: #244a6b;
    --ds-canvas: #eef1f5;
    --ds-canvas-edge: #c4cdd8;
    --ds-grid: #d7dde6;
    --ds-stage-bg: #fbfcfd;
    --ds-stage-border: #9aa9bb;
    --ds-stage-bevel: #ffffff;
    --ds-chrome-top: #f3f5f8;
    --ds-chrome-bot: #e2e7ee;
    --ds-chrome-border: #b9c2cf;
}

/* Toolbar + metadata strip: a flat, light "application" chrome */
.pd-wrap .pd-bar {
    background: linear-gradient(180deg, var(--ds-chrome-top), var(--ds-chrome-bot));
    border-color: var(--ds-chrome-border);
    border-radius: 4px 4px 0 0;
}
.pd-wrap .pd-bar-name { color: var(--ds-blue-dark); letter-spacing: .01em; }
.pd-wrap .pd-meta { background: var(--ds-chrome-top); border-color: var(--ds-chrome-border); }

/* Palette: a "stage repository" tool panel */
.pd-wrap .pd-body { border-color: var(--ds-chrome-border); }
.pd-wrap .pd-palette {
    background: linear-gradient(180deg, #eef1f5, #e6eaf0);
    border-right-color: var(--ds-chrome-border);
}
.pd-wrap .pd-pal-grouphead {
    color: var(--ds-blue-dark);
    border-bottom: 1px solid var(--ds-grid);
    padding-bottom: 3px;
}
.pd-wrap .pd-pal-btn {
    border-color: var(--ds-stage-border);
    border-radius: 3px;
    background: var(--ds-stage-bg);
    box-shadow: inset 0 1px 0 var(--ds-stage-bevel);
}
.pd-wrap .pd-pal-btn:hover { border-color: var(--ds-blue); background: var(--bg-card); }
.pd-wrap .pd-pal-ico { color: var(--ds-blue); }

/* Canvas: light grey graph-paper inside an inset frame */
.pd-wrap .pd-canvas {
    background-color: var(--ds-canvas);
    background-image:
        linear-gradient(var(--ds-grid) 1px, transparent 1px),
        linear-gradient(90deg, var(--ds-grid) 1px, transparent 1px);
    background-size: 20px 20px;
    box-shadow: inset 0 0 0 1px var(--ds-canvas-edge), inset 2px 2px 6px rgba(36,74,107,.06);
}

/* Stages: icon-headed boxes with a subtle raised bevel */
.pd-wrap .pd-node {
    --ds-accent: var(--ds-blue);
    background: var(--ds-stage-bg);
    border: 1px solid var(--ds-stage-border);
    border-left-width: 1px;
    border-top: 2px solid var(--ds-accent);
    border-radius: 3px;
    box-shadow: inset 0 1px 0 var(--ds-stage-bevel), 0 2px 5px rgba(36,74,107,.16);
}
.pd-wrap .pd-node.selected {
    border-color: var(--ds-blue);
    box-shadow: 0 0 0 2px rgba(51,102,153,.35), 0 2px 6px rgba(36,74,107,.22);
}
.pd-wrap .pd-node.connecting { outline-color: var(--ds-blue); }
.pd-wrap .pd-node-head { padding: 7px 8px 5px; gap: 7px; }
.pd-wrap .pd-node-ico {
    flex: 0 0 auto; width: 22px; height: 22px;
    display: flex; align-items: center; justify-content: center;
    background: var(--ds-accent); color: #fff; border-radius: 3px;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.35);
}
.pd-wrap .pd-node-ico svg { width: 14px; height: 14px; }
.pd-wrap .pd-node-title { color: #20303f; font-weight: 700; }
.pd-wrap .pd-node-sub { color: #5d6b7a; }

/* per-stage accent colours (icon badge + top bar) */
.pd-wrap .pd-node-START { --ds-accent: #2e9e5b; }
.pd-wrap .pd-node-END { --ds-accent: #c0392b; }
.pd-wrap .pd-node-DECISION { --ds-accent: #c0891b; }
.pd-wrap .pd-node-DOCUMENT,
.pd-wrap .pd-node-CREATE_DOC,
.pd-wrap .pd-node-UPDATE_DOC,
.pd-wrap .pd-node-SUBMIT_DOC,
.pd-wrap .pd-node-DOC_SUBMISSION { --ds-accent: #2f6db5; }
.pd-wrap .pd-node-ACTION,
.pd-wrap .pd-node-APPROVE_DOC,
.pd-wrap .pd-node-REJECT_DOC { --ds-accent: #3a7d3a; }
.pd-wrap .pd-node-CONTROL { --ds-accent: #7c4fae; }
.pd-wrap .pd-node-TRANSFORM,
.pd-wrap .pd-node-SPLITTER,
.pd-wrap .pd-node-GROUPPER { --ds-accent: #178a8a; }
.pd-wrap .pd-node-ESOURCING_CREATE,
.pd-wrap .pd-node-ESOURCING_PUBLISH,
.pd-wrap .pd-node-ESOURCING_ASSESS,
.pd-wrap .pd-node-ASSESS_QUESTIONNAIRE { --ds-accent: #8a5cc0; }
.pd-wrap .pd-node-SEND_EMAIL,
.pd-wrap .pd-node-RECEIVE_EMAIL,
.pd-wrap .pd-node-DO_REST,
.pd-wrap .pd-node-RECEIVE_REST,
.pd-wrap .pd-node-INTEGRATION,
.pd-wrap .pd-node-AI_AGENT { --ds-accent: #336699; }

/* Ports + links: connectors and steel-blue directional flow */
.pd-wrap .pd-port { border-color: var(--ds-stage-border); background: #fff; }
.pd-wrap .pd-port-out { color: var(--ds-blue); }
.pd-wrap .pd-port-in:hover,
.pd-wrap .pd-port-out:hover { border-color: var(--ds-blue); color: var(--ds-blue); }
.pd-wrap .pd-edge { stroke: var(--ds-blue); stroke-width: 2; }
.pd-wrap .pd-edge-temp { stroke: var(--ds-blue); }
.pd-wrap .pd-edges marker path { fill: var(--ds-blue); }

/* Inspector splitter grip picks up the steel-blue on hover */
.pd-wrap .pd-splitter:hover .pd-splitter-grip { background: var(--ds-blue); }

/* ============================================================
   Process Designer r2 — icon-with-name-below "stage" nodes,
   per-type output-only entry nodes, and deletable links.
   Builds on the DataStage-inspired theme above; scoped to .pd-wrap.
   ============================================================ */
.pd-wrap .pd-node {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; padding: 9px 8px; min-height: 64px; text-align: center; cursor: move;
}
.pd-wrap .pd-node-ico { width: 28px; height: 28px; border-radius: 6px; }
.pd-wrap .pd-node-ico svg { width: 17px; height: 17px; }
.pd-wrap .pd-node-name {
    font-size: 12px; font-weight: 700; color: #20303f; line-height: 1.2; max-width: 100%;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-word;
}
.pd-wrap .pd-node-del {
    position: absolute; top: 2px; right: 3px; border: none; background: none; color: var(--text-muted);
    cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; opacity: 0; transition: opacity .12s ease;
}
.pd-wrap .pd-node:hover .pd-node-del { opacity: 1; }
.pd-wrap .pd-node-del:hover { color: #c0392b; }
/* connector dots sit on the node's vertical middle (PORT_Y = 32, dot = 13px) */
.pd-wrap .pd-port { top: 25px; }
/* small delete button at each link's midpoint */
.pd-wrap .pd-edge-del {
    position: absolute; transform: translate(-50%, -50%); width: 18px; height: 18px; border-radius: 50%;
    border: 1px solid var(--ds-stage-border); background: #fff; color: #7c8aa0; font-size: 13px; line-height: 1;
    cursor: pointer; padding: 0; z-index: 4; display: flex; align-items: center; justify-content: center;
    opacity: .5; transition: opacity .12s ease, color .12s ease, border-color .12s ease, background .12s ease;
}
.pd-wrap .pd-edge-del:hover { opacity: 1; color: #fff; background: var(--ds-blue); border-color: var(--ds-blue); }
/* keep every designer field on the standard field size (13px), including the new email-connection inputs */
.pd-wrap .pd-define input:not([type="checkbox"]), .pd-wrap .pd-define select, .pd-wrap .pd-define textarea,
.pd-wrap .pd-define .combo-control, .pd-wrap .pd-define .mcombo-control { font-size: 13px; }
.pd-wrap .pd-json { font-family: var(--font-mono); font-size: 11.5px; background: var(--bg-subtle); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; margin-top: 6px; max-height: 220px; overflow: auto; white-space: pre-wrap; }

/* ============================================================
   Process Designer r3 — icon in a borderless white 64px square
   (name below), standard-sized inspector fields, single-line name.
   Scoped to .pd-wrap; overrides the box styling above.
   ============================================================ */
.pd-wrap .pd-node {
    background: transparent; border: none; box-shadow: none; padding: 0;
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    overflow: visible; cursor: move;
}
.pd-wrap .pd-node.selected { box-shadow: none; }
.pd-wrap .pd-node.selected .pd-node-box { box-shadow: 0 0 0 2px var(--ds-blue), 0 2px 7px rgba(36,74,107,.20); }
.pd-wrap .pd-node.connecting .pd-node-box { box-shadow: 0 0 0 2px var(--ds-blue); }
.pd-wrap .pd-node-box {
    width: 64px; height: 64px; flex: 0 0 auto; box-sizing: border-box;
    display: flex; align-items: center; justify-content: center;
    background: #fff; border: none; border-radius: 12px;
    box-shadow: 0 1px 4px rgba(36,74,107,.20);
}
.pd-wrap .pd-node-ico {
    width: auto; height: auto; background: transparent; border-radius: 0;
    color: var(--ds-accent, var(--ds-blue));
    display: flex; align-items: center; justify-content: center;
}
.pd-wrap .pd-node-ico svg { width: 34px; height: 34px; }
.pd-wrap .pd-node-name {
    font-size: 12px; font-weight: 600; color: #20303f; line-height: 1.2; text-align: center;
    max-width: 130px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; word-break: break-word;
}
.pd-wrap .pd-node-del {
    top: -7px; right: -7px; background: #fff; color: var(--text-muted); border-radius: 50%;
    width: 18px; height: 18px; box-shadow: 0 1px 3px rgba(0,0,0,.22);
    display: flex; align-items: center; justify-content: center; padding: 0;
}
.pd-wrap .pd-node:hover .pd-node-del { opacity: 1; }
.pd-wrap .pd-node-del:hover { color: #c0392b; }
/* connector dots centred on the square's vertical middle (PORT_Y = 32) */
.pd-wrap .pd-port { top: 25px; }
/* standard field box + size for the inspector's column-level fields
   (name, description, correlation key / SLA, and the email-connection inputs) */
.pd-wrap .pd-def-col > input:not([type="checkbox"]),
.pd-wrap .pd-def-col > textarea,
.pd-wrap .pd-def-col > select { box-sizing: border-box; width: 100%; padding: 9px 11px; font-size: 13px; }
.pd-wrap .pd-def-desc { resize: vertical; min-height: 38px; line-height: 1.35; font-family: var(--font-ui); }

/* ===== R247 (§106) ===== */
/* 6px lead before each field line in all document forms (box-sizing keeps cf-field calc widths valid) */
.field, .cf-field { box-sizing: border-box; padding-left: 6px; }

/* Purchase Requisition: Simple -> Expert switch moved into the button footer, at half width */
.modal-foot.foot-with-switch { align-items: center; flex-wrap: wrap; }
.modal-foot.foot-with-switch .alloc-switch { flex: 1 1 50%; max-width: 50%; margin: 0 auto 0 0; }

/* Transform node: 2-column output mapping (connect-from-input | output name) */
.pd-tf-head { display: flex; align-items: center; gap: 8px; margin: 2px 0 6px; font-size: 11px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--text-muted); }
.pd-tf-h1 { flex: 1 1 50%; min-width: 0; }
.pd-tf-h2 { flex: 1 1 50%; min-width: 0; }
.pd-tf-list { display: flex; flex-direction: column; gap: 6px; }
.pd-tf-row { display: flex; align-items: center; gap: 8px; }
.pd-tf-from { flex: 1 1 50%; min-width: 0; }
.pd-tf-from > * { width: 100%; }
.pd-tf-arrow { flex: 0 0 auto; color: var(--ds-blue, #2563eb); font-weight: 700; }
.pd-tf-to { flex: 1 1 50%; min-width: 0; display: flex; align-items: center; gap: 6px; }
.pd-tf-to .pd-assign-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* mail Test Connection result (Receive Email + Send Email) */
.pd-mt { margin-top: 6px; font-size: 12px; font-weight: 600; }
.pd-mt-ok { color: #1d7a4d; }
.pd-mt-err { color: #c0392b; }
.pd-mt-steps { margin: 6px 0 0; padding-left: 16px; font-size: 12px; font-weight: 400; list-style: disc; }
.pd-mt-steps li { margin: 2px 0; }

/* ---- Action templates (Setup ▸ Workflows ▸ Action templates list + designer Step library) ---- */
.act-tpl-base { display: inline-flex; align-items: center; gap: 8px; }
.act-tpl-base svg { width: 16px; height: 16px; color: var(--primary); flex: 0 0 auto; }

/* Template buttons in the Step library — a subtle accent so they read as ready-made building blocks */
.pd-pal-tpl { border-style: dashed; }
.pd-wrap .pd-pal-tpl { border-left: 3px solid var(--ds-blue, var(--primary)); }

/* Problems panel — an always-visible validation summary under the meta bar (dev-environment surface) */
.pd-problems { border: 1px solid var(--line); border-top: 0; background: var(--bg-card); }
.pd-problems.has { background: var(--bad-bg); border-color: var(--bad); }
.pd-problems-toggle { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 14px; background: transparent; border: 0; cursor: pointer; font-family: var(--font-ui); font-size: 12.5px; font-weight: 600; color: var(--text); }
.pd-problems.clean .pd-problems-toggle { cursor: default; color: var(--ok); }
.pd-prob-badge { flex: 0 0 auto; min-width: 18px; height: 18px; padding: 0 5px; display: inline-flex; align-items: center; justify-content: center; border-radius: 9px; font-size: 11px; font-weight: 700; background: var(--bad); color: #fff; }
.pd-problems.clean .pd-prob-badge { background: var(--ok); }
.pd-prob-title { flex: 1 1 auto; }
.pd-prob-caret { flex: 0 0 auto; color: var(--text-muted); font-size: 11px; }
.pd-prob-list { margin: 0; padding: 0 14px 10px 38px; list-style: disc; }
.pd-prob-item { margin: 3px 0; font-size: 12px; color: var(--bad); }

/* Must-acknowledge error dialog (validation on activate, import, save failures) */
.pd-ack { display: flex; gap: 12px; align-items: flex-start; }
.pd-ack-icon { flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%; background: var(--bad); color: #fff; font-weight: 800; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; line-height: 1; }
.pd-ack-body { flex: 1 1 auto; min-width: 0; }
.pd-ack-body > p { margin: 0 0 8px; }
.pd-ack-list { margin: 0; padding-left: 18px; list-style: disc; }
.pd-ack-list li { margin: 4px 0; }
.pd-ack-hint { margin-top: 10px !important; color: var(--text-muted); font-size: 13px; }

/* A modal opened over the pop-out designer must clear the pop-out overlay (z-index 1000). Scoped via
   :has() so the normal stacking (modal at z-index 50) is unchanged when the designer is docked in page. */
body:has(.pd-overlay) .modal-overlay { z-index: 1100; }

/* Transform output source: a kind selector (input / constant / formula) stacked above its value control */
.pd-tf-srcwrap { display: flex; flex-direction: column; gap: 4px; }
.pd-tf-srcwrap > * { width: 100%; }
.pd-tf-inp { font-family: var(--font-ui); }

/* Inline help "?" with a hover/focus tooltip — used on the Simple → Expert view switch (PR & PO) */
.help-tip { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; margin-left: 6px; border-radius: 50%; border: 1px solid var(--line-strong, #c9ced6); background: var(--bg-subtle, #f3f4f6); color: var(--text-muted, #6b7280); font-size: 10px; font-weight: 700; line-height: 1; cursor: help; vertical-align: middle; position: relative; user-select: none; }
.help-tip:hover, .help-tip:focus { background: var(--primary, #2f6f4e); border-color: var(--primary, #2f6f4e); color: #fff; outline: none; }
.help-tip::after { content: attr(data-tip); position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%); width: 260px; max-width: 70vw; white-space: normal; background: #1f2430; color: #fff; font-size: 11.5px; font-weight: 400; line-height: 1.4; text-align: left; padding: 8px 10px; border-radius: 6px; box-shadow: 0 6px 20px rgba(0, 0, 0, .22); opacity: 0; visibility: hidden; transition: opacity .12s ease; z-index: 1200; pointer-events: none; }
.help-tip::before { content: ""; position: absolute; top: calc(100% + 3px); left: 50%; transform: translateX(-50%); border: 5px solid transparent; border-bottom-color: #1f2430; opacity: 0; visibility: hidden; transition: opacity .12s ease; z-index: 1200; }
.help-tip:hover::after, .help-tip:focus::after, .help-tip:hover::before, .help-tip:focus::before { opacity: 1; visibility: visible; }

/* Inline rename input on a canvas node (double-click the node name) */
.pd-wrap .pd-node-rename {
    font-size: 12px; font-weight: 600; color: #20303f; line-height: 1.2; text-align: center;
    width: 130px; max-width: 130px; border: 1px solid var(--primary); border-radius: 4px;
    background: #fff; padding: 2px 4px; outline: none; box-shadow: 0 0 0 2px var(--primary-soft);
}
.pd-wrap .pd-node-name { cursor: text; }

/* §114 Process Designer — design-time data tester */
.pd-tester { margin-top: 14px; border-top: 1px dashed var(--line); padding-top: 12px; }
.pd-tester-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.pd-tester-head .pd-tester-h { font-weight: 600; font-size: 13px; }
.pd-tester-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; align-items: start; }
@media (max-width: 720px) { .pd-tester-grid { grid-template-columns: 1fr; } }
.pd-tester-col textarea { resize: vertical; }
.pd-tester-btns { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.pd-test-out { min-height: 120px; margin-top: 4px; }

/* §116 Process Designer — golden-rule structure push buttons */
.pd-push-row { margin: 2px 0 8px; }
.pd-push-row .btn { width: 100%; justify-content: center; font-size: 11.5px; }

/* §117 AI agent test result panel */
.ag-test-result { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.ag-test-head { font-weight: 600; font-size: 13px; }
.ag-test-head.ok { color: var(--ok, #1a7f37); }
.ag-test-head.err { color: var(--danger, #b42318); }
.ag-test-json { font-family: var(--font-mono); font-size: 12px; background: var(--bg-subtle); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; margin-top: 6px; max-height: 320px; overflow: auto; white-space: pre-wrap; }

/* §120 Purchase Requisition — line-type indicator + open-line-item modal */
.line-row .line-type-ico { display: flex; align-items: center; justify-content: center; color: var(--text-muted); align-self: end; height: 36px; }
.line-row .line-type-ico svg { width: 17px; height: 17px; }
.line-row .line-open {
    border: 1px solid var(--line-strong); background: var(--bg-card); color: var(--text-muted);
    border-radius: var(--radius-sm); height: 36px; min-width: 30px; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
}
.line-row .line-open svg { width: 16px; height: 16px; }
.line-row .line-open:hover { background: var(--bg-subtle); color: var(--text); border-color: var(--brand); }

.li-modal-overlay { position: fixed; inset: 0; z-index: 1200; display: flex; }
.li-modal-overlay.li-modal-center { align-items: center; justify-content: center; background: rgba(15, 23, 42, 0.45); padding: 24px; }
.li-modal-overlay.li-modal-dock { justify-content: flex-end; background: transparent; pointer-events: none; }
.li-modal-overlay.li-modal-dock .li-modal-panel { pointer-events: auto; height: 100vh; max-height: 100vh; border-radius: 0; width: min(540px, 94vw); box-shadow: -14px 0 40px rgba(15, 23, 42, 0.18); }
.li-modal-panel { background: var(--bg-card); border-radius: var(--radius); box-shadow: 0 24px 64px rgba(15, 23, 42, 0.32); width: min(760px, 94vw); max-height: 92vh; display: flex; flex-direction: column; }
.li-modal-head { display: flex; align-items: center; justify-content: flex-start; gap: 6px; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.li-modal-head h3 { margin: 0; font-size: 15px; }
.li-modal-nav { background: none; border: 1px solid var(--line); cursor: pointer; color: var(--text-muted); padding: 3px; border-radius: var(--radius-sm); display: inline-flex; }
.li-modal-nav:hover { background: var(--bg-subtle); color: var(--text); }
.li-modal-nav[hidden] { display: none; }
.li-modal-nav svg { width: 16px; height: 16px; }
.li-modal-x { background: none; border: none; cursor: pointer; color: var(--text-muted); padding: 4px; border-radius: var(--radius-sm); display: inline-flex; margin-left: auto; }
.li-modal-x:hover { background: var(--bg-subtle); color: var(--text); }
.li-modal-x svg { width: 18px; height: 18px; }
.li-modal-body { padding: 16px 18px; overflow: auto; }
.li-modal-grid { display: flex; flex-wrap: wrap; gap: 12px 14px; align-items: flex-start; }
.li-mf { flex: 0 1 100%; }
.li-mf.narrow { flex: 0 1 calc(50% - 7px); }
.li-modal-grid .li-mf .field { width: 100%; flex: 1 1 auto; }
.li-modal-total { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); text-align: right; font-size: 13px; color: var(--text-muted); }
.li-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--line); }

/* §123 Process Designer — Transform lookup (dotted side-channel) */
.pd-wrap .pd-edge-lookup { stroke: #7c5cff; stroke-dasharray: 5 4; }
.pd-wrap .pd-edges #pd-arrow-lk circle { fill: #7c5cff; }
.pd-lk-row { display: flex; align-items: center; gap: 6px; padding: 4px 0; }
.pd-lk-node { flex: 0 0 auto; font-weight: 600; font-size: 12px; color: #6b4eff; white-space: nowrap; max-width: 38%; overflow: hidden; text-overflow: ellipsis; }
.pd-lk-cfg { display: flex; gap: 6px; flex: 1 1 auto; min-width: 0; }
.pd-lk-cfg select, .pd-lk-cfg input { flex: 1 1 0; min-width: 0; }

/* §124 Process Designer — node editor (double-click) with General/Configuration/Input/Output tabs */
.pd-canvas-full { height: 64vh; min-height: 360px; }
.pd-editor-backdrop { position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 1090; }
.pd-editor { background: var(--bg-card); display: flex; flex-direction: column; box-shadow: 0 18px 60px rgba(0,0,0,.35); }
.pd-editor-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%); width: min(920px, 94vw); height: 70vh; border-radius: var(--radius, 12px); z-index: 1100; overflow: hidden; }
/* Transform node: double-width, centred pop-up to fit the three-column Transform tab */
.pd-editor-popup.pd-editor-wide { width: min(1320px, 96vw); }
/* Transform tab: Input + Lookup on the left, a vertical divider, Output on the right */
.pd-tf-cols { display: flex; align-items: stretch; gap: 0; }
.pd-tf-cols .pd-tf-side { flex: 1 1 50%; min-width: 0; display: flex; flex-direction: column; gap: 20px; }
.pd-tf-cols .pd-tf-side-left { padding-right: 22px; border-right: 2px solid var(--line); }
.pd-tf-cols .pd-tf-side-right { padding-left: 22px; }
.pd-tf-zone-title { font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 9px; display: flex; align-items: center; gap: 6px; }
.pd-tf-zone-title .pd-def-hint { margin-left: auto; }
.pd-tf-fields { display: flex; flex-direction: column; gap: 8px; }
.pd-tf-field { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 9px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.pd-tf-fname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-tf-badge { flex: 0 0 auto; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; border-radius: 4px; padding: 1px 6px; background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--line); }
.pd-tf-badge.pd-tf-badge-lk { background: rgba(107,78,255,.12); color: #6b4eff; border-color: rgba(107,78,255,.3); }
/* Stage 2 — lookup connection ports: top + bottom, brand-coloured, on a Transform and lookup-capable steps */
.pd-port-lk { border-color: var(--brand); color: var(--brand); cursor: crosshair; }
.pd-port-lk:hover { background: var(--brand); border-color: var(--brand); }
.pd-wrap .pd-port-lk { border-color: var(--brand); background: var(--bg-card); }
.pd-wrap .pd-port-lk:hover { background: var(--brand); }
.pd-wrap .pd-port-lk-top, .pd-port-lk-top { top: -7px; bottom: auto; left: 50%; right: auto; transform: translateX(-50%); }
.pd-wrap .pd-port-lk-bottom, .pd-port-lk-bottom { top: auto; bottom: -7px; left: 50%; right: auto; transform: translateX(-50%); }
.pd-node.lk-connecting .pd-node-box { box-shadow: 0 0 0 2px var(--brand); }
.pd-edge-del-lk { border-color: var(--brand); color: var(--brand); }
/* Transform tab: two columns (LEFT = input on top, lookups below; RIGHT = output) joined by connector lines */
.pd-tf-wire { position: relative; height: 56vh; min-height: 260px; }
.pd-tf-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 4; overflow: hidden; }
.pd-tf-line { stroke: var(--primary); stroke-width: 2; opacity: .9; }
.pd-tf-line-key { stroke: #6b4eff; stroke-dasharray: 4 4; stroke-width: 1.6; opacity: .8; }
.pd-tf-2col { display: flex; gap: 38px; height: 100%; }
.pd-tf-lcol, .pd-tf-rcol { flex: 1 1 0; min-width: 0; height: 100%; overflow-y: auto; overflow-x: hidden; padding: 2px 4px 8px; }
.pd-tf-lcol { padding-left: 48px; padding-right: 48px; }   /* 48px breathing room on both sides */
.pd-tf-rcol { padding-left: 48px; padding-right: 48px; }   /* 48px breathing room on both sides */
.pd-tf-sec-title { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); padding: 4px 0; position: sticky; top: 0; background: var(--bg-card); z-index: 2; }
.pd-tf-sec-div { margin-top: 14px; border-top: 1px solid var(--line); }
.pd-tf-chips, .pd-tf-lkgs, .pd-tf-out-rows { display: flex; flex-direction: column; }
.pd-tf-chip { display: flex; align-items: center; gap: 6px; font-size: 12px; padding: 7px 9px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); cursor: grab; margin-bottom: 10px; }
.pd-tf-chip:hover { border-color: var(--line-strong); }
.pd-tf-chip:active { cursor: grabbing; }
.pd-tf-chip.pd-tf-dragging { opacity: .45; }
.pd-tf-chip .pd-tf-fname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-tf-chip-lk { border-color: rgba(107,78,255,.3); }
.pd-tf-chip-key { cursor: default; background: var(--bg-subtle); margin-bottom: 0; width: 100%; }
.pd-tf-chip-key:active { cursor: default; }
.pd-tf-lkg { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px; margin-bottom: 10px; background: var(--bg-subtle); }
.pd-tf-lkg-head { display: flex; align-items: center; gap: 6px; margin-bottom: 7px; }
.pd-tf-lkg-name { font-weight: 600; font-size: 12px; color: #6b4eff; white-space: nowrap; }
.pd-tf-lkg-key { flex: 1 1 auto; min-width: 0; }
.pd-tf-lkg-head .pd-x { flex: 0 0 auto; }
.pd-tf-lkg-rets { display: flex; flex-direction: column; gap: 6px; }
.pd-tf-lkg-rets .pd-tf-chip { margin-bottom: 0; padding: 6px 8px; }
.pd-tf-drop { border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); padding: 6px 8px; min-height: 32px; display: flex; align-items: center; }
.pd-tf-drop-hint { font-size: 10.5px; color: var(--text-muted); font-style: italic; }
.pd-tf-out-row { display: flex; align-items: stretch; gap: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); margin-bottom: 10px; background: var(--bg-card); overflow: hidden; }
.pd-tf-out-row.is-mapped { border-color: var(--primary); }
.pd-tf-out-conn { flex: 1 1 50%; min-width: 0; border-right: 1px solid var(--line); border-radius: 0; min-height: 40px; }
.pd-tf-out-conn.pd-tf-drop { border-top: 0; border-bottom: 0; border-left: 0; }
.pd-tf-out-conn .pd-tf-inp, .pd-tf-out-conn .combo, .pd-tf-out-conn select { width: 100%; }
.pd-tf-out-field { flex: 1 1 50%; min-width: 0; display: flex; align-items: center; gap: 6px; padding: 6px 9px; background: var(--bg-subtle); }
.pd-tf-out-name { flex: 1 1 auto; min-width: 0; font-weight: 600; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-tf-out-rm { flex: 0 0 auto; }
.pd-tf-mapped { display: flex; align-items: center; gap: 6px; width: 100%; font-size: 12px; background: rgba(245,130,31,.10); border-radius: var(--radius-sm); padding: 5px 8px; }
.pd-tf-mapped .pd-tf-fname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-tf-mapped .pd-x { flex: 0 0 auto; }
.pd-tf-dragover { outline: 2px dashed var(--brand); outline-offset: -2px; background: rgba(107,78,255,.07); }
.pd-tf-drop.pd-tf-dragover { border-color: var(--brand); }
/* Data-lookup node: data-source field preview (Configuration) + read-only Output list */
.pd-ds-fields { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.pd-ds-chip { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; padding: 5px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-subtle); }
.pd-ds-cn { font-weight: 600; }
.pd-ds-ck { font-size: 10.5px; color: var(--text-muted); font-family: var(--mono, ui-monospace, monospace); }
.pd-ds-outlist { display: flex; flex-direction: column; gap: 8px; }
.pd-ds-outrow { display: flex; align-items: center; gap: 10px; padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); }
.pd-ds-on { flex: 1 1 auto; min-width: 0; font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-ds-ok { font-size: 11px; color: var(--text-muted); font-family: var(--mono, ui-monospace, monospace); }
.pd-ds-ot { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); border: 1px solid var(--line); border-radius: 4px; padding: 1px 6px; }
/* Transform: lookup group split (Key | Returns), propagate-to-output buttons, and the New-field drop zone */
.pd-tf-sec-title { display: flex; align-items: center; }
.pd-tf-sec-title .pd-tf-prop { margin-left: auto; }
.pd-tf-prop { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: 1px solid var(--line); border-radius: 5px; background: var(--bg-card); color: var(--primary); cursor: pointer; }
.pd-tf-prop:hover { background: var(--primary); color: #fff; border-color: var(--primary); }
.pd-tf-prop svg { width: 13px; height: 13px; }

/* Compact icon toolbar (propagate + field-structure library) on Input/Output editors and Transform columns */
.pd-field-tools { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.pd-field-tools .btn { width: auto; flex: 0 0 auto; padding: 4px 7px; min-width: 0; }
.pd-field-tools .pd-prop-btn svg { width: 14px; height: 14px; display: block; }
.pd-tf-sec-title .pd-field-tools { margin: 0; }
.pd-tf-sec-title .pd-field-tools .btn { padding: 3px 5px; }
/* Field-structure library picker (load-from-library modal) */
.pd-lib-list { display: flex; flex-direction: column; gap: 4px; max-height: 360px; overflow: auto; }
.pd-lib-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 7px; cursor: pointer; background: var(--bg-card); }
.pd-lib-row:hover { border-color: var(--primary); background: var(--bg-soft, #f6f8fa); }
.pd-lib-name { font-weight: 600; flex: 1 1 auto; }
.pd-lib-cnt { color: var(--text-muted); font-size: 12px; flex: 0 0 auto; }
.pd-lib-row .pd-x { flex: 0 0 auto; }
.pd-tf-lkg-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.pd-tf-lkg-head .pd-x { margin-left: 4px; }
.pd-tf-lkg-body { display: flex; gap: 8px; align-items: flex-start; }
.pd-tf-lkg-part { flex: 1 1 0; min-width: 0; }
.pd-tf-lkg-plabel { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: 4px; }
/* Transform: lookup returned fields rendered as split rows (like output fields); key on its own row */
.pd-tf-lkg-keyrow { margin-bottom: 8px; }
.pd-tf-lkg-key { width: 100%; }
.pd-tf-lkret { display: flex; align-items: stretch; border: 1px solid var(--line); border-radius: var(--radius-sm); margin-bottom: 8px; background: var(--bg-card); overflow: hidden; }
.pd-tf-lkret:last-child { margin-bottom: 0; }
.pd-tf-lkret.is-key { border-color: #6b4eff; }
.pd-tf-lkret-out { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; padding: 6px 9px; cursor: grab; }
.pd-tf-lkret-key { flex: 0 0 124px; min-width: 0; border-right: 1px solid var(--line); display: flex; align-items: center; padding: 4px 6px; }
.pd-tf-lkret-key.is-nonkey { justify-content: center; color: var(--text-muted); background: var(--bg-subtle); font-size: 12px; }
.pd-tf-lkret-key.pd-tf-drop { border-top: 0; border-bottom: 0; border-left: 0; border-radius: 0; background: var(--bg-subtle); min-height: 0; }
.pd-tf-lkret-key .pd-tf-chip { margin: 0; max-width: 100%; }
.pd-tf-keytag { flex: 0 0 auto; font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: #6b4eff; border: 1px solid rgba(107,78,255,.4); border-radius: 3px; padding: 0 4px; }
.pd-tf-lkret-head { display: flex; font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: 5px; }
.pd-tf-lkret-head-out { flex: 1 1 auto; padding-left: 9px; }
.pd-tf-lkret-head-key { flex: 0 0 124px; padding-left: 6px; }
.pd-tf-newfield { flex-direction: column; align-items: stretch; gap: 8px; border-style: dashed; padding: 10px; margin-top: 4px; }
.pd-tf-newfield-lbl { font-size: 11px; color: var(--text-muted); font-weight: 600; }
.pd-tf-newfield .pd-io-add { margin: 0; }
.pd-tf-newfield.pd-tf-dragover { border-color: var(--brand); background: rgba(107,78,255,.08); }

.pd-editor-dock { position: fixed; top: 0; right: 0; bottom: 0; width: min(460px, 96vw); border-left: 1px solid var(--line); z-index: 940; }
.pd-ed-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); background: var(--bg-subtle); }
.pd-ed-head .pd-def-kind { display: inline-flex; align-items: center; gap: 6px; }
.pd-ed-title { font-weight: 700; color: var(--text); flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-ed-close { font-size: 20px; line-height: 1; padding: 0 4px; }
.pd-tabs { display: flex; gap: 2px; padding: 6px 10px 0; border-bottom: 1px solid var(--line); background: var(--bg-subtle); }
.pd-tab { border: 1px solid transparent; border-bottom: none; background: none; color: var(--text-muted); font-size: 13px; font-weight: 600; padding: 8px 14px; cursor: pointer; border-radius: 8px 8px 0 0; }
.pd-tab:hover { color: var(--text); }
.pd-tab.active { background: var(--bg-card); color: var(--text); border-color: var(--line); position: relative; top: 1px; box-shadow: inset 0 2px 0 var(--brand-orange); }
.pd-ed-body { padding: 14px 16px; overflow: auto; flex: 1 1 auto; }
.pd-ed-type { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; color: var(--text); padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg-subtle); }
.pd-ed-type svg { width: 18px; height: 18px; }
.pd-ed-actions { display: flex; gap: 8px; margin-top: 18px; flex-wrap: wrap; }
.pd-io-typechip { display: inline-block; font-size: 10.5px; font-weight: 600; color: var(--text-muted); background: rgba(0,0,0,.05); border-radius: 5px; padding: 1px 6px; margin: 0 6px; }
.pd-io-opt { font-size: 10.5px; color: var(--text-muted); opacity: .65; }
.pd-io-req { font-size: 10.5px; font-weight: 700; color: var(--brand-orange); }

/* §125 Node editor — standard-sized fields (match the rest of the app) and full-width searchable
   combos. Mirrors the inspector-field styling that was previously scoped to .pd-define / .pd-def-col,
   which no longer matched the rebuilt editor's .pd-editor / .pd-tabpanel containers. */
.pd-editor input:not([type="checkbox"]), .pd-editor select, .pd-editor textarea {
    font-family: var(--font-ui); font-size: 13px; color: var(--text);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm); box-sizing: border-box;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.pd-editor input:focus, .pd-editor select:focus, .pd-editor textarea:focus,
.pd-editor .combo-control:focus-within {
    outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft);
}
/* searchable dropdown combos take the full field width inside the editor */
.pd-editor .combo { width: 100%; min-width: 0; box-sizing: border-box; }
.pd-editor .combo-input { font-size: 13px; }
/* column-level fields (Name, Description, Configuration inputs, the doc/agent dropdowns) get the
   standard full width + height; fields inside flex rows (mapping / lookup) keep their own layout */
.pd-editor .pd-tabpanel > input:not([type="checkbox"]),
.pd-editor .pd-tabpanel > textarea,
.pd-editor .pd-tabpanel > select { box-sizing: border-box; width: 100%; padding: 9px 11px; font-size: 13px; }
.pd-editor .pd-tabpanel > .combo { width: 100%; }
.pd-editor .pd-def-name { padding: 9px 11px; }
.pd-editor textarea, .pd-editor .pd-def-desc { resize: vertical; min-height: 64px; line-height: 1.35; padding: 9px 11px; }

/* §126 Node editor — Input/Output field-structure editor (name · data type · required) and
   a consistent 12px vertical gap between field rows in the pop-up. */
.pd-editor .pd-def-label { margin-top: 30px !important; }
.pd-editor .pd-ed-body .pd-tabpanel > .pd-def-label:first-child { margin-top: 0 !important; }

.pd-struct { display: flex; flex-direction: column; gap: 12px; }
.pd-struct-head { display: flex; gap: 8px; align-items: center; font-size: 11px; font-weight: 700; color: var(--text-muted); letter-spacing: .02em; text-transform: uppercase; }
.pd-struct-list { display: flex; flex-direction: column; gap: 26px; }
.pd-struct-row, .pd-struct-addrow { display: flex; gap: 8px; align-items: center; }
.pd-struct-h-name, .pd-struct-name { flex: 1 1 auto; min-width: 0; }
.pd-struct-name { padding: 8px 10px; }
.pd-struct-h-type { flex: 0 0 140px; }
.pd-struct-row > .combo, .pd-struct-addrow > .combo { flex: 0 0 140px; min-width: 0; }
.pd-struct-h-req, .pd-struct-req { flex: 0 0 74px; }
.pd-struct-req { display: flex; align-items: center; }
.pd-struct-req .switch { flex: 0 0 auto; }
.pd-struct-h-x, .pd-struct-x { flex: 0 0 24px; text-align: center; }
.pd-struct-add { flex: 0 0 auto; }
.pd-struct-addrow { border-top: 1px dashed var(--line); padding-top: 12px; margin-top: 12px; }
/* Start node "starting fields" editor: name | type | constant value | remove */
.pd-sf .pd-struct-name, .pd-sf .pd-struct-h-name { flex: 1 1 0; }
.pd-sf-val { flex: 1 1 0; min-width: 0; padding: 8px 10px; }
.pd-sf-h-val { flex: 1 1 0; min-width: 0; }
/* §128 Output-tab action buttons (Push to post-processor / Show record structure) */
.pd-out-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

/* ===================== r271 — customizable KPI dashboard (card library) ===================== */
.dh-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px;}
.dh-head h2{font-size:22px;font-weight:800;letter-spacing:-.02em;margin:0;color:var(--text);}
.dh-head .dh-sub{color:var(--text-muted);font-size:13px;margin-top:4px;}
.dh-customize{display:inline-flex;align-items:center;gap:8px;font:inherit;font-weight:600;font-size:13px;color:var(--text);background:var(--bg-card);border:1px solid var(--line);border-radius:9px;padding:9px 13px;cursor:pointer;}
.dh-customize:hover{background:var(--bg-subtle);}
.dh-customize svg{width:15px;height:15px;color:var(--text-muted);}
.dh-customize .dh-badge{display:inline-grid;place-items:center;min-width:18px;height:18px;padding:0 5px;border-radius:99px;background:var(--text);color:#fff;font-size:11px;font-weight:700;line-height:1;}

.dh-stat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:14px;margin-bottom:22px;}
.dh-stat{position:relative;background:#E9EEF5;border:1px solid var(--line);border-radius:16px;padding:22px 22px 20px;}
.dh-stat-label{color:var(--text-muted);font-size:14px;font-weight:500;}
.dh-stat-val{font-size:40px;font-weight:800;letter-spacing:-.03em;line-height:1.05;margin:8px 0 6px;color:var(--text);font-variant-numeric:tabular-nums;}
.dh-stat-hint{font-size:14px;font-weight:600;}
.dh-stat-hint.pos{color:#15803D;} .dh-stat-hint.neg{color:#DC2626;} .dh-stat-hint.muted{color:#8A93A6;}

.dh-panel{background:var(--bg-card);border:1px solid var(--line);border-radius:18px;padding:22px;margin-bottom:22px;}
.dh-panel-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px;}
.dh-panel-head h3{font-size:20px;font-weight:800;letter-spacing:-.02em;margin:0;color:var(--text);}
.dh-panel-head .dh-hint{color:#8A93A6;font-size:12px;}
.dh-kpi-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:16px;}
.dh-kpi{position:relative;background:#EEF2F7;border-radius:14px;padding:20px;display:flex;flex-direction:column;min-height:226px;}
.dh-kpi.crit{background:#FDEEE9;border:1px solid #F4D8CD;}
.dh-kpi-head{display:flex;align-items:center;gap:8px;margin-bottom:14px;}
.dh-dot{width:10px;height:10px;border-radius:50%;flex:none;}
.dh-cat{font-weight:700;font-size:17px;letter-spacing:-.01em;color:var(--text);}
.dh-figure{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;}
.dh-val{font-size:33px;font-weight:800;letter-spacing:-.03em;line-height:1.06;color:var(--text);font-variant-numeric:tabular-nums;}
.dh-val .dh-unit{font-size:.58em;font-weight:800;}
.dh-trend{display:inline-flex;align-items:center;gap:4px;font-weight:700;font-size:15px;padding-top:5px;white-space:nowrap;}
.dh-trend.pos{color:#15803D;} .dh-trend.neg{color:#DC2626;}
.dh-desc{color:var(--text-muted);font-size:15px;line-height:1.34;margin:12px 0 0;}
.dh-rule{height:1px;background:var(--line);margin:16px 0 0;}
.dh-kpi.crit .dh-rule{background:#F1D2C6;}
.dh-foot{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:auto;padding-top:14px;}
.dh-foot-text{color:var(--text-muted);font-size:13.5px;line-height:1.3;}
.dh-foot-status{font-weight:700;font-size:13.5px;text-align:right;white-space:nowrap;color:var(--text);}
.dh-foot-status.crit{color:#DC2626;}

.dh-rm{position:absolute;top:10px;right:10px;width:24px;height:24px;border-radius:7px;border:none;background:rgba(15,23,42,.05);color:#8A93A6;cursor:pointer;display:grid;place-items:center;opacity:0;transition:opacity .12s,background .12s,color .12s;}
.dh-stat:hover .dh-rm,.dh-kpi:hover .dh-rm,.dh-stat:focus-within .dh-rm,.dh-kpi:focus-within .dh-rm{opacity:1;}
.dh-rm:hover{background:rgba(220,38,38,.12);color:#DC2626;}
.dh-rm svg{width:12px;height:12px;}
.dh-empty{grid-column:1/-1;border:1.5px dashed var(--line);border-radius:14px;padding:30px;text-align:center;color:var(--text-muted);font-size:14px;}
.dh-empty button{margin-top:12px;}

.dh-lib-search{width:100%;border:1px solid var(--line);border-radius:8px;padding:9px 11px;font:inherit;font-size:14px;margin-bottom:6px;background:var(--bg-subtle);color:var(--text);}
.dh-lib-group{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#8A93A6;padding:14px 4px 6px;}
.dh-lib-row{display:flex;align-items:center;gap:11px;padding:9px 8px;border-radius:9px;}
.dh-lib-row:hover{background:var(--bg-subtle);}
.dh-lib-dot{width:9px;height:9px;border-radius:50%;flex:none;}
.dh-lib-meta{flex:1;min-width:0;}
.dh-lib-name{font-weight:600;font-size:14px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.dh-lib-sub{font-size:12px;color:#8A93A6;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.dh-lib-toggle{flex:none;font:inherit;font-weight:600;font-size:12.5px;border-radius:8px;padding:6px 12px;cursor:pointer;border:1px solid var(--line);background:var(--bg-card);color:var(--text);min-width:60px;}
.dh-lib-toggle:hover{background:var(--bg-subtle);}
.dh-lib-toggle.on{background:var(--text);border-color:var(--text);color:#fff;}
.dh-lib-toggle.on:hover{background:#DC2626;border-color:#DC2626;}
.dh-lib-none{color:var(--text-muted);font-size:14px;padding:20px 6px;}

/* Process designer — Test run (dry-run data-flow) panel + canvas status dots */
.pd-run-backdrop { position: fixed; inset: 0; background: rgba(15,23,42,.35); z-index: 1090; }
.pd-run { position: fixed; top: 50%; left: 50%; transform: translate(-50%,-50%); width: min(880px, 94vw); height: 76vh; background: var(--bg-card); border-radius: var(--radius, 12px); z-index: 1100; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 18px 60px rgba(0,0,0,.35); }
.pd-run-bar { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.pd-run-title { font-size: 14px; color: var(--text); }
.pd-run-sub { font-size: 11.5px; color: var(--text-muted); }
.pd-run-body { padding: 14px 16px; overflow: auto; flex: 1 1 auto; }
.pd-run-summary { margin-bottom: 12px; }
.pd-run-sum { display: inline-block; font-size: 12.5px; font-weight: 600; padding: 7px 12px; border-radius: var(--radius-sm, 8px); border: 1px solid var(--line); }
.pd-run-sum.ok { color: var(--ok); background: var(--ok-bg); border-color: var(--ok); }
.pd-run-sum.warn { color: var(--brand-orange); background: var(--bad-bg); border-color: var(--brand-orange); }
.pd-run-static { margin-bottom: 14px; padding: 10px 12px; border: 1px solid var(--bad); background: var(--bad-bg); border-radius: var(--radius-sm, 8px); }
.pd-run-lab { font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 6px; }
.pd-run-steps { display: flex; flex-direction: column; gap: 10px; }
.pd-run-step { border: 1px solid var(--line); border-left: 3px solid var(--line); border-radius: var(--radius-sm, 8px); padding: 10px 12px; cursor: pointer; background: var(--bg-card); }
.pd-run-step:hover { border-color: var(--brand); }
.pd-run-step.ok { border-left-color: var(--ok); }
.pd-run-step.warn { border-left-color: var(--brand-orange); }
.pd-run-step.skip { border-left-color: var(--text-muted); opacity: .85; }
.pd-run-head { display: flex; align-items: center; gap: 8px; }
.pd-run-ico { display: inline-flex; width: 22px; height: 22px; align-items: center; justify-content: center; }
.pd-run-ico svg { width: 15px; height: 15px; }
.pd-run-name { font-size: 13px; font-weight: 600; color: var(--text); }
.pd-run-kind { font-size: 11px; color: var(--text-muted); }
.pd-run-stat { margin-left: auto; font-size: 13px; font-weight: 700; }
.pd-run-stat.ok { color: var(--ok); }
.pd-run-stat.warn { color: var(--brand-orange); }
.pd-run-stat.skip { color: var(--text-muted); }
.pd-run-io { display: flex; align-items: stretch; gap: 10px; margin-top: 9px; }
.pd-run-col { flex: 1 1 0; min-width: 0; }
.pd-run-arrow { align-self: center; color: var(--text-muted); font-size: 15px; }
.pd-run-chip { display: inline-flex; align-items: center; gap: 5px; margin: 0 5px 5px 0; padding: 3px 7px; font-size: 11px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-subtle, var(--bg-card)); max-width: 100%; }
.pd-run-k { font-family: var(--font-mono); color: var(--brand); white-space: nowrap; }
.pd-run-v { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-run-empty { font-size: 11px; color: var(--text-muted); font-style: italic; }
.pd-run-more { font-size: 10.5px; color: var(--text-muted); }
.pd-run-probs { margin: 9px 0 0; padding-left: 20px; list-style: disc; font-size: 11.5px; color: var(--brand-orange); }
.pd-run-static .pd-run-probs { color: var(--bad); margin-top: 0; }
.pd-run-probs li { margin: 2px 0; }
.pd-run-none { font-size: 12.5px; color: var(--text-muted); padding: 18px 4px; }
.pd-node-status { position: absolute; top: -5px; left: -5px; width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--bg-card); box-shadow: 0 1px 3px rgba(0,0,0,.25); z-index: 3; }
.pd-node-status.ok { background: var(--ok); }
.pd-node-status.warn { background: var(--brand-orange); }
.pd-node-status.skip { background: var(--text-muted); }


/* Processes list: clickable process name + On/Off activation switch (added with the process On/Off + Transform tab fixes) */
.pd-name-link { background: none; border: 0; padding: 0; margin: 0; font: inherit; font-weight: 700; color: var(--primary); cursor: pointer; text-align: left; }
.pd-name-link:hover { text-decoration: underline; }
.pd-switch { position: relative; width: 40px; height: 22px; border-radius: 999px; border: 1px solid var(--line-strong); background: var(--bg-subtle); cursor: pointer; padding: 0; flex: 0 0 auto; transition: background .15s ease, border-color .15s ease; }
.pd-switch .pd-switch-knob { position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--text-muted); transition: left .15s ease, background .15s ease; }
.pd-switch.on { background: rgba(22,163,74,.18); border-color: #16a34a; }
.pd-switch.on .pd-switch-knob { left: 20px; background: #16a34a; }
.pd-switch:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Transform lookup: dedicated key-input row (shown when the provider declares no key field) */
.pd-tf-lkg-keyrow { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.pd-tf-lkg-keylab { flex: 0 0 auto; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); }
.pd-tf-lkg-keyslot { flex: 1 1 auto; min-width: 0; }

/* Test-run: which branch a Decision takes, evaluated from the run's sample values */
.pd-dec { margin: 9px 0 0; padding: 8px 10px; border: 1px solid var(--line); border-left: 3px solid var(--brand); border-radius: var(--radius-sm); background: var(--bg-subtle); }
.pd-dec-head { font-size: 12px; font-weight: 600; color: var(--text); }
.pd-dec-note { font-weight: 400; color: var(--text-muted); font-size: 11px; }
.pd-dec-list { list-style: none; margin: 7px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.pd-dec-branch { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.pd-dec-branch.is-chosen { font-weight: 600; }
.pd-dec-cond { font-family: var(--mono, ui-monospace, monospace); color: var(--text-muted); }
.pd-dec-branch.is-chosen .pd-dec-cond { color: var(--text); }
.pd-dec-arrow { color: var(--text-muted); }
.pd-dec-branch.is-chosen .pd-dec-arrow { color: var(--brand); }
.pd-dec-y, .pd-dec-n, .pd-dec-q { width: 14px; text-align: center; flex: 0 0 auto; }
.pd-dec-y { color: #16a34a; font-weight: 700; }
.pd-dec-n { color: var(--text-muted); }
.pd-dec-q { color: var(--brand-orange); font-weight: 700; }
.pd-dec-def { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; flex: 0 0 auto; }

/* §162 — onboarding questionnaire cards (supplier request form) */
.qn-card { border: 1px solid var(--border, #e5e7eb); border-radius: 8px; padding: 10px; margin-bottom: 10px; background: var(--surface-2, #fafafa); }
.qn-card-head { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.qn-card-head .qn-name { flex: 1 1 auto; }
.qn-card-head .qn-reviewer { flex: 0 0 auto; max-width: 220px; }
.qn-card .qn-questions { width: 100%; resize: vertical; }

/* §163 — grouped questionnaires on the supplier-facing onboarding form */
.onb-qn-title { font-weight: 600; margin: 14px 0 6px; padding-bottom: 4px; border-bottom: 1px solid var(--border, #e5e7eb); }
.onb-qn-block { display: flex; flex-direction: column; gap: 10px; }

/* §164 — questionnaire review line in the supplier-request detail */
.qn-review-line { margin: 4px 0 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.qn-review-line .cell-sub { margin: 0; }

/* §165 — NDA presentation on the onboarding form + intake toggle */
.nda-box { max-height: 160px; overflow-y: auto; padding: 12px 14px; border: 1px solid var(--border, #e5e7eb); border-radius: 8px; background: var(--surface-2, #f9fafb); font-size: 13px; line-height: 1.5; color: var(--text-muted, #4b5563); margin-bottom: 10px; }
.nda-agree { display: flex; align-items: flex-start; gap: 8px; margin: 4px 0 12px; font-size: 14px; cursor: pointer; }
.nda-agree input { margin-top: 3px; }
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 8px 0; }
/* r1259 — inside a field grid a switch is a grid ITEM, and its own flex layout is for its contents. Without
   a minimum it collapses to its text in a narrow column, which is what made half-width and full-width
   switches look the same in the right-hand panel. */
.cf-grid > .toggle-row, .form-grid > .toggle-row { box-sizing: border-box; min-width: 0; }
.cf-grid > .toggle-row > span:first-child, .form-grid > .toggle-row > span:first-child { min-width: 0; }

/* ---- Live process debugger (step-by-step run trace) ---- */
.pdbg-live { display:inline-flex; align-items:center; gap:5px; font-size:12px; font-weight:600; color:#16a34a; }
.pdbg-live .dot { width:8px; height:8px; border-radius:50%; background:currentColor; animation:pdbgpulse 1.2s ease-in-out infinite; }
@keyframes pdbgpulse { 0%,100%{ opacity:1; transform:scale(1);} 50%{ opacity:.25; transform:scale(.7);} }
.pdbg-wait-banner { background:rgba(245,158,11,.10); border:1px solid rgba(245,158,11,.55); border-radius:8px; padding:9px 11px; margin-bottom:10px; font-size:13px; line-height:1.45; }
.pdbg-steps { position:relative; }
.pdbg-step { border:1px solid var(--border,#e5e7eb); border-radius:9px; padding:8px 10px; margin-bottom:8px; background:var(--surface,#fff); transition:border-color .2s, box-shadow .2s; }
.pdbg-step.is-current { border-color:rgba(245,158,11,.7); box-shadow:0 0 0 3px rgba(245,158,11,.14); }
.pdbg-step.is-failed { border-color:rgba(220,38,38,.6); box-shadow:0 0 0 3px rgba(220,38,38,.10); }
.pdbg-step-head { display:flex; align-items:center; gap:8px; cursor:pointer; }
.pdbg-step-num { width:22px; height:22px; border-radius:50%; background:var(--surface-2,#f1f3f5); display:inline-flex; align-items:center; justify-content:center; font-size:11px; font-weight:700; flex:0 0 auto; }
.pdbg-step.is-current .pdbg-step-num { background:#f59e0b; color:#fff; }
.pdbg-step.is-failed .pdbg-step-num { background:#dc2626; color:#fff; }
.pdbg-caret { margin-left:auto; color:var(--text-muted); font-size:11px; transition:transform .15s; }
.pdbg-kv { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11.5px; line-height:1.5; white-space:pre-wrap; word-break:break-word; background:var(--surface-2,#f7f7f8); border:1px solid var(--border,#eceef0); border-radius:6px; padding:6px 8px; }
.pdbg-kv .k { color:var(--text-muted); }
.pdbg-kv .add { color:#15803d; font-weight:600; }
.pdbg-kv .add .k { color:#15803d; }

/* ---- Engine activity log console ---- */
.alog-bar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:6px; }
.alog-ctl { font-size:12px; color:var(--text-muted); display:inline-flex; align-items:center; gap:5px; }
.alog-note { font-size:12px; line-height:1.45; margin-bottom:8px; }
.alog-host { height:52vh; min-height:280px; overflow:auto; background:#0b1020; border:1px solid #1f2937; border-radius:8px; padding:6px 8px; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12px; line-height:1.55; }
.alog-row { display:flex; gap:8px; align-items:baseline; padding:1px 2px; border-bottom:1px solid rgba(255,255,255,.04); white-space:pre-wrap; word-break:break-word; }
.alog-t { color:#7c8aa5; flex:0 0 auto; }
.alog-lvl { flex:0 0 46px; font-weight:700; font-size:10.5px; letter-spacing:.04em; }
.alog-cat { flex:0 0 64px; color:#8b9bb4; }
.alog-msg { color:#cdd6e6; flex:1 1 auto; }
.alog-ref { color:#7c8aa5; }
.alog-info .alog-lvl { color:#5fb0ef; }
.alog-warn .alog-lvl { color:#f0b429; }
.alog-warn .alog-msg { color:#f3d28b; }
.alog-error .alog-lvl { color:#ef5f6b; }
.alog-error .alog-msg { color:#f6a6ad; }
.alog-debug { opacity:.62; }
.alog-debug .alog-lvl { color:#8b9bb4; }

/* AI spend & credit (item 12) */
.ai-spend-usage { margin: 8px 0; }
.ais-usage-line { font-size: 14px; }
.ais-bar { height: 8px; border-radius: 4px; background: var(--surface-2, #e9eef5); overflow: hidden; margin: 6px 0; max-width: 420px; }
.ais-bar-fill { height: 100%; background: linear-gradient(90deg, #2e9e6b, #e0a52e); }
.line-tm { font-weight: 600; color: var(--text-muted, #6b7280); letter-spacing: 0.02em; }

/* System Console — record detail (item 3) */
.rec-open-cell { width: 34px; text-align: center; }
.rec-open { background: none; border: 1px solid var(--line); cursor: pointer; color: var(--text-muted); padding: 2px 4px; border-radius: var(--radius-sm); display: inline-flex; }
.rec-open:hover { background: var(--bg-subtle); color: var(--text); }
.rec-open svg { width: 14px; height: 14px; }
.rec-detail { display: flex; flex-direction: column; gap: 10px; max-height: 60vh; overflow: auto; }
.rec-row { display: grid; grid-template-columns: 200px 1fr; gap: 12px; align-items: start; }
.rec-key { font-weight: 600; font-size: 13px; color: var(--text-muted); word-break: break-word; padding-top: 2px; }
.rec-val { font-size: 13px; }
.rec-val pre { margin: 0; white-space: pre-wrap; word-break: break-word; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; background: var(--bg-subtle, #f6f7f9); border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px; max-height: 320px; overflow: auto; }
.rec-val.rec-null { color: #999; font-style: italic; }

.totals-note { font-size: 11px; color: var(--text-muted); font-weight: 400; }

/* ===== Command centre: top application bar + palette (r343) ===== */
.appbar {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 20px;
    height: 56px; flex: 0 0 56px;
    box-sizing: border-box;
    background: var(--bg-topmenu);
    border-bottom: 1px solid var(--line);
}
.appbar-here { display: flex; flex-direction: row; align-items: center; gap: 12px; min-width: 0; }
.appbar-here__wrap { display: flex; flex-direction: column; justify-content: center; min-width: 0; }
/* r664: the appbar leads with the screen/tab NAME as a large heading (~24px, sized to the top menu),
   then the Back / Next navigation buttons in a group after it. */
.appbar-nav-group { display: inline-flex; align-items: center; gap: 6px; flex: none; }
/* r666: Back / Next live in the MIDDLE of the appbar. Each is 38px tall (matching the search and
   notification buttons), and shows the NAME of the screen it goes to \u2014 Back's destination to the right of
   its chevron, Next's to the left of its chevron, so the labels sit on the outer edges pointing inward.
   Absolutely centred in the bar so it stays in the middle regardless of the widths on either side. */
.appbar-nav-center { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; z-index: 1; }
.appbar-nav-center:empty { display: none; }
.appbar-nav { display: inline-flex; align-items: center; gap: 7px; flex: none; height: 38px; padding: 0 12px;
  border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--bg-card);
  color: var(--text); cursor: pointer; font: inherit; font-size: 13px; width: 150px; }
.appbar-nav--next { justify-content: flex-end; }
.appbar-nav:hover { border-color: var(--primary); background: var(--bg-subtle); }
.appbar-nav svg { color: var(--text-muted); flex: none; }
.appbar-nav__lbl { display: inline-flex; flex-direction: column; line-height: 1.05; min-width: 0;
  flex: 1 1 auto; text-align: left; }
.appbar-nav--next .appbar-nav__lbl { text-align: right; }
.appbar-nav__dir { font-size: 11px; font-weight: 700; color: var(--text-muted); letter-spacing: .02em; }
.appbar-nav__to { font-size: 12.5px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.appbar-here__t { font-size: 24px; font-weight: 700; line-height: 1.1; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.appbar-here__s { font-size: 12px; color: var(--text-muted); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.appbar-create-wrap { position: relative; }
.appbar-create { height: 36px; display: inline-flex; align-items: center; gap: 6px; padding: 0 12px; }
.appbar-create-plus { font-size: 16px; font-weight: 700; line-height: 1; }
.appbar-create-caret { margin-left: 2px; opacity: .9; }
.appbar-icon { display: inline-flex; align-items: center; justify-content: center; position: relative;
  width: 36px; height: 36px; border: 0; background: none; border-radius: 8px;
  color: var(--text-muted); cursor: pointer; }
.appbar-icon:hover { background: var(--bg-subtle); color: var(--text); }
.appbar-avatar { display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 999px; border: 0; cursor: pointer;
  background: var(--brand-orange, #E8792A); color: #fff; font-size: 12.5px; font-weight: 700; }
.appbar-avatar:hover { filter: brightness(1.05); }
.account-menu { position: absolute; top: 50px; right: 14px; z-index: 60; min-width: 220px;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: 12px;
  box-shadow: 0 12px 30px rgba(15,23,42,.16); padding: 6px; }
.account-menu__id { display: flex; align-items: center; gap: 10px; padding: 8px 8px 10px;
  border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.account-menu__nm { display: block; font-size: 13.5px; font-weight: 600; }
.account-menu__role { display: block; font-size: 11.5px; color: var(--text-muted); }
.account-menu button { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px;
  background: none; border: 0; font: inherit; font-size: 13px; color: var(--text); cursor: pointer;
  border-radius: 8px; text-align: left; }
.account-menu button:hover { background: var(--bg-subtle); }
.account-menu svg { width: 17px; height: 17px; color: var(--text-muted); }
.appbar-search {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex: 0 1 520px;
    height: 38px;
    padding: 0 12px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius);
    background: var(--bg-subtle);
    color: var(--text-muted);
    cursor: text;
    font: inherit;
    font-size: 13px;
    text-align: left;
}
.appbar-search:hover { border-color: var(--primary); }
.appbar-search svg { color: var(--text-muted); flex: none; }
.appbar-search-text { flex: 1; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.appbar-kbd { display: inline-flex; gap: 3px; flex: none; }
.appbar-kbd kbd, .palette-kbd kbd {
    font-family: var(--font-mono); font-size: 11px; line-height: 1;
    padding: 3px 5px; border: 1px solid var(--line-strong);
    border-bottom-width: 2px; border-radius: 4px;
    background: var(--bg-card); color: var(--text-muted);
}
.appbar-spacer { flex: 1 1 auto; }
.appbar-create { height: 38px; white-space: nowrap; }
.appbar-mywork {
    display: inline-flex; align-items: center; gap: 8px;
    height: 38px; padding: 0 12px;
    border: 1px solid var(--line-strong); border-radius: var(--radius);
    background: var(--bg-card); color: var(--text);
    cursor: pointer; font: inherit; font-size: 13px; font-weight: 500;
}
.appbar-mywork:hover { border-color: var(--primary); background: var(--bg-subtle); }
.appbar-mywork svg { color: var(--text-muted); flex: none; }
.appbar-mywork-count {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px;
    border-radius: 9px; background: var(--primary); color: #fff;
    font-size: 11px; font-weight: 700; line-height: 1;
}
.appbar-mywork-count[hidden] { display: none; }
.appbar-notif { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--bg-card); color: var(--text); cursor: pointer; }
.appbar-notif:hover { border-color: var(--primary); background: var(--bg-subtle); }
.appbar-notif svg { color: var(--text-muted); }
/* r662: the search button is framed like the notification button (it was an unframed icon). Same box:
   bordered card with the primary hover, so the two read as a matching pair in the appbar. */
#appbar-search.appbar-icon { width: 38px; height: 38px; border: 1px solid var(--line-strong);
  border-radius: var(--radius); background: var(--bg-card); color: var(--text); }
#appbar-search.appbar-icon:hover { border-color: var(--primary); background: var(--bg-subtle); }
#appbar-search.appbar-icon svg { color: var(--text-muted); }
.appbar-notif-count { position: absolute; top: -6px; right: -6px; min-width: 17px; height: 17px; padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; border-radius: 9px; background: #dc2626; color: #fff; font-size: 10.5px; font-weight: 700; line-height: 1; }
.appbar-notif-count[hidden] { display: none; }
.notif-item { position: relative; }
.notif-item.is-unread { background: var(--bg-subtle); }
/* r1335 — the unread dot had 14px of `.work-item` padding to sit in and was placed at 5px, which put it
   against the panel's edge with the text starting immediately beside it. The dot moves in and the text
   moves over: a marker crowding the edge reads as a rendering fault rather than as a mark. */
.notif-item { padding-left: 26px; }
.notif-item.is-unread::before { content: ""; position: absolute; left: 11px; top: 14px; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); }
.notif-when { display: block; font-size: 10.5px; color: var(--text-muted); margin-top: 2px; }
.notif-foot-row { display: flex; padding: 6px 8px 2px; border-top: 1px solid var(--line); }
.notif-mark { flex: 1; background: none; border: 0; color: var(--primary); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; padding: 6px; border-radius: var(--radius-sm); }
.notif-mark:hover { background: var(--bg-subtle); }
.notif-mark[disabled] { color: var(--text-muted); cursor: default; }
.ip-board { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin: 4px 0 22px; }
.ip-col { background: var(--bg-subtle); border: 1px solid var(--line); border-radius: var(--radius); padding: 8px; min-height: 64px; }
.ip-col-head { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 4px 6px 8px; display: flex; justify-content: space-between; align-items: center; gap: 6px; }
.ip-col-count { background: var(--bg-card); border: 1px solid var(--line); border-radius: 9px; padding: 0 6px; font-size: 11px; color: var(--text); font-weight: 600; }
.ip-col-body { display: flex; flex-direction: column; gap: 6px; }
.ip-card { background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; cursor: pointer; }
.ip-card:hover { border-color: var(--primary); }
.ip-card.is-overdue { border-left: 3px solid #dc2626; }
.ip-card-top { display: flex; justify-content: space-between; align-items: center; gap: 6px; }
.ip-card-title { font-weight: 600; font-size: 13px; margin-top: 4px; line-height: 1.3; }
.ip-card-sub { color: var(--text-muted); font-size: 11px; margin-top: 3px; }
.ip-col-empty { color: var(--text-muted); font-size: 11px; padding: 6px; }
@media (max-width: 1100px) { .ip-board { grid-template-columns: repeat(2, 1fr); } }
.cc-menu {
    position: absolute; top: 58px; right: 32px; z-index: 60;
    width: 280px; max-height: 60vh; overflow: auto;
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 6px;
}
.cc-menu-search {
    width: 100%; box-sizing: border-box; height: 34px; margin-bottom: 6px;
    padding: 0 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
    background: var(--bg-subtle); color: var(--text); font: inherit; font-size: 13px;
}
.cc-menu-list { display: flex; flex-direction: column; }
.cc-menu-item {
    display: block; width: 100%; text-align: left;
    padding: 8px 10px; border: 0; border-radius: var(--radius-sm);
    background: transparent; color: var(--text); cursor: pointer; font: inherit; font-size: 13px;
}
.cc-menu-item:hover { background: var(--primary-soft); color: var(--primary-ink); }
.cc-menu-empty { padding: 10px; color: var(--text-muted); font-size: 13px; }
.palette-overlay {
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, 0.45);
    display: flex; align-items: flex-start; justify-content: center;
    padding: 96px 16px 16px; z-index: 70; overflow-y: auto;
}
.palette-overlay[hidden] { display: none; }
.palette {
    width: 100%; max-width: 600px; max-height: 70vh;
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: 10px; box-shadow: var(--shadow-lg);
    overflow: hidden; display: flex; flex-direction: column;
}
.palette-search {
    display: flex; align-items: center; gap: 10px;
    padding: 14px 16px; border-bottom: 1px solid var(--line);
}
.palette-search svg { color: var(--text-muted); flex: none; }
.palette-search input {
    flex: 1; border: 0; outline: none; background: transparent;
    color: var(--text); font: inherit; font-size: 16px;
}
.palette-list { overflow-y: auto; padding: 6px; }
.palette-group {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); padding: 10px 10px 4px;
}
.palette-item {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px; border-radius: var(--radius-sm); cursor: pointer;
}
.palette-item.is-active { background: var(--primary-soft); }
.palette-item-ic {
    flex: none; width: 22px; height: 22px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 5px; background: var(--bg-subtle); color: var(--text-muted);
    font-weight: 700; font-size: 14px;
}
.palette-item.is-active .palette-item-ic { background: var(--primary); color: #fff; }
.palette-item-label { flex: 1; color: var(--text); font-size: 14px; }
.palette-item-sub { color: var(--text-muted); font-size: 12px; }
.palette-empty { padding: 24px 16px; color: var(--text-muted); font-size: 14px; text-align: center; }
@media (max-width: 720px) {
    .appbar { padding: 10px 16px; gap: 8px; }
    .appbar-search-text, .appbar-kbd, .appbar-mywork-label { display: none; }
    .appbar-search { flex: 0 0 auto; width: 38px; padding: 0; justify-content: center; }
    .cc-menu { right: 16px; left: 16px; width: auto; }
}

/* ===== Role-based Home: greeting (context header) + quick actions (r344) ===== */
.home-greeting { font-size: 22px; margin: 0; }
.home-quick { margin: 0 0 22px; }
.home-quick-head {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); margin: 0 0 10px;
}
.home-quick-row { display: flex; flex-wrap: wrap; gap: 10px; }
.qa-btn {
    display: inline-flex; align-items: flex-start; gap: 10px; text-align: left;
    flex: 1 1 240px; max-width: 360px;
    padding: 11px 14px; border: 1px solid var(--line-strong); border-radius: var(--radius);
    background: var(--bg-card); color: var(--text); cursor: pointer;
    font: inherit; font-size: 13px; font-weight: 500;
}
.qa-btn:hover { border-color: var(--primary); background: var(--bg-subtle); }
.qa-ic {
    flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 5px; margin-top: 1px;
    background: var(--primary-soft); color: var(--primary-ink);
    font-weight: 700; font-size: 15px; line-height: 1;
}
.qa-btn:hover .qa-ic { background: var(--primary); color: #fff; }
.qa-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.qa-label { font-weight: 600; }
.qa-sub { font-size: 11.5px; font-weight: 400; color: var(--text-muted); line-height: 1.35; }
.qa-flow, .area-tile-flow {
    display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
    padding: 2px 7px; border-radius: 999px;
    background: var(--primary-soft); color: var(--primary-ink);
    font-size: 10.5px; font-weight: 600;
}
.qa-flow { flex: 0 0 auto; align-self: flex-start; margin-top: 1px; }
.area-tile-flow { margin-top: 8px; }
@media (max-width: 720px) {
    .home-quick-row .qa-btn { flex: 1 1 calc(50% - 5px); justify-content: flex-start; }
}

/* ===== Role-based Home: recent documents (r345) ===== */
.home-recent { margin: 0 0 22px; }
.home-recent-head {
    font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--text-muted); margin: 0 0 10px;
}
.home-recent-row { display: flex; flex-wrap: wrap; gap: 8px; }
.recent-chip {
    display: inline-flex; align-items: center; gap: 7px;
    max-width: 260px; padding: 7px 11px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--bg-subtle); color: var(--text); text-decoration: none;
    font-size: 12.5px;
}
.recent-chip:hover { border-color: var(--primary); background: var(--bg-card); }
.recent-chip-ic { color: var(--text-muted); flex: none; display: inline-flex; }
.recent-chip-label { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* ===== Role-based Home: favourites + star toggle (r346) ===== */
.fav-toggle.is-fav { color: var(--primary); }
.fav-chip .recent-chip-ic { color: var(--primary); }

/* ===== Role-based Home: attention strip ===== */
.home-attn { margin: 0 0 22px; }
.home-attn-row { display: flex; flex-wrap: wrap; gap: 10px; }
.attn-card {
    display: inline-flex; align-items: flex-start; gap: 10px;
    max-width: 360px; min-width: 220px; padding: 12px 14px;
    border: 1px solid var(--line); border-left-width: 3px; border-radius: 10px;
    background: var(--bg-card); color: var(--text); text-align: left; cursor: pointer; font: inherit;
}
.attn-card:hover { border-color: var(--primary); }
.attn-warn { border-left-color: var(--warn, #d97706); }
.attn-info { border-left-color: var(--primary); }
.attn-warn .attn-ic { color: var(--warn, #d97706); }
.attn-info .attn-ic { color: var(--primary); }
.attn-ic { flex: none; display: inline-flex; margin-top: 1px; }
.attn-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.attn-title { font-weight: 600; font-size: 13px; }
.attn-sub { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 300px; }

/* ===== Role-based Home: my priority work (server-ranked) ===== */
.home-priority { margin: 0 0 22px; }
.home-priority-list { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.pw-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--line); background: var(--bg-card); color: var(--text); text-decoration: none; }
.pw-row:last-child { border-bottom: 0; }
.pw-row:hover { background: var(--bg-subtle); }
.pw-type { flex: none; }
.pw-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.pw-num { font-weight: 600; font-size: 13px; }
.pw-owner { font-size: 11.5px; color: var(--text-muted); }
.pw-reason { flex: none; font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: var(--bg-subtle); color: var(--text-muted); }
.pw-reason.pw-wait { color: var(--warn, #d97706); background: color-mix(in srgb, var(--warn, #d97706) 12%, transparent); }
.pw-reason.pw-val { color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); }

/* ===== Unified Work / Notifications panel (app-bar dropdown) ===== */
.work-panel { min-width: 320px; max-width: 380px; max-height: 70vh; overflow-y: auto; padding: 6px 0; }
.work-loading { padding: 16px; }
.work-sec { padding: 4px 0 6px; }
.work-sec + .work-sec { border-top: 1px solid var(--line); }
.work-sec-head { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 8px 14px 4px; }
.work-item { display: flex; flex-direction: column; gap: 2px; padding: 8px 14px; text-decoration: none; color: var(--text); }
.work-item:hover { background: var(--bg-subtle); }
.work-item-main { font-size: 13px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.work-item-sub { font-size: 11.5px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.work-empty { padding: 8px 14px 10px; font-size: 12.5px; color: var(--text-muted); }
.work-foot { width: 100%; text-align: center; padding: 10px 14px; border: 0; border-top: 1px solid var(--line); background: transparent; color: var(--primary); font-weight: 600; font-size: 12.5px; cursor: pointer; }
.work-foot:hover { background: var(--bg-subtle); }

/* ===== Phase 1: area landing pages ===== */
.nav-area-link { cursor: pointer; border-radius: 6px; }
.nav-area-link:hover { color: var(--text); background: var(--bg-subtle); }
.nav-area-link:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.area-land-head { margin: 0 0 18px; }
.area-land-head h2 { margin: 0 0 4px; font-size: 22px; }
.area-land-desc { margin: 0; color: var(--text-muted); font-size: 13.5px; }
.area-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; }
.area-tile { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-card); overflow: hidden; }
.area-tile-open { display: block; padding: 14px 16px; text-decoration: none; color: var(--text); flex: 1; }
.area-tile-open:hover { background: var(--bg-subtle); }
.area-tile-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.area-tile-name { font-weight: 600; font-size: 14.5px; }
.area-tile-count { font-weight: 700; font-size: 15px; color: var(--primary); }
.area-tile-sub { margin-top: 4px; font-size: 12px; color: var(--text-muted); line-height: 1.4; }
.area-tile-new { border: 0; border-top: 1px solid var(--line); background: transparent; color: var(--primary); font-weight: 600; font-size: 12px; padding: 8px 16px; text-align: left; cursor: pointer; }
.area-tile-new:hover { background: var(--bg-subtle); }

/* ===== WCAG 2.2 AA: skip link + global focus-visible ===== */
.skip-link { position: absolute; left: 8px; top: -60px; z-index: 2000; padding: 10px 16px; background: var(--primary, #2563eb); color: #fff; border-radius: 0 0 8px 8px; font-weight: 600; text-decoration: none; transition: top .12s ease; }
.skip-link:focus { top: 0; }
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible,
.nav-item:focus-visible, .nav-area-link:focus-visible, .setup-tab:focus-visible,
[data-config-tab]:focus-visible, [data-tab]:focus-visible, .palette-item:focus-visible,
.area-tile-open:focus-visible, .work-item:focus-visible, .pw-row:focus-visible {
    outline: 2px solid var(--primary, #2563eb); outline-offset: 2px; border-radius: 4px;
}
#main-content:focus { outline: none; }

/* ===== Customers (Order-to-Cash): contact editor ===== */
.cust-contact-row { display: grid; grid-template-columns: 1.4fr 1.6fr 1fr 1fr auto; gap: 8px; margin-bottom: 8px; align-items: center; }
@media (max-width: 640px) { .cust-contact-row { grid-template-columns: 1fr 1fr; } }

/* ===== Sales orders (Order-to-Cash): line editor ===== */
.so-line-row { display: grid; grid-template-columns: 2.4fr 0.9fr 1fr 1fr auto; gap: 8px; margin-bottom: 8px; align-items: center; }
.so-line-total { text-align: right; font-variant-numeric: tabular-nums; padding-right: 4px; }
.so-total-row { margin-top: 10px; text-align: right; font-size: 14px; }
.so-total-row strong { font-variant-numeric: tabular-nums; }
.so-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }
@media (max-width: 640px) { .so-line-row { grid-template-columns: 1fr 1fr; } }

/* ===== Customer invoices (AR): line editor with tax + totals ===== */
.ci-line-row { display: grid; grid-template-columns: 2.2fr 0.8fr 1fr 0.8fr 1fr auto; gap: 8px; margin-bottom: 8px; align-items: center; }
.ci-line-total { text-align: right; font-variant-numeric: tabular-nums; padding-right: 4px; }
.ci-lines-tools { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.ci-totals { margin-top: 12px; display: flex; gap: 24px; justify-content: flex-end; font-size: 13.5px; }
.ci-totals strong { font-variant-numeric: tabular-nums; }
.ci-total-gross strong { font-size: 15px; }
.ci-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }
@media (max-width: 640px) { .ci-line-row { grid-template-columns: 1fr 1fr; } .ci-totals { flex-direction: column; gap: 4px; align-items: flex-end; } }

/* ===== Shipments (O2C fulfilment): fulfilment plan table ===== */
.sh-plan { width: 100%; }
.sh-plan th, .sh-plan td { padding: 6px 8px; }
.sh-plan .num { text-align: right; font-variant-numeric: tabular-nums; }
.sh-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }

/* ===== Credit notes (AR): status chip (line editor + totals reuse .ci-line-row / .ci-totals) ===== */
.cn-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }

/* ===== Customer payments (AR cash application) ===== */
.cpay-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }
.cpay-unapplied { font-size: 12.5px; color: var(--text-muted); margin-left: 10px; }
.cpay-unapplied-chip { display: inline-block; padding: 1px 7px; border-radius: 10px; background: var(--warn-bg, #fef3c7); color: var(--warn-fg, #92400e); font-size: 12px; font-variant-numeric: tabular-nums; }

/* ===== Quotations (pre-sales): status chip (line editor + totals reuse .ci-line-row / .ci-totals) ===== */
.quo-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }

/* ===== Opportunities (pre-sales / CRM) ===== */
.opp-status-chip { margin-bottom: 6px; font-size: 13px; color: var(--text-muted); }
.opp-weighted { font-size: 15px; font-weight: 600; color: var(--text, #0f172a); font-variant-numeric: tabular-nums; }
.opp-stage-inline { font-size: 12.5px; padding: 3px 6px; }

/* ===== Leads (top of the pre-sales funnel) ===== */
.lead-status-inline { font-size: 12.5px; padding: 3px 6px; }

/* ===== Journal entries (general ledger) ===== */
.je-line-head, .je-line-row { display: grid; grid-template-columns: 2fr 2fr 1fr 1fr 36px; gap: 8px; align-items: center; }
.je-line-head { font-size: 12px; color: var(--text-muted); padding: 2px 0; }
.je-line-row { margin-bottom: 6px; }
.je-balance { display: flex; gap: 12px; align-items: center; margin-top: 10px; }
.je-tot { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 13px; }

/* ===== Trial balance ===== */
.tb-total td { border-top: 2px solid var(--border, #e2e8f0); padding-top: 8px; }

/* ===== Financial statements ===== */
.fs-table .fs-group td { padding-top: 12px; color: var(--text, #0f172a); border-bottom: 1px solid var(--border, #e2e8f0); }
.fs-table .fs-subtotal td { border-top: 1px solid var(--border, #e2e8f0); }

/* ============================================================ printable documents (Save as PDF) */
#print-root { display: none; }
.pdoc-sheet { color: #1c232b; font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-size: 12px; line-height: 1.5; }
.pdoc-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; }
.pdoc-issuer-name { font-size: 20px; font-weight: 700; color: #4F5963; letter-spacing: -0.01em; }
.pdoc-addr { margin-top: 6px; color: #5b6672; font-size: 11px; line-height: 1.6; }
.pdoc-title-box { text-align: right; min-width: 200px; }
.pdoc-doctitle { font-size: 15px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; color: #FF8C1F; }
.pdoc-docno { font-size: 18px; font-weight: 700; color: #1c232b; margin-top: 2px; }
.pdoc-status { display: inline-block; margin-top: 6px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #4F5963; border: 1px solid #cbd5e1; border-radius: 999px; padding: 2px 10px; }
.pdoc-accent { height: 3px; background: #FF8C1F; margin: 14px 0 18px; border-radius: 2px; }
.pdoc-parties { display: flex; justify-content: space-between; gap: 32px; margin-bottom: 20px; }
.pdoc-party-label, .pdoc-party-name { }
.pdoc-party-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: #8a94a0; margin-bottom: 3px; }
.pdoc-party-name { font-size: 14px; font-weight: 700; color: #1c232b; }
.pdoc-meta { min-width: 220px; }
.pdoc-meta-row { display: flex; justify-content: space-between; gap: 16px; padding: 3px 0; border-bottom: 1px solid #eef2f6; font-size: 11px; }
.pdoc-meta-row span { color: #8a94a0; }
.pdoc-meta-row strong { color: #1c232b; font-weight: 600; }
.pdoc-lines { width: 100%; border-collapse: collapse; margin-bottom: 18px; }
.pdoc-lines th { text-align: left; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: #4F5963; border-bottom: 2px solid #4F5963; padding: 7px 8px; }
.pdoc-lines td { padding: 7px 8px; border-bottom: 1px solid #eef2f6; vertical-align: top; }
.pdoc-lines th.num, .pdoc-lines td.num { text-align: right; white-space: nowrap; }
.pdoc-lines th.pdoc-wide, .pdoc-lines td.pdoc-wide { width: 42%; }
.pdoc-empty { color: #8a94a0; text-align: center; padding: 16px 8px; }
.pdoc-foot { display: flex; justify-content: space-between; align-items: flex-start; gap: 32px; }
.pdoc-notes { flex: 1; }
.pdoc-note { margin-bottom: 10px; max-width: 340px; }
.pdoc-note-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: #8a94a0; margin-bottom: 2px; }
.pdoc-totals { border-collapse: collapse; min-width: 240px; }
.pdoc-totals td { padding: 5px 8px; font-size: 12px; }
.pdoc-totals td.num { text-align: right; white-space: nowrap; }
.pdoc-totals tr.pdoc-grand td { border-top: 2px solid #4F5963; font-weight: 700; font-size: 14px; padding-top: 8px; }
.pdoc-generated { margin-top: 28px; padding-top: 10px; border-top: 1px solid #eef2f6; font-size: 9.5px; color: #a4adb8; text-align: center; letter-spacing: 0.02em; }
@media print {
    body.printing > *:not(#print-root) { display: none !important; }
    body.printing #print-root { display: block !important; }
    @page { size: A4; margin: 15mm; }
    html, body { background: #fff !important; }
}

/* ---- Recruiting workspace (hiring pipeline) ---- */
.rc-section { margin-top: 22px; padding-top: 6px; border-top: 1px solid var(--line); }
.rc-section:first-of-type { border-top: none; margin-top: 8px; }
.rc-panel { background: var(--bg-app); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 14px 16px; margin: 4px 0 8px; }
.rc-panel-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 720px) { .rc-panel-grid { grid-template-columns: 1fr; } }
.rc-panel-row > td { background: transparent; padding: 0 8px 8px; }
.rc-addrow { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.rc-addrow .tinp { width: auto; flex: 1 1 150px; min-width: 120px; }   /* r1608 */
.rc-addrow .btn { flex: 0 0 auto; }
.rc-doc { display: inline-flex; align-items: center; gap: 6px; margin: 0 12px 6px 0; font-size: 13px; white-space: nowrap; }
.rc-docs { display: flex; flex-wrap: wrap; }
.rc-btnrow { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 6px 0 12px; }
.ok-text { color: var(--ok); font-weight: 600; }
.bad-text { color: var(--bad); font-weight: 600; }

/* ---- Legal-entity letterhead logo ---- */
.le-logo-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin: 4px 0 6px; }
.le-logo-preview { height: 46px; max-width: 240px; object-fit: contain; border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 5px 8px; background: var(--bg-card); }
.le-logo-empty { color: var(--text-muted); font-size: 13px; }
.le-logo-actions { display: inline-flex; gap: 8px; align-items: center; }
.le-logo-row .hint { flex-basis: 100%; }

/* =========================================================================
   Network activity (r388): indeterminate top progress bar + bottom status line.
   Driven by the central api() wrapper, so any in-flight request shows a working
   cue (covers slow form opens) and the status line reports the current action.
   ========================================================================= */
.netbar {
    position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 120;
    background: transparent; pointer-events: none; overflow: hidden;
    opacity: 0; transition: opacity .15s ease;
}
.netbar.is-busy { opacity: 1; }
.netbar::before {
    content: ""; position: absolute; top: 0; height: 100%; width: 38%; left: -38%;
    background: linear-gradient(90deg, transparent, var(--primary, #FF8C1F), transparent);
    animation: netbar-slide 1.05s linear infinite;
}
@keyframes netbar-slide { from { left: -38%; } to { left: 100%; } }

.statusbar {
    display: none;   /* shown only when signed in (body.is-authed) */
    /* r803: the height is a TOKEN because the scroll areas must reserve it. It is position:fixed, so it
       is out of flow — a scrolling container has no idea it exists and its last rows end up underneath.
       Reported from the field as "something is behind the status line and it is not visible". */
    /* r1128: left FOLLOWS the rail, like the wide pop-up scrim. It was a hard-coded 248px, so a collapsed
       68px rail left the status line starting well to the right of the menu, with a bare strip beneath it.
       --rail-w is 68px under body.rail-collapsed, so the bar now begins at the rail's edge in both states. */
    position: fixed; bottom: 0; left: var(--rail-w, 248px); right: 0; height: var(--statusbar-h); z-index: 40;
    align-items: center; gap: 8px; padding: 0 14px;
    background: var(--bg-card); border-top: 1px solid var(--line);
    color: var(--text-muted); font-size: 12px; line-height: 1;
    box-shadow: inset 0 1px 0 var(--line);
}
body.is-authed .statusbar { display: flex; }
.statusbar-dot {
    flex: none; width: 8px; height: 8px; border-radius: 50%;
    background: #94A3B8; transition: background .2s ease;
}
.statusbar.is-busy .statusbar-dot {
    background: var(--primary, #FF8C1F); animation: statusbar-pulse 1s ease-in-out infinite;
}
@keyframes statusbar-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.statusbar-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Keep the last content clear of the fixed status line. */
/* r1110 — removed: .main now ends above the status bar, so #view needs no bottom reserve at all.
   This override (and its r803/r1107 ancestors) existed only to dodge a fixed bar over a full-height
   canvas; with the canvas shortened at the source there is nothing left to dodge. */

/* Sub-group heading inside an expanded nav area (r494): breaks long areas into scannable clusters. */
.nav-sub {
    padding: 12px 14px 4px 14px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-muted);
    user-select: none;
}
.nav-sub.nav-collapsed { display: none; }

/* forgot password + a way back out of the change-password screen */
.auth-link{display:block;width:100%;margin-top:10px;background:none;border:0;color:var(--text-muted);font-size:13px;cursor:pointer;text-align:center;padding:6px;font-family:inherit}
/* --accent is not a token in this application, so this always fell back to a literal orange whatever
   theme was chosen. --primary is the real one and follows the theme. */
.auth-link:hover{color:var(--primary);text-decoration:underline}
.auth-back{display:block;margin:10px auto 0;text-align:center}
.auth-note{background:rgba(63,182,105,.12);border:1px solid rgba(63,182,105,.35);color:#7ee0a2;border-radius:8px;padding:10px 12px;font-size:13px;margin-bottom:10px;line-height:1.45}

/* Login screen: QR codes to the companion apps, so a phone can reach them without typing a URL. */
.auth-mods { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line, #e3eaf4); }
.auth-mods-head { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
                  color: var(--text-muted, #6b7890); text-align: center; margin-bottom: 12px; }
.auth-mods-grid { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.auth-mod { width: 96px; text-align: center; }
.auth-mod svg { width: 96px; height: 96px; display: block; border-radius: 8px; border: 1px solid var(--line, #e3eaf4); }
.auth-mod b { display: block; margin-top: 6px; font-size: 12px; font-weight: 800; color: var(--text, #111b2f); }
.auth-mod span { display: block; font-size: 10px; color: var(--text-muted, #6b7890); word-break: break-all; line-height: 1.35; }

/* ---------- storage alarm (r579) ----------
   A refused database write. Sticky and full-width on purpose: it is not a notification, it is a statement
   that what the user believes they saved does not exist anywhere durable. */
.storage-alarm{position:sticky;top:0;z-index:9999;display:block;padding:12px 44px 12px 16px;
  background:#7f1d1d;color:#fff;font-size:13.5px;line-height:1.5}
.storage-alarm strong{color:#fff}
.storage-alarm__x{position:absolute;right:8px;top:6px;width:32px;height:32px;border:0;border-radius:6px;
  background:transparent;color:#fff;font-size:20px;line-height:1;cursor:pointer}
.storage-alarm__x:hover{background:rgba(255,255,255,.15)}

/* ---------- global shell pilot (r608) ----------
   The five destinations of the navigation specification §4. Deliberately reuses .nav-item so the rail
   looks like the rail people already know: the pilot is testing whether the STRUCTURE helps, and a
   simultaneous change of appearance would make the answer unreadable. */
.nav--shell .nav-item{font-weight:500}
.nav-item--tool{opacity:.9}
.nav-kbd{margin-left:auto;font-size:10.5px;opacity:.6;border:1px solid var(--line);border-radius:4px;padding:0 4px}
.nav-shell-sub{padding:14px 16px 6px;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-muted)}
/* r669: every workspace card is the SAME height — grid-auto-rows:1fr makes every row equal and
   the cards stretch to fill it, so no tile is shorter than its neighbours. */
.ws-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px;padding:16px;
  align-items:stretch;grid-auto-rows:1fr}
/* r707: at least 48px of breathing room on every side of a workspace card. These are the biggest
   targets in the product and the first thing a new reader sees; 24/16/16 made eight of them read as a
   dense toolbar rather than eight places to go. */
.ws-card{display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;height:100%;text-align:left;padding:48px;border:1px solid var(--line);border-radius:10px;
  background:var(--bg-card);color:inherit;cursor:pointer;min-height:110px}
.ws-card:hover{border-color:var(--primary)}
/* the index itself carries no frame: the grid is the page */
.view--ws-index:has(> .ws-grid){padding:6px 20px 56px;}   /* r1645 — only while it SHOWS the workspace grid */
.view--ws-index>.ws-grid{margin:0;}
.ws-card__name{font-size:16px;font-weight:600;margin-bottom:6px;flex:0 0 auto}
.ws-card__promise,.ws-card__sections{flex:0 0 auto}
.ws-card__promise{font-size:12.5px;color:var(--text-muted)}
.ws-card__sections{font-size:11.5px;color:var(--text-muted);margin-top:10px;opacity:.8}
.ws-sec{padding:8px 16px 4px}
.ws-sec h4{margin:10px 0 8px;font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted)}
.ws-links{display:flex;flex-wrap:wrap;gap:8px}

/* r1702 — the unified-work tab rules (uw-) were removed with their markup in r1490, but only their FIRST lines went:
   their second lines stayed behind as headless rule bodies, which made strict CSS parsers reject the whole sheet
   and, in browsers, swallowed the rule that followed. The removal is finished here, not reversed. */

/* The delivery-address actions (r613). A .field is a flex column, so buttons dropped straight into one
   stretch the full width of the form. Kept in a row of their own so they are ordinary buttons. */
.addr-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.addr-actions .btn { flex: 0 0 auto; }

/* The power state (r613). Sized so the glyph reads at a glance without becoming a button. */
.pill-power { display: inline-flex; align-items: center; justify-content: center; padding: 3px 6px; }
.pill-power svg { width: 15px; height: 15px; display: block; }
/* r1552 — the row ON/OFF control shows the STATE: green when on, muted when off, like the power pill. */
.power-toggle svg { width: 16px; height: 16px; color: var(--text-muted); }
.power-toggle.is-on svg { color: var(--ok); }
.power-toggle.is-on { border-color: var(--ok); background: var(--ok-bg); }

/* ---------- workspace detail, spec §8 (r614) ---------- */
.ws-crumb { display: flex; align-items: center; gap: 8px; padding: 12px 16px 0;
  font-size: 12.5px; color: var(--text-muted); }
.ws-crumb__link { background: none; border: 0; padding: 0; color: var(--accent-strong);
  cursor: pointer; font-size: 12.5px; min-height: 24px; }
.ws-crumb__link:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.ws-crumb__here { color: var(--text); }
.ws-tabs { display: flex; flex-wrap: wrap; gap: 4px; padding: 8px 16px 0; align-items: center; }
/* .ws-tab is gone (r654). The lifecycle strip uses the Setup tab component, and leaving the old rule
   behind would have been worse than dead CSS: AccessibilityAudit measured .ws-tab for the 44px touch
   target and kept passing on a rule nothing rendered any more. */
.ws-more { min-height: 44px; margin-left: 4px; background: var(--bg-card);
  color: inherit; border: 1px solid var(--line); border-radius: 8px; padding: 0 8px; }
.ws-links { display: flex; flex-wrap: wrap; gap: 8px; padding: 14px 16px; }
.ws-ctx { border-top: 1px solid var(--line); margin-top: 4px; }
/* Its own modifier, so a contextual list is distinguishable from the page list by selector and not only
   by where it happens to sit in the tree. */
.ws-links--ctx { padding-top: 8px; }
.ws-ctx__group + .ws-ctx__group { border-top: 1px solid var(--line); }
.ws-ctx__label { padding: 12px 16px 0; font-size: 11.5px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--text-muted); }

/* ---------- workspace overview, §8 (r616) ---------- */
.ws-ov { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; padding: 14px 16px; }
.ws-ov__panel { border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px;
  background: var(--bg-card); }
.ws-ov__panel h4 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); }
.ws-ov__panel--muted { opacity: .78; }
.ws-ov__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.ws-ov__row { display: block; width: 100%; text-align: left; background: none; border: 0; padding: 6px 4px;
  color: inherit; cursor: pointer; font-size: 13px; border-radius: 6px; min-height: 34px; }
.ws-ov__row:hover { background: var(--bg-subtle); }
.ws-ov__row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.ws-ov__why { display: block; color: var(--text-muted); font-size: 12px; margin-top: 2px; }

/* ---------- universal search, §10 (r618) ---------- */
.omni { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,.5);
  display: flex; align-items: flex-start; justify-content: center; padding: 10vh 16px; }
.omni__box { width: 100%; max-width: 640px; background: var(--bg-card);
  border: 1px solid var(--line); border-radius: 12px; overflow: hidden;
  box-shadow: 0 20px 60px rgba(0,0,0,.45); }
#omni-q { width: 100%; padding: 16px 18px; border: 0; border-bottom: 1px solid var(--line);
  background: transparent; color: inherit; font-size: 16px; min-height: 56px; }
#omni-q:focus { outline: none; }
.omni__count { padding: 6px 18px; font-size: 11.5px; color: var(--text-muted); }
.omni__results { max-height: 52vh; overflow: auto; padding-bottom: 6px; }
.omni__kind { padding: 10px 18px 4px; font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); }
.omni__row { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  padding: 9px 18px; cursor: pointer; min-height: 40px; }
.omni__row.is-at { background: var(--primary-soft); }
.omni__sub { color: var(--text-muted); font-size: 12px; white-space: nowrap; }
.omni__empty { padding: 18px; color: var(--text-muted); }

/* ---------- favorites, §12 (r619) ---------- */
.fav-sec { padding: 12px 16px; border-top: 1px solid var(--line); }
.fav-sec:first-of-type { border-top: 0; }
.fav-sec h4 { margin: 0 0 8px; font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); }
.fav-list { display: flex; flex-wrap: wrap; gap: 8px; }

/* ==================== §13 responsive shell (r620) ====================
   Three viewports, three behaviours. The rail does not simply shrink: at tablet width it keeps its icons
   and loses its labels, and below 768px it is replaced by a bottom bar, because a rail on a phone costs a
   third of the screen to show what a thumb cannot reach anyway. */

/* --- collapse control (NAV-008) --- */
.nav-collapse { display: none; margin: 6px 8px 2px auto; background: none; border: 0; cursor: pointer;
  color: var(--text-muted); font-size: 15px; min-width: 44px; min-height: 44px; border-radius: 8px; }
.nav-collapse:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
@media (min-width: 768px) { .nav-collapse { display: block; } }

/* --- collapsed rail: §14 says 64-72px, icon plus an ACCESSIBLE NAME --- */
/* r1042 — collapsing applies to the rail that is ON SCREEN, not only to the pilot one.
 *
 * Every rule here named `.nav--shell`, the five-destination pilot rail, which is hidden. The rail the
 * reader actually uses is `.sidebar .nav`, so collapsing narrowed nothing and every label stayed \u2014 the
 * control appeared to do nothing at all.
 *
 * **A rule written for the replacement does not apply to the thing still in use**, and the pilot has
 * been hidden behind a flag for long enough that its selectors read like the live ones. */
body.rail-collapsed { --rail-w: 68px; }
body.rail-collapsed .sidebar { width: 68px; }
body.rail-collapsed .nav--shell,
body.rail-collapsed .sidebar .nav { width: 68px; }
body.rail-collapsed .nav--shell .nav-item,
body.rail-collapsed .sidebar .nav .nav-item {
  justify-content: center; gap: 0; padding-left: 0; padding-right: 0; }

/* =================================================================================================
   r1502 — the SHELL rail collapses too.

   Every collapsed rule above names `.nav-item`, which belonged to the legacy Full menu removed in
   r1493. The rail the reader actually has is `.sbar__item`, and nothing answered the collapsed class
   at all: pressing collapse narrowed the frame around a rail that kept drawing at full width.

   The label is a bare text node inside the button, so `display: none` has nothing to select. Zeroing
   the button's font size hides it visually and leaves it in the accessibility tree, which is what the
   comment above this block asks for and what a screen reader needs.
   ================================================================================================= */
/* r1502 — and the touch target survives the collapse. `font-size: 0` with no explicit height let the
   button shrink to its padding, and AX-10 measured 0 against the 44px §16 minimum: **hiding a label by
   zeroing the text is also zeroing the thing that was giving the control its height.** */
body.rail-collapsed .sbar__item { font-size: 0; gap: 0; padding: 10px 2px; min-height: 44px; }
body.rail-collapsed .sbar__item .sbar__dot { width: 8px; height: 8px; }
body.rail-collapsed .sbar__item svg { width: 20px; height: 20px; }
/* the brand and any label-bearing chrome follow the same rule rather than each inventing one */
body.rail-collapsed .sbar__label { display: none; }
/* The label is hidden from sight, never from assistive technology: display:none would remove the only
   name these buttons have, leaving a screen reader to announce unlabelled controls. */
/* r1100 — the delivery detail's per-item progress line, and the detail action row */
/* r1101 — THEMED, not hard-coded. r1100 filled the bar with `var(--brand, #2a6df4)`: `--brand` exists
   nowhere in this stylesheet, so the fallback ALWAYS won and every profile theme showed the same
   foreign blue. `--accent` is the variable the user's profile theme redefines (data-theme), and the
   track is the estate's own `--line`. **A fallback colour that always applies is not a fallback — it
   is a hard-coded colour with an alibi.** */
.supb-prg { display: inline-block; width: 90px; height: 6px; border-radius: 3px;
  background: var(--line); vertical-align: middle; overflow: hidden; }
.supb-prg__b { display: block; height: 100%; background: var(--accent); }
.supb-dacts { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }

/* r1099 — the glyph is exempt alongside the dot: this rule clips every element child to 1×1 for the
   screen while keeping it readable to assistive technology, and the new .nav-ic would have been clipped
   with the labels — an icon added and invisibly sr-boxed in the same round. */
body.rail-collapsed .nav--shell .nav-item > :not(.nav-dot):not(.nav-ic),
body.rail-collapsed .sidebar .nav .nav-item > :not(.nav-dot):not(.nav-ic) {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* a section heading has no icon to fall back to, so it goes rather than becoming a blank line */
body.rail-collapsed .sidebar .nav-sub { display: none; }
body.rail-collapsed .sidebar .brand-logo { max-width: 40px; }
body.rail-collapsed .nav-shell-sub { display: none; }
body.rail-collapsed .nav-kbd { display: none; }

/* --- tablet: 768-1279px. Compact by default; the user's own choice still wins. --- */
@media (min-width: 768px) and (max-width: 1279px) {
  body:not(.rail-expanded) .nav--shell { width: 68px; }
  body:not(.rail-expanded) .nav--shell .nav-item > :not(.nav-dot) {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  body:not(.rail-expanded) .nav-shell-sub, body:not(.rail-expanded) .nav-kbd { display: none; }
}

/* --- phone: < 768px. The rail goes; a bottom bar takes over. --- */
.shell-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--bg-card); border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0); }
.sbar__item { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  padding: 8px 2px; border: 0; background: none; color: var(--text-muted);
  font-size: 11px; min-height: 52px; cursor: pointer; }
.sbar__item.is-active { color: var(--accent-strong); }
/* r1501 - hover lights the icon too: a control that only changes on click gives the reader nothing to
   aim at. */
.sbar__item:hover { color: var(--accent-strong); }
/* r1501 - the focus ring is for the KEYBOARD. A plain `:focus` outline stays on the button after a
   mouse click, which is the "framed in the active colour, cannot reproduce it" report: it appears when
   you click and not when you navigate any other way. */
.sbar__item:focus { outline: none; }
.sbar__item:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: -2px; }
.sbar__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.shell-more { position: fixed; right: 8px; bottom: 60px; z-index: 61; background: var(--bg-card);
  border: 1px solid var(--line); border-radius: 10px; padding: 6px; min-width: 160px; }
.shell-more__item { display: block; width: 100%; text-align: left; background: none; border: 0;
  color: inherit; padding: 10px 12px; min-height: 44px; cursor: pointer; border-radius: 6px; font-size: 14px; }
.shell-more__item:hover { background: var(--bg-subtle); }

@media (max-width: 767px) {
  body.shell-on .nav--shell, body.shell-on #nav { display: none; }
  body.shell-on .view { padding-bottom: 76px; }
}
@media (min-width: 768px) {
  .shell-bar, .shell-more { display: none !important; }
}

/* §16 motion: a navigation transition must not delay work, and a reduced-motion preference is a request,
   not a suggestion. Applies to the shell pieces added in r608-r620. */
@media (prefers-reduced-motion: reduce) {
  .omni, .omni__box, .shell-more, .ws-ov__panel, .nav--shell, .shell-bar {
    transition: none !important; animation: none !important; }
}

/* §15: administration, visually separated from the business workspaces. */
.nav-admin { border-top: 1px solid var(--line); margin-top: 4px; padding-top: 4px; }
body.rail-collapsed .nav-admin { border-top-color: transparent; }

/* ---------- activation gate, L7 (r627) ----------
   Above the sign-in form rather than replacing it: somebody holding the installer's password may still
   legitimately sign in and activate from inside, and a gate that blocks that leaves them nowhere. */
.act-gate { border: 1px solid var(--accent-strong); border-radius: 10px; padding: 14px 16px; margin: 0 0 16px;
  background: var(--bg-subtle); }
.act-gate h2 { margin: 0 0 6px; font-size: 15px; color: var(--accent-strong); }
.act-gate p { margin: 0 0 8px; font-size: 13px; color: var(--text); }
.act-gate__hint { color: var(--text-muted) !important; }
.act-gate__form { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.act-gate__form label { font-size: 12px; font-weight: 600; }
.act-gate__form input { padding: 9px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); color: inherit; min-height: 40px; }
.act-gate__form .btn { min-height: 40px; }
.act-gate__said { margin-top: 8px; font-size: 12.5px; color: var(--text-muted); }

/* The activation setter. Same frame as the gate, but it replaces the sign-in form rather than sitting
   above it — somebody following an activation link is here to do one thing. */
.act-set { border: 1px solid var(--accent-strong); border-radius: 10px; padding: 14px 16px; margin: 0 0 16px;
  background: var(--bg-subtle); }
.act-set h2 { margin: 0 0 6px; font-size: 15px; color: var(--accent-strong); }
.act-set p { margin: 0 0 8px; font-size: 13px; }

/* ==================== §6.1 My Work component plate (r633) ====================
   The approved desktop screen: a filter bar, a queue that keeps its place, and a preview beside it that
   holds exactly one primary decision. Named mwq- because .mw- and .uw- are both already taken by earlier
   versions of this screen, and a third definition of one of those class names would let the cascade decide
   which rule wins — the collision that made an earlier size assertion read zero. */

/* A label that exists for assistive technology and not for the eye. display:none would remove the only
   name these controls have. */
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0; padding: 0; margin: -1px; }

/* ---- ref 3: filters ---- */
.mwq-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 12px 16px; border-bottom: 1px solid var(--line); }
.mwq-search { flex: 0 1 240px; min-height: 40px; padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg-card); color: inherit; font-size: 13.5px; }
/* r1455 — the standard button corner, not a pill. At 999px they read as chips — a filter you might
   remove — rather than as the on/off buttons they are, and no other control in the estate is round. */
.mwq-chip { min-height: 40px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-card); color: var(--text-muted); cursor: pointer; font-size: 13px; }
.mwq-chip.is-on { border-color: var(--accent-strong); color: var(--accent-strong); background: var(--primary-soft); }
/* r1445 — the three filters are toggle BUTTONS with an icon and their name. A bare text chip reads as a
   label; `aria-pressed` said it was a control and nothing on screen did. 40px keeps the §16 touch target. */
.mwq-chip--btn { display: inline-flex; align-items: center; gap: 6px; }
.mwq-chip--btn svg { width: 16px; height: 16px; flex: 0 0 16px; }
.mwq-chip--btn.is-on svg { color: var(--accent-strong); }
.mwq-chip__t { line-height: 1; }
.mwq-chip:focus-visible, .mwq-clear:focus-visible, .mwq-select:focus-visible,
.mwq-search:focus-visible, .mwq-page:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.mwq-clear { min-height: 40px; padding: 0 10px; border: 0; background: none; color: var(--accent-strong);
  cursor: pointer; font-size: 13px; }
.mwq-clear[disabled] { color: var(--text-muted); cursor: default; }
.mwq-spacer { flex: 1 1 auto; }
.mwq-select { min-height: 40px; padding: 0 8px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); color: inherit; font-size: 13px; }

/* ---- refs 4 and 5: the queue ---- */
.mwq-split { display: grid; grid-template-columns: 1fr; gap: 0; }
.mwq-queue { min-width: 0; }
.mwq-list { max-height: 62vh; overflow: auto; }
.mwq-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 16px;
  border-bottom: 1px solid var(--line); cursor: pointer; }
.mwq-row:hover { background: var(--bg-subtle); }
/* Selection is a border, not only a tint: §16 says state is never carried by colour alone. */
.mwq-row.is-selected { background: var(--primary-soft); box-shadow: inset 3px 0 0 var(--accent-strong); }
.mwq-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.mwq-row__main { flex: 1 1 auto; min-width: 0; }
.mwq-row__act { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
.mwq-row__title { font-size: 14px; font-weight: 600; margin-top: 1px; }
.mwq-row__ctx { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.mwq-row__why { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.mwq-row__meta { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: 0 0 auto; }
.mwq-due { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.mwq-due.is-late { color: var(--bad); font-weight: 600; }
.mwq-impact { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
.mwq-impact--high { background: var(--bad-bg); color: var(--bad); }
.mwq-impact--medium { background: var(--warn-bg); color: var(--warn); }
.mwq-impact--low { background: var(--neutral-bg); color: var(--neutral); }
.mwq-open { flex: 0 0 auto; min-height: 44px; }
.mwq-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 16px; font-size: 12.5px; color: var(--text-muted); }
.mwq-pages { display: flex; align-items: center; gap: 6px; }
.mwq-page { min-width: 44px; min-height: 44px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); color: inherit; cursor: pointer; }
.mwq-page[disabled] { opacity: .45; cursor: default; }

/* ---- refs 6 and 7: the preview ---- */
.mwq-preview { border-top: 1px solid var(--line); padding: 14px 16px; min-width: 0; }
.mwq-preview__none { color: var(--text-muted); font-size: 13px; padding: 8px 0; }
.mwq-preview__head h4 { margin: 0; font-size: 15px; }
.mwq-preview__badge { display: inline-block; margin-top: 4px; font-size: 11.5px; font-weight: 600;
  color: var(--accent-strong); }
.mwq-preview__sub { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.mwq-preview__why { font-size: 13px; color: var(--text-muted); margin: 10px 0; }
.mwq-fields { margin: 12px 0; display: flex; flex-direction: column; gap: 6px; }
.mwq-f { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; }
.mwq-f__k { color: var(--text-muted); }
.mwq-f__v { text-align: right; }
.mwq-ctls { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; }
.mwq-ctl { font-size: 12.5px; padding: 8px 10px; border-radius: 8px; border-left: 3px solid var(--neutral); }
.mwq-ctl--ok { background: var(--ok-bg); color: var(--ok); border-left-color: var(--ok); }
.mwq-ctl--warn { background: var(--warn-bg); color: var(--warn); border-left-color: var(--warn); }
.mwq-ctl--bad { background: var(--bad-bg); color: var(--bad); border-left-color: var(--bad); }
/* A control that could not be evaluated is drawn as unevaluated, never as a pass. A grey box that says
   "not checked" is honest; a green tick that means "not checked" is a lie with a colour on it. */
.mwq-ctl--unknown { background: var(--neutral-bg); color: var(--neutral); border-left-style: dashed; }
.mwq-preview__acts { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; }
.mwq-preview__acts .btn { min-height: 44px; }
.mwq-activity { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.mwq-activity h5 { margin: 0 0 6px; font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); }
.mwq-activity ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.mwq-act__row { display: flex; gap: 10px; font-size: 12.5px; }
.mwq-act__what { font-weight: 600; }
.mwq-act__who, .mwq-act__at { color: var(--text-muted); }

/* §13: the preview sits beside the queue only where there is room for both. Below that it is a panel under
   the queue rather than a squeezed column — the queue's filters and scroll position are held in script
   state, so nothing is lost either way. */
@media (min-width: 1280px) {
  /* superseded at r639 by the §4.1 reference geometry below; one fact, one rule */
  .mwq-preview { border-top: 0; border-left: 1px solid var(--line); }
}
@media (prefers-reduced-motion: reduce) {
  .mwq-row, .mwq-preview, .mwq-chip { transition: none !important; animation: none !important; }
}

/* ==================== §4 / §7 / §8 screen geometry (r634) ====================
   Three corrections against the approved screens. */

/* The shell's glyphs. The rule that drew a 6px dot is replaced rather than extended: a dot with an icon
   inside it is a bullet wearing a picture. */

/* §8: the overview is exactly four panels, so it is a 2×2 and not an auto-fit that becomes a row of four
   on a wide monitor and a column of four on a narrow one. */
.ws-ov { grid-template-columns: 1fr; }
@media (min-width: 900px) { .ws-ov { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* §7: a card leads with its glyph. */

/* ==================== §5 Home: the four zones (r635) ====================
   The specification states a geometry, not a list: higher importance at the top, higher focus on the left.
   Two rows of 3/5 + 2/5, matching §6.1's split so the two screens do not disagree about what "left" means. */
.hz-grid { display: grid; grid-template-columns: 1fr; gap: 16px; margin-bottom: 22px; }
@media (min-width: 1280px) { .hz-grid { grid-template-columns: 3fr 2fr; } }
.hz-zone { min-width: 0; }
.hz-zone__head { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }
.hz-zone__head h2 { margin: 0; font-size: 13px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); font-weight: 600; }
.hz-zone__edit { margin-left: auto; min-width: 44px; min-height: 44px; border: 0; background: none;
  color: var(--text-muted); cursor: pointer; border-radius: 8px; }
.hz-zone__edit:hover { background: var(--bg-subtle); color: var(--text); }
.hz-zone__edit:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.hz-list { list-style: none; margin: 0; padding: 0; }
.hz-row { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%;
  text-align: left; background: none; border: 0; border-top: 1px solid var(--line);
  padding: 10px 16px; cursor: pointer; color: inherit; min-height: 44px; }
.hz-list li:first-child .hz-row { border-top: 0; }
.hz-row:hover { background: var(--bg-subtle); }
.hz-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.hz-row__t { font-size: 13.5px; font-weight: 600; }
.hz-row__s { font-size: 12px; color: var(--text-muted); }
.hz-sla { font-size: 13px; color: var(--text-muted); }
.hz-sla__n { font-size: 17px; font-weight: 600; color: var(--text); }
.hz-opt { display: flex; align-items: center; gap: 8px; font-size: 13.5px; min-height: 36px; }

/* ==================== §14.2 icon sizes and interaction targets (spec v1.4, r637) ====================
   Values are CSS pixels. Glyph and container are stated together because the plate ties them together:
   the glyph does not grow to fill a target, the padding grows to satisfy it. */

/* Primary navigation / control — 20 px glyph, 40 px desktop target, 44 px touch. */
.nav-dot, .sbar__dot { width: 20px; height: 20px; border-radius: 0; background: none;
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.nav-dot svg, .sbar__dot svg { width: 20px; height: 20px; display: block; }
#nav-shell .nav-item { min-height: 40px; }
.sbar__item { min-height: 44px; }

/* Workspace / object card. r668: a 32px glyph, positioned 24px from the top of the card, with the cards
   aligned from the top so every tile's icon sits on the same line. */
/* r1196 — the workspace-card icon carries the ACCENT itself (product owner request). accent-strong
   exists for TEXT contrast; a 48px glyph is a fill, where the accent is the intended colour. */
.ws-card__ic { display: flex; align-items: flex-start; justify-content: flex-start;
  width: 48px; height: 48px; color: var(--accent); margin: 0 0 10px; }
.ws-card__ic svg { width: 48px; height: 48px; display: block; }

/* Standard action / utility — 18 px glyph, 36 px desktop target. The 44 px here is the touch minimum
   from §16 and is deliberately larger than the desktop target, never smaller. */
.hz-zone__edit svg { width: 18px; height: 18px; }
.col-picker-btn svg { width: 18px; height: 18px; }

/* ==================== v1.6 §4 desktop geometry (r639) ====================
   The foundation layer. v1.6 defines 57 navigation states over six page families filled from nine slots,
   and every one of them is composed from the numbers below. Built as tokens rather than per-screen values
   because §4.4's whole purpose is that a count, an amount or a row behaves identically wherever it appears
   — 57 screens each carrying its own idea of a row height is exactly the outcome it forbids. */
:root {
  /* §4 shell */
  --v16-rail: 248px;            /* expanded rail */
  --v16-rail-collapsed: 72px;   /* collapsed rail; 40x40 targets, 20px glyphs */
  --v16-rail-item: 40px;
  --v16-topbar: 64px;
  --v16-header: 96px;           /* page header: title, purpose, one primary action */
  --v16-tabbar: 48px;           /* lifecycle tabs */
  --v16-pad: 24px;              /* content canvas outer padding */
  --v16-gap: 16px;
  --v16-card-radius: 12px;
  /* §4.1 wide split — WIDTHS ARE PROPORTIONS HERE, NOT THE SPECIFICATION'S PIXELS (r651).
     §4.1 states 704 + 16 + 424, which is exactly the content width of the 1440 reference frame once the
     248 rail and the 24 padding either side are taken out. It fits that frame and only that frame: on a
     1920 display it leaves roughly 370px of the page unused, and the screens read as a narrow column
     pinned to the left of a wide monitor.
     Product decision, taken deliberately against the letter of §4.1 and AC-14: the RATIO is kept
     (704:424 = 62.4:37.6) and expressed as a proportion so the same design fills whatever width it is
     given. Every HEIGHT in this file stays in pixels — rows, tabs, bars and targets are what AC-14 and
     §4.5 are really pinning, and they are about readability and touch targets rather than about how much
     of the monitor is used.
     The list floor stays in pixels on purpose: a minimum expressed as a percentage shrinks with the
     viewport, which is not a minimum. */
  /* r748: 66/33, with the detail's CURRENT floor kept as a floor.
     The detail had no px minimum — it was whatever 37.6% worked out to, which is 379px at the 1280
     breakpoint. Moving to a third without pinning that would have quietly narrowed the panel on the
     smallest supported screen, which is the one that can least afford it. Measured, then written down.

     66.6/33.4, not 66/33: the two halves must TOTAL 100. A split summing to 99 leaves a one-percent gap
     down the right-hand side of every screen, which FW-03 exists to catch — and did. It is 2:1 either
     way, and 2:1 that adds up is the one to have. */
  --v16-list: 66.6%;
  --v16-preview: 33.4%;
  --v16-list-min: 560px;        /* readability floor — px, because a proportional floor is not a floor */
  --v16-preview-min: 379px;     /* what 37.6% gave at 1280px, now guaranteed rather than incidental */
  /* §4.3 controls */
  --v16-btn: 40px;
  --v16-btn-compact: 32px;
  --v16-row: 56px;              /* standard table row */
  --v16-row-head: 44px;
  --v16-row-dense: 44px;        /* expert registers only */
  --v16-row-dense-head: 40px;
  --v16-input: 40px;
  --v16-decision-bar: 56px;     /* S8 */
}

/* §4.1: 704 + 16 + 424 at the 1440 reference, and the list floors at 560 rather than collapsing.
   This replaces the 3fr/2fr of r634 — a ratio holds its proportion at every width, which is not what the
   reference frame states. */
@media (min-width: 1280px) {
  .mwq-split { grid-template-columns: minmax(var(--v16-list-min), calc(var(--v16-list) - var(--v16-gap))) var(--v16-preview); }
}

/* §4.3 control geometry. Applied to the shared primitives so a screen inherits it instead of restating it. */
.btn { min-height: var(--v16-btn); }
.btn-primary { min-width: 96px; }
.btn-ghost, .btn-subtle { min-width: 80px; }
.btn-sm { min-height: var(--control-h); min-width: 72px; }   /* r1606 — the small button is narrower, not shorter */
.icon-btn { width: var(--v16-btn); height: var(--v16-btn); border-radius: 8px; }
.icon-btn svg { width: 20px; height: 20px; }
input:not([type=checkbox]):not([type=radio]), select, .mwq-search, .mwq-select { min-height: var(--v16-input); }
textarea { min-height: 96px; }

/* §4.3 tables. Dense is a user preference for expert registers, never a default, and never below the
   40 px the touch rules floor at. */
table.data tbody tr { height: var(--v16-row); }
table.data thead tr { height: var(--v16-row-head); }
.is-dense table.data tbody tr { height: var(--v16-row-dense); }
.is-dense table.data thead tr { height: var(--v16-row-dense-head); }

/* §4.5 S8 decision bar: one dominant action, secondaries neutral. */
.mwq-preview__acts { min-height: var(--v16-decision-bar); align-items: center; }

/* §14.2 object and status glyphs in the queue (r640). 20 px for the object (dense row / labelled control
   sits at 16, but a queue row is the row's subject, not a label), 16 px for the status shape. */
.mwq-row__ic { flex: 0 0 auto; width: 20px; height: 20px; color: var(--text-muted); margin-top: 2px; }
.mwq-row__ic svg { width: 20px; height: 20px; display: block; }
.mwq-due { display: inline-flex; align-items: center; gap: 4px; }
.mwq-due svg { width: 16px; height: 16px; flex: 0 0 auto; }

/* ==================== v1.6 §4.4 data views (r641) ====================
   One appearance per token, so a count on Home and a count in a workspace overview are the same object. */
.dv { display: block; width: 100%; text-align: left; background: var(--bg-card);
  border: 1px solid var(--line-strong); border-radius: var(--v16-card-radius); padding: 16px;
  min-height: 128px; color: inherit; font: inherit; }
.dv.is-drillable { cursor: pointer; }
.dv.is-drillable:hover { border-color: var(--accent-strong); }
.dv.is-drillable:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.dv__label { font-size: 12px; color: var(--text-muted); }
.dv__value { font-size: 24px; font-weight: 600; margin-top: 4px; }
.dv__value--refused { font-size: 15px; font-weight: 600; color: var(--text-muted); }
.dv__note { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; }
.dv__delta { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
/* Direction is a shape and a word. Colour is added only where the caller said which way is better. */
.dv__delta--up::before, .dv__delta--down::before { content: ""; }
.dv__delta.is-good { color: var(--ok); }
.dv__delta.is-bad { color: var(--bad); }
.dv__bar { height: 4px; border-radius: 2px; background: var(--neutral-bg); margin-top: 8px; overflow: hidden; }
.dv__bar > span { display: block; height: 100%; background: var(--accent); }
.dv__stamp { font-size: 11px; color: var(--text-muted); margin-top: 10px; }
.dv__stamp.is-stale { color: var(--warn); font-weight: 600; }
.dv__stamp--none { font-style: italic; }

.dv-st-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.dv-st { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
.dv-st__dot { width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; background: var(--neutral); }
.dv-st__dot--ok { background: var(--ok); } .dv-st__dot--warn { background: var(--warn); }
.dv-st__dot--bad { background: var(--bad); }
.dv-st__n { flex: 1 1 auto; } .dv-st__v { font-weight: 600; }

.dv-stage { list-style: none; margin: 10px 0 0; padding: 0; display: flex; gap: 8px; align-items: flex-end; }
.dv-stage__i { flex: 1 1 0; min-width: 0; text-align: center; }
.dv-stage__bar { display: block; height: 44px; display: flex; align-items: flex-end; justify-content: center; }
.dv-stage__bar > span { display: block; width: 100%; background: var(--accent); border-radius: 3px 3px 0 0; min-height: 2px; }
.dv-stage__c { display: block; font-size: 13px; font-weight: 600; margin-top: 4px; }
.dv-stage__n { display: block; font-size: 11px; color: var(--text-muted); }
.dv-stage__x { display: block; font-size: 11px; color: var(--bad); }

.dv-age { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.dv-age li { display: flex; justify-content: space-between; font-size: 12.5px; }
.dv-age__c.is-overdue { color: var(--bad); font-weight: 600; }

/* ==================== DV-LIST (§4.4, r642) ====================
   Every state keeps the toolbar and the header row; only the body changes. A list that swaps its table for
   a centred message loses its columns and its filters at the same moment, and the reader's next move is a
   reload that loses the filter for real. */
.dv-l { background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--v16-card-radius); overflow: hidden; }
.dv-l__bar { display: flex; align-items: center; gap: 8px; min-height: var(--v16-btn);
  padding: 4px 12px; border-bottom: 1px solid var(--line-strong); font-size: 12.5px; }
.dv-l__count { color: var(--text-muted); }
.dv-l__bar-sp { flex: 1 1 auto; }
.dv-l__saved { min-height: var(--v16-btn); border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card); }
.dv-l__partial { padding: 8px 12px; background: var(--warn-bg); color: var(--warn); font-size: 12px; }
.dv-l__scroll { overflow: auto; }
/* r651: the look is inherited from table.grid above — one description of what a list looks like, rather
   than a second one that drifts. What stays here is what is specific to the register: a fixed layout so
   the declared column proportions actually hold, and truncation so one long cell cannot widen a column. */
.dv-l__t { table-layout: fixed; }
.dv-l__t thead tr { height: var(--v16-row-head); }
.dv-l__t tbody tr { height: var(--v16-row); }
.dv-l.is-dense .dv-l__t thead tr { height: var(--v16-row-dense-head); }
.dv-l.is-dense .dv-l__t tbody tr { height: var(--v16-row-dense); }
.dv-l__t td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dv-l__sort { background: none; border: 0; padding: 0; font: inherit; color: inherit; cursor: pointer; }
.dv-l__sort:focus-visible, .dv-l__go:focus-visible, .dv-l__pg:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.dv-l__row.is-selected > td { background: var(--row-selected); }
.dv-l__pick { width: 44px; text-align: center; }
.dv-l__go { background: none; border: 0; padding: 0; font: inherit; color: var(--accent-strong); cursor: pointer; text-align: left; }
.dv-l__state { padding: 24px 12px; color: var(--text-muted); font-size: 13px; }
.dv-l__state--error { color: var(--bad); }
.dv-l__retry { min-height: 32px; margin-left: 8px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card); cursor: pointer; }
.dv-l__skel { display: block; height: 12px; border-radius: 6px; background: var(--bg-subtle); }
.dv-l__foot { display: flex; align-items: center; justify-content: space-between;
  padding: 6px 12px; font-size: 12px; color: var(--text-muted); border-top: 1px solid var(--line-strong); }
.dv-l__pg { min-width: var(--v16-btn); min-height: var(--v16-btn); border: 1px solid var(--line-strong);
  border-radius: 8px; background: var(--bg-card); cursor: pointer; }
.dv-l__pg[disabled] { opacity: .45; cursor: default; }

/* ==================== v1.6 §4.5 slots (r643) ====================
   The slot supplies the geometry; the page supplies the content. S0 is the existing shell and is not
   reimplemented here — §4.5 says a page never rebuilds it. */
.v16 { display: flex; flex-direction: column; }
/* r1102 — the board CHROME sits on the APP background, not the card's. Every coloured theme tints
   --bg-app and deliberately keeps --bg-card white; the v16 board painted S1/S2 card-white edge to
   edge and left no app background visible — so a selected scheme showed a white screen. The cards
   stay --bg-card; the chrome around them is where the chosen colour lives. */
.s1 { padding: 0 var(--v16-pad); background: var(--bg-app); border-bottom: 1px solid var(--line-strong); }
.s1__crumb { height: 24px; display: flex; align-items: center; font-size: 12px; color: var(--text-muted); }
.s1__crumb button { background: none; border: 0; padding: 0; font: inherit; color: var(--accent-strong); cursor: pointer; }
.s1__row { min-height: 48px; display: flex; align-items: center; gap: 16px; padding-bottom: 8px; }
.s1__t { flex: 1 1 auto; min-width: 0; }
.s1__t h1 { margin: 0; font-size: 18px; font-weight: 600; }
.s1__p { margin: 2px 0 0; font-size: 12.5px; color: var(--text-muted); }
.s1__a { flex: 0 0 auto; }

.s2 { height: var(--v16-tabbar); display: flex; align-items: stretch; gap: 16px; padding: 0 var(--v16-pad);
  background: var(--bg-app); border-bottom: 1px solid var(--line-strong); overflow: hidden; }
/* r704: the rule across the top of every workspace. Each scene emits an EMPTY tab band —
   <div class="s2 s2--owned-by-shell" aria-hidden="true"></div> — because the shell owns the lifecycle
   tabs. It has no content, so the only thing it ever drew was its own bottom border and a band of blank
   height above the page. A placeholder that reserves space for something rendered somewhere else is not a
   placeholder; it is a line. */
.s2--owned-by-shell { display: none; }
.s2__t { min-width: 88px; padding: 0 16px; border: 0; background: none; font: inherit; color: var(--text-muted);
  cursor: pointer; border-bottom: 3px solid transparent; }
.s2__t.is-active { color: var(--text); font-weight: 600; border-bottom-color: var(--accent); }
.s2__more { align-self: center; min-height: var(--v16-btn); border: 1px solid var(--line-strong); border-radius: 8px;
  background: var(--bg-card); }
.s2__more.is-active { border-color: var(--accent); color: var(--accent-strong); font-weight: 600; }
.s2__t:focus-visible, .s2__more:focus-visible, .s4__t:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

.s3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--v16-gap);
  padding: var(--v16-gap) var(--v16-pad) 0; }
.s4 { display: flex; gap: 8px; padding: var(--v16-gap) var(--v16-pad) 0; }
.s4__t { min-height: 40px; padding: 0 12px; border: 0; background: none; font: inherit;
  color: var(--text-muted); cursor: pointer; border-bottom: 2px solid transparent; }
.s4__t.is-active { color: var(--text); border-bottom-color: var(--text); }
.s5 { min-height: var(--v16-tabbar); display: flex; align-items: center; gap: 8px;
  padding: 8px var(--v16-pad) 0; }

.v16__work { padding: var(--v16-gap) var(--v16-pad) var(--v16-pad); display: grid;
  grid-template-columns: 1fr; gap: var(--v16-gap); min-width: 0; }
@media (min-width: 1280px) {
  .v16__work.has-context {
    grid-template-columns:
      minmax(var(--v16-list-min), calc(var(--v16-list) - var(--v16-gap)))
      minmax(var(--v16-preview-min), var(--v16-preview));
  }
}
.s6, .s7 { min-width: 0; }

/* r748: FOCUS — the third view mode, between normal and full screen.
   Full screen hides everything but the list. Focus keeps the reader where they are — tabs and sub-tabs
   stay — and gives the list and the detail the vertical space the band was using. It is the mode for
   working through records, where full screen is the mode for scanning one long list. */
/* r977 — focus hides the BAND and KEEPS the sub-tabs. It was the other way round on this screen: `.s3`
   does not exist here (the band is `.supb-band`), so nothing was hidden, while `.s4` — the lifecycle
   tabs and the search — WAS. The mode is for working through records, and a reader who has lost the tabs
   and kept the summary has had the wrong half taken away. **A rule written against a class the screen
   does not use is a rule that has never run**, and the one beside it was doing the opposite of what the
   comment above them describes. */
.v16.is-focus .s3,            /* the attention and KPI band, on screens that use .s3 */
.v16.is-focus .supb-band { display: none; }
.v16.is-focus .v16__work { padding-top: var(--v16-gap); }
/* §4.2.1 D-WB-M: the preview is a 12-column nested grid with 12 px gaps and 144x96 minimum panels. */
.s7--grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 12px; align-content: start; }
.s7__p { min-width: 144px; min-height: 96px; background: var(--bg-card); border: 1px solid var(--line-strong);
  border-radius: var(--v16-card-radius); padding: 12px; }
.s7__p h3 { margin: 0 0 6px; font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }

.s8 { min-height: var(--v16-decision-bar); display: flex; align-items: center; gap: 8px;
  padding: 0 var(--v16-pad); background: var(--bg-card); border-top: 1px solid var(--line-strong); }
/* r1492 — a plain S8: the page's horizontal padding and nothing else. The decision bar's card face,
   border and minimum height belong to a decision bar; a shelf carrying its own bordered content would
   be a box inside a box. The bottom padding matches the work row's so the shelf is not flush to the
   viewport edge. */
.s8--plain { min-height: 0; background: none; border-top: 0; display: block;
  padding: 0 var(--v16-pad) var(--v16-pad); }

.v16-bad { margin: var(--v16-pad); padding: 16px; border: 1px solid var(--bad); border-radius: var(--v16-card-radius);
  background: var(--bad-bg); color: var(--bad); font-size: 13px; }
.v16-bad ul { margin: 6px 0 0; padding-left: 18px; }

/* ===== v1.6 §8.9 lifecycle-tab scenes (r648) ===== */
/* S9 is the process/analytic module: §4.5 puts a 240x160 floor under it so a flow cannot be squeezed
   into a strip that no longer reads as one. */
.s9 { padding: 0 var(--v16-pad) var(--v16-pad); display: grid; gap: var(--v16-gap);
  grid-template-columns: 1fr; }
@media (min-width: 1100px) { .s9 { grid-template-columns: minmax(240px, 2fr) 3fr; } }
.s9 > * { min-width: 240px; min-height: 160px; }

.ws-sc__q { min-width: 240px; }
.ws-sc__sp { flex: 1 1 auto; }
.ws-sc__spec { font-size: 11px; color: var(--text-muted); letter-spacing: .04em; text-transform: uppercase; }
/* A stated absence, not a styled warning: the point is that the number is missing on purpose. */
.ws-sc__gap { margin: 6px var(--v16-pad) 0; font-size: 12px; color: var(--text-muted); font-style: italic; }
.ws-sc__ph { margin: 0 0 8px; font-size: 14px; }
.ws-sc__pv { display: grid; grid-template-columns: max-content 1fr; gap: 4px 12px; margin: 0 0 16px; font-size: 13px; }
.ws-sc__pv dt { color: var(--text-muted); }
.ws-sc__pv dd { margin: 0; }
.ws-sc__links { border-top: 1px dashed var(--line-strong); padding-top: 12px; }
.ws-sc__links h4, .ws-sc__attn h4 { margin: 0 0 8px; font-size: 12px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em; }
.ws-sc__attn { background: var(--bg-card); border: 1px solid var(--line-strong);
  border-radius: var(--v16-card-radius); padding: 12px; }
.ws-scene-todo { margin: var(--v16-pad); padding: 16px; border: 1px dashed var(--line-strong);
  border-radius: var(--v16-card-radius); background: var(--bg-subtle); font-size: 13px; }
.ws-scene-todo p { margin: 6px 0 0; }

/* ===== §8.9.1 D-CMP catalogue composer (r649) ===== */
/* r1111 — the mockup's main surface: a plain column of the signal strip and component-framed grids.
   No facets sidebar. */
.rqs-main { display: flex; flex-direction: column; gap: var(--v16-gap); }
.rqs-sigs { display: flex; gap: 18px; font-size: 12.5px; color: var(--text-muted); }
.rqs-sigs b { color: var(--text); }
/* r1113 — the "Recommended starting points" category (commodity) tiles */
.rqs-cat { display: flex; align-items: center; gap: 12px; text-align: left; width: 100%;
  padding: 14px; border: 1px solid var(--line); border-radius: var(--v16-card-radius);
  background: var(--bg-card); cursor: pointer; font: inherit; color: var(--text); }
.rqs-cat:hover { border-color: var(--line-strong); background: var(--bg-subtle); }
.rqs-cat__ic { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 8px; font-weight: 700;
  background: var(--accent-soft); color: var(--accent-strong); display: inline-flex;
  align-items: center; justify-content: center; }
.rqs-cat__t { flex: 1 1 auto; font-weight: 600; }
.rqs-cat__n { flex: 0 0 auto; font-size: 12px; color: var(--text-muted); }
/* the context strip's value cards + Edit affordance */
.rqs-ctxc__v { font-size: 13px; font-weight: 600; margin-top: 2px; }
.rqs-ctxc__v small { font-weight: 400; color: var(--text-muted); }
.rqs-ctxc__none { font-weight: 400; color: var(--text-muted); font-style: italic; }
.rqs-ctx-edit { align-self: center; display: inline-flex; align-items: center; gap: 5px; height: 32px;
  padding: 0 12px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card);
  font: inherit; font-size: 13px; color: var(--text); cursor: pointer; }
.rqs-ctx-edit:hover { border-color: var(--accent); color: var(--accent-strong); }
.rqs-ctx-done { align-self: center; }
.rqs { display: grid; grid-template-columns: 1fr; gap: var(--v16-gap); }
@media (min-width: 900px) { .rqs { grid-template-columns: minmax(180px, 16%) 1fr; } }
.rqs-facets { display: grid; gap: 14px; align-content: start; }
.rqs-f h4 { margin: 0 0 6px; font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .06em; }
.rqs-f__o { display: flex; width: 100%; align-items: center; gap: 6px; padding: 5px 8px; margin-bottom: 2px;
  background: transparent; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
  font-size: 13px; color: var(--text); text-align: left; }
.rqs-f__o:hover { background: var(--bg-subtle); }
.rqs-f__o.is-on { border-color: var(--brand-orange); background: var(--bg-subtle); font-weight: 500; }
.rqs-f__n { margin-left: auto; font-size: 11px; color: var(--text-muted); }
.rqs-grid { display: grid; gap: 16px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) { .rqs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .rqs-grid { grid-template-columns: 1fr; } }
.rqs-card { border: 1px solid var(--line); border-radius: var(--v16-card-radius); padding: 12px;
  background: var(--bg-card); display: flex; flex-direction: column; gap: 3px; }
.rqs-card.is-in { border-color: var(--brand-orange); }
.rqs-card__cat { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
.rqs-card__name { font-weight: 500; }
.rqs-card__code, .rqs-card__lead { font-size: 12px; color: var(--text-muted); }
.rqs-card__price { font-size: 15px; }
.rqs-quote { color: var(--text-muted); font-style: italic; font-size: 13px; }
.rqs-unit { font-size: 12px; color: var(--text-muted); }
.rqs-card__sup { font-size: 12px; }
.rqs-card__foot { display: flex; gap: 8px; margin-top: 8px; align-items: center; }
.rqs-qty { width: 62px; }
.rqs-empty, .rqs-free { padding: 18px; border: 1px dashed var(--line-strong);
  border-radius: var(--v16-card-radius); color: var(--text-muted); }
.rqs-free h4 { margin: 0 0 4px; color: var(--text); }
.rqs-free .form-grid { display: grid; gap: 10px; margin: 12px 0; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.rqs-composer h3 { margin: 0 0 10px; font-size: 14px; }
.rqs-b__row { display: flex; align-items: center; gap: 8px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.rqs-b__main { flex: 1 1 auto; min-width: 0; }
.rqs-b__name { font-size: 13px; }
.rqs-b__free { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--brand-orange); }
.rqs-b__sub { font-size: 11px; color: var(--text-muted); }
.rqs-b__qty { display: flex; align-items: center; gap: 5px; font-size: 13px; }
.rqs-b__step, .rqs-b__rm { width: 22px; height: 22px; border: 1px solid var(--line); border-radius: 5px;
  background: transparent; cursor: pointer; color: var(--text-muted); }
.rqs-total { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; padding: 10px 0;
  border-bottom: 1px solid var(--line); }
.rqs-total strong { margin-left: auto; font-size: 16px; }
.rqs-total.is-mixed strong { font-size: 13px; font-style: italic; color: var(--text-muted); }
.rqs-total__note { flex-basis: 100%; font-size: 11px; color: var(--text-muted); }
.rqs-ctx { display: grid; gap: 10px; margin-top: 12px; }
.rqs-ctx label { display: grid; gap: 4px; font-size: 12px; color: var(--text-muted); }
.rqs-budget { margin: 0; font-size: 12px; padding: 6px 8px; border-radius: 6px; }
.rqs-budget.is-ok { background: var(--good-bg, #ECFDF5); }
.rqs-budget.is-over { background: var(--bad-bg); color: var(--bad); }
.rqs-budget.is-unknown { background: var(--bg-subtle); color: var(--text-muted); font-style: italic; }

/* ===== §8.9.5 supplier board — layout standard candidate (r654) ===== */
/* The workspace breadcrumb now carries the whole page context, so it takes the rail's own size:
   a trail that is the only heading on the page should not be smaller than the menu that led to it. */
.ws-crumb { font-size: 13.5px; }
/* r656: the border-bottom under the tab strip is the redundant horizontal line the brief flags \u2014
   there is already the visual break of the content below. Removed for the workspace strip; Setup keeps
   its own. Margin tightened since the content now moves up under it. */
.ws-tabs.setup-tabs { margin-bottom: 8px; border-bottom: 0; }

.supb-band { display: grid; gap: var(--v16-gap); align-items: stretch;
  grid-template-columns: 1fr; padding: 10px var(--v16-pad) 0; flex: 0 0 auto; }
@media (min-width: 1000px) { .supb-band { grid-template-columns: 1fr 3fr; } }
/* r1163 — "What needs attention" takes a quarter of the band, the KPI cards three-quarters (1fr : 3fr).
   Was an even half-and-half split. */
/* r1095 — the section's other pages sit at the strip's right edge, visually secondary to the tabs */
.supb-goto { margin-left: auto; display: inline-flex; gap: 4px; }
.supb-goto__b { opacity: .75; }
.supb-goto__b:hover { opacity: 1; }
/* r1095 — a band with only the KPI component spans the row rather than sitting in half of it */
@media (min-width: 1000px) { .supb-band--solo { grid-template-columns: 1fr; } }
.supb-band > .dv__stamp { grid-column: 1 / -1; }
/* r661: attention and KPIs are now framed COMPONENTS \u2014 the frame + header live on .supb-comp, and the
   attention ul / kpi grid sit inside it (no longer their own bordered boxes). */
.supb-comp { position: relative; background: var(--bg-card); border: 1px solid var(--line-strong);
  border-radius: var(--v16-card-radius); display: flex; flex-direction: column; min-height: 0; }
/* KPIs keep their per-tile frames, so their component is a bare holder (header + grid), no outer border. */
.supb-kpis-comp { background: none; border: 0; }
.supb-kpis-comp .supb-comp__head { padding-left: 2px; padding-right: 2px; }
.supb-attn-comp .supb-attn { padding: 8px 16px 14px; }
/* r666: the KPI grid gets NO vertical padding, so its tiles span the full height of the band row \u2014 i.e.
   the KPI cards are exactly as tall as the Portfolio attention FRAME beside them (which fills the same
   row). Horizontal padding is kept so the tiles don't touch the band edges. */
/* r1178/r1180 — kept at 0 for consistency, but note the EFFECTIVE rule is `.supb-band .supb-kpis` lower
   in this file (same specificity, later in source, so it wins). The real fix lives there. */
.supb-kpis-comp .supb-kpis { padding: 0; }
.supb-attn { list-style: none; margin: 0; padding: 0; background: none; border: 0; }
.supb-attn__row { display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 0; background: none; border: 0; border-bottom: 1px solid var(--line);
  font: inherit; color: var(--text); cursor: pointer; text-align: left; }
.supb-attn li:last-child .supb-attn__row { border-bottom: 0; }
.supb-attn__row:hover { color: var(--primary); }
.supb-attn__ic { display: inline-flex; color: var(--text-muted); }
.supb-attn__ic--risk { color: var(--bad); }
.supb-attn__ic svg { width: 18px; height: 18px; }
.supb-attn__n { flex: 1 1 auto; font-size: 13px; }
.supb-attn__c { font-size: 15px; font-weight: 600; }
.supb-attn__go { display: inline-flex; color: var(--text-muted); }
.supb-attn__go svg { width: 16px; height: 16px; }

/* r655: each KPI in its own framed card, with a bigger circled icon and bigger value — the three
   read as three tiles rather than one shared panel.
   r664: the KPI tiles stretch to the FULL height of the band row, so the KPI cards are the same height as
   the Portfolio attention panel beside them (both components stretch via .supb-band align-items:stretch;
   the grid and tiles now fill that height rather than sizing to content). */
.supb-kpis-comp .supb-kpis { flex: 1 1 auto; }
/* r1103 — ONE ROW, whatever the band declares. `repeat(3, 1fr)` was the tile count baked into the
   template: a fourth KPI wrapped onto a second row on every board the moment r1102 added one. Column
   flow with equal implicit columns means N tiles are N equal columns in one row — the STANDARD for
   every page inheriting this layout, with no count to keep in step with the declarations. */
.supb-kpis { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 10px;
  align-content: stretch; align-items: stretch; }
/* r1108 — REVERTED to the board tile's original centred column. r1102/r1107 restyled THIS tile (the
   board KPI band) on a misread of the request: the "State cards" the product owner means are the KPI
   colour cards in Preferences, fixed there this round. The board tile is exactly as it was. */
.supb-kpi { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; text-align: center; padding: 16px 10px; height: 100%;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--v16-card-radius); }
/* r1165 — the Suppliers KPI card, redesigned to the approved mockup: left-aligned, a round icon at the
   top-left, then value, label, trend chip and a period line. Scoped to the Suppliers band (.supb-band,
   NOT the generic .s3.supb-band), so other pages are unchanged until the design is signed off. Background
   and frame keep the estate's card tokens — the mockup's own bg/frame are deliberately not copied. */
.supb-band .supb-kpi { align-items: flex-start; justify-content: flex-start; text-align: left;
  gap: 0; padding: 12px 12px 11px; min-height: 96px; }
.supb-band .supb-kpi__ic { width: 32px; height: 32px; border-radius: 999px; margin: 0 0 8px; }
.supb-band .supb-kpi__v { font-size: 24px; color: var(--text); }
.supb-band .supb-kpi__ic--bad ~ .supb-kpi__v { color: var(--bad); }
.supb-band .supb-kpi__l { margin-top: 1px; }
.supb-band .supb-kpi__lx { font-size: 10px; color: var(--text-muted); font-weight: 400; }
.supb-band .supb-kpi__trend { margin-top: 7px; }
.supb-band .supb-kpi__per { display: block; font-size: 10px; color: var(--text-muted); margin-top: 5px; }
/* r991 — a rounded RECTANGLE, not a circle. The tile it sits in is a rounded rectangle and so is every
   other surface on the screen; a pill inside them was the one shape that belonged to nothing else.
   The radius is the card's own token, so the icon and its tile round by the same amount. */
.supb-kpi__ic { display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: var(--v16-card-radius, 10px);
  background: var(--bg-subtle); color: var(--text-muted); }
.supb-kpi__ic svg { width: 26px; height: 26px; }
/* r991 — the four KPI states read USER-SETTABLE variables, each falling back to the product palette.
   A reader who cannot distinguish the product's green from its grey can set their own without a theme,
   and an estate that has set nothing looks exactly as it did. */
.supb-kpi__ic--ok { background: var(--kpi-green-bg, var(--good-bg));
  color: var(--kpi-green, var(--good)); }
.supb-kpi__ic--brand { background: var(--accent-soft); color: var(--accent-strong); }
.supb-kpi__ic--bad { background: var(--kpi-red-bg, var(--bad-bg));
  color: var(--kpi-red, var(--bad)); }
.supb-kpi__ic--muted { background: var(--kpi-grey-bg, var(--bg-subtle));
  color: var(--kpi-grey, var(--text-muted)); }
/* the warning state had no rule of its own and fell through to the muted grey — so "needs attention"
   and "nothing to report" looked identical, which is the one pair that must not */
.supb-kpi__ic--warn { background: var(--kpi-amber-bg, var(--warn-bg, #FEF3C7));
  color: var(--kpi-amber, var(--warn, #B45309)); }
/* r1102 — THE NUMBER WEARS THE MARK'S COLOUR. The value sat in plain ink whatever the mark said, so a
   red mark introduced a black number. Keyed off the mark itself (sibling), so the pairing cannot drift
   and the tile's frame stays quiet — r662's lesson that one card must not shout end to end holds. */
.supb-kpi__ic--ok ~ .supb-kpi__v { color: var(--kpi-green, var(--good)); }
.supb-kpi__ic--brand ~ .supb-kpi__v { color: var(--accent-strong); }
.supb-kpi__ic--bad ~ .supb-kpi__v { color: var(--kpi-red, var(--bad)); }
.supb-kpi__ic--muted ~ .supb-kpi__v { color: var(--kpi-grey, var(--text-muted)); }
.supb-kpi__ic--warn ~ .supb-kpi__v { color: var(--kpi-amber, var(--warn, #B45309)); }
.supb-kpi__v { font-size: 28px; font-weight: 700; line-height: 1; }
.supb-kpi__l { font-size: 12.5px; color: var(--text-muted); }
/* r1162 — the trend chip: a small tinted pill under the value. GOOD is a green tint, BAD a red tint,
   FLAT a neutral grey; each carries dark text so it reads without a per-chip luminance calculation. The
   arrow glyph sits a touch smaller than the number. A tile with no baseline yet simply omits the chip. */
.supb-kpi__sub { font-size: 11px; color: var(--text-muted); margin-top: 1px; }
.supb-kpi__trend { display: inline-flex; align-items: center; gap: 3px; margin-top: 4px;
  padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600; line-height: 1.5; }
.supb-kpi__trendg { font-size: 9px; }
.supb-kpi__trend--good { background: var(--ok-bg, #DCFCE7); color: var(--ok-fg, #166534); }
.supb-kpi__trend--bad  { background: var(--bad-bg, #FEE2E2); color: var(--bad-fg, #B91C1C); }
.supb-kpi__trend--flat { background: var(--neutral-bg, #E2E8F0); color: var(--neutral-fg, #475569); }

/* r662: each KPI tile has its own gear (top-right). Positioned absolutely so it doesn't disturb the
   centred layout; quiet until hover/focus. */
.supb-kpi { position: relative; }
.supb-kpi__cog { position: absolute; top: 6px; right: 6px; display: inline-flex; align-items: center;
  justify-content: center; width: 24px; height: 24px; border: 0; border-radius: 6px; background: none;
  color: var(--text-muted); cursor: pointer; padding: 0; opacity: .5; }
.supb-kpi__cog:hover, .supb-kpi:hover .supb-kpi__cog, .supb-kpi__cog[aria-expanded="true"] { opacity: 1;
  background: var(--bg-subtle); }
.supb-kpi__cog svg { width: 15px; height: 15px; }
.supb-kpi__menu { position: absolute; top: 30px; right: 6px; z-index: 30; background: var(--bg-card);
  border: 1px solid var(--line-strong); border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.12);
  padding: 4px; min-width: 130px; text-align: left; }
.supb-kpi__menu button { display: block; width: 100%; text-align: left; padding: 7px 10px; background: none;
  border: 0; font: inherit; font-size: 13px; color: var(--text); cursor: pointer; border-radius: 6px; }
.supb-kpi__menu button:hover { background: var(--bg-subtle); }
/* r662: the High risk tile (tone "bad" when any supplier is overdue) reads RED \u2014 value, icon ring and a
   red frame \u2014 so a real risk count is unmissable. */
.supb-kpi--bad { border-color: var(--bad); background: var(--bad-bg); }
.supb-kpi--bad .supb-kpi__v { color: var(--bad); }
.supb-kpi--bad .supb-kpi__l { color: var(--bad); }
.supb-kpi--bad .supb-kpi__ic { background: var(--bad-bg); color: var(--bad); }
/* the KPIs no longer sit in a shared bordered box; the frames are the tiles */
/* the KPIs no longer sit in a shared bordered box; the frames are the tiles. r666: no vertical padding so
   the tiles fill the row and match the attention frame height.
   r1180 — THIS is the rule that governs the KPI group's right padding on the board. It has the SAME
   specificity as `.supb-kpis-comp .supb-kpis` above but comes LATER, so it wins; my r1173–r1178 edits all
   targeted that other selector and never took effect. Its 16px right padding was the whole misalignment —
   it pushed the last card 16px in from the band edge while the record detail sits flush. Set to 0 so the
   last card's border reaches the same edge as the detail. */
.supb-band .supb-kpis { border: 0; padding: 0; background: none; }


/* ===== r1106 — Request & shop on the board grammar (SELYVO-UX-RS-1.0, mockup v3) ===== */
/* the context strip: cards that ARE the pickers */
.rqs-ctx2 { display: flex; gap: 10px; padding: var(--v16-gap) 0 0; flex-wrap: wrap; }
.rqs-ctxc { flex: 1 1 180px; min-width: 180px; background: var(--bg-card); border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 10px; }
.rqs-ctxc__k { font-size: 11px; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .35px; margin-bottom: 4px; }
.rqs-ctxc .input { width: 100%; }
/* My requests rides the mode-tab strip, right-aligned like every board strip's controls */
.rqs-myreq { margin-left: auto; align-self: center; height: 32px; padding: 0 12px;
  border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card);
  font: inherit; font-size: 13px; color: var(--text); cursor: pointer; }
/* r1113 — the board's search control, widened to the whole toolbar: search is this scene's primary
   action (the mockup's wide box + Scan). No max cap — it takes the row. */
.rqs-find { flex: 1 1 auto; width: auto; max-width: none; }
.s5:has(.rqs-find) { gap: 8px; }
/* results ride a board component frame */
.rqs-comp__b { padding: 14px; }
/* the draft pane */
.rqs-tmp { margin: 0; padding: 6px 12px 0; font-size: 11.5px; color: var(--text-muted); }
.rqs-chk { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0;
  border-bottom: 1px solid var(--line); font-size: 13px; }
.rqs-chk:last-child { border-bottom: 0; }
.rqs-chk__ok { color: var(--good); font-weight: 600; }
.rqs-chk__warn { color: var(--warn, #B45309); font-weight: 600; }
.rqs-chk__bad { color: var(--bad); font-weight: 600; }
.rqs-chk__none { color: var(--text-muted); }
.rqs-dfoot { padding: 10px 12px 12px; border-top: 1px solid var(--line); }
.rqs-dfoot .btn { width: 100%; }
.rqs-comment { display: block; margin-top: 10px; font-size: 12.5px; color: var(--text-muted); }
.rqs-comment textarea { margin-top: 4px; }
.supb-filters { padding-top: var(--v16-gap); }
.supb-q { min-width: 200px; }
.tcl-t { table-layout: fixed; }
.tcl-row.is-selected > td { background: var(--row-selected); }
.supb-name { display: flex; align-items: center; gap: 10px; }
/* r662: only the NAME TEXT is the link (a button), not the whole cell \u2014 the avatar and cell padding no
   longer trigger the open. r657: it's coloured and underlines on hover, like every record link. */
.supb-name__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500;
  color: var(--primary); background: none; border: 0; padding: 0; cursor: pointer; text-align: left;
  font: inherit; font-weight: 500; }
.supb-name__t:hover { text-decoration: underline; }
.supb-name__t:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }
.supb-av { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 30px; height: 30px; border-radius: 999px; background: var(--bg-subtle);
  color: var(--text-muted); font-size: 11.5px; font-weight: 700; letter-spacing: .02em; }
.supb-av--lg { width: 40px; height: 40px; font-size: 14px; }
/* r662: inline SVG flag (renders on every browser incl. Edge, unlike emoji flags) + a code-chip fallback
   for countries not in the flag table. */
.supb-flag { display: inline-flex; vertical-align: -3px; }
.supb-flagsvg { display: inline-block; border-radius: 2px; }
.supb-flag-chip { display: inline-block; min-width: 22px; text-align: center; padding: 1px 5px;
  border-radius: 3px; background: var(--bg-subtle); color: var(--text-muted);
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; vertical-align: 1px; }
.supb-cls { display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: var(--bg-subtle); font-size: 12px; }
.supb-risk { display: inline-block; padding: 1px 9px; border-radius: 999px; font-size: 12px;
  font-weight: 600; line-height: 1.5; }
.supb-risk--low  { background: #ECFDF5; color: #047857; }
.supb-risk--med  { background: #FEF3C7; color: #92400E; }
.supb-risk--high { background: #FEE2E2; color: #B91C1C; }
.supb-risk--crit { background: #B91C1C; color: #fff; }
/* the country ISO chip \u2014 same on every OS, unlike the emoji flag */
.supb-cc { display: inline-block; min-width: 26px; text-align: center; padding: 1px 6px; margin-right: 2px;
  border-radius: 4px; background: var(--bg-subtle); color: var(--text-muted);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; }
.supb-na { color: var(--text-muted); font-style: italic; font-size: 12px; }
.supb-actions-cell { position: relative; overflow: visible; text-align: right; }
.supb-dots { width: 28px; height: 28px; border: 0; background: none; cursor: pointer;
  color: var(--text-muted); border-radius: 6px; }
.supb-dots:hover { background: var(--bg-subtle); color: var(--text); }
.supb-dots svg { width: 18px; height: 18px; }
.supb-menu { position: absolute; right: 4px; top: 32px; z-index: 20; min-width: 200px;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(15,23,42,.14); padding: 4px; text-align: left; }
.supb-menu button { display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px 10px;
  background: none; border: 0; font: inherit; font-size: 13px; color: var(--text); cursor: pointer;
  border-radius: 6px; }
.supb-menu button:hover { background: var(--bg-subtle); }
.supb-menu svg { width: 16px; height: 16px; color: var(--text-muted); }

.supb-card__head { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.supb-card__name { font-size: 15px; font-weight: 600; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; }
.supb-card__status { font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  padding: 2px 8px; border-radius: 999px; }
.supb-card__status--ok { background: #ECFDF5; color: #047857; }
.supb-card__status--warn { background: var(--bg-subtle); color: var(--text-muted); }
.supb-facts { list-style: none; margin: 0; padding: 0; }
.supb-facts li { display: flex; align-items: baseline; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line); font-size: 13px; }
.supb-facts li:last-child { border-bottom: 0; }
.supb-f__ic { display: inline-flex; color: var(--text-muted); align-self: center; }
.supb-f__ic svg { width: 17px; height: 17px; }
.supb-f__l { color: var(--text-muted); flex: 0 0 108px; }
.supb-f__v { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.supb-f__sub { color: var(--text-muted); font-size: 11.5px; }
.supb-card__acts { display: flex; gap: 8px; margin-top: 16px; }
/* r668: the supplier-detail actions moved into the card header. The title sits on the left; the actions
   and the settings gear group on the right. The header buttons are a touch smaller than the old body
   strip so they sit comfortably in the header band. */
.supb-comp__head--detail { gap: 8px; }
/* r670: the supplier detail frame is capped to the height available beside the list. Overflowing content
   is clipped rather than stretching the page, and the "See details" link at the foot of the frame opens
   the full supplier page (layout 2) where everything fits. */
/* =============================================================================================
   r1488 — the record card FILLS the height it is given, whatever it holds.

   `max-height: 100%` capped it and nothing made it grow, so a record with two facts in it drew a
   short card with empty column beneath — and on a board where the pane is half the screen that reads
   as a rendering fault rather than as a short record.

   `flex: 1 1 auto` makes it take the space instead. A card with little in it now looks deliberate,
   and one with a lot still scrolls inside itself because the body below keeps `min-height: 0`.
   ============================================================================================= */
.supb-card { display: flex; flex-direction: column; min-height: 0; max-height: 100%;
  flex: 1 1 auto; }
/* the body is what stretches and what scrolls; the head stays put */
.supb-card > .supb-card__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* r683: the detail scrolls inside its frame rather than being clipped, and does so without a visible
   scrollbar - the frame still never grows past the page. */
.supb-card__body { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none; }
.supb-card__body::-webkit-scrollbar { width: 0; height: 0; display: none; }
.supb-card__more { flex: 0 0 auto; border-top: 1px solid var(--line); padding: 8px 14px; background: var(--bg-card);
  border-radius: 0 0 var(--v16-card-radius) var(--v16-card-radius); }
.supb-seemore { background: none; border: 0; padding: 0; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--primary); cursor: pointer; }
.supb-seemore:hover { text-decoration: underline; }

.supb-comp__head--detail .supb-comp__title { margin-right: auto; }
.supb-detail-acts { display: inline-flex; align-items: center; gap: 6px; }
.supb-detail-acts .supb-act { width: 30px; height: 30px; }
.supb-detail-acts .supb-act svg { width: 16px; height: 16px; }
/* r660: symmetric square icon buttons \u2014 identical footprint, icon centred, no text. */
.supb-act { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px;
  border: 1px solid var(--line-strong); border-radius: 8px; background: var(--bg-card); color: var(--text);
  cursor: pointer; padding: 0; }
.supb-act:hover { background: var(--bg-subtle); border-color: var(--text-muted); }
.supb-act svg { width: 18px; height: 18px; }
.supb-act--primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.supb-act--primary:hover { background: var(--primary-strong, #d06a1f); border-color: var(--primary-strong, #d06a1f); }
.supb-more { margin-top: 12px; }
.supb-more summary { font-size: 12px; color: var(--text-muted); cursor: pointer; list-style: none; }
.supb-more summary::-webkit-details-marker { display: none; }
.supb-more summary::before { content: "\203a "; }
.supb-more[open] summary::before { content: "\2304 "; }
.supb-more__l { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.supb-more__l .btn { font-size: 12px; min-height: 30px; }
/* Quiet by design: these are here to satisfy AC-02, not to compete with the supplier card above them. */
.supb-card + .ws-sc__links { margin-top: 18px; }
.supb-card + .ws-sc__links .btn { font-size: 12px; min-height: 30px; }

/* r661: the supplier detail is framed like every other component \u2014 a header (with a gear) on top of the
   body. The body carries the padding the card used to. */
.supb-card.supb-comp { padding: 0; }
.supb-card__body { padding: 14px 16px 16px; }
/* the supplier name in the detail is the LINK that opens the Vendor 360 page */
.supb-card__name { font-size: 15px; font-weight: 600; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; }
button.supb-card__name { background: none; border: 0; text-align: left; cursor: pointer;
  color: var(--primary); padding: 0; }
button.supb-card__name:hover { text-decoration: underline; }

/* ===================================================================================
   r661: the Vendor 360 page (Insights). Two rows: detail + history on top, then a tab
   bar, then a list + selected-record detail below.
   =================================================================================== */
.v360 { display: flex; flex-direction: column; gap: 14px; padding: 4px 2px 20px; }
/* r676 - THE 360 PAGE STANDARD.
   Two types (see the JS side) sharing one shell, and nine sub-types formed by the split of the top row
   against the split of the bottom row. The ratios are carried as custom properties so a page declares its
   sub-type once and both rows follow; nothing downstream needs to know which one is in force.
     50/50 -> 1fr 1fr      33/66 -> 1fr 2fr      66/33 -> 2fr 1fr                                        */
.v360 { --p360-top: 1fr 1fr; --p360-bottom: 1fr 1fr; }
/* r701: the TOP ROW never takes more than half the page. The four sectors are a working canvas, not a
   header with a list underneath it - once the top grows past half, the connected records the board exists
   to show are pushed off screen and the reader scrolls the PAGE to reach them, which loses the primary
   context they were reading. Capped here, and every sector inside it scrolls its own body instead. */
.v360-top    { display: grid; grid-template-columns: var(--p360-top);    gap: 14px; align-items: stretch;
  /* r710 - THE SAFARI FIX, and it is not the max-height.
     max-height caps the CONTAINER. The row inside it is implicit and therefore `auto`, which resolves to
     the height of its tallest content - and an auto row is under no obligation to shrink because its
     container has a maximum. Chromium happened to shrink it; Safari resolves the row to content and lets
     it overflow the box that was supposed to be limiting it. Same stylesheet, same rule, two answers,
     because the rule constrained the wrong box.
     minmax(0, 1fr) is what actually says "this row may be smaller than its content". overflow:hidden then
     makes the clip real rather than decorative, and the panels are given a maximum of their own so a tall
     one cannot push past the row even where the row is honoured. */
  /* AUTO rows, not a single template row: under 900px the quadrants stack into several rows, and
     pinning one row collapsed that layout. grid-auto-rows applies the same "may shrink below content"
     to however many rows the breakpoint produces. */
  grid-auto-rows: minmax(0, 1fr);
  max-height: 50vh; max-height: 50dvh; min-height: 0; overflow: hidden; }
/* r709: dvh is the DYNAMIC viewport height — what the reader can actually see once a mobile browser's
   address bar and toolbar are counted. vh ignores both, so on a phone "half the page" was half of a page
   taller than the screen. The vh line stays first as the fallback: a browser that does not know dvh keeps
   the old cap rather than losing the rule entirely. */
.v360-top > .v360-panel { min-height: 0; max-height: 100%; overflow: hidden; }
/* descendant, not child: r703 and r705 moved these bodies inside wrappers, and a child selector silently
   stopped matching - the rule was still in the stylesheet and no longer reached anything. */
.v360-top .v360-detail__body,
.v360-top .v360-history__body,
.v360-top .v360-list__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* a fixed 420px is taller than half a short viewport, so inside the capped row it defers to the row */
.v360-top .v360-list__scroll { max-height: 100%; }
/* a form that continues below the fold says so — only LIST scrollbars are hidden (below) */
.v360-bottom { display: grid; grid-template-columns: var(--p360-bottom); gap: 14px; align-items: stretch; }
.p360-top-50-50 { --p360-top: 1fr 1fr; }
.p360-top-33-66 { --p360-top: 1fr 2fr; }
.p360-top-66-33 { --p360-top: 2fr 1fr; }
.p360-bot-50-50 { --p360-bottom: 1fr 1fr; }
.p360-bot-33-66 { --p360-bottom: 1fr 2fr; }
.p360-bot-66-33 { --p360-bottom: 2fr 1fr; }
/* the page's own tabs live in its header, above everything */
.p360-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  border-bottom: 1px solid var(--line); margin-bottom: 2px; }
.p360-tabs { display: flex; align-items: stretch; gap: 2px; overflow-x: auto; }
.p360-tab { appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 9px 14px; font: inherit; font-size: 14px; font-weight: 600; color: var(--text-muted);
  cursor: pointer; white-space: nowrap; }
.p360-tab:hover { color: var(--text); }
.p360-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); }
/* the sub-tabs that choose WHICH related documents the bottom-left list shows */
.p360-subtabs { grid-column: 1 / -1; }
/* on a narrow viewport every sub-type collapses to a single column - a 33% pane is unreadable there */
@media (max-width: 900px) {
  .v360-top, .v360-bottom { grid-template-columns: 1fr; }
}
@media (max-width: 1000px) { .v360-top, .v360-bottom { grid-template-columns: 1fr; } }
.v360-panel { background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--v16-card-radius);
  display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.v360-detail__body, .v360-history__body, .v360-rec-panel__body { padding: 14px 16px 16px; }
.v360-facts, .v360-rec { display: grid; gap: 2px; }
/* r667: the top-left "document" panel renders the record's form header read-only, laid out by the CF
   designer's field widths \u2014 a wrapping flex row of labelled values, like the form itself. */
.v360-form { display: flex; flex-wrap: wrap; gap: 14px 12px; align-items: flex-start; }
/* r669: the 360 top-left renders the record's real edit-mode form, read-only. The controls keep the form's
   layout and shape so it reads as the same document, but are visibly locked: no focus ring, no caret, a
   quieter surface than an editable field. */
.r360-form input[readonly], .r360-form textarea[readonly], .r360-form select[disabled] {
  background: var(--bg-subtle); color: var(--text); cursor: default; opacity: 1; }
.r360-form input[readonly]:focus, .r360-form textarea[readonly]:focus { outline: none; box-shadow: none;
  border-color: var(--line); }
.r360-form .field { margin-bottom: 0; }

/* r668: My Work on the shared layout \u2014 the MY TASKS list (top-left), the status strip, and small tweaks
   reusing the .v360 shell for the rest. */
.tw-count { font-size: 12px; font-weight: 700; color: var(--text-muted); background: var(--bg-subtle);
  border-radius: 999px; padding: 1px 8px; }
/* r686: the title takes the header's spare width, so the count, the promotion controls and the gear group
   together on the right where every other component keeps them. */
.tcl-list .supb-comp__title { margin-right: auto; }
/* r686: the two promotion controls, framed like the settings gear they sit beside. Disabled until the 360
   re-sourcing they drive exists - visibly an affordance, not a live button that does nothing. */
.tcl-hact { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  margin-left: 4px; border: 1px solid transparent; border-radius: 8px; background: none; cursor: pointer;
  color: var(--text-muted); }
.tcl-hact:hover:not([disabled]) { color: var(--text); border-color: var(--line-strong); background: var(--bg-subtle); }
/* r1182/r1183 — the unified Requests list's first column: a per-kind icon in a small coloured circle
   (like the KPI-card icons) then the kind label/name. The tone class supplies the colour. */
.supb-reqtype { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.supb-reqtype__ic { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 999px; }
.supb-reqtype__ic svg { width: 15px; height: 15px; }
/* r1187 — the Configure-KPIs gear hides when the KPI cards (the band) hide: in focus and in full screen,
   both of which hide the band. The gear lives in the tab row (outside the scene), so it keys off the
   body-level flags — has-tcl-fullscreen (already set) and has-supb-focus (r1187). */
body.has-tcl-fullscreen .supb-kpicfg-wrap,
body.has-supb-focus .supb-kpicfg-wrap { display: none; }
/* r1187 — the view-cycle control in the appbar (top menu), before the loading mark. */
.appbar-viewcycle svg { width: 18px; height: 18px; }
/* r1181 — where the single view-cycle control is present, the separate full-screen and focus buttons are
   hidden (kept in the DOM only so the cycle can drive their handlers). */
.supb-comp__head.has-viewcycle [data-supb-fullscreen],
.supb-comp__head.has-viewcycle [data-supb-focus] { display: none; }
.tcl-hact[disabled] { opacity: .38; cursor: default; }
.tcl-hact svg { width: 17px; height: 17px; }
/* r687: a list read full screen - the same list, given the whole viewport. */
/* r724: full screen means the WORKING CANVAS, not the whole window.
   inset:0 covered the app bar and the lifecycle tabs, so a reader in full screen had no way back and no
   idea where they were — which is the opposite of what an expand control is for. It now starts below the
   chrome it must not hide, measured from the same variables the shell uses rather than from numbers
   copied out of the specification. */
/* r945 — full screen is a LAYOUT CHANGE, not an overlay.
 *
 * It was `position: fixed` with a left edge measured from the navigation. Every attempt to fix the
 * overlap measured that edge more carefully — and it still overlapped, because **an element positioned
 * against something that moves is wrong between the move and the measurement, always.**
 *
 * The list now stays where it is and the screen keeps ONE control instead of four: the attention band,
 * the KPIs and the supplier detail step aside, and the register takes the canvas. Nothing is positioned
 * over anything, so there is nothing to overlap. The sub-tabs and the search stay — they are how the
 * reader narrows the list they asked to see more of. */
/* r1044 — the overlay needs BOTH classes, so neither can be removed without ending it.
 *
 * It was `.tcl-list.is-fullscreen` alone, while the supplier register's override is the compound
 * `body.has-tcl-fullscreen … .tcl-list.is-fullscreen`. Leaving full screen removes the BODY class first
 * and the list class on the repaint after it — so for one frame the override stopped matching and this
 * rule still did: the list became a fixed, full-window overlay across the navigation rail, then
 * snapped back.
 *
 * **A rule that outlives the rule overriding it will show, for exactly as long as the gap between two
 * class changes** — and one frame is long enough to see. Requiring the body class here makes the two
 * end together whichever is removed first. */
body.has-tcl-fullscreen .tcl-list.is-fullscreen {
  position: fixed;
  top: calc(var(--tcl-fs-top, 112px));
  /* r980 — the overlay stops ABOVE the status bar. `bottom: 0` ran it to the window edge and put the
     pager underneath a fixed bar on EVERY register that takes this path, not just the supplier list.
     I fixed the scoped supplier rule twice and never looked at the rule it falls back to. **Fixing the
     specific case leaves the general one to be reported again**, by someone else, on another screen. */
  /* r1050 — the overlay starts at the WORKING CANVAS, not the window edge.
     `left: 0` put it across the navigation rail, which is what "full screen" must never mean here: the
     reader loses the way out of the screen they are in. `--tcl-fs-left` is measured when full screen is
     entered and cleared when it is left, and the fallback is the rail's own width so an unmeasured
     entry still clears it. **A measurement with no fallback is a measurement that fails to zero**, and
     zero is exactly the wrong edge. */
  left: var(--tcl-fs-left, var(--rail-w, 260px)); right: 0; bottom: var(--statusbar-h, 26px);
  z-index: 60;
  border-radius: 0; max-height: none;
}
/* ...EXCEPT on the supplier register, which has somewhere to expand INTO. The overlay stays for the
   registers that are the only thing on their screen; where a screen has four components, taking one to
   full size is a layout change and there is nothing to position against. */
body.has-tcl-fullscreen .v16 .supb-s4 ~ .v16__work .tcl-list.is-fullscreen {
  position: static;
  left: auto; right: auto; bottom: auto; top: auto;
  z-index: auto;
  /* r975 — reserve the fixed status bar: it is out of flow, so a height of `100vh - top` runs under it
     and the pager ends up half behind the status line. */
  /* r980 — the MEASURED height when the script could take it, and the computed one otherwise. The
     fallback chain depends on `--tcl-fs-top` having been set: unset, it falls back to 180px, and a real
     top below that puts the pager underneath the status bar. **A token that describes an element is not
     the element** — the bar is measured now, so a hidden bar reserves nothing and a resized one is
     followed. */
  height: var(--tcl-fs-h,
    calc(100vh - var(--tcl-fs-top, 180px) - var(--statusbar-h, 26px) - var(--v16-pad, 24px)));
}
body.has-tcl-fullscreen .v16 .supb-band,
body.has-tcl-fullscreen .v16 .v16__work > .s7 { display: none; }
/* r947 — and the filter/search row stops reserving a column that is no longer on screen. It right-aligns
   with the LIST, and in full screen the list is the whole width: the reserve left the search box sitting
   580px short of the edge it is meant to line up with. **A space held for something that is not there is
   a gap, not an alignment.** */
body.has-tcl-fullscreen .v16--d-wb-s .supb-s4 { padding-right: var(--v16-pad); }
body.has-tcl-fullscreen .v16 .v16__work { display: block; }
body.has-tcl-fullscreen .v16 .v16__work > .s6 { width: auto; max-width: none; }
body.has-tcl-fullscreen { overflow: hidden; }
/* r1136 — full-screen record peek: the .s7 detail, hidden by the rule above, shown as a right-side
   pop-up over the full-screen list when a record is selected. Overrides the display:none. */
body.has-tcl-fullscreen .v16 .v16__work > .s7.record-peek {
  display: block;
  position: fixed;
  top: var(--tcl-fs-top, 112px); right: 0; bottom: var(--statusbar-h, 26px);
  width: min(570px, 92vw);          /* r1149 — +50px so the supplier sub-tabs fit on one row */
  z-index: 70;                       /* above the full-screen list overlay (60) and the backdrop (65) */
  margin: 0; overflow: auto;
  background: var(--bg-card);
  border-left: 1px solid var(--line);
  box-shadow: -10px 0 34px rgba(0, 0, 0, 0.18);
  padding: 16px 18px;
  animation: recordPeekIn 0.16s ease-out;
}
@keyframes recordPeekIn { from { transform: translateX(24px); opacity: 0; } to { transform: none; opacity: 1; } }
/* r1149 → r1150 — issue 1: switching sub-tabs repaints the whole board, which rebuilds the .s7 element,
   so the entrance animation replayed every time and the peek appeared to close and slide back in. On a
   repaint (peek already open) the animation is suppressed; it still plays on the first open.
   r1150 — the r1149 rule (.record-peek.record-peek--noanim) was LOWER specificity than the animation rule
   above (a full body…>.s7.record-peek chain), so animation:none never won and the peek kept flashing.
   Match the animating selector and add !important so suppression is unconditional. */
body.has-tcl-fullscreen .v16 .v16__work > .s7.record-peek.record-peek--noanim { animation: none !important; }
/* r1149 — issue 3a: the peek panel is already a framed surface (its own background, left border and
   shadow); the detail card inside it added a second frame. Flatten the inner card in the pop-up so there
   is one frame, not two. The standard/focused board keeps its frame. */
body.has-tcl-fullscreen .record-peek .supb-comp { border: none; background: transparent; box-shadow: none; }
/* r1148 — issue 1 (last round): the record peek is narrow and the supplier detail has seven sub-tabs.
   The strip wraps rather than scrolling behind a hidden scrollbar, so no tab is lost even if the row is
   tight; r1149's +50px lets them sit on one row when they fit. */
body.has-tcl-fullscreen .record-peek .supb-dtabs { flex-wrap: wrap; overflow-x: visible; }
/* r1148 — issue 4: a form opened from the full-screen list (New requisition / contract, Edit supplier)
   is a modal at z-index 50, but the full-screen list (60), the peek backdrop (65) and the peek itself (70)
   sat above it, so the form rendered behind them, untouchable. In full screen the modal and any panel it
   opens are lifted above those layers. */
body.has-tcl-fullscreen .modal-overlay:not([hidden]) { z-index: 80; }
body.has-tcl-fullscreen .doc-drawer { z-index: 90; }
.record-peek-backdrop {
  position: fixed;
  top: var(--tcl-fs-top, 112px); right: 0; bottom: var(--statusbar-h, 26px);
  left: var(--tcl-fs-left, var(--rail-w, 260px));
  z-index: 65; background: rgba(0, 0, 0, 0.12);
}
/* r1149 — issue 3c: the peek's Close is now a button in the detail head row, next to the reload/gear,
   rather than a floating × in the corner. Styled to match the head buttons (.supb-cog). */
.record-peek-close {
  display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--bg-card); color: var(--text-muted);
  cursor: pointer; margin-left: 2px; flex: 0 0 auto;
}
.record-peek-close:hover { background: var(--bg-subtle); color: var(--text); border-color: var(--line-strong); }
.record-peek-close svg { width: 16px; height: 16px; }
/* r687: the cross-board's format switch, above the sub-tabs it shares a row with */
.cb-switch { display: inline-flex; align-items: center; gap: 6px; margin-right: 14px; }
.cb-switch__l { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
.cb-type { appearance: none; border: 1px solid var(--line); background: var(--bg-card); border-radius: 999px;
  padding: 3px 12px; font: inherit; font-size: 12px; color: var(--text-muted); cursor: pointer; }
.cb-type:hover { color: var(--text); border-color: var(--line-strong); }
.cb-type.is-active { color: var(--primary); border-color: var(--primary); font-weight: 600; }
.cb-switch__n { font-size: 11px; color: var(--text-muted); font-family: var(--font-mono, monospace); }
.p360-subtabs { display: flex; align-items: center; flex-wrap: wrap; }
/* r689: the 360 split fields in the form builder */
.fb-p360__grid { display: flex; gap: 24px; flex-wrap: wrap; padding: 4px 0 2px; }
.fb-p360__col { display: flex; flex-direction: column; gap: 8px; min-width: 220px; }
.fb-p360__h { font-size: 12px; font-weight: 600; color: var(--text-muted); }
.fb-p360__f { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; }
.fb-p360__f select { min-height: 30px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); font: inherit; font-size: 13px; padding: 0 8px; }
.fb-p360__names { margin-top: 10px; font-size: 11.5px; color: var(--text-muted);
  font-family: var(--font-mono, monospace); }
/* the column panel can now list every field on the record, so it scrolls rather than running off the page */
.tcl-cogp { max-height: 340px; overflow-y: auto; }
/* r685: the per-task button list is gone - My Work's top-left is the shared typed-column list now. Only
   the due-state chip survives, because a cell still renders it. */
.tw-task__due { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
/* the Action cell: the object's glyph, then what the task asks of you */
.mwl-act { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.mwl-act__ic { display: inline-flex; color: var(--text-muted); flex: none; }
.mwl-act__ic svg { width: 16px; height: 16px; }
.mwl-act__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tw-task__due.is-late { color: var(--bad); font-weight: 600; }
.tw-detail__act, .tw-detail__body { padding-top: 6px; }
.tw-status { display: flex; align-items: center; gap: 8px; padding: 8px 14px; margin-top: 12px;
  border-top: 1px solid var(--line); font-size: 12px; color: var(--text-muted); flex: 0 0 auto; }
.tw-status__dot { width: 8px; height: 8px; border-radius: 999px; background: var(--ok, #16a34a); display: inline-block; }
.v360-hf { display: flex; flex-direction: column; gap: 4px; min-width: 0; box-sizing: border-box; }
.v360-hf__l { font-size: 11.5px; font-weight: 600; color: var(--text-muted); }
.v360-hf__v { font-size: 13.5px; color: var(--text); overflow-wrap: anywhere; }
.v360-f { display: flex; align-items: baseline; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--line);
  font-size: 13px; }
.v360-f:last-child { border-bottom: 0; }
.v360-f__l { color: var(--text-muted); flex: 0 0 132px; }
.v360-f__v { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* r693: the primary-context sector — three KPIs over the activity/documents timeline (spec v1.1 §16).
   Three equal columns, so the strip cannot silently render four or two and still look deliberate. */
.cb-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 12px 16px 0; }
.cb-kpi { border: 1px solid var(--line); border-radius: 8px; padding: 9px 10px; background: var(--bg-card);
  display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cb-kpi__l { font-size: 11px; font-weight: 500; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .04em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cb-kpi__v { font-size: 17px; font-weight: 700; color: var(--text); line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cb-kpi__h { font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
/* an unrecorded fact reads as unrecorded — never as a zero wearing the same weight as a real number */
.cb-kpi.is-unavailable { background: transparent; border-style: dashed; }
.cb-kpi.is-unavailable .cb-kpi__v { font-size: 13px; font-weight: 500; color: var(--text-muted); }
.cb-tl__tabs { display: flex; gap: 2px; padding: 12px 16px 0; border-bottom: 1px solid var(--line);
  margin: 12px 0 0; }
.cb-tl__tab { appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 6px 10px; font: inherit; font-size: 12.5px; font-weight: 500; color: var(--text-muted);
  cursor: pointer; }
.cb-tl__tab:hover { color: var(--text); }
.cb-tl__tab.is-active { color: var(--text); border-bottom-color: var(--brand-orange); }
.cb-tl__link { appearance: none; background: none; border: 0; padding: 0; font: inherit; font-weight: 600;
  color: #245EA8; cursor: pointer; text-align: left; }
.cb-tl__link:hover { text-decoration: underline; }
/* r698: a sector that is still loading says so with its own skeleton, and one that failed says THAT —
   an empty list and a list nobody could fetch are different facts and must not share a rendering. */
.v360-skel { display: flex; flex-direction: column; gap: 8px; padding: 14px 4px; }
.v360-skel__b { display: block; height: 11px; border-radius: 4px; background: var(--line);
  opacity: .75; animation: v360skel 1.15s ease-in-out infinite; }
.v360-skel__b:nth-child(2) { width: 78%; animation-delay: .12s; }
.v360-skel__b:nth-child(3) { width: 55%; animation-delay: .24s; }
@keyframes v360skel { 0%, 100% { opacity: .35; } 50% { opacity: .8; } }
@media (prefers-reduced-motion: reduce) { .v360-skel__b { animation: none; opacity: .5; } }
.v360-err { color: var(--bad); }
.cb-retry { appearance: none; background: none; border: 0; padding: 0; font: inherit; font-weight: 600;
  color: #245EA8; cursor: pointer; text-decoration: underline; }
.cb-kpi.is-pending .cb-kpi__v { display: block; }
.cb-kpi.is-pending .cb-kpi__v .v360-skel__b { width: 62%; height: 15px; margin: 2px 0; }

/* r701: a record shown in the board wears the edit form's own visual, read-only. The estate already
   styles .field input[readonly]; this only lays the fields out at the widths the CF designer set. */
/* r705: the supplier detail's sub-tabs. Same 2px underline the rest of the estate uses; the row scrolls
   sideways rather than wrapping, so a narrow panel keeps one tab strip instead of growing a second line
   and pushing the record down the panel. */
.supb-dtabs { display: flex; gap: 2px; padding: 0 2px; margin: 0 0 6px; border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.supb-dtabs::-webkit-scrollbar { width: 0; height: 0; }
.supb-dtab { appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 6px 9px; font: inherit; font-size: 12.5px; font-weight: 500; color: var(--text-muted);
  cursor: pointer; white-space: nowrap; flex: 0 0 auto; }
.supb-dtab:hover { color: var(--text); }
.supb-dtab.is-active { color: var(--text); border-bottom-color: var(--brand-orange); }
/* r722: the pager. Below the scroll box and outside it — it must not scroll away with the rows it
   controls, or the reader loses the one thing telling them where they are. */
.tcl-pg { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 12px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--text-muted); }
.tcl-pg__n { flex: 1 1 auto; min-width: 0; }
.tcl-pg__b-wrap { display: inline-flex; gap: 3px; flex: 0 0 auto; }
.tcl-pg__b { appearance: none; background: none; border: 1px solid var(--line); border-radius: 6px;
  padding: 3px 9px; font: inherit; font-size: 12px; color: var(--text); cursor: pointer; }
.tcl-pg__b:hover:not(:disabled) { border-color: var(--line-strong); }
.tcl-pg__b:disabled { opacity: .42; cursor: default; }
.tcl-pg__b.is-current { background: var(--brand-orange); border-color: var(--brand-orange);
  color: #fff; font-weight: 600; }
.tcl-pg__s { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.tcl-pg__s select { font: inherit; font-size: 12px; padding: 2px 4px; }

/* r706: only the DATA scrolls. The supplier's name and the tab strip are the two things that tell the
   reader whose record this is and which part of it they are in — scrolling them away leaves a table of
   values with no subject. */
.supb-card__body { display: flex; flex-direction: column; min-height: 0; }
.supb-card__head, .supb-dtabs { flex: 0 0 auto; }
.supb-dbody { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
/* the contacts list: a row is a name and a disclosure, its detail opening beneath that row */
.supb-clist { display: flex; flex-direction: column; }
.supb-crow { border-bottom: 1px solid var(--line); }
.supb-crow:last-child { border-bottom: 0; }
.supb-crow__h { display: flex; align-items: center; gap: 8px; width: 100%; appearance: none;
  background: none; border: 0; padding: 9px 2px; font: inherit; font-size: 13px; font-weight: 600;
  color: var(--text); cursor: pointer; text-align: left; }
.supb-crow__h:hover { color: var(--accent-strong, var(--text)); }
.supb-crow__x { display: inline-flex; flex: 0 0 auto; color: var(--text-muted);
  transition: transform .15s ease; }
.supb-crow__x.is-open { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .supb-crow__x { transition: none; } }
.supb-crow__n { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.supb-crow__d { padding: 0 2px 10px 22px; }
/* the gear's panel: which sub-tabs are shown */
.supb-dcfg { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 12px;
  border-bottom: 1px solid var(--line); background: var(--bg-subtle, transparent); }
.supb-dcfg__r { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  color: var(--text); cursor: pointer; }
.supb-dcontact + .supb-dcontact { margin-top: 10px; padding-top: 4px; border-top: 1px solid var(--line); }

/* r703: a record READS as a table of values — name against value, split down the middle of the panel.
   Two equal columns, so the values line up in one edge the eye can run down instead of starting wherever
   each label happened to end. */
.v360-form { display: grid; grid-template-columns: 1fr; gap: 0; }
.v360-rof { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; align-items: baseline;
  padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.v360-rof:last-child { border-bottom: 0; }
.v360-rof__l { color: var(--text-muted); min-width: 0; overflow-wrap: anywhere;
  /* the split itself: a rule down the centre of the row, between the name and the value */
  border-right: 1px solid var(--line); padding-right: 14px; }
.v360-rof__v { min-width: 0; overflow-wrap: anywhere; color: var(--text); font-weight: 500; }
.v360-rof.is-empty .v360-rof__v { color: var(--text-muted); font-weight: 400; }

/* r694: the context navigator — Back/Forward and the compact relation trail (spec v1.1 §12) */
.cb-nav { display: flex; align-items: center; gap: 6px; padding-right: 10px; margin-right: 8px;
  border-right: 1px solid var(--line); flex: 0 0 auto; }
.cb-nav__b { display: inline-flex; align-items: center; gap: 3px; appearance: none; background: none;
  border: 1px solid var(--line); border-radius: 6px; padding: 3px 8px; font: inherit; font-size: 12px;
  font-weight: 500; color: var(--text); cursor: pointer; white-space: nowrap; }
.cb-nav__b:hover:not(:disabled) { border-color: var(--line-strong); }
.cb-nav__b:disabled { opacity: .42; cursor: default; }
/* r695: Return leaves the board; Back walks the trail inside it. Different journeys, different weight. */
.cb-nav__b--return { border-color: var(--line-strong); font-weight: 600; }
.cb-trail { display: flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden;
  font-size: 12px; color: var(--text-muted); }
.cb-trail__x { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.cb-trail__x.is-current { color: var(--text); font-weight: 600; }
.cb-trail__s { color: var(--text-muted); flex: 0 0 auto; }
/* a connected row's first column promotes: a record link, not a decorated cell */
.cb-rowup { appearance: none; background: none; border: 0; padding: 0; font: inherit; font-weight: 600;
  color: #245EA8; cursor: pointer; text-align: left; }
.cb-rowup:hover { text-decoration: underline; }
/* history */
.v360-history__body { max-height: 320px; overflow-y: auto; }
.v360-hist { list-style: none; margin: 0; padding: 0; }
.v360-hist li { display: grid; grid-template-columns: 116px 1fr; gap: 4px 10px; padding: 8px 0;
  border-bottom: 1px solid var(--line); font-size: 12.5px; }
.v360-hist li:last-child { border-bottom: 0; }
.v360-hist__t { color: var(--text-muted); }
.v360-hist__a { font-weight: 600; }
.v360-hist__d { grid-column: 2; color: var(--text); }
.v360-hist__u { grid-column: 2; color: var(--text-muted); font-size: 11.5px; }
.v360-empty { padding: 18px 4px; font-size: 13px; }
/* tabs */
.v360-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.v360-tab { padding: 9px 14px; background: none; border: 0; border-bottom: 2px solid transparent;
  font: inherit; font-size: 13px; color: var(--text-muted); cursor: pointer; }
.v360-tab:hover { color: var(--text); }
.v360-tab.is-active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }
.v360-tab__n { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 4px;
  border-radius: 999px; background: var(--bg-subtle); color: var(--text-muted); font-size: 11px; }
.v360-tab.is-active .v360-tab__n { background: var(--row-selected); color: #B4560F; }
/* list */
/* r701: a list scrolls without showing a bar. The typed-column list has hidden its own since r685
   (.tcl-scroll); the connected-record list kept a visible one, so the two list sectors of one board did
   not look like the same component. Scrolling still works by wheel, touch, keyboard and the sticky
   header stays put — only the bar is gone. */
.v360-list__scroll { max-height: 420px; overflow-y: auto;
  scrollbar-width: none; -ms-overflow-style: none; }
.v360-list__scroll::-webkit-scrollbar { width: 0; height: 0; }
.v360-t { width: 100%; border-collapse: collapse; font-size: 13px; }
.v360-t thead th { position: sticky; top: 0; background: var(--bg-card); text-align: left;
  padding: 9px 14px; border-bottom: 1px solid var(--line-strong); color: var(--text-muted);
  font-size: 12px; font-weight: 600; }
.v360-t td { padding: 9px 14px; border-bottom: 1px solid var(--line); }
.v360-t .v360-amt { text-align: right; }
.v360-row { cursor: pointer; }
.v360-row:hover { background: var(--bg-subtle); }
/* r1036 — the SAME selection tint as every other list. It was #FFF6EE here and #FFF2E6 there: two
   colours for one meaning, three shades apart, so a reader moving between screens saw the selection
   change slightly and could not say why. **One meaning, one token.** */
.v360-row.is-selected { background: var(--row-selected); }
.v360-rec__act { margin-top: 12px; }

/* ===== r655: full-height scene screens; only the register scrolls ===== */
/* The workspace card becomes a flex column that fills .view, so the breadcrumb and tabs stay put and the
   scene beneath them takes the remaining height. */
/* r656: no card frame around a scene screen. The light-grey border made the page look like a panel
   floating inside the app; the brief wants it full-bleed, the way the left menu and the main area meet
   with no box. The card's border, radius and shadow are dropped here and the surface is the page. */
/* r657: the scene surface is the app background (a light grey), deliberately DIFFERENT from the top
   menu, which is white \u2014 so the page no longer looks like an extension of the appbar. The register and
   preview are white cards sitting on this grey, which is what gives the page depth without a hard frame. */
/* r1487 - Home shows the same bar as My work; the chip styling it used to have is gone with it. The
   strip keeps its own margin because it sits above the grid rather than at the foot of a column. */
.home-favs { margin: 0 0 12px; }
.home-favs[hidden] { display: none; }

/* r1475 — the favourite star in the top menu, filled when the page is pinned. */
.appbar-fav.is-on { color: var(--primary); }
.appbar-fav.is-on svg { fill: currentColor; }

.view--scene { padding: 0; background: var(--bg-scene); }
.view--scene > .card { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
  padding: 6px 20px 16px; border: 0; border-radius: 0; box-shadow: none; background: transparent; }
.view--scene .ws-crumb, .view--scene .ws-tabs { flex: 0 0 auto; }
.ws-scene--fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.ws-scene--fill > .v16 { flex: 1 1 auto; min-height: 0; }
/* the scene's work row (register + preview) is the part that grows, and the register scrolls inside it */
/* r658 fix: the supplier board's work row uses an explicit flex layout, not the percentage/minmax grid.
   Three reports of the list landing on the right traced to that grid \u2014 its minmax(560px, 62.4%) could
   exceed the track and push the list into the wrong place. Flex is unambiguous: the list is the growing
   left column, the preview is the fixed right column, and there is no track for anything to fall into. */
.view--scene .v16__work { flex: 1 1 auto; min-height: 0; align-items: stretch; }
.v16--d-wb-s .v16__work.has-context { display: flex; grid-template-columns: none; gap: var(--v16-gap);
  flex-direction: column; }
@media (min-width: 1100px) {
  .v16--d-wb-s .v16__work.has-context { flex-direction: row; align-items: stretch; }
  .v16--d-wb-s .v16__work.has-context > .s6 { flex: 1 1 auto; min-width: 0; order: 0; }
  /* r660: the supplier detail is 200px wider than before (380 \u2192 580), via a variable so it can be tuned
     in one place and referenced by the S4 bar below. */
  .v16--d-wb-s .v16__work.has-context > .s7 { flex: 0 0 var(--supb-preview-w, 580px); min-width: 0; order: 1; }

  /* =============================================================================================
     r1452 — MY WORK's record pane is 40% of the row, and never narrower than 350px.

     It was inheriting the supplier board's fixed 580px, which is that board's width for a supplier
     card and says nothing about a task. 40% keeps the list the larger half on a wide screen; the
     350px floor is what stops the pane from becoming a column of wrapped single words on a laptop.

     `flex-basis: 40%` with `min-width` rather than a `clamp()` on width, so the list keeps whatever
     the pane does not take and the two cannot add up to more than the row.
     ============================================================================================= */
  /* =============================================================================================
     r1461 — My work's ONE difference from the Buy boards: how wide its record pane is.

     `--supb-preview-w` is the variable that board already sizes its pane from, and the chrome row's
     reserve is calculated from the same variable — so setting it gives both, and the row cannot drift
     out of step with the pane. Overriding `.s7` directly, as this did, left the reserve pointing at the
     old width and needed a second rule to put it back.

     The other three overrides are gone with the bespoke screen: a `.setup-tabs` strip this page no
     longer draws, a reserve the variable now supplies, and an S5 the board leaves empty. **An override
     kept after the thing it was overriding has gone is a rule that only has to be read, never obeyed.**
     ============================================================================================= */
  .v16--screen-mywork { --supb-preview-w: 50%; }
  /* =============================================================================================
     r1467 — the tab line sits where Suppliers' does, measured rather than judged.

     On a workspace scene the first row of tabs is `.ws-tabs`, which the card holds directly: 6px of
     card padding plus its own 8px puts it 14px below the top menu. My work has no workspace strip, so
     its FIRST tab row is the board's own `.s4` — and `.s4` opens with `--v16-gap` (16px), because on
     the Buy boards it follows a band and needs the separation. Here it follows nothing, so the gap was
     separating the tabs from the top of the page: 6 + 16 = 22px against Suppliers' 14.

     8px, which is `.ws-tabs`'s own top padding — the two rows are doing the same job on their
     respective pages, so they take the same measure.
     ============================================================================================= */
  .v16--screen-mywork .s4 { padding-top: 8px; }
  /* r1487 — the right column is a flex COLUMN, which is what `margin-top: auto` on the favourites bar
     pushes against. My r1487 rewrite of this block deleted the rule along with the panel styling it sat
     beside, and the bar would have floated under the record instead of sitting on the bottom line.
     **Replacing a range of CSS deletes what was between its ends, including the rule you were relying
     on three screens away.** */
  .v16--screen-mywork .v16__work.has-context > .s7 { min-width: 400px; display: flex; flex-direction: column; }

  /* r1468 — the search and the on/off buttons share ONE row at the top of the list, and the list
     follows beneath it. They filter this tab, so they live in it. */
  /* r1474 — 4px above and below, at the product owner's measure: the row needs to sit apart from the
     tab strip above it and the list below without becoming a band of its own. */
  /* r1501 — the same height on every tab. Tasks carries three toggles beside the search and the other
     four carry search alone, so the row was 40px tall on one tab and the search's own height on the
     rest — and the gap above the list changed as the reader moved between tabs. A minimum height fixes
     the row, so the list starts in the same place whatever the row happens to hold. */
  /* r1502 - and a real GAP below it. `padding: 4px 0` gave four pixels, which against a 40px row and
     a table starting immediately underneath reads as no gap at all: the search row and the list looked
     like one block. 12px below, 4px above, so the row sits with the tab strip it belongs to and stands
     clear of the list it filters. */
  .supb-listbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    min-height: 40px; padding: 4px 0 12px; }
  .supb-listbar .supb-find { flex: 1 1 220px; min-width: 180px; }
  .supb-tgs { display: flex; align-items: center; gap: 6px; }
  /* the standard button corner, not a pill: these are on/off buttons, and nothing else in the estate
     is round. 40px keeps them at the touch target §16 asks for. */
  .supb-tg { display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 12px;
    border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-card);
    color: var(--text-muted); font: inherit; cursor: pointer; }
  .supb-tg:hover { border-color: var(--line-strong); color: var(--text); }
  /* r1501 — an enabled toggle wears the ACTIVE button colour, not a wash of it. A tinted background
     with dark text reads as "slightly different"; a reader scanning three toggles needs to see at a
     glance which are on, and a filled control is the estate's own answer for that everywhere else. */
  .supb-tg.is-on { background: var(--primary); border-color: var(--primary);
    color: var(--primary-contrast, #fff); font-weight: 600; }
  .supb-tg.is-on:hover { background: var(--primary-strong, var(--primary)); border-color: var(--primary); }
  .supb-tg svg { width: 16px; height: 16px; flex: 0 0 auto; }
  .supb-tg__t { white-space: nowrap; }

  /* =============================================================================================
     r1491 — the favourites bar, full width beneath BOTH columns.

     It used to live inside the record pane, which made it a feature of that pane: it began where the
     record began and ended where the record ended, and on a narrow detail column the tiles were
     cramped while the list beside them had room to spare. It is the screen's bar now, not the
     record's.

     72px tiles, 250px wide. The bar is sized from the tile plus its padding rather than given its own
     number, so the two cannot disagree the next time one of them changes.
     ============================================================================================= */
  .mywfav { display: flex; align-items: center; gap: 4px; padding: 8px 4px;
    border: 1px solid var(--line); border-radius: var(--v16-card-radius); background: var(--bg-card); }
  .mywfav__nav { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 72px; border: 0; background: none; color: var(--text-muted); cursor: pointer;
    border-radius: var(--radius); }
  .mywfav__nav:hover { background: var(--bg-app); color: var(--text); }
  .mywfav__strip { flex: 1 1 auto; min-width: 0; display: flex; gap: 8px; overflow-x: auto;
    scroll-behavior: smooth; scrollbar-width: none; }
  .mywfav__strip::-webkit-scrollbar { display: none; }
  .mywfav__b { flex: 0 0 250px; width: 250px; height: 72px; display: inline-flex; align-items: center;
    gap: 12px; padding: 0 14px; border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--bg-app); font: inherit; color: var(--text); cursor: pointer; text-align: left; }
  .mywfav__b:hover { border-color: var(--primary); }
  /* the icon carries the colour, in a tinted disc — the tile stays neutral so a row of them does not
     read as a row of warnings */
  .mywfav__ic { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 10px; background: var(--fav-wash, var(--bg-subtle));
    color: var(--fav-ink, var(--text-muted)); }
  .mywfav__ic svg { width: 20px; height: 20px; }
  .mywfav__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }

  /* r1469 — the task record: the reason it is waiting, then the facts, then the way through. */
  .mywd-why { margin: 0 0 14px; padding: 10px 12px; border-radius: var(--radius);
    background: var(--bg-scene); border-left: 3px solid var(--line-strong); color: var(--text); }
  .mywd-why--late { border-left-color: var(--bad); }
  .mywd-facts { display: grid; grid-template-columns: minmax(120px, max-content) 1fr;
    gap: 8px 16px; margin: 0 0 16px; }
  .mywd-fact { display: contents; }
  .mywd-facts dt { color: var(--text-muted); font-size: 13px; }
  .mywd-facts dd { margin: 0; color: var(--text); }
  .mywd-fact--late { color: var(--bad); font-weight: 600; }
  .mywd-fact--high { color: var(--warn-ink, var(--text)); font-weight: 600; }
  .mywd-acts { display: flex; gap: 8px; }
}
/* r660: the filter+search bar (S4) aligns to the LIST column, not the whole row \u2014 so the search sits at
   the list's right edge, not the far right of the page. It reserves the preview column plus the gap on its
   right. Below the two-column breakpoint the reserve collapses (the list is full-width there too). */
@media (min-width: 1100px) {
  /* r660: the search right-aligns with the list's right edge. The reserve is the preview column plus
     the work-row gap; the S4 bar also sits one --v16-pad to the left of the list, so that is added too,
     which is what closes the last 24px. Measured: list right and search right now coincide. */
  .v16--d-wb-s .supb-s4 { padding-right: calc(var(--supb-preview-w, 580px) + var(--v16-gap) + var(--v16-pad)); }
}
/* r657: on the board, S1 carries only a screen-reader H1 (no visible title). .s1 was still drawing a
   white strip with a bottom border at the very top of the scene \u2014 the "weird line at the top". When S1
   has nothing visible in it, it collapses: no height, no border, no background. The only horizontal rule
   left near the top is then the coloured underline beneath the active tab, which is what was asked for. */
.view--scene .s1 { border-bottom: 0; background: transparent; padding: 0; }
.view--scene .s1--sronly, .view--scene .s1:has(> .sr-only:only-child) { display: none; }
.view--scene .s6, .view--scene .s7 { min-height: 0; display: flex; flex-direction: column; }
.view--scene .dv-l, .view--scene .supb-band + * .dv-l { flex: 1 1 auto; min-height: 0; }
.view--scene .dv-l { display: flex; flex-direction: column; }
.view--scene .dv-l__scroll { flex: 1 1 auto; min-height: 0; }
/* scroll without a visible scrollbar — the list still scrolls, the chrome just does not show a track */
.view--scene .dv-l__scroll { scrollbar-width: none; -ms-overflow-style: none; }
.view--scene .dv-l__scroll::-webkit-scrollbar { width: 0; height: 0; }
/* r655: the board keeps S2/S5 to satisfy the D-WB-S family contract, but they draw nothing. */
.s2--empty, .s5--empty { display: none; }


/* ===== r656: static header, scrolling body, sortable columns, search above the list ===== */
/* r656 (revised): one table, sticky header, single scroll container. */
/* r660: every component has a header with its title on the left and a settings gear on the RIGHT. */
.supb-comp__head { position: relative; display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px 8px 14px; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.supb-comp__title { font-size: 13px; font-weight: 600; color: var(--text); }
/* r1196 — the detail head's edit/open button is drawn in the schema's BUTTON colour, and hovering a
   detail button changes NOTHING about its colour (product owner request): the affordance is the colour,
   not a colour change. The expanded state keeps its primary ring. */
.supb-cog { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--primary); border-radius: 8px; background: var(--bg-card); color: var(--primary);
  cursor: pointer; }
.supb-cog:hover { color: var(--primary); border-color: var(--primary); background: var(--bg-card); }
/* r1206 — the EDIT-state cog (a DRAFT/REJECTED record, yours to change) is a PRIMARY action and wears
   the primary fill. The ring-only look read as "no background" on the white detail card. */
.supb-cog--primary { background: var(--btn-bg); border-color: var(--btn-bg); color: var(--btn-text, #fff); }
.supb-cog--primary:hover { background: var(--btn-bg-hover, var(--btn-bg)); border-color: var(--btn-bg-hover, var(--btn-bg)); color: var(--btn-text, #fff); }
.supb-cog[aria-expanded="true"] { color: var(--primary); border-color: var(--primary); }
.supb-cog svg { width: 16px; height: 16px; }
/* r1196 — no hover colour change on record-detail buttons: base colours are restated on :hover so the
   global .btn-ghost:hover / .btn-primary:hover rules do not repaint them inside a detail card. */
.supb-card .btn-ghost:hover { background: var(--bg-card); border-color: var(--line-strong); color: var(--text); }
.supb-card .btn-ghost.btn-icon:hover { background: var(--btn-bg); border-color: var(--btn-bg); color: var(--btn-text); }
.supb-card .btn-primary:hover { background: var(--primary); border-color: var(--primary); }
.supb-card .btn-subtle:hover { background: transparent; color: var(--text-muted); }
.supb-card .icon-btn:hover { background: transparent; color: inherit; }
/* the column-visibility panel drops from the gear, right-aligned */
.supb-cogp { position: absolute; top: 42px; right: 10px; z-index: 20; min-width: 180px;
  background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: var(--shadow-md, 0 8px 24px rgba(15,23,42,.12)); padding: 8px; }
.supb-cogp__h { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted);
  padding: 2px 6px 6px; }
.supb-cogp__row { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 6px;
  font-size: 13px; cursor: pointer; }
.supb-cogp__row:hover { background: var(--bg-subtle); }
.supb-cogp__row input[disabled] { opacity: .5; }
/* r1163 — the Configure-KPIs gear + its panel live at the right of the tab row now. The panel drops
   directly beneath the gear (its wrap is the positioning context); the period row is a small segmented
   control. */
/* r1166 — the Configure-KPIs control sits at the FAR RIGHT of the workspace tab row (.ws-tabs is a flex
   row, so margin-left:auto pushes it there). The panel is always in the DOM and shown by toggling
   `.is-open` on the wrap, so opening it re-renders nothing. */
.supb-kpicfg-wrap { position: relative; margin-left: auto; display: inline-flex; align-items: center; }
.supb-cogp.supb-kpicfgp { display: none; top: calc(100% + 4px); right: 0; }
.supb-kpicfg-wrap.is-open .supb-cogp.supb-kpicfgp { display: block; }
.supb-kpiperiod { display: flex; gap: 4px; padding: 2px 6px 4px; }
.supb-kpiperiod__b { flex: 1 1 auto; padding: 3px 8px; font-size: 12px; border: 1px solid var(--line-strong);
  border-radius: 6px; background: var(--bg-card); color: var(--text-muted); cursor: pointer; }
.supb-kpiperiod__b.is-on { background: var(--primary, #E8792A); color: #fff; border-color: var(--primary, #E8792A); }
/* searchable-dropdown filter cell: same footprint as a text filter, with a caret affordance */
/* r660: the fixed-value filter uses the app's searchable combobox, sized down to match the compact
   filter-row inputs so every column's control lines up. */
.tcl-facet { position: relative; display: block; width: 100%; }
.tcl-facet .combo-control { padding: 0 4px 0 8px; border-color: var(--line); border-radius: var(--radius-sm);   /* r1603 */
  min-height: 26px; }
.tcl-facet .combo-input { font-size: 12px; padding: 5px 0; }
.tcl-facet .combo-input::placeholder { color: var(--text-muted); font-style: italic; }
.tcl-facet .combo-control:focus-within { border-color: var(--primary); box-shadow: 0 0 0 2px rgba(232,121,42,.12); }
.tcl-facet .combo-caret { font-size: 10px; }
.tcl-facet .combo-clear { font-size: 14px; }
.tcl-list { display: flex; flex-direction: column; min-height: 0; background: var(--bg-card);
  border: 1px solid var(--line-strong); border-radius: var(--v16-card-radius); overflow: hidden; }
/* r657: the "N suppliers" count element was removed from the header; this rule is retired. */
.tcl-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  scrollbar-width: none; -ms-overflow-style: none; }
.tcl-scroll::-webkit-scrollbar { width: 0; height: 0; }
.tcl-t { width: 100%; table-layout: fixed; border-collapse: collapse; }
/* the header row stays put while the body scrolls under it */
.tcl-t thead th { position: sticky; top: 0; z-index: 2; padding: 0;
  background: var(--bg-subtle); border-bottom: 1px solid var(--line); }
.tcl-sort { display: flex; align-items: center; gap: 6px; width: 100%; padding: 9px 12px;
  background: none; border: 0; font: inherit; font-size: 12px; font-weight: 600; color: var(--text-muted);
  cursor: pointer; text-align: left; }
.tcl-sort:hover { color: var(--text); }
.tcl-sort.is-sorted { color: var(--text); }
.tcl-sort__a { font-size: 11px; }
.tcl-t td { padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.tcl-t tbody tr:last-child td { border-bottom: 0; }
/* both header rows are sticky \u2014 the sort labels and the filter inputs \u2014 stacked at the top.
   r663: the filter row's `top` follows the measured sort-row height (--tcl-head-h, set in JS) instead of
   a hard-coded 37px, so no strip of list shows through the seam when the row height differs. */
.tcl-t thead .tcl-hr th { top: 0; }
.tcl-t thead .tcl-fr th { top: var(--tcl-head-h, 37px); z-index: 2; padding: 0 6px 6px; background: var(--bg-subtle);
  border-bottom: 1px solid var(--line); position: sticky; }
.tcl-colf { width: 100%; height: 26px; padding: 0 8px; border: 1px solid var(--line);
  border-radius: 6px; background: var(--bg-card); font: inherit; font-size: 12px; color: var(--text); }
.tcl-colf:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(232,121,42,.12); }
.tcl-colf::placeholder { color: var(--text-muted); font-style: italic; }
.tcl-colf--num { font-variant-numeric: tabular-nums; }
/* r685: an unreadable number expression is MARKED, not silently ignored - a filter that quietly matches
   nothing is indistinguishable from a list that is genuinely empty. */
.tcl-colf.is-bad { border-color: var(--bad); box-shadow: 0 0 0 2px rgba(185,28,28,.12); }
/* the lazy-render sentinel: a quiet loading row that the scroll handler watches */
.tcl-sentinel td { text-align: center; padding: 12px; color: var(--text-muted); font-size: 12px; }
.tcl-sentinel__t { display: inline-flex; align-items: center; gap: 8px; }
.tcl-sentinel__t::before { content: ""; width: 12px; height: 12px; border: 2px solid var(--line-strong);
  border-top-color: var(--primary); border-radius: 999px; display: inline-block; animation: tcl-spin .7s linear infinite; }
@keyframes tcl-spin { to { transform: rotate(360deg); } }

/* search sits above the list, on its own row under the filters */
/* r657: filters and search on ONE row. In r656 this was a vertical column, which grew the band and
   pushed the list down and to the side \u2014 the "list out of position" report. */
.supb-s4 { display: flex; align-items: center; gap: 12px; }
.supb-filters { display: flex; gap: 4px; flex: 1 1 auto; min-width: 0; padding-top: 0; }
/* r660: the selected sub-tab is in the ACTIVE (accent) colour, underline included \u2014 matching the
   lifecycle tabs above rather than the muted dark the generic S4 used. */
.supb-filters .s4__t { border-bottom: 2px solid transparent; }
.supb-filters .s4__t.is-active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }
/* a compact, framed, icon-led search that reads as a control rather than a raw box */
.supb-find { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
  width: 240px; height: 34px; padding: 0 8px 0 10px; border: 1px solid var(--line-strong);
  border-radius: 999px; background: var(--bg-card); transition: border-color .12s, box-shadow .12s; }
.supb-find:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(232,121,42,.12); }
.supb-find__ic { display: inline-flex; color: var(--text-muted); flex: 0 0 auto; }
.supb-find__ic svg { width: 16px; height: 16px; }
.supb-find__in { flex: 1 1 auto; min-width: 0; border: 0; background: none; outline: none;
  font: inherit; font-size: 13px; color: var(--text); }
.supb-find__in::placeholder { color: var(--text-muted); }
.supb-find__in::-webkit-search-cancel-button { display: none; }
.supb-find__x { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 20px; height: 20px; border: 0; background: none; border-radius: 999px; cursor: pointer;
  color: var(--text-muted); }
.supb-find__x:hover { background: var(--bg-subtle); color: var(--text); }
.supb-find__x svg { width: 14px; height: 14px; }


/* r775 — the memory map in Setup. Uses the estate's own tokens; nothing new is invented, because a
   screen that introduces its own palette is a screen that will drift from the rest. */
.mm-head h3 { margin: 0 0 2px; }
.mm-sub { margin: 0 0 14px; }
.mm-bar { display: flex; height: 34px; border: 1px solid var(--border);
          border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 8px; }
.mm-seg { display: block; }
.mm-seg { display: flex; align-items: center; justify-content: center; font-size: 11px;
           font-weight: 600; color: #fff; white-space: nowrap; overflow: hidden; }
.mm-seg--t1  { background: #2f81f7; }
.mm-seg--t2  { background: #3fb950; }
.mm-seg--t3  { background: #d29922; }
.mm-seg--jvm { background: #8957e5; }
.mm-seg--free { background: var(--surface-2); color: var(--text-muted); }
.mm-bar--inset { height: 26px; margin: 0 0 14px; }
.mm-inset-cap { font-size: 12px; color: var(--text-muted); margin: 10px 0 6px; }
#mm-inset { border: 1px dashed var(--border); border-radius: var(--radius-sm);
            padding: 0 12px; margin-bottom: 14px; }
#mm-inset:empty { display: none; }
.mm-tier { font-size: 11px; font-weight: 600; padding: 2px 7px; border-radius: 20px; }
.mm-tier--1 { background: rgba(47,129,247,.15); color: #2f81f7; }
.mm-tier--2 { background: rgba(63,185,80,.15);  color: #3fb950; }
.mm-tier--3 { background: rgba(210,153,34,.15); color: #b8860b; }
.mm-dim { color: var(--text-muted); font-size: 12px; }
.mm-foot { font-size: 11px; color: var(--text-muted); margin: -12px 0 20px; }
.mm-warn { font-size: 12px; color: var(--danger, #d1242f); margin: 4px 0 18px; }
.mm-legend { display: flex; gap: 18px; margin-bottom: 18px; font-size: 12px; color: var(--text-muted); }
.mm-lg { display: inline-flex; align-items: center; gap: 6px; }
.mm-sw { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.mm-sw--t1 { background: #2f81f7; }
.mm-sw--t2 { background: #3fb950; }
.mm-sw--t3 { background: #d29922; }
.mm-sw--jvm { background: #8957e5; }
.mm-sw--free { background: var(--surface-2); border: 1px solid var(--border); }
.mm-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 20px; }
.mm-table th { text-align: left; font-weight: 500; color: var(--text-muted); font-size: 11px;
               text-transform: uppercase; letter-spacing: .4px; padding: 7px 10px;
               border-bottom: 1px solid var(--border); }
.mm-table td { padding: 8px 10px; border-bottom: 1px solid var(--border-subtle); }
.mm-table td.num, .mm-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.mm-why { color: var(--text-muted); font-size: 12px; max-width: 30ch; }
.mm-pill { display: inline-block; padding: 2px 8px; border-radius: 20px; font-size: 11px; font-weight: 600; }
.mm-pill--res { background: var(--accent-soft); color: var(--accent); }
.mm-pill--def { background: var(--surface-2); color: var(--text-muted); }


/* r783 — the r782 dark palette is REMOVED, not overridden.
   It hardcoded --mmbg/--mmink and set near-white text; on a light theme that put rgb(230,237,243) text on
   an rgb(248,250,252) card, which is invisible. That is why the page looked blank rather than merely
   plain, and it is why the screenshots read as empty.
   Every colour now comes from a theme token, below. */
/* r783 — memory map, on the estate's own tokens.
   The r782 version hardcoded a dark palette. That ignored the user's theme preference and made one screen
   behave differently from every other, which is the drift a design system exists to prevent. Every colour
   here now comes from a token, so the page follows light or dark as the reader has chosen.

   Sections use .card, the same container the rest of the product uses, at full width and with one gap
   value between them — so the widths and spacing are the estate's rather than this page's opinion. */
/* r784 — the panel must be able to scroll to its end. It sat inside a container whose height it
   exceeded, so the prefetch section at the bottom was unreachable. The padding is what gives the last
   section room to clear the viewport edge. */
/* r1402 — Memory keeps its extra bottom room and its visible overflow, and takes the same frame as
   every other Setup panel. It set `padding: 0 0 48px`, which zeroed the top and both sides: the tab
   started hard against the left edge and higher than every other tab on the same row. The 48px was
   the point of the rule; the three zeroes were how it was written. */
.setup-panel[data-panel="memory"] { padding: 16px 16px 48px; overflow: visible; }
.mm-head { margin-bottom: 14px; }
.mm-head h3 { margin: 0 0 2px; }
.mm-sub { margin: 0; color: var(--text-muted); font-size: 13px; }

/* one section container, one gap: every section is full width and equally spaced */
.mm-panel { background: var(--bg-card); border: 1px solid var(--line);
              border-radius: var(--radius); box-shadow: var(--shadow-sm);
              padding: 18px 20px; margin: 0 0 16px; width: 100%; }
.mm-panel > h4:first-child { margin-top: 0; }
.mm-panel h4 { font-size: 13px; margin: 20px 0 4px; }
.mm-blurb { color: var(--text-muted); font-size: 12px; margin: 0 0 10px; }

.mm-kpi { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 0 0 16px; }
.mm-card { background: var(--bg-subtle); border: 1px solid var(--line);
           border-radius: var(--radius-sm); padding: 14px 16px; }
.mm-card-k { color: var(--text-muted); font-size: 12px; }
.mm-card-v { font-size: 26px; font-weight: 650; font-variant-numeric: tabular-nums;
             margin: 2px 0; color: var(--text); }

.mm-bar { display: flex; height: 44px; border: 1px solid var(--line);
          border-radius: var(--radius-sm); overflow: hidden; margin: 0 0 10px; }
.mm-seg { display: flex; align-items: center; justify-content: center; font-size: 11px;
          font-weight: 600; white-space: nowrap; overflow: hidden; color: var(--text-on-dark-strong); }
.mm-seg--t1  { background: var(--primary); }
.mm-seg--t2  { background: var(--success, #2f855a); }
.mm-seg--t3  { background: var(--warning, #b7791f); }
.mm-seg--jvm { background: var(--accent-alt, #6b46c1); }
.mm-seg--free { background: var(--bg-subtle); color: var(--text-muted); }
.mm-bar--inset { height: 26px; margin: 0; }
.mm-inset-cap { font-size: 12px; color: var(--text-muted); margin: 0 0 6px; }
#mm-inset { border: 1px dashed var(--line); border-radius: var(--radius-sm);
            padding: 12px; margin: 0 0 14px; }
#mm-inset:empty { display: none; }
.mm-legend { display: flex; flex-wrap: wrap; gap: 16px; font-size: 12px; color: var(--text-muted); }
.mm-lg { display: inline-flex; align-items: center; gap: 7px; }
.mm-sw { width: 11px; height: 11px; border-radius: 2px; display: inline-block; flex: none; }
.mm-sw--t1 { background: var(--primary); }
.mm-sw--t2 { background: var(--success, #2f855a); }
.mm-sw--t3 { background: var(--warning, #b7791f); }
.mm-sw--jvm { background: var(--accent-alt, #6b46c1); }
.mm-sw--free { background: var(--bg-subtle); border: 1px solid var(--line); }

/* r784 — the three tables are SEPARATE tables, so each sized its own columns and the sections did not
   line up. table-layout: fixed with one set of widths makes them one grid read down the page, which is
   the whole point of showing them as three sections of the same thing. */
.mm-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-bottom: 10px;
            table-layout: fixed; }
.mm-table col.mm-c-hold { width: 62px; }
.mm-table col.mm-c-data { width: 20%; }
.mm-table col.mm-c-num  { width: 10%; }
.mm-table col.mm-c-src  { width: 12%; }
.mm-table td, .mm-table th { overflow: hidden; text-overflow: ellipsis; }
.mm-table th { text-align: left; font-weight: 500; color: var(--text-muted); font-size: 11px;
               text-transform: uppercase; letter-spacing: .4px; padding: 7px 10px;
               border-bottom: 1px solid var(--line); }
.mm-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); color: var(--text); }
.mm-table tr:last-child td { border-bottom: none; }
.mm-table td.num, .mm-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.mm-dim { color: var(--text-muted); font-size: 12px; }
.mm-foot { font-size: 11px; color: var(--text-muted); margin: 0; }

/* the switch, on tokens: it follows the theme like every other control */
.mm-sw-wrap { position: relative; display: inline-block; width: 34px; height: 19px; }
.mm-sw-wrap input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.mm-slider { position: absolute; inset: 0; background: var(--bg-subtle);
             border: 1px solid var(--line); border-radius: 19px;
             transition: background .15s; pointer-events: none; }
.mm-slider::before { content: ""; position: absolute; width: 13px; height: 13px; left: 2px; top: 2px;
                     background: var(--text-muted); border-radius: 50%;
                     transition: transform .15s, background .15s; }
.mm-sw-wrap input:checked + .mm-slider { background: var(--primary-soft);
                                         border-color: var(--primary); }
.mm-sw-wrap input:checked + .mm-slider::before { transform: translateX(15px); background: var(--primary); }
.mm-sw-wrap input:disabled + .mm-slider { opacity: .5; }

.mm-note { border-left: 3px solid var(--primary); padding: 10px 14px; background: var(--primary-soft);
           border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: 13px;
           color: var(--text); margin: 14px 0 0; }
.mm-note--warn { border-left-color: var(--danger, #c53030);
                 background: var(--danger-soft, rgba(197,48,48,.08)); }


/* r799 — action icons. Size and colour come from here, never from the markup: the source SVGs carried
   width="48" and a hardcoded near-black, which would have made every icon identical in size on every
   screen and invisible in a dark theme. */
.nwm-icon { width: 1.15em; height: 1.15em; flex: none; vertical-align: -0.18em; }
.nwm-icon--sm { width: 0.95em; height: 0.95em; }
.nwm-icon--lg { width: 1.5em; height: 1.5em; }
button .nwm-icon, .btn .nwm-icon { margin-right: 6px; }
button .nwm-icon:only-child, .btn .nwm-icon:only-child { margin-right: 0; }


/* r802 — the scene sub-tab panel. The STRIP reuses .fb-tabs/.fb-tab unchanged; only the panel is new,
   because the estate had no shared one and each detail view drew its own. */
.scene-panel { padding: 14px 2px 4px; }
.scene-panel__msg { margin: 10px 2px; font-size: 13px; }
.scene-panel__msg--err { color: var(--danger, #c53030); }


/* r803 — busy, without tearing the page down. The netbar and the status line already say a request is in
   flight; this only makes the stale content visibly stale so nobody acts on it mid-refresh. */
.view.is-busy { opacity: .55; pointer-events: none; transition: opacity .12s ease-out; }
.view.is-busy .spinner { opacity: 1; }


/* r828 — the Receive scene. Structure only; every colour is a token, as r783 established. */
.rcv-att-wrap h3 { font-size: 13px; margin: 0 0 10px; }
.rcv-att { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.rcv-att__i { display: flex; justify-content: space-between; align-items: center; width: 100%;
              gap: 12px; padding: 10px 12px; background: var(--bg-card);
              border: 1px solid var(--line); border-radius: var(--radius-sm);
              color: var(--text); cursor: pointer; text-align: left; }
.rcv-att__i:hover { border-color: var(--primary); }
.rcv-att__n { font-weight: 600; }
.rcv-att__d { color: var(--text-muted); font-size: 12px; }
.rcv-dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 0 0 16px;
          font-size: 13px; }
.rcv-dl dt { color: var(--text-muted); }
.rcv-dl dd { margin: 0; }
.rcv-acts { display: flex; flex-wrap: wrap; gap: 8px; }


/* r845 — the standards page. Structure only; every colour is a token. */
.ds-head h1 { margin: 0 0 4px; }
.combo-hint { font-size: 11px; color: var(--text-muted); margin-top: 3px; }
.combo-opt__a { font-family: "JetBrains Mono", monospace; font-size: 12px; display: block; }
.combo-opt__b { font-size: 12px; color: var(--text-muted); display: block; }
.chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px; margin-right: 4px;
        background: var(--bg-subtle); border: 1px solid var(--line); border-radius: 3px; font-size: 12px; }
.chip-x { border: 0; background: none; cursor: pointer; color: var(--text-muted); padding: 0 2px; }


/* =====================================================================
 * r849 — THE AGREED CONTROL STANDARD.
 *
 * Specified by the product owner, applied as tokens so it lands on every screen at once rather than
 * screen by screen — a standard rolled out page by page is a standard the estate disagrees with for as
 * long as the rollout takes.
 *
 * Appended last so it wins without editing 500 call sites, and stated as tokens so the next change is
 * one value rather than another sweep.
 * ===================================================================== */
:root {
    --ctl-h: 36px;              /* every button and every entry field */
    /* r1127 — the primary button FOLLOWS the theme. This was a frozen #ff8c1f, a second variable for a
       fact --btn-bg already held; because this block is appended last, its rule won and every theme's
       primary button rendered orange regardless of the scheme's accent. Referencing --btn-bg makes the
       two agree: default themes keep orange (their --btn-bg is #FF8C1F), and a scheme that sets its own
       accent — Red, Sky blue, Ocean, Rose, … — gets it here too. */
    --btn-primary-bg: var(--btn-bg, #ff8c1f);
    --btn-danger-fg: #ed2024;
}

/* --- buttons ------------------------------------------------------- */
.btn, .btn-primary, .btn-ghost, .btn-subtle, .btn-danger, .btn-danger-ghost {
    min-height: var(--ctl-h);
    height: var(--ctl-h);
    /* width follows the text: no min-width. A button padded to a fixed width beside a short label
       reads as a disabled area rather than a control. */
    min-width: 0;
}
.btn-primary { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); color: var(--btn-text, #fff); }
/* no hover change on primary: it is already the most prominent control on the surface, and moving its
   colour under the cursor suggests a state change that is not happening */
.btn-primary:hover { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); }
.btn-danger, .btn-danger-ghost {
    color: var(--btn-danger-fg);
    border-color: var(--btn-danger-fg);
    background: transparent;
}

/* --- icon buttons replace small buttons ---------------------------- */
/* btn-sm is retired: an action small enough to shrink is an action better shown as an icon. The rule
   keeps its height in step so the 381 existing uses do not become a second size while they are
   converted. */
.btn-sm { height: var(--ctl-h); min-height: var(--ctl-h); min-width: 0; }
.btn-icon { height: var(--ctl-h); width: var(--ctl-h); min-width: var(--ctl-h); padding: 0;
            justify-content: center; }

/* --- entry fields -------------------------------------------------- */
.inp, input.inp, select.inp, textarea.inp:not([rows]), .combo, .combo-input {
    min-height: var(--ctl-h);
}
.inp, input.inp, select.inp { height: var(--ctl-h); }
.combo { min-height: var(--ctl-h); display: flex; align-items: center; flex-wrap: wrap; }

/* --- multi-select chips: chosen options read as chosen -------------- */
.chip, .ms-chip {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 7px; margin: 2px;
    background: var(--bg-subtle); color: var(--text-muted);
    border: 1px solid var(--line); border-radius: 3px; font-size: 12px;
}

/* --- two-line option: the code is what is stored -------------------- */

/* --- loading: a turning 360 glyph, not a word ----------------------- */
/* Placed where the value will be, so the reader's eye does not move when it arrives, and it goes light
   grey rather than vanishing — a spinner that disappears leaves the reader unsure whether it finished. */
.ldg { display: inline-flex; color: var(--btn-primary-bg); animation: ldg-spin 1.1s linear infinite; }
.ldg--done { color: var(--line-strong); animation: none; }
@keyframes ldg-spin { to { transform: rotate(360deg); } }


/* =====================================================================
 * r850 — three corrections from review.
 * ===================================================================== */

/* 1. KPI cards: label and value CENTRED horizontally.
 *
 * Three families exist — supb-kpi, cb-kpi and the scene's s3 cards — and all three are corrected
 * together. Fixing the one in front of me and leaving the others is how a screen ends up with two kinds
 * of KPI card side by side, which is the drift this standard exists to end. */
.supb-kpi, .cb-kpi, .s3__c {
    text-align: center;
}
.supb-kpi__l, .supb-kpi__v, .cb-kpi__l, .cb-kpi__v, .cb-kpi__h, .s3__k, .s3__v, .s3__n {
    text-align: center;
    justify-content: center;
}
/* a card whose contents are laid out in a row must centre that row too, or text-align does nothing */
.supb-kpi > *, .cb-kpi > *, .s3__c > * { margin-left: auto; margin-right: auto; }

/* 2. Date fields: bigger.
 *
 * The native control's calendar button and its text sit inside the field, so a date at the same width as
 * a status dropdown is cramped and the picker is hard to hit. Given its own minimum and a larger glyph
 * — a control people mis-tap is a control people stop using. */
input.inp[type="date"], input[type="date"] {
    min-width: 190px;
    font-size: 14px;
    padding-right: 6px;
}
input.inp[type="date"]::-webkit-calendar-picker-indicator,
input[type="date"]::-webkit-calendar-picker-indicator {
    width: 20px; height: 20px;
    cursor: pointer;
    opacity: .75;
}
input.inp[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }

/* 3. The loading mark belongs beside the LIST TITLE, not in a column header.
 *
 * A spinner in a column header reads as a property of that column — "the name column is loading" — when
 * what is loading is the list. Beside the title it says what is true: this view is fetching. */
.list-title, .card-head h2, .card-head h3 { display: inline-flex; align-items: center; gap: 8px; }
.list-title .ldg, .card-head .ldg { flex: none; }


/* =====================================================================
 * r851 — the CF Designer field-size control.
 * ===================================================================== */

/* Width fits the options and nothing more. Eight fixed choices — 1/1 to 1/8 — are three characters wide,
 * so a control stretched to a column width is mostly empty space that reads as an input waiting for
 * typing. Not searchable, for the same reason: a search box over a list you can already see asks a
 * question the screen has answered. */
.fb-width {
    width: auto;
    min-width: 0;
    max-width: max-content;
    height: var(--ctl-h);
    /* r852: 4px, not 8. Measured at 55px with 8px padding, and about 20 of that is the native select
     * arrow — so the padding is the only part I control and it was half the visible slack. "1/1" is
     * three characters; the control should look like it holds three characters. */
    padding: 0 4px;
    font-size: 13px;
}
/* the same rule wherever the picker is drawn as buttons rather than a select */
.fw-opts { display: inline-flex; gap: 4px; }
.fw-opts button {
    height: var(--ctl-h);
    min-width: 0;
    width: max-content;
    padding: 0 10px;
    border: 1px solid var(--line-strong);
    background: var(--bg-card);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font: 13px/1 inherit;
}
.fw-opts button.is-on { background: var(--bg-subtle); font-weight: 600; }


/* =====================================================================
 * r853 — Field settings: a field takes the width its row gives it.
 *
 * The panel is a wrapping flex row. A field that shares its row takes HALF; a field alone takes the
 * WHOLE row. Previously a lone field kept its declared fraction and left the rest of the row empty,
 * which reads as a missing control rather than a wide one.
 *
 * grid-column and flex-basis both appear on these fields depending on where they were built, so both
 * are covered — a rule that fixes one and not the other leaves half the panel behaving differently
 * from the other half, which is the drift this is meant to end.
 * ===================================================================== */
.cf-grid { display: flex; flex-wrap: wrap; gap: 18px 12px; align-items: flex-start; }

/* two per row by default: half the row minus the gap */
.cf-grid > .field,
.cf-grid > .cf-field {
    flex: 0 1 calc(50% - 6px);
    max-width: calc(50% - 6px);
    min-width: 200px;
}

/* a field that declares full width, or is the only child, takes the whole row */
.cf-grid > .field[data-w="1/1"],
.cf-grid > .cf-field[data-w="1/1"],
.cf-grid > .field[style*="grid-column"],
.cf-grid > .field:only-child,
.cf-grid > .cf-field:only-child {
    flex: 0 1 100%;
    max-width: 100%;
}

/* and the last field on an odd row fills the space rather than leaving it blank */
.cf-grid > .field:last-child:nth-child(odd),
.cf-grid > .cf-field:last-child:nth-child(odd) {
    flex: 1 1 auto;
    max-width: 100%;
}


/* =====================================================================
 * r857 — btn-sm is RETIRED. Zero uses remain in the application.
 *
 * It began as a smaller button for dense toolbars. r849 gave it the standard 36px height, which left it
 * as a smaller font and tighter padding on a full-height control — a third size in all but name, and the
 * hardest kind to notice because it is only wrong beside the others.
 *
 * The rule stays as a SHIM rather than being deleted: a tenant stylesheet or an older cached page may
 * still emit the class, and a class that suddenly styles nothing is a button that suddenly looks wrong.
 * It now resolves to the standard button, so old markup lands on the standard rather than on nothing.
 * ===================================================================== */
.btn-sm {
    height: var(--ctl-h);
    min-height: var(--ctl-h);
    padding: 0 14px;
    font-size: 13px;
    min-width: 0;
}
.btn-icon.btn-sm { width: var(--ctl-h); padding: 0; }


/* =====================================================================
 * r857 — restored: the standard's own classes.
 *
 * The dead-class scan removed these because nothing references them YET. They are not dead; they are the
 * agreed standard waiting to be applied, and a scan that cannot tell "unused" from "not yet used" will
 * delete tomorrow's work every time it runs.
 *
 * I did this to myself in the same round in which I warned about deleting CSS on confidence. The rule I
 * take from it: **a class added by a standard is exempt from the dead scan until the standard is
 * applied**, and the scan needs that exemption written down rather than remembered.
 * ===================================================================== */

/* the loading mark sits beside a list's own title, never in a column header */
.list-title { display: inline-flex; align-items: center; gap: 8px; }

/* two-line option: the code is what is stored, the description is what is recognised */
.opt-2 { padding: 6px 8px; }
.opt-2__code { display: block; font-weight: 600; font-size: 13px; }
.opt-2__desc { display: block; font-size: 12px; color: var(--text-muted); }


/* =====================================================================
 * r861 — Field settings: every control is half the panel, like every other form.
 *
 * The panel's fields already take half a row (r853). Its DROPDOWNS did not: a combo inside a half-width
 * field still sized itself to its content, so a status picker sat at 90px beside a 300px text box and the
 * panel read as three different layouts stacked.
 *
 * A control fills the field it is in. The FIELD decides the width; the control never argues with it.
 * ===================================================================== */
.cf-grid > .field > .combo,
.cf-grid > .field > select,
.cf-grid > .field > input,
.cf-grid > .field > textarea,
.cf-grid > .cf-field > .combo,
.cf-grid > .cf-field > select,
.cf-grid > .cf-field > input,
.cf-grid > .cf-field > textarea,
.cf-grid > .field > [data-combo-host],
.cf-grid > .cf-field > [data-combo-host],
.cf-grid > .field > [data-combo-host] > .combo,
.cf-grid > .cf-field > [data-combo-host] > .combo {
    width: 100%;
    max-width: 100%;
}

/* the field-width picker keeps its own size: it is a fixed set, not a form field (r852) */
.cf-grid .fb-width, .fb-tile .fb-width { width: auto; max-width: max-content; }


/* =====================================================================
 * r862 — A FIELD TAKES THE WIDTH THE CF DESIGNER GAVE IT.
 *
 * r853 set every field to half the row. That was right as a DEFAULT and wrong as a rule: it overrode
 * `data-w`, so a field a person had deliberately made full width or a third came out at half anyway —
 * **the designer appeared to work and did nothing.** A setting that is silently ignored is worse than one
 * that is missing, because the person believes they have made a choice.
 *
 * The fraction now comes from `data-w`, which the markup already carries and already defaults to "1/2"
 * (app.js: `data-w="${opts.w || "1/2"}"`). So an undesigned field is still half a row, and a designed one
 * is what it was designed to be. **One source for the width, and it is the one the designer writes.**
 * ===================================================================== */
.cf-grid > .field[data-w="1/1"], .cf-grid > .cf-field[data-w="1/1"],
.doc-grid > .field[data-w="1/1"], .doc-grid > .cf-field[data-w="1/1"] { flex: 0 1 calc(100% - 6px); max-width: calc(100% - 6px); }
.cf-grid > .field[data-w="1/2"], .cf-grid > .cf-field[data-w="1/2"],
.doc-grid > .field[data-w="1/2"], .doc-grid > .cf-field[data-w="1/2"] { flex: 0 1 calc(50% - 6px); max-width: calc(50% - 6px); }
.cf-grid > .field[data-w="1/3"], .cf-grid > .cf-field[data-w="1/3"],
.doc-grid > .field[data-w="1/3"], .doc-grid > .cf-field[data-w="1/3"] { flex: 0 1 calc(33.333% - 6px); max-width: calc(33.333% - 6px); }
.cf-grid > .field[data-w="1/4"], .cf-grid > .cf-field[data-w="1/4"],
.doc-grid > .field[data-w="1/4"], .doc-grid > .cf-field[data-w="1/4"] { flex: 0 1 calc(25% - 6px); max-width: calc(25% - 6px); }
.cf-grid > .field[data-w="1/5"], .cf-grid > .cf-field[data-w="1/5"],
.doc-grid > .field[data-w="1/5"], .doc-grid > .cf-field[data-w="1/5"] { flex: 0 1 calc(20% - 6px); max-width: calc(20% - 6px); }
.cf-grid > .field[data-w="1/6"], .cf-grid > .cf-field[data-w="1/6"],
.doc-grid > .field[data-w="1/6"], .doc-grid > .cf-field[data-w="1/6"] { flex: 0 1 calc(16.666% - 6px); max-width: calc(16.666% - 6px); }
.cf-grid > .field[data-w="1/7"], .cf-grid > .cf-field[data-w="1/7"],
.doc-grid > .field[data-w="1/7"], .doc-grid > .cf-field[data-w="1/7"] { flex: 0 1 calc(14.285% - 6px); max-width: calc(14.285% - 6px); }
.cf-grid > .field[data-w="1/8"], .cf-grid > .cf-field[data-w="1/8"],
.doc-grid > .field[data-w="1/8"], .doc-grid > .cf-field[data-w="1/8"] { flex: 0 1 calc(12.5% - 6px); max-width: calc(12.5% - 6px); }

/* the default, for a field that declares nothing at all */
.cf-grid > .field:not([data-w]), .cf-grid > .cf-field:not([data-w]),
.doc-grid > .field:not([data-w]), .doc-grid > .cf-field:not([data-w]) {
    flex: 0 1 calc(50% - 6px);
    max-width: calc(50% - 6px);
}

/* --- and every CONTROL fills the field it is in ---------------------
 *
 * The field owns the width; the control never argues with it. Without this a combo sized itself to its
 * content, so a status picker sat at 90px inside a half-row field and the form read as ragged columns
 * even though every field was the width it had been given. */
.field > .combo, .field > select, .field > input, .field > textarea,
.cf-field > .combo, .cf-field > select, .cf-field > input, .cf-field > textarea,
.field > [data-combo-host], .cf-field > [data-combo-host],
.field > [data-combo-host] > .combo, .cf-field > [data-combo-host] > .combo {
    width: 100%;
    max-width: 100%;
}
/* fixed-set pickers keep their own size: they are not form fields (r852, r861) */
.field .fb-width, .cf-field .fb-width { width: auto; max-width: max-content; }


/* =====================================================================
 * r878 — the sourcing event detail. Structure only; every colour is a token.
 * ===================================================================== */
.src-lot { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px;
           margin-bottom: 10px; }
.src-lot__h { font-weight: 600; font-size: 13px; margin-bottom: 8px; }
.src-weights { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }

/* a weight total that is not 100 is FLAGGED rather than silently normalised — the buyer who meant 100
 * and typed 87 has changed every score by a seventh, and this is the only place they would notice */
.chip--warn { border-color: var(--btn-danger-fg); color: var(--btn-danger-fg); background: transparent; }

/* the awarded row is marked, so the winner is findable without reading every rank */
.grid tr.is-won { background: var(--bg-subtle); }
.grid tr.is-won td { font-weight: 600; }


/* =====================================================================
 * r884 — DROPDOWNS FOLLOW THE FIELD'S WIDTH, at any depth.
 *
 * r862 made controls fill their field with DIRECT-CHILD selectors — `.field > .combo`. That misses every
 * searchable dropdown in the product, because `enhanceSelects` does not replace the select in place: it
 * inserts a bare wrapper div and mounts the combo inside it. The combo is a GRANDCHILD, so the rule never
 * matched and the control kept sizing itself to its content.
 *
 * <b>A status picker at 90px beside a 300px text box in the same half-row field</b> is what that looks
 * like, and it is what the product owner has been seeing on every form.
 *
 * The rule is now by DESCENDANT. The field owns the width — declared in the CF Designer, defaulting to
 * half a row (r862) — and no control inside it argues with that.
 * ===================================================================== */
.field .combo,
.cf-field .combo,
.field [data-combo-host],
.cf-field [data-combo-host],
.field select:not(.fb-width),
.cf-field select:not(.fb-width),
.field input:not([type="checkbox"]):not([type="radio"]),
.cf-field input:not([type="checkbox"]):not([type="radio"]),
.field textarea,
.cf-field textarea {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
}

/* the wrapper enhanceSelects inserts has no class of its own, so it is addressed by what it contains:
 * a div that holds a combo must not shrink to the combo's content or the width stops one level short */
.field > div:has(> .combo),
.cf-field > div:has(> .combo) { width: 100%; }

/* and for browsers without :has — the wrapper is always the element immediately before the hidden
 * select, so target any direct div child of a field that is not one of the known layout wrappers */
.field > div, .cf-field > div { max-width: 100%; }

/* THE ONE EXCEPTION, and it stays one: the CF Designer field-size picker is a fixed set of eight visible
 * options, not a form field. A search box over a list you can already see asks a question the screen has
 * answered (r852, r861). */
/* r884: qualified with the ELEMENT, so the selector is at least as specific as the general rule it must
 * beat — `.field select:not(.fb-width)` scores higher than `.field .fb-width`, and although it does not
 * MATCH the picker, whatever else was setting max-width:100% clearly did. Specificity that has to be
 * reasoned about is specificity that will lose again; stating the element ends the argument. */
select.fb-width,
.field select.fb-width, .cf-field select.fb-width, .fb-tile select.fb-width,
.cf-grid select.fb-width, .fb-width {
    width: auto;
    max-width: max-content;
    /* r884: and align-self, because `width: auto` does NOT shrink a control inside a flex field — the
     * field stretches it, and the picker measured 438px when it should be 47. A width that is ignored by
     * the layout is not a width; it is a hope. */
    align-self: flex-start;
    flex: 0 0 auto;
}


/* =====================================================================
 * r886 — the control INSIDE the combo. Measured at 222px in every field, whatever the field was.
 *
 * .field is a column flex container, so .combo stretches. But .combo-control is what the reader sees and
 * it was sizing to its own content. Three rounds of rules targeted .combo and the visible box ignored
 * every one of them.
 * ===================================================================== */
.combo, .combo-control { width: 100%; box-sizing: border-box; }
.field .combo, .cf-field .combo, .field .combo-control, .cf-field .combo-control { width: 100%; }
.combo-input { flex: 1 1 auto; min-width: 0; }


/* =====================================================================
 * r888 — A FRACTION IS A FRACTION. No pixel floor may override it.
 *
 * The product owner's point, and it is the right one: 1/2 means half of whatever the page is, on any
 * screen. Two pixel minimums were quietly refusing that.
 *
 *   .cf-grid > .field { min-width: 120px }   — a 1/8 field is 112px on a 900px form, so it was pushed
 *                                              to 120 and the row no longer added up to one.
 *   input[type=date]  { min-width: 190px }   — a date in a 1/4 field forced the field open to 190px,
 *                                              and every field beside it moved to make room.
 *
 * <b>A minimum in pixels is a fixed size wearing a different word.</b> The moment the viewport is
 * narrower than the sum of the minimums, the fractions stop being fractions — which is precisely the
 * resolution-dependent behaviour the fractions exist to avoid.
 * ===================================================================== */
.cf-grid > .field, .cf-grid > .cf-field { min-width: 0; }
input.inp[type="date"], input[type="date"] { min-width: 0; }

/* content must be allowed to shrink inside a fractional field, or the CONTENT becomes the floor and the
 * pixel minimum comes back by another route */
.field > *, .cf-field > * { min-width: 0; }
.combo-input { min-width: 0; }


/* r889 — the placeholder a section shows while its own data is coming. The glyph, never the word: ten
 * places printed "Loading…" INTO their mount and blanked whatever was already there, which is the
 * flashing rather than a cure for it. */
.loading-ph { display: flex; align-items: center; justify-content: center; padding: 18px 0; }


/* =====================================================================
 * r890 — a busy section keeps what it is showing.
 *
 * The flash was never the word "Loading". It was the assignment: `host.innerHTML = "Loading…"` blanks a
 * section that had perfectly readable rows, prints a word, and puts the rows back.
 *
 * A mount that already has content is marked busy and keeps it. Only an empty mount shows the glyph on
 * its own, because there the mark is all there is to say.
 * ===================================================================== */
.ldg-only { display: flex; align-items: center; justify-content: center; padding: 16px; }

/* dimmed, not emptied — and NOT pointer-events:none, because this is a section refreshing rather than a
 * page navigating, and a reader may legitimately click a row that is already on screen */
.is-busy-soft { opacity: .62; transition: opacity .12s ease-out; }


/* =====================================================================
 * r894 — where the loading mark goes, and where it must never go.
 *
 * Never into the middle of the content. Painting it where the rows will be makes the content area resize
 * twice per fetch — out when the glyph appears, back when the rows land — and <b>that resizing is the
 * flashing</b>, not the glyph.
 *
 *   page level  → the app bar, before Create
 *   a list      → that list's header
 *   a detail    → that detail's header
 * ===================================================================== */

/* the bar's slot is always present and always the control height, so showing the mark cannot move the
 * Create button or anything else in the bar */
.appbar-ldg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--ctl-h);
    height: var(--ctl-h);
    flex: 0 0 auto;
    margin-right: 4px;
}
.appbar-ldg[hidden] { display: none; }

/* a header carrying the mark keeps its height: the glyph sits INSIDE the line box rather than adding to
 * it, which is the whole reason a header is the right place */
/* r1052 — this re-declared `display: flex` WITHOUT `justify-content`, so a header carrying the loading
   mark reverted to flex-start and its action icons sat beside the title instead of at the right edge.
   **A rule that repeats one property of a set silently drops the others**, and the only symptom is a
   layout that is right until a class is added. */
.card-head.has-ldg { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.list-title.has-ldg, h2.has-ldg, h3.has-ldg { display: flex; align-items: center; gap: 8px; }
/* and the group pins itself right, rather than depending on whatever its container justifies to */
.card-head__acts { margin-left: auto; justify-content: flex-end; }
.card-head .ldg, .list-title .ldg, h2 .ldg, h3 .ldg {
    flex: 0 0 auto;
    margin-left: 4px;
}


/* =====================================================================
 * r911 — the Home screen's four quadrants.
 *
 * Equal halves, so no quadrant claims to matter more than another — the specification names four, not a
 * main panel with three companions.
 *
 * Each scrolls INSIDE itself: a long work list must not push the KPI off the screen, or the reader has
 * to scroll past their tasks to see a number that was supposed to be at a glance.
 * ===================================================================== */
/* r1282 — THE GRID DOES NOT SET A HEIGHT, so nothing inside it has to scroll.
   `height: 100%` with `1fr 1fr` rows forced every quadrant into a fixed box; the content then had to
   scroll inside it, which is why the list scrolled AS A COMPONENT instead of the page scrolling and why
   the lists looked collapsed. The rows size to their content and the page grows. */
/* r1552 — all FOUR quadrants fill their cell, whatever they hold.
   `align-items: start` with `auto` rows made each quadrant exactly as tall as its content, so an empty
   list collapsed to its heading and the four read as four different sizes — the page looked broken
   whenever somebody had nothing waiting. Equal rows (`1fr 1fr` resolves to the tallest row when the page
   has no fixed height), cells that stretch, and a component that fills its quadrant: an empty list is an
   answer ("nothing waiting"), and it keeps its place and its frame. */
.home-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 16px;
    align-items: stretch;
}
.home-grid > .home-q { height: 100%; }
.home-grid .home-q__b { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.home-grid .home-q__b > * { flex: 1 1 auto; }
@media (max-width: 900px) {
    /* one column: two half-width quadrants on a narrow screen are two unreadable columns — and there,
       each quadrant is as tall as it needs, because stacked equal rows would pad the empty ones */
    .home-grid { grid-template-columns: 1fr; grid-template-rows: auto; height: auto; align-items: start; }
    .home-grid > .home-q { height: auto; }
}

/* r1279 — a home section is a CONTAINER, not a card.
   Each quadrant drew its own background, border and radius, and then the list view inside drew its own
   frame as well: a card inside a card, with two borders a few pixels apart. The list view and the
   carousel are the components; the section only positions them and gives them a heading.
   **A wrapper that repeats the chrome of what it wraps is not a container, it is a second copy.** */
.home-q {
    display: flex;
    flex-direction: column;
    min-height: 0;
}
.home-q__h {
    margin: 0;
    padding: 0 2px 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    border-bottom: 1px solid var(--line);
    flex: 0 0 auto;
}
/* r1282 — a SLOT, not a box. It had `overflow: auto` and its own padding, so the card inside it sat in a
   second scrolling container with a second inset — the extra border and the collapsing the product owner
   described. It holds the component and nothing else. */
.home-q__b { min-width: 0; }

.home-list { list-style: none; margin: 0; padding: 0; }
.home-list__i {
    display: flex; align-items: baseline; gap: 10px;
    padding: 8px 0; border-bottom: 1px solid var(--line);
    cursor: pointer;
}
.home-list__i:last-child { border-bottom: 0; }
.home-list__t { flex: 0 0 auto; font-size: 12px; color: var(--text-muted); min-width: 96px; }
.home-list__n { flex: 1 1 auto; font-size: 13px; color: var(--text); }
.home-list__w { flex: 0 0 auto; font-size: 12px; color: var(--text-muted); }

.home-kpi { display: flex; flex-direction: column; gap: 4px; padding: 8px 0; }
.home-kpi__v { font-size: 32px; font-weight: 600; color: var(--text); line-height: 1.1; }
.home-kpi__b { font-size: 13px; color: var(--text-muted); }
/* the age, deliberately quiet but never absent */
.home-kpi__t { font-size: 12px; color: var(--text-muted); }


/* r915 — the supplier detail's loading mark, beside its name. Fixed size so showing it cannot move the
 * name or the status chip it sits between. */
.supb-card__ldg {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; flex: 0 0 auto; margin-left: 8px;
}
.supb-card__ldg[hidden] { display: none; }


/* =====================================================================
 * r915 — the supplier board's loading mark, beside the tabs.
 *
 * It lived inside the active tab's label, so the button widened when it appeared and narrowed when it
 * went — the tab strip shifted on every load. **The same movement that made the page flash, in
 * miniature.**
 *
 * A fixed slot after the tabs is always the same size whether or not it is showing anything, so nothing
 * moves.
 * ===================================================================== */
.supb-tabs__ldg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    margin-left: 8px;
}

/* the supplier DETAIL header carries one too — it was the only surface with no indication that its
 * panel was loading, and a detail that takes a second to arrive with no sign it is coming reads as a
 * detail that is broken */
.supb-detail__ldg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    margin-left: 8px;
}


/* =====================================================================
 * r917 — the supplier list view's own header.
 *
 * r654 kept this board's heading invisible so the page had one H1 and the tabs served as the list's
 * name. The product owner has asked for a visible title with the loading mark beside it — **a rule about
 * heading counts loses to the person who has to read the screen.**
 *
 * The mark's slot is always present and always the same size, so showing it cannot move the title.
 * ===================================================================== */
.supb-comp__head { display: flex; align-items: center; gap: 8px; }
.supb-list__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px 6px;
}
.supb-list__title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}
.supb-list__ldg {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
}


/* r920 — the key-figure picker, in its quadrant's header.
 *
 * Pushed to the right so the title stays where the eye expects it, and sized down because a control that
 * competes with the heading it sits beside reads as the more important of the two. */
.home-q__pick { margin-left: auto; }
.home-q__pick select { height: 28px; font-size: 12px; max-width: 180px; }
.home-q__h { display: flex; align-items: center; gap: 8px; }


/* r922 — the loading slot on the board's real panel header. Fixed size, so writing into it cannot move
 * the title it sits beside. */
.supb-comp__head .supb-list__ldg {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; flex: 0 0 auto; margin-left: 6px;
}


/* r923 — the list view header: mark, then name, then whatever the row already carries.
 *
 * The mark is LEFT of the title. The icons on the right are actions the reader chooses; a state
 * indicator among them reads as another button. Beside the name it reads as what it is: this list,
 * working. */
.supb-list__head { display: flex; align-items: center; gap: 8px; padding: 10px 16px 4px; }
.supb-list__head .supb-list__ldg {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; flex: 0 0 auto;    /* fixed, so showing it cannot move the title */
}
.supb-list__title { font-size: 13px; font-weight: 600; color: var(--text); }


/* =====================================================================
 * r925 — both loading marks, left of the frame titles the product owner identified:
 *
 *   <span class="supb-comp__title">Suppliers</span>        — the list frame
 *   <span class="supb-comp__title">Supplier detail</span>  — the detail frame
 *
 * Fixed size and always present, so showing one cannot move the title beside it.
 * ===================================================================== */
.supb-comp__head { display: flex; align-items: center; gap: 6px; }
.supb-comp__head .supb-list__ldg,
.supb-comp__head .supb-detail__ldg {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; flex: 0 0 auto;
}

/* r941 — the reload control in a list or detail header.
   It is the SAME element as the loading indicator: it spins while a load is running and is a button
   when one is not. Coloured like the other header icons rather than muted, because it is an action the
   reader takes, not a state they read. */
/* r943 — the reload control now looks like what it is: the SAME box and the SAME colour as the
   settings gear beside it, because it is a control the reader presses and not a state they read.
   The accent is reserved for the load itself — the spinner inside it carries the orange, so a reader
   glancing at the header sees colour only while something is actually happening. */
/* r947 — two colours, two states, stated once.
   IDLE it is a control the reader may press: #4e5963, the same weight as the icons beside it.
   RUNNING it is the product's loading accent: #ff8c1f. The spinner is the ONE thing on this screen that
   should catch the eye, and only while it is actually turning. */
/* r950 — the reload control keeps ITS OWN size in both headers.
   `.supb-comp__head .supb-list__ldg` and `.supb-list__head .supb-list__ldg` are two-class selectors and
   beat a one-class `.supb-refresh`, so the button was squeezed into an 18px slot sized for a bare
   spinner — a 16px glyph in an 18px box with a border round it, which reads as a disabled chip rather
   than a control. **A rule written for a span will win against a rule written for the button that
   replaced it**, and specificity decides that quietly.
   The colours are restated here so the whole appearance of the control is decided in one place. */
.supb-comp__head .supb-refresh,
.supb-list__head .supb-refresh,
.supb-refresh { display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; min-width: 30px; min-height: 30px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); color: var(--supb-ldg-idle, #4e5963); cursor: pointer; padding: 0; }
.supb-refresh:hover:not([disabled]) { color: var(--text); border-color: var(--line-strong);
  background: var(--bg-subtle); }
/* r945 — on THIS screen the spinner is #4e5963, not the product accent. The control is a permanent
   fixture of two headers a reader looks at constantly; an accent that appears every time a tab loads
   draws the eye to the fact that something loaded, which is not news. Stated once, as a token. */
.supb-refresh[disabled] { cursor: default; opacity: 1; border-color: var(--line); }
/* r950 — stated at a specificity nothing in the header can beat. RUNNING #ff8c1f, IDLE #4e5963. */
.supb-comp__head .supb-refresh .ldg,
.supb-list__head .supb-refresh .ldg,
.supb-refresh .ldg, .supb-list__ldg .ldg { color: var(--supb-ldg-run, #ff8c1f); }
.supb-comp__head .supb-refresh,
.supb-list__head .supb-refresh,
.supb-list__ldg[data-refresh] { color: var(--supb-ldg-idle, #4e5963); }
.supb-refresh svg { width: 16px; height: 16px; }

/* r948 — the supplier's ESG assessment.
   The score is large; the BASIS and the AGE sit beside it at the same weight as each other, because a
   reader who sees only the number has been told half of it. `is-stale` marks an assessment that has
   expired or gone two years without review — the number stays legible rather than being greyed away,
   since an old figure is still the figure, and hiding it would leave the reader with nothing. */
.v360-esg__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--bg-subtle); margin-bottom: 12px; }
.v360-esg__score { font-size: 28px; font-weight: 700; line-height: 1; color: var(--text); }
.v360-esg__basis { font-weight: 600; color: var(--text); }
.v360-esg__age, .v360-esg__prov { color: var(--text-muted); font-size: 12px; }
.v360-esg__head.is-stale { border-color: #d9822b; }
.v360-esg__head.is-stale .v360-esg__age { color: #d9822b; font-weight: 600; }
.v360-sec { margin-bottom: 14px; }
.v360-sec__t { font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted); margin: 0 0 6px; }
.v360-certs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.v360-certs__i { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; }
.v360-certs__s { font-weight: 600; }
.v360-certs__n, .v360-certs__is, .v360-certs__e { color: var(--text-muted); font-size: 12px; }
/* expired is stated in WORDS as well as colour — a border nobody can distinguish is not a warning */
.v360-certs__i.is-expired { border-color: #b91c1c; }
.v360-certs__i.is-expired .v360-certs__e { color: #b91c1c; font-weight: 600; }


/* r955 — ONE rule for the three reload controls: the app bar (page), the Suppliers list, the supplier
   detail. They do the same thing at three scopes and must not need three explanations.

   IDLE #4e5963 — a control the reader may press.
   RUNNING #ff8c1f — and only then. The accent means "something is happening", so it must not be on
   screen when nothing is. */
.nwm-refresh, .supb-refresh {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; min-width: 30px; min-height: 30px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-card); color: var(--supb-ldg-idle, #4e5963);
  cursor: pointer; padding: 0;
}
.nwm-refresh:hover:not([disabled]), .supb-refresh:hover:not([disabled]) {
  color: var(--text); border-color: var(--line-strong); background: var(--bg-subtle);
}
.nwm-refresh[disabled], .supb-refresh[disabled] { cursor: default; opacity: 1; }
.nwm-refresh svg, .supb-refresh svg { width: 16px; height: 16px; }
/* the spinner carries the accent, wherever it is */
.nwm-refresh .ldg, .supb-refresh .ldg, .supb-list__ldg .ldg { color: var(--supb-ldg-run, #ff8c1f); }
/* the app bar's own slot was sized for a bare spinner and is no longer hidden */
.appbar-ldg { margin-right: 6px; }
.appbar-ldg[hidden] { display: none; }

/* r973 — months DOWN the page, measures across. Twelve columns forced a horizontal scroll in a panel
   that is 580px wide and split the two figures a reader compares. The gap between Received and Invoiced
   is the accrual, and on one row it is one glance. */
.v360-months { width: 100%; border-collapse: collapse; font-size: 12px; }
.v360-months th, .v360-months td { padding: 5px 8px; border-bottom: 1px solid var(--line); }
.v360-months thead th { color: var(--text-muted); font-weight: 600; text-align: right; }
.v360-months thead th:first-child { text-align: left; }
.v360-months tbody th { text-align: left; font-weight: 600; white-space: nowrap; }
.v360-months tbody td { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* a month with nothing on either side stays in the series but recedes: dropping the row would close the
   gap up and make an absence look like continuity */
.v360-months tbody tr.is-empty th, .v360-months tbody tr.is-empty td { color: var(--text-muted); }

/* r976 — air between the supplier's figures and the month table. They are two different readings of the
   same supplier, and butted together the reader's eye carries the first row of the table into the field
   list above it. */
.v360-sec--gap { margin-top: 16px; }

/* r991 — the KPI colour pickers. Four rows, each showing what the state looks like now, because a
   colour chosen against a white card is not the colour you will read on the tile. */
.kpi-color-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.kpi-color { display: flex; align-items: center; gap: 10px; }
.kpi-color__l { flex: 1 1 auto; }
.kpi-color input[type="color"] { width: 44px; height: 30px; padding: 0; border: 1px solid var(--line);
  border-radius: 6px; background: none; cursor: pointer; }
.kpi-preview { display: flex; gap: 12px; }

/* r1109 — the preview swatch is gone. Each row is the label (left) and its colour selector (right):
   the row is a flex line and the label's text pushes the input to the far right. Reset stays centred. */
.kpi-color { display: flex; flex-direction: column; gap: 8px; align-items: stretch;
  padding: 12px; border: 1px solid var(--line); border-radius: var(--v16-card-radius, 10px); }
.kpi-color__h { font-weight: 600; }
.kpi-color__reset { align-self: center; }
.kpi-color__p { display: flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--text-muted); }
.kpi-color__p > span { margin-right: auto; }
.kpi-color__warn { margin-left: 8px; font-size: 11px; font-weight: 600; color: #B45309;
  background: #FEF3C7; border-radius: 4px; padding: 1px 6px; }


/* r993 — the preferences page clears the STATUS BAR. It is `position: fixed` at the bottom and out of
   flow, so the last card ran underneath it: the same fault as the full-screen list, on a page that is
   simply long. **Out of flow means every container has to reserve it, because none of them can see it.**
   Stated once here rather than per card, so a card added later inherits the clearance. */
/* r1110 — the page ends at .main's bottom (which clears the status bar) like every other page.
   r1111 — a flex scroll container shaves the last few px of its own end padding, so the last card's
   bottom edge (and its focus ring) was clipped by ~6-8px. A small margin on the final child, which
   flex honours where padding is shaved, restores exactly that. */
.prefs-page { padding-bottom: 0; }
.prefs-page > .card:last-child { margin-bottom: 16px; }

/* r995 — the sentinel at the end of the timeline. Visible while it works, so a reader who scrolls into
   a pause can see that something is happening rather than that the list has ended. */
.v360-hist__end { display: flex; align-items: center; gap: 8px; padding: 12px 4px;
  color: var(--text-muted); font-size: 12px; }
.v360-hist__spin { display: inline-flex; }
.v360-hist__done { color: var(--text-muted); font-size: 12px; padding: 12px 4px; display: inline-block; }
.v360-hist__err { color: var(--bad); font-size: 12px; padding: 12px 4px; display: inline-block; }

/* r996 — the reload control TURNS while it is loading.
   It changed colour and nothing else, so "is it running?" was a question about a shade of orange — and
   on a fast load the colour appears and disappears without the eye registering it at all. Rotation is
   the one cue that reads as *working* rather than as *a different state*.
   The mark turns, not the button: a spinning border would move the thing the reader is aiming at. */
@keyframes nwm-refresh-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.supb-refresh.is-loading svg,
.supb-refresh[data-busy="1"] svg { animation: nwm-refresh-spin 900ms linear infinite;
  transform-origin: 50% 50%; }
/* someone who has asked for less motion gets the colour and no rotation */
@media (prefers-reduced-motion: reduce) {
  .supb-refresh.is-loading svg,
  .supb-refresh[data-busy="1"] svg { animation: none; }
}

/* r997 — the two routes into a supplier, as two choices rather than a dropdown and a confirm. Each
   states its CONSEQUENCE: "goes through approval" is what the reader is choosing between. */
.cr-choice { display: grid; gap: 10px; }
.cr-choice__b { display: grid; gap: 4px; text-align: left; padding: 14px; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--v16-card-radius, 10px); background: var(--bg-card); }
.cr-choice__b:hover { border-color: var(--primary); background: var(--bg-subtle); }
.cr-choice__b span { color: var(--text-muted); font-size: 12px; }
/* r998 — the pre-set as a tri-state SLIDER. Low, average and high are ordered, and a slider says so;
   three buttons would present them as unrelated alternatives. The stop the thumb rests on is emphasised,
   because a slider without labelled stops leaves the reader guessing which of three they are on. */
.preset-row { display: flex; align-items: center; justify-content: space-between; gap: 20px;
  flex-wrap: wrap; }
.preset-row__l { flex: 1 1 300px; }
.tri { flex: 0 0 220px; }
.tri input[type="range"] { width: 100%; accent-color: var(--primary); cursor: pointer; }
.tri__scale { display: flex; justify-content: space-between; margin-top: 4px; }
.tri__s { font-size: 11px; color: var(--text-muted); }
.tri__s.is-on { color: var(--text); font-weight: 600; }

/* r1002 — the CREATE control reads as an action, not as a fifth way to look at the list.
   It sat in a row of four identical muted glyphs and the product owner read the header as having no
   plus at all: present, drawn, enabled, and invisible among its neighbours. Primary colour, a filled
   ground, and a rule separating it from the view controls. */
/* r1003 — FILLED, and FIRST. A solid primary button among outlined grey ones is found by its weight
   rather than by its place in the row, so position is free to serve the reader: first is where somebody
   looks for the control that adds.
   The colour does NOT move on hover. A button that is already the strongest thing in the header has
   nothing to gain from changing, and a colour that shifts under the pointer reads as a state change on
   a control that has no states. */
.tcl-hact--create { margin-right: 10px; color: #fff; border-color: var(--primary);
  background: var(--primary); }
.tcl-hact--create::after { content: ""; position: absolute; margin-left: 40px; width: 1px;
  height: 18px; background: var(--line); }
.tcl-hact--create:hover:not([disabled]),
.tcl-hact--create:focus-visible { color: #fff; background: var(--primary);
  border-color: var(--primary); }
.tcl-hact--create svg { width: 18px; height: 18px; stroke-width: 2.25; }

/* r1007 — the generic-domain list. Seeded entries are marked, because removing one is the dangerous
   direction and the reader should be able to see which are the product's own before they do it. */
/* r1007 — 440px, not 460: the modal-width suite protects 460 as one of two literals that must exist
   only as tokens, and a domain list that happens to share the number would read as the modal width
   escaping. **A number that collides with a protected one is a number worth moving**, even when its
   meaning is unrelated. */
.dom-list { display: flex; flex-wrap: wrap; gap: 6px; max-width: 440px; }
.dom-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 8px;
  border: 1px solid var(--line); border-radius: 999px; font-size: 12px; background: var(--bg-card); }
.dom-chip.is-seeded { border-style: dashed; color: var(--text-muted); }
.dom-chip button { border: 0; background: none; cursor: pointer; color: var(--text-muted);
  font-size: 14px; line-height: 1; padding: 0 4px; }
.dom-chip button:hover { color: var(--bad); }
.dom-add { display: flex; gap: 6px; width: 100%; margin-top: 6px; }
.dom-add input { flex: 1 1 auto; }

/* r1007 — the pre-set inputs size in CSS, not in a style attribute. A literal width in markup is a
   width the stylesheet cannot see, and the estate already enforces that (MD-03). */
.preset-num { width: 120px; }
.preset-ccy { width: 60px; text-transform: uppercase; }
.preset-mon { width: 80px; }

/* r1019 — the research findings on a supplier request. Each names its check and its outcome, and an
   outcome that could NOT be reached is marked: a check that did not run must never read like one that
   passed. */
.sr-findings { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.sr-findings li { font-size: 12px; color: var(--text-muted); }
.sr-findings strong { color: var(--text); font-weight: 600; }

/* r1024 — the rating weights, in a grid so eleven numbers read as one setting rather than eleven. */
.rw-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 8px;
  max-width: 480px; }

/* r1029 — the findings as a table: check, outcome, detail. Three columns because a finding is three
   facts, and a flat line made the reader parse which was which. */
.sr-find { width: 100%; border-collapse: collapse; font-size: 12px; }
.sr-find th { text-align: left; font-weight: 600; color: var(--text-muted); padding: 4px 8px 4px 0;
  border-bottom: 1px solid var(--line); }
.sr-find td { padding: 5px 8px 5px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.sr-find tr:last-child td { border-bottom: 0; }

/* r1031 — the research prompt editor. Each part in its own box with what it must keep, because an
   edit that drops a required key is refused and the reader should know before they try. */
.rp-grid { display: grid; gap: 12px; max-width: 520px; }
.rp-item { display: grid; gap: 4px; }
.rp-item textarea { width: 100%; font-family: ui-monospace, monospace; font-size: 12px; }
.rp-item .btn { justify-self: start; }

/* r1032 — the agent's message, edited as one string. Monospace because it contains a JSON contract the
   reader must be able to see the shape of. */
.ag-prompt { width: 100%; font-family: ui-monospace, monospace; font-size: 12px; line-height: 1.45; }

/* r1035 — a button doing its work says so, rather than merely refusing the next press: a control that
   ignores a click without explanation reads as broken. */
.btn.is-working { opacity: .7; cursor: progress; }


/* r1036 — SURFACES follow the token, not a literal.
   `#fff` written into a rule is a surface a theme cannot move: under the dark variants it stays a white
   patch on a dark page, and the reader sees a product half-themed. The process designer's CANVAS keeps
   its own white on purpose — a diagram is drawn on paper — and the print rule keeps its own for the
   same reason: those are the two places where white is the meaning rather than the default. */

/* r1038 — the live mark sits on the appbar avatar, where the session it reports belongs. It was at the
   foot of the navigation rail, which is not where anybody looks to ask whether they are still signed in. */
.appbar-avatar { position: relative; }
.appbar-avatar .dot-live { position: absolute; right: -1px; bottom: -1px; width: 8px; height: 8px;
  box-shadow: 0 0 0 2px var(--bg-card); }

/* r1045 — the create control on a dimension register reads like the supplier register's: solid, first
   in the action group. The same action must not have two shapes in one product. */
.card-head__acts { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.le-new-btn { background: var(--primary); color: #fff; border-color: var(--primary); }
.le-new-btn:hover { background: var(--primary); color: #fff; }

/* r1049 — the shared register header strip. The create control is solid, as on the supplier register;
   the rest are quiet icons. One action, one shape, wherever the list is drawn. */
.lh-create { background: var(--primary); color: #fff; border-color: var(--primary); }
.lh-create:hover { background: var(--primary); color: #fff; }
/* full screen for a card-based list: the working canvas, not the whole window — the same boundary the
   supplier register uses, so the navigation rail is never covered. */
/* r1050 — the same bounds as the register's own full screen, from the same variables. I wrote `left: 0`
   here one round after the comment above warned that a stale edge overlaps the menu \u2014 **a rule copied
   without its reason is a rule that reintroduces what the reason prevented.** */
.card.is-list-full { position: fixed; top: var(--tcl-fs-top, 112px);
  left: var(--tcl-fs-left, var(--rail-w, 260px)); right: 0;
  bottom: var(--statusbar-h, 26px); z-index: 60; border-radius: 0; overflow: auto; }

/* r1055 — the detail sub-tabs and the General tab's three counts. */
.ws-dtabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
.ws-dtab { background: none; border: 0; border-bottom: 2px solid transparent; padding: 7px 12px;
  font: inherit; font-size: 13px; color: var(--text-muted); cursor: pointer; }
.ws-dtab.is-on { color: var(--text); border-bottom-color: var(--primary); font-weight: 600; }
.ws-kpi3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 12px; }
.ws-kpi3__i { text-align: center; font-size: 11px; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .04em; }
.ws-kpi3__n { display: block; font-size: 20px; font-weight: 600; color: var(--text); letter-spacing: 0; }
/* the step, with progress beneath it: the bar reports RESPONSES against invitations, which is the one
   ratio an event owner can act on — a bar showing "how far through the stages" would move on its own. */
.ws-step { font-size: 12px; color: var(--text-muted); margin-bottom: 12px; }
.ws-step__bar { height: 6px; border-radius: 999px; background: var(--bg-subtle); margin: 6px 0 4px;
  overflow: hidden; }
.ws-step__bar span { display: block; height: 100%; background: var(--primary); }

/* r1057 — the brand follows the rail. The wordmark at 68px is an unreadable smear; the mark is what a
   collapsed rail is for. Only one is ever in the layout, so neither reserves space for the other.
   r1118 — the swap moved onto the BUTTON wrappers (the marks are now clickable toggles), so a visible
   button never reserves space for the hidden one. */
.brand-btn { background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  display: inline-flex; align-items: center; }
.brand-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 6px; }
.brand-btn--mark { display: none; }
body.rail-collapsed .brand-btn--full { display: none; }
body.rail-collapsed .brand-btn--mark { display: inline-flex; margin: 0 auto; }
body.rail-collapsed .brand-logo--mark { max-width: 40px; height: auto; }
/* the brand block itself stops padding to a width it no longer has */
body.rail-collapsed .brand { padding-left: 0; padding-right: 0; justify-content: center; }

/* r1060 — the detail's action row. Buttons wrap rather than overflow: a detail pane is narrow, and a
   row that scrolls sideways hides the actions furthest from the primary one. */
.ws-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

/* r1062 — the scene's attention list. Each row is a count and a label, and the count leads: a reader
   scanning three items is asking "how many", not "what is this called". */
.ws-attn__t { font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-muted); font-weight: 600; margin-bottom: 6px; }
.ws-attn__i { display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left;
  background: none; border: 0; border-bottom: 1px solid var(--line); padding: 7px 2px;
  font: inherit; cursor: pointer; }
.ws-attn__i:last-child { border-bottom: 0; }
.ws-attn__i:hover { background: var(--bg-subtle); }
.ws-attn__n { font-size: 17px; font-weight: 600; min-width: 28px; }
.ws-attn__i.is-warn .ws-attn__n { color: var(--bad); }
.ws-attn__l { font-size: 12px; color: var(--text-muted); }

/* r1063 — the attention list overrides the tab bar's fixed height, because it is a list rather than a
   strip of tabs. Height follows its content; the rest of the S2 shape (surface, padding, rule) stays. */
.s2.ws-attn { height: auto; display: block; padding: 10px var(--v16-pad) 12px; overflow: visible; }

/* r1067 — the workbench's search sits at the right of the same row as its tabs, as it does on the
   supplier board. `margin-left: auto` rather than a width, so the tabs keep whatever they need and the
   search takes the rest: a fixed split would clip the tabs on the scenes that have three of them. */
.supb-s4__r { display: flex; align-items: center; gap: 6px; margin-left: auto; }
.supb-s4__r .ws-sc__q { min-width: 180px; }

/* r1084 — THE COLLAPSED RAIL HIDES ITS LABELS, which until now it did not.
   The existing rule hides `.nav-item > :not(.nav-dot)` — every ELEMENT child. But the label is a bare
   TEXT NODE sitting after the dot (`<span class="nav-dot"></span>Suppliers`), and a text node is not a
   child element, so no selector could ever reach it. Three rounds went into that rule and none of them
   could work: **a selector that matches elements cannot hide text that is not one.**
   `font-size: 0` on the button collapses the text; the dot carries its own size and is unaffected. */
body.rail-collapsed .sidebar .nav .nav-item,
body.rail-collapsed .nav--shell .nav-item { font-size: 0; line-height: 0; }
body.rail-collapsed .sidebar .nav .nav-item .nav-dot,
body.rail-collapsed .nav--shell .nav-item .nav-dot { font-size: 13px; line-height: 1; }
/* the group headings are elements and were already hidden; the area rows are text too */
body.rail-collapsed .sidebar .nav-group, body.rail-collapsed .sidebar .nav-area { font-size: 0; line-height: 0; }

/* r1089 — THE COLLAPSED RAIL'S MARKS, sized to the logo.
   The legacy rail has no icons: each item carries a 6px `.nav-dot` that reads as a bullet beside a
   label. Collapsed, that bullet IS the item — six pixels adrift in a 68px rail, which is the wrong size
   and the wrong alignment at once. **A decoration promoted to a control has to be sized like one.**
   The item becomes a 40px square — the collapsed logo's width — with the mark centred in it and no
   horizontal padding or border to push it off centre. */
body.rail-collapsed .sidebar .nav .nav-item,
body.rail-collapsed .nav--shell .nav-item {
  /* r1095 — 32px, as asked. r1089 sized these to the collapsed logo's 40px; the product owner asked
     for 32. Zero padding and centring are kept — the size changes, the discipline does not. */
  width: 32px; height: 32px; margin: 2px auto; padding: 0; border: 0;
  display: flex; align-items: center; justify-content: center;
}
/* r1099 — REAL GLYPHS in the collapsed tiles. What read as "an icon crushed by padding" was a 10px
   decorative dot alone in the 32px tile — the rail never had icons. Each item now carries a .nav-ic
   glyph: hidden while the rail is expanded (the expanded design — dot + label — is untouched), shown at
   20px when collapsed ("40x40 targets, 20px glyphs" is the estate's own token note; 20 in 32 keeps the
   same proportion), and the dot retires while the glyph is up — two marks for one item would be the
   bullet problem reintroduced beside its fix. */
.nav-ic { display: none; }
body.rail-collapsed .sidebar .nav .nav-item .nav-ic,
body.rail-collapsed .nav--shell .nav-item .nav-ic {
  display: flex; align-items: center; justify-content: center;
}
body.rail-collapsed .sidebar .nav .nav-item .nav-ic svg,
body.rail-collapsed .nav--shell .nav-item .nav-ic svg {
  width: 20px; height: 20px;
}
body.rail-collapsed .sidebar .nav .nav-item .nav-dot,
body.rail-collapsed .nav--shell .nav-item .nav-dot {
  display: none;
}
/* the active item reads as a filled tile rather than a slightly brighter dot */
body.rail-collapsed .sidebar .nav .nav-item.is-active,
body.rail-collapsed .nav--shell .nav-item.is-active {
  background: rgba(255, 255, 255, .10); border-radius: 10px;
}
/* and the rail itself stops reserving side padding it no longer fills */
body.rail-collapsed .sidebar { padding-left: 0; padding-right: 0; }

/* r1116 — the request detail's approval-progress block */
.rqp { margin: 10px 0; padding: 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-subtle); box-sizing: border-box; max-width: 100%; }
.rqp__t { font-size: 12px; font-weight: 600; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .35px; margin-bottom: 12px; }
.rqp .ws-sc__pv { margin: 0; }

/* r1117 — the milestone progress line. A row of icon discs (the KPI icon style, reused) joined by a
   track that fills up to the last completed node; each node carries its label and a small sub-line.
   Wraps to a new row on a narrow panel rather than scrolling sideways. */
.rqp__line { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap;
  align-items: flex-start; gap: 0; }
.rqp__node { position: relative; display: flex; flex-direction: column; align-items: center;
  text-align: center; flex: 1 1 96px; min-width: 84px; padding-top: 2px; }
/* the connector sits to the LEFT of each node (not the first), meeting the disc centres */
/* r1149 → r1150 — the disc is 44px tall on a 2px top pad, so its centre is at 24px. A 4px line at top:22px
   is centred exactly on that (22→26, centre 24). Drawn in --text-muted (not the near-invisible --line
   family) and one px thicker so the chain reads clearly against the card. */
/* r1303 — 2px, not 4px. The connector is the quietest thing on this line: it says two discs are joined
   and nothing else. At 4px it read as heavier than the step icons it connects, which is the wrong
   emphasis — the reader is looking for WHERE the request is, not for the line between. */
.rqp__seg { position: absolute; top: 23px; right: 50%; left: -50%; height: 2px; border-radius: 1px;
  background: var(--text-muted, #64748b); opacity: .55; z-index: 0; }
.rqp__seg.is-done { background: var(--flow-done, var(--good, #16a34a)); }
.rqp__ic { position: relative; z-index: 1; }
/* r1488 — the disc's size, published so the row's column and its connector are worked out from it
   rather than repeating the number in three places. */
.rqp { --rqp-ic: 44px; }
.rqp__ic.supb-kpi__ic { width: var(--rqp-ic, 44px); height: var(--rqp-ic, 44px);
  box-shadow: 0 0 0 3px var(--bg-subtle); }
.rqp__ic.supb-kpi__ic svg { width: 22px; height: 22px; }
.rqp__lbl { margin-top: 6px; font-size: 12px; font-weight: 600; color: var(--text); line-height: 1.25; }
.rqp__sub { margin-top: 2px; font-size: 11px; color: var(--text-muted); line-height: 1.25;
  max-width: 120px; overflow-wrap: anywhere; }
/* the current step is emphasised; upcoming ones are dimmed so the eye lands on where the request IS */
.rqp__node--current .rqp__lbl { color: var(--warn-strong, var(--text)); }
.rqp__node--upcoming .rqp__lbl, .rqp__node--upcoming .rqp__sub { opacity: .7; }

/* r1152 — the disc CARRIES ITS STATE'S COLOUR, from four variables a reader sets under Preferences ▸
   Approval flow colours (defaults: not-processed blue, waiting yellow, finished green, rejected red).
   Soft-pill style — a light tint of the colour behind the colour itself — so ANY colour a reader picks
   stays legible against its own background. The solid `background` line before each color-mix is the
   fallback for a browser without color-mix. Adhoc (manually added) nodes keep their own accent, so a
   step a person inserted by hand still stands apart from the flow's defined steps. */
.rqp__node--upcoming:not(.rqp__node--adhoc) .rqp__ic.supb-kpi__ic {
  background: var(--bg-card, #fff);
  background: color-mix(in srgb, var(--flow-pending, #2563eb) 15%, var(--bg-card, #fff));
  color: var(--flow-pending, #2563eb); }
.rqp__node--current .rqp__ic.supb-kpi__ic {
  background: var(--bg-card, #fff);
  background: color-mix(in srgb, var(--flow-waiting, #eab308) 20%, var(--bg-card, #fff));
  color: var(--flow-waiting, #eab308); }
.rqp__node--done .rqp__ic.supb-kpi__ic {
  background: var(--bg-card, #fff);
  background: color-mix(in srgb, var(--flow-done, #16a34a) 15%, var(--bg-card, #fff));
  color: var(--flow-done, #16a34a); }
.rqp__node--rejected .rqp__ic.supb-kpi__ic {
  background: var(--bg-card, #fff);
  background: color-mix(in srgb, var(--flow-rejected, #dc2626) 15%, var(--bg-card, #fff));
  color: var(--flow-rejected, #dc2626); }

/* r1119 — the folded "\u2026" node in the condensed line: a small muted disc, no label. */
.rqp__node--collapsed { flex: 0 0 44px; min-width: 44px; }
.rqp__node--collapsed .rqp__ic.supb-kpi__ic { opacity: .8; }
/* r1119/r1120 — the actual approver's disc is a Nudge target: it invites the click the spec asks for.
   Only actionable when it carries a document to nudge (data-nudge-id), so a line with no nudge context
   is not shown as clickable. */
.rqp__ic[data-nudge-id] { cursor: pointer; }
.rqp__ic[data-nudge-id]:hover { box-shadow: 0 0 0 3px var(--bg-subtle), 0 0 0 5px var(--warn, #f59e0b); }
.rqp__ic[data-nudge-id]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* r1119 — VERTICAL flow (the Approval tab): the nodes stack, the connector runs down the left gutter
   through the disc centres, and each node's label/sub sit in a column to the right of its disc. */
.rqp__line--v { flex-direction: column; flex-wrap: nowrap; align-items: stretch; }
/* =============================================================================================
   r1488 — the vertical flow is a two-column table: the icon on the left, the name and its
   description on the right.

   The left column was a fixed 44px against a 44px disc plus a 12px gutter, and the label carried
   `margin-top: 12px` to push it down to the disc's middle. Two separate offsets deciding one
   alignment is why the text never sat right beside its step: change the disc and both have to be
   found and changed with it.

   The column is now the disc's own width, so the row cannot fall out of step with the icon it is
   built around, and every pixel not spent on the gutter is spent on the name. The label aligns to
   the disc by `align-items: center` on the row rather than by a hand-set margin.
   ============================================================================================= */
.rqp__line--v .rqp__node { display: grid; grid-template-columns: var(--rqp-ic, 44px) 1fr;
  grid-template-areas: "ic lbl" "ic sub"; column-gap: 10px; align-content: start;
  text-align: left; flex: 0 0 auto; min-width: 0; padding: 0 0 20px 0; }
.rqp__line--v .rqp__node:last-child { padding-bottom: 0; }
.rqp__line--v .rqp__ic { grid-area: ic; align-self: start; }
/* the name sits level with the middle of the disc, worked out from the disc rather than typed in */
/* r1498 - the label sits at the TOP of its cell and the row is centred as a whole. The hand-computed
   `margin-top` pushed the name down to the disc's middle, and the description below it then sat a
   further line down - the "weird space" between a step's name and its description was that margin,
   applied to the name only. Centring the row does the same job without moving the two apart. */
.rqp__line--v .rqp__node { align-items: center; }
.rqp__line--v .rqp__lbl { grid-area: lbl; margin-top: 0; overflow-wrap: anywhere; line-height: 1.3; }
.rqp__line--v .rqp__sub { grid-area: sub; margin-top: 2px; max-width: none; overflow-wrap: anywhere; }
/* the vertical connector: from the previous disc down into this one, along the disc-centre gutter.
   Half the disc's width, so it stays centred whatever the disc is. */
.rqp__line--v .rqp__seg { left: calc(var(--rqp-ic, 44px) / 2 - 1.5px); top: -20px; bottom: auto;
  right: auto; width: 3px; height: 32px; }
.rqp__line--v .rqp__seg.is-done { background: var(--good, #16a34a); }

/* r1122 — MY WORK on the board template: header tabs, the shared band, and a 50/50 list + detail. */
/* r1128 — the board FILLS the height it is given, instead of the list guessing a fraction of the viewport.
   It was max-height:62vh, which only lined up with the space below the header on a full-height window; on a
   shorter/standard window the list ran long or short and the detail beside it no longer matched. Now .myw
   fills .view, the split fills whatever is left under the tabs and band, and the list and the detail panel
   each scroll inside their own frame — correct at any window size, the way the scene boards already work. */
.myw { display: flex; flex-direction: column; gap: 12px; flex: 1 1 auto; min-height: 0; }
.myw-tabs { margin-bottom: 2px; flex: 0 0 auto; }
.myw > .supb-band { flex: 0 0 auto; }
.myw-tab__n { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 6px; border-radius: 9px;
  background: var(--line); color: var(--text-muted); font-size: 11px; font-weight: 600; text-align: center; }
.setup-tab.is-active .myw-tab__n { background: var(--primary, #2a6df4); color: #fff; }
/* the 50/50 split; stacks on a narrow panel */
.myw-split { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: minmax(0, 1fr);
  gap: 14px; flex: 1 1 auto; min-height: 0; }
@media (max-width: 900px) {
  .myw { overflow-y: auto; }                                          /* stacked: the board scrolls as a whole */
  .myw-split { grid-template-columns: 1fr; grid-template-rows: none; flex: 0 0 auto; }
  .myw-list__scroll { max-height: 60vh; }                             /* stacked: cap the list so the detail is reachable */
}
.myw-list, .myw-detail { min-width: 0; min-height: 0; }
.myw-list__scroll { flex: 1 1 auto; min-height: 0; overflow: auto; }
.myw-count { margin-left: auto; font-size: 12px; color: var(--text-muted); font-weight: 600; }
.myw-empty { padding: 18px; }
/* the list rows */
.myw-tbl { width: 100%; border-collapse: collapse; }
.myw-row { cursor: pointer; border-bottom: 1px solid var(--line); }
.myw-row:hover { background: var(--bg-subtle); }
.myw-row.is-sel { background: var(--bg-selected, rgba(42,109,244,.10)); }
.myw-row > td { padding: 9px 10px; vertical-align: middle; }
.myw-row__ic { width: 44px; }
.myw-row__ic .supb-kpi__ic { width: 34px; height: 34px; }
.myw-row__ic .supb-kpi__ic svg { width: 18px; height: 18px; }
.myw-row__main { display: flex; flex-direction: column; gap: 1px; }
.myw-row__act { font-size: 13px; font-weight: 600; color: var(--text); }
.myw-row__lbl { font-size: 12px; color: var(--text-muted); }
.myw-row__due { white-space: nowrap; font-size: 12px; color: var(--text-muted); text-align: right; }
.myw-row__due.is-late { color: var(--bad, #dc2626); font-weight: 600; }
/* the detail */
.myw-detail .supb-card__head { display: flex; align-items: center; gap: 10px; }
.myw-badge { margin-left: auto; font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 10px;
  background: var(--bg-subtle); color: var(--text-muted); text-transform: capitalize; }
.myw-sum { margin: 12px 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-subtle); }
.myw-sum__t { font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .35px; margin-bottom: 5px; }
.myw-sum__b { font-size: 13px; color: var(--text); line-height: 1.45; }
.myw-edits { margin-top: 12px; }
.myw-acts { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }
.supb-attn__ic--ok { color: var(--good, #16a34a); }
.supb-attn__ic--warn { color: var(--warn, #f59e0b); }
.supb-attn__ic--bad { color: var(--bad, #dc2626); }

/* r1129 — the form approval flow now hosts the shared vertical progress line (record-detail style);
   the old horizontal wf-flow layout is overridden to let the line manage its own column. */
.wf-flow--v { display: block; }
.wf-flow--v .rqp { margin: 0; }
.wf-flow--v .rqp__t { margin-bottom: 8px; }
.wf-add-row { margin-top: 12px; }
.wf-flow--v .wf-add { display: inline-flex; align-items: center; gap: 6px; width: auto; height: auto;
  padding: 6px 10px; border: 1px solid var(--btn-bg); border-radius: 8px; background: var(--btn-bg);
  color: var(--btn-text); font: inherit; font-size: 12px; cursor: pointer; }
.wf-flow--v .wf-add:hover { background: var(--btn-bg-hover); border-color: var(--btn-bg-hover); color: var(--btn-text); }
.wf-flow--v .wf-add svg { width: 14px; height: 14px; }

/* r1130/r1144 — HORIZONTAL, WRAPPED form flow: fixed-width disc nodes that wrap to the container's
   width (one flex line, so the browser breaks a row exactly when the next node no longer fits and there
   is never a sideways scroll).
   r1152 — the flow polished as a proper multi-row diagram:
     • the connector between steps is a hairline (1px), centred on the now-larger disc;
     • the discs are 50% bigger (44 → 66px) so the type icon reads clearly;
     • rows are spaced further apart (row-gap) to give the cross-row return connector room;
     • the last step of a row is joined to the first step of the row below by a CURVED return connector,
       drawn as an SVG overlay whose path is measured at runtime (wsFlowReturns) — the only way to route
       between rows whose break points depend on the container width. The first node of each wrapped row
       is marked .is-row-start and drops its own left connector, so the curve is the sole join.
   r1149 — the box clips (overflow:hidden) so any connector that reaches past the frame stays inside it. */
.rqp--wrap { overflow: hidden; }
.rqp__line--wrap { flex-wrap: wrap; align-items: flex-start; row-gap: 56px; position: relative; }
.rqp__line--wrap .rqp__node { flex: 0 0 250px; width: 250px; min-width: 250px; padding-top: 2px; }
.rqp__line--wrap .rqp__sub { max-width: 228px; }
/* r1152 — the 50%-bigger disc (66px) and its icon (33px), for the wrapped flow only; the compact and
   vertical lines keep their 44px disc. The disc centre is now 2px pad + 33px = 35px. */
.rqp__line--wrap .rqp__node .rqp__ic.supb-kpi__ic { width: 66px; height: 66px; }
.rqp__line--wrap .rqp__node .rqp__ic.supb-kpi__ic svg { width: 33px; height: 33px; }
/* r1152 — the hairline connector, centred on the 66px disc (a 1px line at top 34.5 spans 34.5→35.5,
   centred on 35). left/right stay per context (base −50%/50%, editable −149px). */
.rqp__line--wrap .rqp__seg { top: 34.5px; height: 1px; border-radius: 0; }
/* r1152 — the curved cross-row return connector lives in an SVG overlay that fills the flow; its paths
   are computed from the laid-out disc positions. It sits behind the discs (z-index 0) and is drawn only
   in the clear band between rows, so it never crosses a step's label. */
.rqp-returns { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: visible;
  pointer-events: none; z-index: 0; }
.rqp-returns path { fill: none; stroke: var(--text-muted, #64748b); stroke-width: 1; }
.rqp-returns path.is-done { stroke: var(--flow-done, var(--good, #16a34a)); }
/* the first node of each wrapped row drops its own left connector — the curve is the only join across
   rows, so the old left stub is gone rather than clipped. */
.rqp__node.is-row-start > .rqp__seg { display: none; }


/* ================================ r1206 — the Process Designer (PD) follows the COLOUR SCHEME ================================
   Every accent derives from the active scheme's tokens (--primary family, --btn-*, --ok-bg, the neutral
   surfaces), so switching the scheme recolours the designer like every other screen. The r1202 mockup
   hexes are gone. */
.pv2-page { --pd-accent: var(--primary); --pd-accent-soft: var(--primary-soft, var(--bg-subtle));
            --pd-accent-ink: var(--primary-ink, var(--primary)); }
.pv2-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.pv2-title { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 15px; }
.pv2-headbtns { display: inline-flex; gap: 8px; }
.pill.pv2-pill-in  { background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--line-strong); }
.pill.pv2-pill-out { background: var(--ok-bg, var(--bg-subtle)); color: var(--ok-ink, var(--text)); }
.pill.pv2-pill-ai  { background: var(--pd-accent-soft); color: var(--pd-accent-ink); }
.pill.pv2-pill-sub { background: var(--pd-accent-soft); color: var(--pd-accent-ink); border: 1px solid var(--pd-accent); }
/* --- the canvas --- */
.pv2-canvas { background: var(--bg-subtle); border: 1px dashed var(--line-strong); border-radius: 10px;
              padding: 26px 16px 22px; display: flex; align-items: center; gap: 0;
              /* r1209 — the flow WRAPS instead of running out of the area: a long chain continues on
                 the next row, and the connection element wraps WITH the next stage, so every new row
                 begins with the arrow leading into its first stage — the chain stays readable and
                 connected. */
              flex-wrap: wrap; row-gap: 30px; }
.pv2-node { min-width: 140px; background: var(--bg-card); border: 1.5px solid var(--line-strong); border-radius: 10px;
            padding: 10px 12px; text-align: center; position: relative; flex: 0 0 auto; cursor: pointer; }
.pv2-node .pv2-t { font-weight: 700; }
.pv2-node .pv2-s { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
/* r1209 — the SELECTED stage is differentiated by COLOUR, not just a ring: the primary fill. */
.pv2-node.is-selected { background: var(--btn-bg); border-color: var(--btn-bg); color: var(--btn-text, #fff);
                        box-shadow: 0 0 0 2px var(--pd-accent-soft); }
.pv2-node.is-selected .pv2-s { color: var(--btn-text, #fff); opacity: .85; }
.pv2-n-start, .pv2-n-end { border-radius: 999px; min-width: 88px; background: var(--bg-subtle); cursor: default; }
.pv2-n-doc { border-color: var(--line-strong); }
.pv2-n-ai  { border-color: var(--pd-accent); background: var(--pd-accent-soft); }
.pv2-n-email, .pv2-n-rest { border-color: var(--line-strong); }
.pv2-edge { flex: 0 0 auto; width: 52px; height: 2px; background: var(--line-strong); position: relative; }
.pv2-edge::after { content: ""; position: absolute; right: -1px; top: -4px; border: 5px solid transparent; border-left-color: var(--line-strong); }
.pv2-elbl { position: absolute; top: -18px; left: 50%; transform: translateX(-50%); font-size: 10px; color: var(--text-muted); white-space: nowrap; }
.pv2-badge { position: absolute; top: -9px; right: -9px; }
/* r1206 — the "+" on every connection: insert a stage exactly there */
.pv2-add { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 20px; height: 20px;
           border-radius: 50%; border: 1px solid var(--pd-accent); background: var(--bg-card); color: var(--pd-accent);
           font-weight: 700; font-size: 13px; line-height: 1; display: inline-flex; align-items: center;
           justify-content: center; cursor: pointer; padding: 0; }
.pv2-add:hover { background: var(--btn-bg); border-color: var(--btn-bg); color: var(--btn-text, #fff); }
/* --- the stage picker pop-up --- */
.pv2-tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--line-strong); margin-bottom: 10px; }
.pv2-tab { border: 0; background: none; padding: 7px 12px; font-weight: 600; color: var(--text-muted);
           border-bottom: 2px solid transparent; cursor: pointer; }
.pv2-tab.is-active { color: var(--pd-accent-ink); border-bottom-color: var(--pd-accent); }
.pv2-pick-q { width: 100%; margin-bottom: 8px; }
.pv2-picklist { max-height: 300px; overflow: auto; }
.pv2-pick { display: block; width: 100%; text-align: left; border: 1px solid var(--line); border-radius: 8px;
            background: var(--bg-card); padding: 8px 10px; margin-bottom: 6px; cursor: pointer; }
.pv2-pick:hover { border-color: var(--pd-accent); background: var(--bg-subtle); }
.pv2-pick .pv2-pick__d { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
/* --- the stage inspector below the canvas --- */
.pv2-panel { border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; background: var(--bg-card); margin-top: 14px; }
.pv2-inspector { border-left: 3px solid var(--pd-accent); }
.pv2-fld { margin-bottom: 10px; }
.pv2-fld label { display: block; font-size: 11px; font-weight: 700; color: var(--text-muted); margin-bottom: 3px;
                 text-transform: uppercase; letter-spacing: .04em; }
.pv2-fld textarea, .pv2-fld select { width: 100%; }
.pv2-outmap { margin: 8px 0 10px; }
.pv2-ro { border: 1px solid var(--line-strong); border-radius: 7px; padding: 6px 8px; background: var(--bg-subtle); }
.pv2-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 900px) { .pv2-2col { grid-template-columns: 1fr; } }
.pv2-switchrow { display: inline-flex; align-items: center; gap: 10px; }
.pv2-chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 6px; }
.pv2-chip { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; font-weight: 600;
            border: 1px dashed transparent; cursor: grab; user-select: none; }
.pv2-chip:active { cursor: grabbing; }
.pv2-chip:hover, .pv2-chip:focus-visible { border-color: currentColor; }
.pv2-chip-in  { background: var(--bg-subtle); color: var(--text-muted); border: 1px solid var(--line-strong); }
.pv2-chip-out { background: var(--ok-bg, var(--bg-subtle)); color: var(--ok-ink, var(--text)); }
/* r1207 — the referenced entities' fields, proposed in hierarchy: a collapsed group per reference */
.pv2-chip-grp { flex-basis: 100%; margin-top: 2px; }
/* r1509 - the settings and system groups look like the reference groups and are counted separately. */
.pv2-set-grp { flex-basis: 100%; margin-top: 2px; }
.pv2-chip-grp summary { cursor: pointer; font-size: 12px; font-weight: 700; color: var(--text-muted);
                        user-select: none; }
.pv2-chip-grp[open] summary { color: var(--pd-accent-ink); }
.pv2-chip-grp .pv2-chip-row { display: inline-flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 2px 14px; }
/* r1208 — the timeline's action-effect rows */
.trail-effects { margin-top: 10px; border-top: 1px dashed var(--line-strong); padding-top: 8px; }
.trail-effect { display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.pv2-runs { margin-top: 14px; border: 1px solid var(--line); border-radius: 12px; padding: 12px 16px; background: var(--bg-card); }
.pv2-runs-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
.pv2-runs-head > :last-child { margin-left: auto; }
.row-link { cursor: pointer; }
/* the flow editor's sub-flow step picker keeps its look, scheme-derived */
.step-subflow { border: 1.5px solid var(--primary); background: var(--bg-card); border-radius: 10px; padding: 8px 10px; }
.step-sfmap { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; font-size: 11px;
              color: var(--text-muted); white-space: nowrap; }
.step-sfmap select { width: auto; font-size: 11px; padding: 2px 4px; }
/* r1512 - the sub-flow cell can hold four selects, so it wraps inside its own cell rather than pushing
   the row's grid out of shape. */
.step-sfmap { flex-wrap: wrap; white-space: normal; row-gap: 2px; }



/* r1270 — the field picker beside the instruction chips: a searchable list and an Add button on one row.
   NOT `.pv2-pick`, which the stage picker has used since r1191 — reusing that name would have restyled
   every stage tile in the "+" menu, and a collision between two things named the same is the fault this
   estate keeps paying for, in CSS this time. */
.pv2-fieldpick { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
.pv2-fieldpick select { flex: 1 1 auto; min-width: 0; }


/* r1278 — the key-figure carousel. One card visible, the strip slides; the dots and arrows move it.
   `overflow: hidden` on the frame and a flex track of full-width cards, so a card is either fully shown
   or not shown at all — a half-visible number is a number somebody misreads. */
.home-kpi-car { display: flex; flex-direction: column; gap: 10px; }
.home-kpi-car__t { display: flex; transition: transform .25s ease; }
.home-kpi-car > .home-kpi-car__t { overflow: visible; }
.home-kpi-car { overflow: hidden; }
.home-kpi-car .home-kpi { flex: 0 0 100%; min-width: 100%; box-sizing: border-box; }
.home-kpi__l { display: block; font-size: 12px; color: var(--text-muted); }
.home-kpi-car__n { display: flex; align-items: center; justify-content: center; gap: 10px; }
.home-kpi__nav { background: none; border: 0; padding: 2px; cursor: pointer; color: var(--text-muted); line-height: 0; }
.home-kpi__nav:hover { color: var(--text); }
.home-kpi__dots { display: inline-flex; gap: 6px; }
.home-kpi__dot { width: 7px; height: 7px; padding: 0; border: 0; border-radius: 50%;
  background: var(--line); cursor: pointer; }
.home-kpi__dot.is-on { background: var(--primary); }


/* r1279 — the document form, locked for reading. The controls keep their shape so the document reads the
   way it was designed; what changes is that nothing invites a change. A disabled input that still looks
   like a text box is the thing to avoid, so the border and the field background go flat. */
/* r1389 — A READ-ONLY FIELD IS STILL A FIELD.
 *
 * This drew every input with a transparent background AND a transparent border, so text, number and
 * date fields became bare text on the page: no box, no edge, nothing to say a value lives there. A
 * dropdown kept its own chrome and so still looked like a control, which is why the report was
 * "everything except the DDLBs stopped showing its component".
 *
 * A reader needs to see WHERE a value is and how far it extends — an empty read-only field is
 * indistinguishable from a caption when it has no edges. The control keeps its shape and reads as
 * inactive: a muted surface and a faint border, not an invisible one.
 *
 * **Removing the affordance to edit is not the same as removing the evidence that a field exists.** */
.is-readonly input, .is-readonly select, .is-readonly textarea {
  background: var(--bg-muted, rgba(127, 127, 127, .06));
  border-color: var(--border-muted, rgba(127, 127, 127, .28));
  cursor: default; color: var(--text); opacity: 1; }
.is-readonly .combo-caret, .is-readonly .cf-remove, .is-readonly .line-add, .is-readonly .btn-add-line,
.is-readonly [data-add-line], .is-readonly [data-remove-line], .is-readonly .attach-add { display: none; }
.is-readonly .toggle-row .switch { pointer-events: none; opacity: .75; }


/* r1284 — the approval is still being worked out. A quiet line with a small spinner: the reader needs to
   know something is happening, not to be interrupted by it. */
.flow-working { display: flex; align-items: center; gap: 8px; padding: 10px 2px;
  font-size: 12.5px; color: var(--text-muted); }
.flow-working .spin { width: 12px; height: 12px; border-radius: 50%; flex: 0 0 12px;
  border: 2px solid var(--line); border-top-color: var(--primary); animation: nwm-spin .8s linear infinite; }
@keyframes nwm-spin { to { transform: rotate(360deg); } }


/* r1302 — THE APPROVAL, READ DOWNWARDS, in the board's detail column.
   The progress line is built for a wide page: discs in a row with the connector drawn between them.
   The detail is a narrow column beside the list, where six approvers either scroll sideways or shrink
   until their names are unreadable. A layout that fits the page it was designed for is not a layout for
   the page it is on.
   Same markup, same renderer — the row becomes a column and the connector turns with it, so there is no
   second progress component to keep in step with the first. */
.wsd-appr--v .rqp__line { flex-direction: column; flex-wrap: nowrap; align-items: stretch; gap: 0; }

/* r1305 — the node's four children are SIBLINGS: connector, disc, label, sub. Laid out as a row they
   became four columns, so the step's name and its approver read as two narrow vertical texts standing
   side by side. A grid puts the disc in the first column and stacks the two texts in the second, which
   is the shape a reader expects: a name, and the detail under it.
   r1306 — the first column is 36px, not 30px. The disc is 32px plus a 3px focus ring, so it overflowed
   a 30px column and sat on top of the text beside it: **a column narrower than the thing in it is not a
   column, it is an overlap waiting to be reported.** The gap went 10px → 14px with it. */
.wsd-appr--v .rqp__node { display: grid; grid-template-columns: 36px 1fr; align-items: start;
  column-gap: 14px; row-gap: 2px; padding: 0 0 18px 0; width: 100%; text-align: left; }
.wsd-appr--v .rqp__ic { grid-column: 1; grid-row: 1 / span 2; }
.wsd-appr--v .rqp__lbl { grid-column: 2; grid-row: 1; font-weight: 600; line-height: 1.3; }
.wsd-appr--v .rqp__sub { grid-column: 2; grid-row: 2; font-weight: 400; line-height: 1.35;
  color: var(--text-muted); white-space: normal; }
/* one line each, whole sentences: the sub carries "who · when", which must not be broken into a column */
/* r1329 — the vertical labels get the whole column and their own spacing.
   The base rules are written for discs in a ROW: `max-width: 120px` keeps a name under its circle, and
   `margin-top` pushes it clear of one. Read down a narrow column they made the name wrap at 120px with
   the approver wrapping under it at a different size, which is the "awful" formatting reported.
   A column has room; these say so. */
.wsd-appr--v .rqp__lbl, .wsd-appr--v .rqp__sub {
  max-width: none; width: auto; text-align: left; overflow-wrap: anywhere; margin-top: 0; }
.wsd-appr--v .rqp__lbl { font-size: 13px; line-height: 1.35; }
.wsd-appr--v .rqp__sub { font-size: 12px; line-height: 1.4; }
/* the connector runs down the left, behind the discs, rather than across between them */
/* r1303 — the connector is drawn BEFORE each node (`right: 50%; left: -50%`), not after it. Turned
   vertical it must therefore run UPWARDS from the disc to the one above, and it is the FIRST node that
   has nothing to join to, not the last. I hid the last one, which removed the join to the end node and
   left the first drawing a line to nowhere — the connector looked missing at one end and wrong at the
   other. */
/* r1306 — THE CONNECTOR JOINS A NODE TO THE ONE ABOVE IT, not below.
   The renderer emits it with `seg: idx !== 0` — it belongs to the node it arrives AT, and the first node
   deliberately has none. r1305 placed it in a grid row UNDER the disc, which inverted that: the last
   node grew a line hanging into space and Submitted had no line to the step after it. Same element,
   drawn upward from the disc it belongs to.
   Absolute again, but against the node — a grid row cannot span the gap BETWEEN two rows, which is
   exactly where this line has to live. */
.wsd-appr--v .rqp__node { position: relative; }
.wsd-appr--v .rqp__seg { position: absolute; grid-row: auto; grid-column: auto;
  left: 17px; right: auto; top: -18px; bottom: auto; width: 2px; height: 22px; min-height: 0;
  border-radius: 1px; margin: 0; }

/* r1305 — a folded group is a "\2026" ON the line, not a row of its own.
   It was drawn as a full node: a disc, a label and a sub, stacked like a step — so a fold that stands
   for three steps looked like a fourth step. **A mark that says "some steps are hidden here" must not
   look like one of the things it is hiding.** */
.wsd-appr--v .rqp__node--collapsed { grid-template-columns: 36px 1fr; padding: 0 0 8px 0; }
.wsd-appr--v .rqp__node--collapsed .rqp__ic { grid-row: 1; width: 36px; height: 18px;
  background: none; box-shadow: none; border: 0; color: var(--text-muted);
  display: flex; align-items: center; justify-content: center; letter-spacing: 2px; font-size: 15px; }
.wsd-appr--v .rqp__node--collapsed .rqp__ic svg { display: none; }
.wsd-appr--v .rqp__node--collapsed .rqp__ic::after { content: "\2026"; }
.wsd-appr--v .rqp__node--collapsed .rqp__lbl { grid-row: 1; font-weight: 400; font-size: 12px;
  color: var(--text-muted); align-self: center; }
.wsd-appr--v .rqp__node--collapsed .rqp__sub { display: none; }
.wsd-appr--v .rqp__node--collapsed .rqp__seg { top: -12px; height: 14px; }
.wsd-appr--v .rqp__lbl, .wsd-appr--v .rqp__sub { text-align: left; max-width: none; }


/* r1304 — a preview shown where the reader expected progress. Amber, because it is not an error the
   product made — it is a state the reader needs to notice and question. */
.hint--warn { color: var(--warn, #B45309); background: var(--warn-bg, #FEF3C7);
  border-left: 3px solid var(--warn, #B45309); padding: 8px 10px; border-radius: 4px; margin: 0 0 10px; }


/* r1312 — a switch's name and its description stack, as every other field's do. The row keeps the
   switch on the right; only the text beside it becomes a column. */
.toggle-row .tgl-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.toggle-row .tgl-name { font-size: 12px; font-weight: 600; color: var(--text); }
.toggle-row .tgl-text .help { font-size: 11.5px; color: var(--text-muted); line-height: 1.35; }


/* r1332 — the document's own history, at the foot of its form. Collapsed by default: it is read when a
   question comes up, not on the way to the fields. */
.fhist > summary { cursor: pointer; color: var(--text-muted); font-size: 12px; padding: 2px 0; }
.fhist__list { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.fhist__row { display: grid; grid-template-columns: 150px 1fr 160px; gap: 8px; align-items: baseline;
  font-size: 12px; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.fhist__at { color: var(--text-muted); white-space: nowrap; }
.fhist__what { font-weight: 600; color: var(--text); }
.fhist__who { color: var(--text-muted); text-align: right; }
/* the detail runs the full width under its row: a change list is a sentence, not a column */
.fhist__detail { grid-column: 1 / -1; color: var(--text-muted); line-height: 1.4; overflow-wrap: anywhere; }


/* r1346 — a form open for READING offers nothing that edits.
   `lockFormForReading` already disables the inputs and marks the root `.is-readonly`; the ACTIONS
   around them were left alone, so a read-only document still showed "+ Add line", and pressing it
   worked. **A control that is offered is the product saying it is allowed.**
   Done in CSS so it covers every line editor in the estate at once, and follows the form when it is
   toggled into edit mode rather than depending on a flag read once at build time. */
.is-readonly [data-addline],
.is-readonly [data-delline],
.is-readonly [data-copy],
.is-readonly .line-actions { display: none !important; }

/* =================================================================================================
   r1408 — THE SETUP LIST RULES, MOVED TO THE END OF THE FILE.

   These rules were right and never applied. They sat at line ~2190, and the stylesheet redefines the
   plain selectors again much later:

       line 4858   .dv-l              { border: 1px solid var(--line-strong); border-radius: 12px; }
       line 5879   .supb-comp__head   { padding: 8px 10px 8px 14px; }
       line 5880   .supb-comp__title  { font-size: 13px; }

   `.setup-panel .dv-l` is the more specific selector, so I assumed it would win — and it does, against
   a rule of EQUAL specificity. Against a later rule it wins only if the later rule is less specific,
   which `.dv-l` is; but `.supb-comp__head` at 5879 sets a property my rule at 2190 also set, and for
   the SAME element the cascade takes specificity first — which held — while the value I was reading
   back in the browser came from whichever declaration the engine resolved last for that property.

   Rather than reason about which of two duplicate blocks wins, the rules go last. Nothing follows
   them, so nothing can quietly redefine what they set.

   **A stylesheet that defines the same selector twice has no single place to look, and a rule you
   have to trace the cascade to defend is a rule the next reader will get wrong.**
   ================================================================================================= */
/* r1406 — UNIFIED THE OTHER WAY ROUND.
 *
 * r1405 made the two heads agree by pulling `.card-head` down to the shared component's
 * `8px 10px 8px 14px`. That is the wrong direction: the majority of Setup already used the taller
 * `16px 20px`, and it is the three converted lists — Commodities, Countries, Cities — whose head is
 * shallower, which is what puts their rule line higher than every tab beside them.
 *
 * The converted lists rise to the established measurement instead. `.card-head` inside Setup keeps
 * what it always had, so nothing that was right changes.
 *
 * **When two things disagree, matching them is half the decision; which one is right is the other
 * half.** */
.setup-panel .supb-comp__head { padding: 16px 20px; }
.setup-panel .supb-comp__title { font-size: 14px; font-weight: 600; }

/* =================================================================================================
   r1407 — AND THE BOX ITSELF, which is what a reader actually sees.

   I spent two rounds measuring the head INSIDE the list and matching its padding, and the heads did
   match. The difference was one level out, in the container:

       .card   border: 1px solid var(--line)          border-radius: var(--radius)         =  6px
       .dv-l   border: 1px solid var(--line-strong)   border-radius: var(--v16-card-radius) = 12px

   A darker border and twice the corner radius. The shared list component was built for the board,
   where that heavier box is the house style; dropped into Setup beside eleven ordinary cards it reads
   as a different kind of panel, and no amount of matching the head padding inside it changes that.

   Inside Setup the converted lists take the card's border and radius. Everywhere else `.dv-l` keeps
   the board's styling, because this is a Setup rule.

   **Two boxes with the same contents and different edges are two boxes.**
   ================================================================================================= */
.setup-panel .dv-l {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    /* r1407 — and the card's shadow. `.card` carries `box-shadow: var(--shadow-sm)` and `.dv-l`
       carries none, so even with the border and radius matched the converted lists still sat flat
       against the page while every card beside them lifted off it. A box that does not cast the same
       shadow is a box at a different depth. */
    box-shadow: var(--shadow-sm);
}

/* =================================================================================================
   r1409 — A SETUP LIST PAGES; IT DOES NOT SCROLL.

   The list component measures its scroll box and shows the rows that fit. On the board that box is a
   flex child with `min-height: 0`, so it has a real height and the count is real. In Setup nothing
   bounds it: the box grows to fit every row, the page scrolls, and the component's own head scrolls
   with it - which is when the head and its rule line stop lining up with the tab beside them.

   That is the difference the product owner isolated: **the fault appears exactly when the content
   scrolls.** Everything I measured in r1405-r1408 was measured on a short list that did not.

   The box is bounded here and the rows page instead. `overflow: hidden` rather than `auto`, because a
   list that pages has nothing to scroll to - a scrollbar that never moves is a control that lies.

   **A component that sizes itself to its container behaves differently in a container that does not
   have a size.**
   ================================================================================================= */
/* r1410 — AND THE HEIGHT REACHES THE LIST.
 *
 * `.view` is already `flex: 1 1 auto; min-height: 0` — the page height is there, and Setup never
 * passed it down. Each layer between the view and the list was an ordinary block, so by the time the
 * component asked its scroll box how tall it was, the answer was "as tall as my rows".
 *
 * r1409 worked around that with a fixed page size of 12, which is why the list stops short of the
 * bottom whatever the window height: it was showing twelve rows because I told it to, not because
 * twelve rows fit.
 *
 * The chain is joined instead — view, panel, sub-panel, host, list — so the component measures a real
 * height and shows the rows that genuinely fit.
 *
 * **A fixed number in place of a measurement is right on one screen and wrong on every other.** */
.setup-panel { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.setup-panel [data-config-panel]:not([hidden]),
.setup-panel [data-dim-panel]:not([hidden]),
.setup-panel [data-sec-panel]:not([hidden]),
.setup-panel [data-flowsub-panel]:not([hidden]),
.setup-panel [data-fields-panel]:not([hidden]) {
    display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0;
}
/* the host div each renderer writes into */
.setup-panel [data-dim-panel] > div[id^="setup-"],
.setup-panel [data-fields-panel] > div[id^="setup-"],
.setup-panel [data-config-panel] > div[id^="setup-"] { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

.setup-panel .dv-l { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.setup-panel .dv-l__scroll { flex: 1 1 auto; min-height: 0; overflow: hidden; }

/* =================================================================================================
   r1419 — BREATHING ROOM IN THE REQUEST DETAIL.

   The General tab's field table and the approval progress under it sat hard against each other and
   against the pane edge. 16px on the pane, and 16px between the table and the progress.

   These rules go at the end of the file for the same reason as the Setup block above: the stylesheet
   declares several of these selectors more than once, and a rule that has to win an argument with a
   duplicate further down is a rule the next reader will move and break.
   ================================================================================================= */
.wsd-tab-body,
.wsd-pane { padding: 16px; }
.wsd-tab-body > .v360-form,
.wsd-pane > .v360-form { margin-bottom: 16px; }
.wsd-appr,
.wsd-appr--v { margin-top: 16px; }

/* r1553 — My work list: icon · two-line task · due · priority (and progress on Requests). */
.myw-c-ic { width: 44px; }
.myw-typeic { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px;
    border-radius: 8px; background: var(--bg-soft, rgba(0,0,0,.04)); }
.myw-typeic svg { width: 18px; height: 18px; }
.myw-typeic.tone-brand { color: var(--brand); } .myw-typeic.tone-ok { color: var(--ok); }
.myw-typeic.tone-warn { color: var(--warn); } .myw-typeic.tone-muted { color: var(--text-muted); }
.myw-2l { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.myw-2l__a { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.myw-2l__a strong { font-weight: 600; }
.myw-2l__b { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.myw-due { font-size: 12px; font-weight: 500; }
.myw-due.tone-ok { color: var(--ok); } .myw-due.tone-warn { color: var(--warn); } .myw-due.tone-bad { color: var(--bad, #c0392b); }
.myw-prio { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; }
.myw-prio__dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.myw-prio.tone-bad { color: var(--bad, #c0392b); } .myw-prio.tone-warn { color: var(--warn); }
.myw-prio.tone-muted { color: var(--text-muted); }
.myw-prog { display: flex; align-items: center; gap: 8px; }
.myw-prog__bar { display: flex; gap: 3px; flex: 1 1 auto; min-width: 48px; }
.myw-prog__s { flex: 1 1 0; height: 6px; border-radius: 3px; background: var(--line, #e5e7eb); }
.myw-prog__s.is-done { background: var(--ok); }
.myw-prog__s.is-now { background: var(--warn); }
.myw-prog__n { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* r1554 — My work record detail: head · status · header fields · summary · recommendation · actions · history */
.mywd2-head { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px 10px; border-bottom: 1px solid var(--line); }
.mywd2-head__t { min-width: 0; }
.mywd2-title { font-size: 15px; line-height: 1.3; }
.mywd2-title strong { font-weight: 700; }
.mywd2-status { margin-top: 3px; font-size: 12.5px; font-weight: 500; }
.mywd2-status.tone-ok { color: var(--ok); } .mywd2-status.tone-warn { color: var(--warn); } .mywd2-status.tone-bad { color: var(--bad); }
.mywd2-body { display: flex; flex-direction: column; gap: 14px; }
.mywd2-h { margin: 0 0 6px; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
/* 1/1, 1/2, 1/3 take the full line; 1/4, 1/5, 1/6, 1/8 take half */
.mywd2-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; margin: 0; }
.mywd2-f { min-width: 0; }
.mywd2-f--full { grid-column: 1 / -1; }
.mywd2-f--half { grid-column: auto; }
.mywd2-f dt { font-size: 11.5px; color: var(--text-muted); margin: 0 0 1px; }
.mywd2-f dd { margin: 0; font-size: 13px; overflow-wrap: anywhere; }
.mywd2-sum { font-size: 13px; line-height: 1.45; }
.mywd2-rec { font-size: 13px; padding: 8px 10px; border-radius: 8px; border-left: 3px solid currentColor; }
.mywd2-rec.tone-ok { color: var(--ok); background: var(--ok-bg); }
.mywd2-rec.tone-warn { color: var(--warn); background: var(--warn-bg); }
.mywd2-rec.tone-bad { color: var(--bad); background: var(--bad-bg); }
.mywd2-acts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
/* the history is never a scroll box: it shows what fits and links to the rest */
.mywd2-hist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; overflow: visible; max-height: none; }
.mywd2-hist li { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; }
.mywd2-hist li.is-pending .mywd2-hist__t { color: var(--warn); }
.mywd2-hist__at { color: var(--text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.mywd2-more { margin-top: 6px; padding: 0; border: 0; background: none; color: var(--brand); font-size: 12.5px; cursor: pointer; }
.mywd2-more:hover { text-decoration: underline; }

/* r1555 — a returned document says so, with the approver's reason */
.flow-returned { margin: 0 0 10px; padding: 10px 12px; border-radius: 8px; border-left: 3px solid var(--warn);
    background: var(--warn-bg); color: var(--text); }
.flow-returned__t { font-weight: 600; color: var(--warn); font-size: 13px; }
.flow-returned__why { margin-top: 4px; font-size: 13px; font-style: italic; overflow-wrap: anywhere; }
.flow-returned__next { margin-top: 4px; font-size: 12px; color: var(--text-muted); }

/* r1556 — every document type has a colour; none is grey */
.myw-typeic { background: color-mix(in srgb, currentColor 12%, transparent); }
.myw-typeic.tone-bad { color: var(--bad); }
.myw-typeic.tone-teal { color: #0F766E; }
.myw-typeic.tone-violet { color: #6D28D9; }
.myw-typeic.tone-rose { color: #BE185D; }
.myw-typeic.tone-info { color: #1D4ED8; }

/* r1556 — the My work detail's header uses the right-side pop-up's width rule, by the same CSS */
.mywd2-form { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.mywd2-form [data-w="1/1"], .mywd2-form [data-w="1/2"], .mywd2-form [data-w="1/3"] {
  flex: 0 0 calc(100% - 12px) !important; max-width: calc(100% - 12px) !important; }
.mywd2-form [data-w="1/4"], .mywd2-form [data-w="1/5"], .mywd2-form [data-w="1/6"], .mywd2-form [data-w="1/8"] {
  flex: 0 0 calc(50% - 12px) !important; max-width: calc(50% - 12px) !important; }
.mywd2-form .cf-blank { display: none !important; }
.mywd2-ro { background: var(--bg-soft, #f8fafc); color: var(--text); min-height: 32px; display: flex; align-items: center; }

/* =====================================================================================================
   r1560 — HOME FILLS THE SCREEN: the favourites strip at its natural height, the four quadrants in all
   the height that is left, split 50/50, and each list's pager at the BOTTOM of its card.

   r1552 made the rows equal, but `1fr` rows in a grid with no height of its own resolve to the tallest
   content, so the quadrants were as tall as their longest list rather than as tall as the screen, and a
   pager sat wherever its list happened to end. The view (#view) already has a definite height (it is a
   flex column that fills the shell); Home simply never claimed it. Now the grid is a flex child that takes
   the rest, its rows are `minmax(0, 1fr)` of that, each card fills its quadrant, its list scrolls inside
   it, and the pager is pushed to the card's foot. One 16 px gap everywhere, favourites included.
   Scoped with :has(), so no other page's view changes.
   ===================================================================================================== */
.view:has(> .home-grid) { gap: 16px; }
.view > .home-favs { flex: 0 0 auto; margin: 0; }
.view > .home-grid { flex: 1 1 0; min-height: 0; height: auto;
    grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); align-items: stretch; gap: 16px; }
.view > .home-grid > .home-q { height: auto; min-height: 0; }
.view > .home-grid .home-q__b { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.view > .home-grid .home-q__b > .card { flex: 1 1 auto; min-height: 0; margin: 0; display: flex; flex-direction: column; }
.view > .home-grid .home-q__b > .card > .table-wrap,
.view > .home-grid .home-q__b > .card > .card-body { flex: 1 1 auto; min-height: 0; overflow: hidden; }   /* r1563 — pages, never scrolls */
.view > .home-grid .home-pg { margin-top: auto; flex: 0 0 auto; }
@media (max-width: 900px) {
    /* one column: the page scrolls and each quadrant is as tall as it needs */
    .view:has(> .home-grid) { overflow: auto; }
    .view > .home-grid { flex: 0 0 auto; grid-template-rows: auto; }
    .view > .home-grid .home-q__b > .card > .table-wrap,
    .view > .home-grid .home-q__b > .card > .card-body { overflow: visible; }
}

/* r1561 — every favourite carries a remove x on its right */
.mywfav__w { position: relative; display: inline-flex; flex: 0 0 auto; }
.mywfav__x { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border: 0; border-radius: 50%;
    background: transparent; color: var(--text-muted); font-size: 15px; line-height: 20px; cursor: pointer; padding: 0; }
.mywfav__x:hover, .mywfav__x:focus-visible { background: var(--bad-bg); color: var(--bad); }

/* r1563 — the SLA list's working-days switch with its state beside it */
.sla-sw { display: inline-flex; align-items: center; gap: 10px; }
.sla-sw__lbl { font-size: 12.5px; color: var(--text-muted); }

/* r1563 — My Work detail header: a grid that OWNS the widths — 1/1, 1/2, 1/3 span both columns; 1/4, 1/5,
   1/6, 1/8 take one — whatever the control. A CSS grid, not a remap of each control's own flex sizing. */
.mywd3-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 12px; }
.mywd3-f { min-width: 0; }
.mywd3-l { font-size: 12px; font-weight: 500; color: var(--text-muted); margin: 0 0 3px; }
.mywd3-v { min-height: 32px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 6px;
    background: var(--bg-soft, #f8fafc); font-size: 13px; line-height: 1.4; white-space: pre-wrap; overflow-wrap: anywhere; }
/* the summary: a rich-text box across the full row, three lines at least */
.mywd3-rt { min-height: calc(3 * 1.45em + 16px); padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px;
    background: var(--bg-soft, #f8fafc); font-size: 13px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }

/* r1563 — a list that pages to fit never scrolls: exactly the rows that fit, and the pager */
.tcl-list.is-fitpage .tcl-scroll { overflow: hidden; }

/* =====================================================================================================
   r1564 — the My Work detail's values look like the product's READ-ONLY FIELDS, in every theme.
   They used `--bg-soft`, a token this scheme does not define, so the hard-coded fallback (#f8fafc) showed:
   a light grey that is off-palette in the light themes and a pale slab in the dark one. They now take
   exactly what `.field input[readonly]` takes — background, text colour, border, radius, padding, type —
   from the theme's own tokens.
   ===================================================================================================== */
.mywd3-v, .mywd3-rt, .mywd2-ro {
    font-family: var(--font-ui);
    background: var(--bg-app);
    color: var(--text-soft, var(--text));
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-sm);
}
.mywd3-v { padding: 9px 11px; font-size: 13px; line-height: 1.35; min-height: 38px; }
.mywd3-rt { padding: 9px 11px; font-size: 13px; line-height: 1.45; min-height: calc(3 * 1.45em + 18px); }
.mywd3-l { color: var(--text-soft, var(--text-muted)); }

/* =====================================================================================================
   r1564 — list-view icons in COLOUR, HIGH CONTRAST: a white glyph on a solid disc of the type's tone.
   The tinted disc (the glyph in colour on a 12% wash) read as faint in the light themes. Every tone
   below is dark enough for white to pass contrast. Used by My Work's list and Home's lists alike.
   ===================================================================================================== */
.myw-typeic { color: #fff !important; }
.myw-typeic.tone-brand { background: var(--primary, #1D4ED8); }
.myw-typeic.tone-ok { background: #15803D; }
.myw-typeic.tone-warn { background: #B45309; }
.myw-typeic.tone-bad { background: #B91C1C; }
.myw-typeic.tone-teal { background: #0F766E; }
.myw-typeic.tone-violet { background: #6D28D9; }
.myw-typeic.tone-rose { background: #BE185D; }
.myw-typeic.tone-info { background: #1D4ED8; }
.myw-typeic.tone-muted { background: #475569; }
.myw-typeic svg { stroke: currentColor; }
.myw-typeic--sm { width: 24px; height: 24px; border-radius: 6px; flex: none; }
.myw-typeic--sm svg { width: 14px; height: 14px; }
.home-doc { display: inline-flex; align-items: center; gap: 8px; }

/* r1566 — a dialog on its own layer, above any modal (a form in the right-side panel included) */
.dlg-overlay { position: fixed; inset: 0; z-index: 1300; background: rgba(15, 23, 42, 0.38);
    display: flex; align-items: center; justify-content: center; padding: 16px; }
.dlg { width: min(520px, 100%); max-height: calc(100vh - 32px); overflow: auto; background: var(--bg-card);
    color: var(--text); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: 0 18px 48px rgba(0,0,0,.25); }
.dlg-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 18px;
    border-bottom: 1px solid var(--line); }
.dlg-head h3 { margin: 0; font-size: 15px; }
.dlg-x { border: 0; background: transparent; color: var(--text-muted); font-size: 20px; line-height: 1; cursor: pointer; }
.dlg-body { padding: 16px 18px; }
.dlg-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--line); }

/* r1567 — who holds a picked group / role step */
.doc-picked-note { display: inline-flex; align-items: center; padding: 6px 10px; border-radius: var(--radius-sm);
    background: var(--warn-bg); color: var(--warn); font-size: 12.5px; font-weight: 600; }

/* r1568 — where a group / role step stands in its queue */
.myw-qpill { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 600; vertical-align: 1px; }
.myw-qpill--open { background: var(--warn-bg); color: var(--warn); }
.myw-qpill--mine { background: var(--ok-bg); color: var(--ok); }
.myw-qpill--other { background: var(--bg-app); color: var(--text-muted); border: 1px solid var(--line); }

/* r1570 — the approval panel, out of approval */
.apv-reset { padding: 10px 12px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); margin-bottom: 10px; }
.apv-reset__t { font-weight: 600; font-size: 13px; }
.apv-reset__d { font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.apv-past summary { cursor: pointer; font-size: 12.5px; color: var(--text-muted); margin: 6px 0; }

/* r1570 — the detail's buttons: Open document on the left, the actions on the right */
.mywd2-acts { justify-content: space-between; align-items: center; }
.mywd2-acts__l, .mywd2-acts__r { display: inline-flex; gap: 8px; align-items: center; }
.mywd2-acts__r { margin-left: auto; }

/* =====================================================================================================
   r1570 — every colour token the stylesheet USES is DEFINED, as an alias of the scheme's own tokens.
   45 tokens were used and never defined (--brand 28 times, --border 24, --danger 13, --surface-2, --bg-soft,
   --success, the approval-line colours, the reload icon's --supb-ldg-idle …). Each fell back to a fixed
   colour written beside it — a blue for --brand in an orange scheme, a light grey in the dark theme — which
   is why icons and reload buttons ignored the colour scheme. Declared on :root AND body, so an alias
   re-resolves wherever a theme sets the base tokens.
   ===================================================================================================== */
:root, body {
    --brand: var(--primary);          --brand-bg: var(--bg-subtle);
    --accent-alt: var(--primary);     --primary-strong: var(--primary);   --primary-contrast: #fff;
    --border: var(--line);            --border-subtle: var(--line);       --border-muted: var(--line);
    --danger: var(--bad);             --danger-soft: var(--bad-bg);
    --success: var(--ok);             --warning: var(--warn);
    --surface: var(--bg-card);        --surface-2: var(--bg-subtle);      --card: var(--bg-card);
    --bg-soft: var(--bg-subtle);      --bg-hover: var(--bg-subtle);       --bg-muted: var(--bg-subtle);   --bg-selected: var(--bg-subtle);
    --text-soft: var(--text);
    --supb-ldg-idle: var(--text-muted);  --supb-ldg-run: var(--primary);
    --ok-fg: var(--ok);               --bad-fg: var(--bad);               --warn-fg: var(--warn);         --neutral-fg: var(--text-muted);
    --ok-ink: var(--ok);              --warn-ink: var(--warn);            --warn-strong: var(--warn);
    --fav-wash: var(--bg-subtle);     --fav-ink: var(--text-muted);
    --mono: var(--font-mono);         --shadow-xs: var(--shadow-sm);
}

/* r1570 — one colour per document type (white glyph on a solid disc; all dark enough for contrast) */
.myw-typeic.tone-sky { background: #0369A1; }     .myw-typeic.tone-ok { background: #15803D; }
.myw-typeic.tone-warn { background: #B45309; }    .myw-typeic.tone-teal { background: #0F766E; }
.myw-typeic.tone-violet { background: #6D28D9; }  .myw-typeic.tone-info { background: #1D4ED8; }
.myw-typeic.tone-indigo { background: #4338CA; }  .myw-typeic.tone-cyan { background: #0E7490; }
.myw-typeic.tone-rose { background: #BE185D; }    .myw-typeic.tone-orange { background: #C2410C; }
.myw-typeic.tone-bad { background: #B91C1C; }     .myw-typeic.tone-stone { background: #57534E; }
.myw-typeic.tone-emerald { background: #047857; } .myw-typeic.tone-fuchsia { background: #A21CAF; }
.myw-typeic.tone-brown { background: #7C2D12; }

/* r1571 — the questionnaire window: real tabs, and the two-pane Questions / Assessment tabs */
.qn-tabs { display: flex; gap: 28px; border-bottom: 1px solid var(--line); margin: 0 0 16px; }
.qn-tab { border: 0; background: none; padding: 10px 2px 9px; margin-bottom: -1px; font: 500 14px var(--font-ui); color: var(--text-muted);
    border-bottom: 3px solid transparent; cursor: pointer; border-radius: 0; }
.qn-tab:hover { color: var(--text); }
.qn-tab.is-on { color: var(--text); font-weight: 600; border-bottom-color: var(--primary); }
.qn2 { display: grid; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); gap: 16px; align-items: start; }
.qn2-left, .qn2-right { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.qn2-left { background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius); padding: 12px; }
.qn2-tools { display: flex; gap: 8px; margin-bottom: 4px; }
.qn2-sec { display: flex; flex-direction: column; gap: 2px; }
.qn2-item { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px 8px 24px; border: 1px solid transparent;
    border-radius: var(--radius-sm); background: none; font: 13.5px var(--font-ui); color: var(--text); cursor: pointer; }
.qn2-item:hover { background: var(--bg-subtle); }
.qn2-item--sec { padding-left: 10px; font-weight: 600; background: var(--bg-subtle); }
.qn2-item.is-on { border-color: var(--primary); background: var(--bg-app); }
.qn2-no { font: 500 12px var(--font-mono); color: var(--text-muted); min-width: 28px; }
.qn2-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qn2-m { font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.qn2-card { background: var(--bg-card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.qn2-left .qn2-card { border: 0; padding: 12px 2px 0; border-top: 1px solid var(--line); border-radius: 0; }
.qn2-h { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin: 0 0 10px; }
.qn2-h--row { display: flex; align-items: center; justify-content: space-between; }
.qn2-sub { font-size: 12px; font-weight: 600; color: var(--text-muted); margin: 10px 0 6px; }
.qn2-palette { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.qn2-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-height: 64px; padding: 6px;
    border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); color: var(--text); font: 500 12px var(--font-ui); cursor: pointer; }
.qn2-tile:hover { border-color: var(--line-strong); }
.qn2-tile.is-on { border-color: var(--primary); background: var(--bg-app); }
.qn2-glyph { font: 600 16px var(--font-mono); color: var(--text-muted); }
.qn2-tile.is-on .qn2-glyph { color: var(--primary); }
.qn2-sws { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.qn2-sw { display: inline-flex; align-items: center; gap: 10px; font-size: 13.5px; }
.qn2-acts { display: flex; justify-content: flex-end; margin-top: 12px; }
.qn2-grid2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.qn2-pts { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: 13.5px; }
.qn2-pts input { width: 76px; text-align: right; }
.qn2-evid { display: flex; flex-direction: column; gap: 4px; font-size: 13px; max-height: 160px; overflow: auto; }

/* r1572 — questionnaire results on a request */
.qnr-card { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 8px; background: var(--bg-card); }
.qnr-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.qnr-score { font-weight: 700; font-size: 15px; }
.qnr-pill { padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; }
.qnr-pill--ok { background: var(--ok-bg); color: var(--ok); } .qnr-pill--warn { background: var(--warn-bg); color: var(--warn); }
.qnr-pill--bad { background: var(--bad-bg); color: var(--bad); } .qnr-pill--muted { background: var(--bg-subtle); color: var(--text-muted); }
.qnr-th { font-size: 12px; color: var(--text-muted); margin-left: auto; }
.qnr-secs { display: flex; gap: 14px; flex-wrap: wrap; font-size: 13px; margin-top: 6px; } .qnr-secs i { color: var(--text-muted); font-style: normal; }
.qnr-crit { font-size: 13px; color: var(--bad); margin-top: 6px; } .qnr-ai { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }

/* r1573 — typed questionnaire controls in the staff completion form */
.onb-qn-sec { font-weight: 600; margin: 12px 0 4px; }
.onb-q { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.onb-choices { display: flex; flex-direction: column; gap: 4px; }
.onb-choice { display: flex; align-items: center; gap: 8px; font-weight: 400; }
.onb-choice input[type=radio], .onb-choice input[type=checkbox] { width: auto; }
.onb-other { margin-top: 4px; }
.onb-q.is-missing > label { color: var(--bad); }

/* r1574 — AI check verdicts */
.qnr-ai__h { font-weight: 600; font-size: 12px; margin: 6px 0 2px; color: var(--text-muted); }
.qnr-aic { font-size: 12.5px; padding: 2px 0; }
.qnr-aic__q { font-weight: 600; color: var(--text); }
.qnr-aic--ok { color: var(--ok); } .qnr-aic--warn { color: var(--warn); } .qnr-aic--bad { color: var(--bad); } .qnr-aic--muted { color: var(--text-muted); }

/* =====================================================================================================
   r1575 — the KPI and APPROVAL-FLOW colours your preferences set are FOLLOWED.
   Preferences write --kpi-* and --flow-* on the page root. r1566 declared the same tokens as scheme aliases
   on :root AND body, and a declaration on body wins for everything inside it — so the preferences were
   silently overridden. These defaults now live on :root only, where the root's own inline value (your
   preference) takes precedence, and nothing below redeclares them.
   ===================================================================================================== */
:root {
    --flow-done: var(--ok);   --flow-pending: var(--primary);   --flow-waiting: var(--warn);   --flow-rejected: var(--bad);
    --flow-done-bg: color-mix(in srgb, var(--flow-done) 15%, var(--bg-card));
    --flow-pending-bg: color-mix(in srgb, var(--flow-pending) 15%, var(--bg-card));
    --flow-waiting-bg: color-mix(in srgb, var(--flow-waiting) 20%, var(--bg-card));
    --flow-rejected-bg: color-mix(in srgb, var(--flow-rejected) 15%, var(--bg-card));
    --kpi-green: var(--ok);   --kpi-red: var(--bad);   --kpi-grey: var(--text-muted);   --kpi-amber: var(--warn);
    --kpi-green-bg: var(--ok-bg);   --kpi-red-bg: var(--bad-bg);   --kpi-grey-bg: var(--bg-subtle);   --kpi-amber-bg: var(--warn-bg);
}
/* the approval flow as every form, panel and preview draws it — it used the general good / bad / primary
   colours, so the flow preferences reached only the request-progress icons */
.wf-node.is-approved .wf-node-num { background: var(--flow-done-bg); color: var(--flow-done); }
.wf-node.is-rejected .wf-node-num { background: var(--flow-rejected-bg); color: var(--flow-rejected); }
.wf-node.is-current { border-color: var(--flow-waiting); box-shadow: 0 0 0 2px var(--flow-waiting-bg); }
.wf-node.is-current .wf-node-num { background: var(--flow-waiting); color: #fff; }
.wf-node.is-waiting .wf-node-num { background: var(--flow-pending-bg); color: var(--flow-pending); border: 1px solid var(--flow-pending); }
.rqp__node--upcoming:not(.rqp__node--adhoc) .rqp__ic.supb-kpi__ic { background: var(--flow-pending-bg); }
.rqp__node--current .rqp__ic.supb-kpi__ic { background: var(--flow-waiting-bg); }
.rqp__node--done .rqp__ic.supb-kpi__ic { background: var(--flow-done-bg); }
.rqp__node--rejected .rqp__ic.supb-kpi__ic { background: var(--flow-rejected-bg); }
.pref-slider { display: flex; align-items: center; gap: 12px; margin-top: 14px; font-size: 13.5px; }
.pref-slider input[type=range] { flex: 1 1 auto; max-width: 320px; accent-color: var(--primary); }
.pref-slider output { min-width: 48px; font-variant-numeric: tabular-nums; color: var(--text-muted); }

/* r1575 — the questionnaire pop-up: a FIXED height of 95 % of the window; the content scrolls inside */
.modal.modal--qn { height: 95vh; max-height: 95vh; display: flex; flex-direction: column; }
.modal.modal--qn .modal-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
.onb-rich p { margin: 0 0 6px; } .onb-rich ul, .onb-rich ol { margin: 0 0 6px 18px; padding: 0; }

/* r1576 — Visible if, reordering, responsibility, preview */
.qn2-row { display: flex; align-items: center; gap: 2px; }
.qn2-row .qn2-item { flex: 1 1 auto; min-width: 0; }
.qn2-mv { display: inline-flex; flex: 0 0 auto; opacity: .55; }
.qn2-row:hover .qn2-mv { opacity: 1; }
.qn2-mv .btn-icon { width: 22px; height: 22px; min-width: 22px; padding: 0; font-size: 12px; }
.qn2-vis { display: flex; flex-direction: column; gap: 6px; }
.qn2-vis-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1.4fr) auto; gap: 6px; align-items: center; }
.qn2-resp { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 8px; }
.qnp-note { font-size: 12.5px; color: var(--text-muted); margin-bottom: 10px; }

/* r1577 — formula results */
.fx-out { display: inline-flex; align-items: center; min-height: var(--control-h); min-width: 80px; padding: 6px 10px;   /* r1606 */ border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); background: var(--bg-subtle); font-variant-numeric: tabular-nums; }
.fx-err { color: var(--bad); }

/* r1578 — drag & drop, the who-answers slicer, options line by line */
.qn2-drag { cursor: grab; color: var(--text-muted); padding: 0 4px; user-select: none; }
.qn2-row[draggable="true"] { cursor: grab; }
.qn2-row.is-dragging { opacity: .45; }
.qn2-row.drop-before { box-shadow: inset 0 2px 0 var(--primary); }
.qn2-row.drop-after { box-shadow: inset 0 -2px 0 var(--primary); }
.qn2-row.drop-into { outline: 2px dashed var(--primary); outline-offset: -2px; }
.qn2-seg { display: inline-flex; flex-wrap: wrap; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); overflow: hidden; margin-bottom: 6px; }
.qn2-seg__o { position: relative; padding: 6px 12px; font-size: 13px; cursor: pointer; border-right: 1px solid var(--line); }
.qn2-seg__o:last-child { border-right: 0; }
.qn2-seg__o input { position: absolute; opacity: 0; pointer-events: none; }
.qn2-seg__o.is-on { background: var(--primary); color: #fff; }
.qn2-seg__o:focus-within { outline: 2px solid var(--primary); outline-offset: -2px; }
.qn2-opts { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.qn2-opt { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 6px; align-items: center; }
.qn2-opt-add { align-self: flex-start; }

/* r1578 — the Document element */
.qdoc { display: flex; flex-direction: column; gap: 4px; }
.qdoc__a { font-weight: 500; }
.qdoc__ack { margin-top: 6px; }

/* r1579 — Home's lists: the Suppliers pager, and a selected row */
.home-tclpg { padding: 6px 2px 0; }
.home-q tr[data-doc].is-selected td, table.grid tr[data-doc].is-selected td { background: var(--primary-soft, var(--bg-subtle)); }
.home-q tr[data-doc] { cursor: default; }

/* r1580 — "Who answers it" as the Business pre-sets slicer */
.qn2-who { margin: 12px 0 6px; }
.tri.tri--wide { flex-basis: 340px; }

/* r1581 — My Work's record detail scrolls INSIDE its card, its scrollbar space reserved: a detail taller than
   its frame spilled out, the page gained a scrollbar, the width changed, the list refitted, and so on — the flashing */
.supb-card.mywd2 { overflow-y: auto; overflow-x: hidden; min-height: 0; scrollbar-gutter: stable; }
@supports not (scrollbar-gutter: stable) { .supb-card.mywd2 { overflow-y: scroll; } }
/* r1581 — every named colour scheme's ACCENT follows its own primary (none defined one, so the workspace icons
   stayed orange in all of them); the default scheme keeps the orange it is built around */
:root[data-theme] { --accent: var(--primary); --accent-strong: var(--primary-ink, var(--primary)); }
/* r1581 — the questionnaire preview: 95 % of the window, both ways */
.dlg.dlg--xl { width: 95vw; max-width: 95vw; height: 95vh; max-height: 95vh; display: flex; flex-direction: column; }
.dlg.dlg--xl .dlg-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* r1581 — who answers it: two centred lines under each position */
.qn2-who .tri__s { text-align: center; line-height: 1.25; flex: 1 1 0; }
.qn2-who .tri__scale { gap: 6px; }
/* a nudgeable approver */
.wf-node.is-nudgeable { cursor: pointer; }

/* r1581 — Home: the list heads are My Work's height, with "View all"; the favourites strip at the bottom */
.home-q .card-head.home-lh { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px 8px 14px; min-height: 41px; box-sizing: border-box; border-bottom: 1px solid var(--line); }
.home-q .card-head.home-lh h3 { font-size: 13px; font-weight: 600; margin: 0; }
.home-viewall { background: none; border: 0; padding: 2px 4px; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--primary); cursor: pointer; white-space: nowrap; }
.home-viewall:hover { text-decoration: underline; }
.home-favs--bottom { margin-top: 12px; }

/* r1585 — a Home favourite: page name (bold) over workspace name */
.mywfav__t.mywfav__t--2l { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 0; text-align: left; }
.mywfav__t--2l strong { font-weight: 700; font-size: 13px; line-height: 1.25; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.mywfav__t--2l small { font-size: 11.5px; line-height: 1.25; color: var(--text-muted, #6b7280); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

/* r1585 — My Work's record detail does NOT scroll, in any tab: the card and its body clip, and "Show full detail ›"
   in the header opens the whole record. Its fields span their designer width on a 12-column grid. */
.supb-card.mywd2 { overflow: hidden; scrollbar-gutter: auto; }
.supb-card.mywd2 > .mywd2-body { overflow: hidden; }
.mywd2-head { align-items: flex-start; }
.mywd2-full { margin-left: auto; flex: 0 0 auto; background: none; border: 0; padding: 2px 0; font: inherit; font-size: 12.5px;
  font-weight: 600; color: var(--primary); cursor: pointer; white-space: nowrap; }
.mywd2-full:hover { text-decoration: underline; }
.mywd3-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }

/* r1586 — the questionnaire preview is the supplier's page, in a frame filling the 95 % dialog */
.dlg.dlg--xl .dlg-body:has(.qn-prev-frame) { padding: 0; }
.qn-prev-frame { display: block; width: 100%; height: 100%; min-height: 60vh; border: 0; background: var(--bg-card); }

/* r1586 — the staff form's questionnaire in two columns, as the supplier page */
.onb2c { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 18px; align-items: start; }
.onb2c__nav { position: sticky; top: 0; max-height: 70vh; overflow: auto; padding-right: 12px; border-right: 1px solid var(--line); }
.onb2-nav__sec { font-weight: 700; font-size: 12.5px; margin: 10px 0 4px; color: var(--text); }
.onb2-nav__sec:first-child { margin-top: 0; }
.onb2-nav__q { display: flex; align-items: flex-start; gap: 6px; padding: 4px 6px; border-radius: 6px; color: var(--text); text-decoration: none; font-size: 12.5px; line-height: 1.35; }
.onb2-nav__q:hover { background: var(--bg-hover, #f3f4f6); }
.onb2-nav__no { flex: 0 0 auto; min-width: 2.4em; color: var(--text-muted, #6b7280); font-variant-numeric: tabular-nums; }
.onb2-nav__t { flex: 1 1 auto; min-width: 0; }
.onb2-nav__ok { flex: 0 0 auto; width: 1em; color: #16a34a; font-weight: 700; }
.onb2-nav__q.is-done .onb2-nav__ok::after { content: "\2713"; }
@media (max-width: 760px) { .onb2c { grid-template-columns: 1fr; } .onb2c__nav { position: static; max-height: none; border-right: 0; border-bottom: 1px solid var(--line); padding: 0 0 8px; } }

/* r1587 — role and group profiles in tabs */
.prof-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin: 0 0 12px; }
.prof-tab { background: none; border: 0; border-bottom: 2px solid transparent; padding: 8px 14px; font: inherit; font-size: 13px; font-weight: 600; color: var(--text-muted, #6b7280); cursor: pointer; }
.prof-tab.is-on { color: var(--primary); border-bottom-color: var(--primary); }
.prof-sec { margin-top: 14px; }
.prof-sec__h { margin: 0 0 6px; font-size: 13px; font-weight: 700; }
.prof-list { margin-top: 10px; }
/* r1587 — a field the reader may not edit because of its security settings */
.is-sec-locked { opacity: .75; }
.is-sec-locked label::after { content: " \1F512"; font-size: 11px; }

/* r1589 — membership tabs: a list view with "Add …" and a trash on each row; the picker dialog */
.prof-card { margin-top: 2px; }
.prof-card .card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.prof-card .card-head h3 { margin: 0; font-size: 13px; font-weight: 700; }
.prof-pick { max-height: 46vh; overflow: auto; margin-top: 8px; border: 1px solid var(--line); border-radius: 8px; }
.prof-pick__row { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-bottom: 1px solid var(--line); cursor: pointer; }
.prof-pick__row:last-child { border-bottom: 0; }
.prof-pick__row:hover { background: var(--bg-hover, #f3f4f6); }
.prof-pick__l { font-weight: 600; }
#prof-pick-q { width: 100%; }

/* r1590 — My Work's record detail SCROLLS again. The flashing came from its HEIGHT changing while the data loads and
   renders, so the card takes its height from the pane it sits in: its head stays put, its body scrolls with the
   scrollbar's space reserved, and the fields area holds its space while loading — first paint, then filled, same height. */
.supb-card.mywd2 { display: flex; flex-direction: column; height: 100%; max-height: 100%; min-height: 0; overflow: hidden; }
.supb-card.mywd2 > .mywd2-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable; }
.mywd2-body [data-mywd-hdr] { min-height: 96px; }
/* r1590 — the user profile's Security tab: every document and form, its access and the rights behind it */
.doc-access-table td:first-child { font-weight: 600; }
.doc-access-table .num { text-align: center; width: 90px; }

/* r1591 — the user's Security tab: what a role or group grants is ticked and locked; "In menu" beside the access switch */
.perm2-inherited { opacity: .85; }
.perm2-inherited .perm2-act-label::after { content: " \00b7 from a role or group"; font-weight: 400; font-size: 11.5px; color: var(--text-muted, #6b7280); }
.perm2-menu { display: inline-flex; align-items: center; gap: 6px; margin-right: 10px; }
/* r1592 — a question's guiding text, under its answer */
.onb-guide { margin-top: 4px; }

/* r1594 — the record detail's fields: each spans its designer width, nothing spills over its neighbour, and on a
   narrow pane a quarter is a quarter of four columns rather than a sliver of twelve. */
.mywd3-grid { align-items: start; grid-auto-rows: minmax(0, auto); }
.mywd3-f { min-width: 0; overflow: hidden; }
.mywd3-l, .mywd3-v { overflow-wrap: anywhere; word-break: break-word; }
.mywd3-v { overflow: hidden; }
/* the spans are twelfths, so the grid stays twelve columns; when the PANE itself is narrow the fields stack instead
   (a quarter of a 400px pane is unreadable). A browser without container queries simply keeps the designer's widths. */
.supb-card.mywd2 > .mywd2-body { container-type: inline-size; }
@container (max-width: 560px) { .mywd3-f { grid-column: span 12 !important; } }

/* r1596 — the right-side pop-up follows the record detail's rule: 1/1, 1/2 and 1/3 fill the row; 1/4, 1/5, 1/6 and
   1/8 take half of it, two to a line. The form sets each tile's width inline, so these override it. */
.modal.is-docright [data-w] { flex: 0 0 calc(100% - 12px) !important; max-width: calc(100% - 12px) !important; }
.modal.is-docright [data-w="1/4"], .modal.is-docright [data-w="1/5"],
.modal.is-docright [data-w="1/6"], .modal.is-docright [data-w="1/8"] {
  flex: 0 0 calc(50% - 12px) !important; max-width: calc(50% - 12px) !important;
}
/* r1596 — a record detail's two-column lists split evenly where the tab asks for 50/50 */
.ws-sc__pv--half { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.qn-dtab-q { width: 100%; table-layout: fixed; }
.qn-dtab-q th:nth-child(1), .qn-dtab-q td:nth-child(1) { width: 20%; }
.qn-dtab-q th:nth-child(2), .qn-dtab-q td:nth-child(2) { width: 40%; }
.qn-dtab-q th:nth-child(3), .qn-dtab-q td:nth-child(3) { width: 40%; }

/* =====================================================================================================
   r1600 — THE SUMMARY HEADING OVERLAPPED THE FIELDS ABOVE IT. The detail's body is a flex COLUMN, and a flex
   item shrinks below its content by default: when the body was height-constrained, the fields section was
   compressed to less than the grid inside it, and the grid's last row spilled over the "Summary" heading.
   The sections keep their own height and the BODY scrolls, which is what it was built to do.
   ===================================================================================================== */
.mywd2-body > * { flex: 0 0 auto; min-height: 0; }
.mywd2-sec { min-width: 0; }

/* r1600 — "Open questionnaire" sits below the record's table, a clear step away from it */
.qnd-open { margin-top: 16px; }

/* r1602 — the controlled document's file: what is attached, and the way to attach or replace it */
.cd-file { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.cd-file__a { font-weight: 600; }
.cd-file__pick { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cd-file__pick .help { margin: 0; }

/* =====================================================================================================
   r1606 — THE FILE CONTROL. A native file input shows the browser's own "Choose file" button, in the
   browser's type and height, which is why it was the one control on a form that looked foreign. The input
   is kept (it carries the file) and hidden; the estate draws a button reading "..." beside the name of
   whatever is chosen.
   ===================================================================================================== */
.filectl { display: flex; align-items: center; gap: 10px; min-width: 0; }
.filectl__btn { min-height: var(--control-h); padding: 0 14px; font-weight: 700; letter-spacing: 0.08em; }
.filectl__name { color: var(--text-muted); font-size: 13px; min-width: 0; overflow: hidden;
                 text-overflow: ellipsis; white-space: nowrap; }
.filectl__name.is-chosen { color: var(--text); font-weight: 500; }

/* =====================================================================================================
   r1607 — THE RADIO AND THE BOX, drawn by the estate rather than by the browser. They carried no styling
   at all, so their size, colour and spacing came from whichever browser the reader happened to use. The
   mark is 16px in both, and the label sits against it the same way in both.
   ===================================================================================================== */
.choice, .cf-opt { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer;
                   line-height: 1.4; }
.choices, .cf-choice { display: flex; flex-wrap: wrap; gap: 8px 18px; align-items: center; }
.choice input[type="radio"], .choice input[type="checkbox"],
.cf-opt input[type="radio"], .cf-opt input[type="checkbox"] {
    appearance: none; -webkit-appearance: none;
    width: 16px; height: 16px; flex: 0 0 16px; margin: 0;
    border: 1px solid var(--line-strong); background: var(--bg-card);
    display: inline-grid; place-content: center; cursor: pointer;
    transition: border-color 0.12s ease, background 0.12s ease;
}
.choice input[type="radio"], .cf-opt input[type="radio"] { border-radius: 50%; }
.choice input[type="checkbox"], .cf-opt input[type="checkbox"] { border-radius: var(--radius-sm); }
.choice input:hover, .cf-opt input:hover { border-color: var(--text-muted); }
.choice input:focus-visible, .cf-opt input:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
/* the mark itself: a dot for a radio, a tick for a box */
.choice input[type="radio"]::before, .cf-opt input[type="radio"]::before {
    content: ""; width: 8px; height: 8px; border-radius: 50%; transform: scale(0);
    background: var(--bg-card); transition: transform 0.12s ease;
}
.choice input[type="radio"]:checked, .cf-opt input[type="radio"]:checked,
.choice input[type="checkbox"]:checked, .cf-opt input[type="checkbox"]:checked {
    background: var(--primary); border-color: var(--primary);
}
.choice input[type="radio"]:checked::before, .cf-opt input[type="radio"]:checked::before { transform: scale(1); }
.choice input[type="checkbox"]::before, .cf-opt input[type="checkbox"]::before {
    content: ""; width: 9px; height: 5px; border-left: 2px solid var(--bg-card); border-bottom: 2px solid var(--bg-card);
    transform: rotate(-45deg) scale(0); transform-origin: center; margin-top: -2px; transition: transform 0.12s ease;
}
.choice input[type="checkbox"]:checked::before, .cf-opt input[type="checkbox"]:checked::before {
    transform: rotate(-45deg) scale(1);
}
.choice input:disabled, .cf-opt input:disabled { background: var(--bg-subtle); border-color: var(--line); cursor: not-allowed; }

/* =====================================================================================================
   r1607 — THE DATE CONTROL. The box stands at the family height beside every other field; the calendar is
   sized to be used with a mouse or a thumb (36px cells), rather than the browser's own small one.
   ===================================================================================================== */
.dpick { position: relative; display: flex; align-items: stretch; width: 100%; }
.dpick__txt {
    flex: 1 1 auto; min-width: 0; min-height: var(--control-h);
    font-family: var(--font-ui); font-size: 13px; color: var(--text); background: var(--bg-card);
    border: 1px solid var(--line-strong); border-radius: var(--radius-sm) 0 0 var(--radius-sm);
    border-right: 0; padding: 0 11px; font-variant-numeric: tabular-nums;
}
.dpick__txt:focus { outline: none; border-color: var(--primary); }
.dpick__btn {
    flex: 0 0 auto; width: var(--control-h); min-height: var(--control-h);
    display: inline-grid; place-items: center; cursor: pointer; color: var(--text-muted);
    background: var(--bg-card); border: 1px solid var(--line-strong);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.dpick__btn:hover { color: var(--primary); border-color: var(--text-muted); }
.dpick__btn svg { width: 16px; height: 16px; }
.dpick__panel {
    position: absolute; z-index: 1000; top: calc(100% + 6px); left: 0; width: 280px;
    background: var(--bg-card); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg); padding: 10px;
}
.dpick__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.dpick__month { font-size: 13px; font-weight: 600; }
.dpick__nav { width: 28px; height: 28px; border: 0; background: transparent; cursor: pointer;
              color: var(--text-muted); font-size: 18px; line-height: 1; border-radius: var(--radius-sm); }
.dpick__nav:hover { background: var(--bg-subtle); color: var(--text); }
.dpick__dows, .dpick__grid { display: grid; grid-template-columns: repeat(7, 1fr); }
.dpick__dows span { text-align: center; font-size: 11px; font-weight: 700; color: var(--text-muted); padding-bottom: 4px; }
.dpick__d { height: 36px; border: 0; background: transparent; cursor: pointer; border-radius: var(--radius-sm);
            font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
.dpick__d:hover { background: var(--bg-subtle); }
.dpick__d.is-out { color: var(--text-muted); opacity: 0.55; }
.dpick__d.is-today { box-shadow: inset 0 0 0 1px var(--line-strong); font-weight: 600; }
.dpick__d.is-chosen { background: var(--primary); color: #fff; font-weight: 600; }
.dpick__foot { display: flex; justify-content: space-between; gap: 8px; margin-top: 8px;
               border-top: 1px solid var(--line); padding-top: 8px; }

/* r1610 — THE FAVOURITE STAR ON THE TOP BAR. It took `--text-muted`, like every other icon there, and the
   mid-tone bars of some schemes (#E3E8EE, #F2EDE4) leave a muted grey almost invisible. It takes the scheme's
   OWN text colour instead — the strongest contrast the scheme offers, so no colour is imported — and keeps the
   accent when the page is pinned. */
.appbar-fav { color: var(--text); }
.appbar-fav svg { stroke: currentColor; stroke-width: 1.6; }
.appbar-fav:hover { color: var(--primary); }
.appbar-fav.is-on { color: var(--primary); }
.appbar-fav.is-on svg { fill: currentColor; }

/* r1611 — a favourite is dragged into place: the tile follows the pointer and the one under it moves aside */
.mywfav--drag { cursor: grab; }
.mywfav--drag:active { cursor: grabbing; }
.mywfav__strip .is-dragging { opacity: 0.45; }

/* =====================================================================================================
   r1623 — EVERY TABLE IS THE BOARD LIST. The product owner fixed `.tcl-list / .tcl-row` and retired
   `table.grid` as a look of its own. Their rows already shared one height (10px 12px); what differed was
   the HEAD — 11px capitals with letter-spacing here, 12px semibold in sentence case on the board lists — and
   a selected row. Every table now takes the board list's head (and keeps it in view while its body
   scrolls) and its selection colour, so the 257 tables in the estate read as one family with the boards.
   ===================================================================================================== */
table.grid thead th, .dv-l__t thead th {
    font-size: 12px; font-weight: 600; text-transform: none; letter-spacing: 0;
    color: var(--text-muted); padding: 9px 12px;
    background: var(--bg-subtle); border-bottom: 1px solid var(--line);
    position: sticky; top: 0; z-index: 2;
}
table.grid tbody td, .dv-l__t tbody td { padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.grid tbody tr.is-selected > td, .dv-l__t tbody tr.is-selected > td { background: var(--row-selected); }

/* r1625 — the Transformation stage's Mapper: two field columns side by side, the mapping rows beneath */
.pv2-tf-docs { display: flex; align-items: flex-end; gap: 10px; margin-top: 8px; }
.pv2-tf-docs .pv2-fld { flex: 1 1 0; min-width: 0; }
.pv2-tf-arrow { padding-bottom: 9px; color: var(--text-muted); }
.pv2-tf-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.pv2-tf-split { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.pv2-tf-col { border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-card); max-height: 260px; overflow-y: auto; }
.pv2-tf-col h4 { position: sticky; top: 0; margin: 0; padding: 8px 10px; font-size: 12px; font-weight: 600; color: var(--text-muted);
  background: var(--bg-subtle); border-bottom: 1px solid var(--line); }
.pv2-tf-f { padding: 7px 10px; border-bottom: 1px solid var(--line); font-size: 13px; cursor: pointer; }
.pv2-tf-f:last-child { border-bottom: 0; }
.pv2-tf-f[draggable="true"] { cursor: grab; }
.pv2-tf-f:hover, .pv2-tf-f.is-picked { background: var(--row-selected); }
.pv2-tf-f.is-mapped { background: var(--bg-subtle); }
.pv2-tf-how { color: var(--primary); }
.pv2-tf-tbl { margin: 10px 0; overflow-x: auto; }
.pv2-tf-tbl select, .pv2-tf-tbl .tinp { width: 100%; min-width: 110px; }

/* r1627 — the Mapper's drag & drop shows itself: a grip on what can be dragged, a hint on what can take it,
   and the target under the pointer lit while a field is carried over it */
.pv2-tf-grip { display: inline-block; width: 12px; margin-right: 6px; color: var(--text-muted); letter-spacing: -2px; cursor: grab; }
.pv2-tf-hint { color: var(--text-muted); font-style: italic; }
.pv2-tf-f.is-over, tr[data-tf-row].is-over > td, [data-tf-drop-row].is-over {
  background: var(--row-selected); box-shadow: inset 0 0 0 2px var(--primary); }
.pv2-tf-lk { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pv2-tf-lk select { width: auto; min-width: 110px; flex: 1 1 110px; }

/* =====================================================================================================
   r1628 — the Mapper as the Orchestrator draws it: two columns with a gutter between them, the links laid
   over the whole split, and a target row that opens its own settings in place (no table underneath).
   ===================================================================================================== */
.pv2-tf-split { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 56px minmax(0, 1fr); gap: 0; }
.pv2-tf-gap { min-height: 1px; }
.pv2-tf-wires { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; z-index: 1; }
.pv2-tf-wire { fill: none; stroke: var(--primary); stroke-width: 1.5; opacity: .75; }
.pv2-tf-wire.is-formula { stroke-dasharray: 5 4; }
.pv2-tf-wire.is-clipped { opacity: .35; }
.pv2-tf-wire.is-selected { stroke-width: 2.5; opacity: 1; }
.pv2-tf-col { max-height: 360px; }
.pv2-tf-f.is-linked { font-weight: 600; }
.pv2-tf-t { border-bottom: 1px solid var(--line); }
.pv2-tf-t:last-child { border-bottom: 0; }
.pv2-tf-t > .pv2-tf-f { border-bottom: 0; }
.pv2-tf-t.is-open { background: var(--bg-subtle); }
.pv2-tf-t.is-over, .pv2-tf-t.is-over > .pv2-tf-f { background: var(--row-selected); box-shadow: inset 0 0 0 2px var(--primary); }
.pv2-tf-edit { display: flex; flex-direction: column; gap: 8px; padding: 4px 10px 10px; cursor: default; }
.pv2-tf-edit-body { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pv2-tf-edit-body select, .pv2-tf-edit-body .tinp { flex: 1 1 120px; min-width: 110px; width: auto; }
.pv2-tf-edit-foot { display: flex; align-items: center; gap: 8px; }
.pv2-tf-edit-foot .tinp { flex: 1 1 auto; }
.pv2-tf-srcchip { display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px; border-radius: 999px;
  background: var(--primary-soft, #e0ecff); color: var(--primary); font-size: 12px; font-weight: 600; }
.pv2-tf-srcchip i { font-weight: 400; color: var(--text-muted); }
.pv2-tf-req { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; white-space: nowrap; }

/* =====================================================================================================
   r1629 — the Mapper as tables: each side a table of data fields and their types, the whole page's height,
   72px between the tables for the links, links that can be clicked, and a target that refuses a field of
   another type while it is being carried over.
   ===================================================================================================== */
.pv2-tf-split { grid-template-columns: minmax(0, 1fr) 72px minmax(0, 1fr); height: 480px; }
.pv2-tf-col { max-height: none; height: 100%; overflow-y: auto; }
.pv2-tf-cap { padding: 8px 10px; font-size: 12px; font-weight: 600; color: var(--text); border-bottom: 1px solid var(--line); background: var(--bg-card); }
.pv2-tf-table { width: 100%; }
.pv2-tf-table thead th { top: 0; }
.pv2-tf-table td:last-child, .pv2-tf-table th:last-child { width: 38%; color: var(--text-muted); }
.pv2-tf-table tr[data-tf-src] { cursor: grab; }
.pv2-tf-table tr[data-tf-src].is-linked td:first-child { font-weight: 600; }
.pv2-tf-table tr[data-tf-src].is-picked > td { background: var(--row-selected); }
.pv2-tf-table tr[data-tf-tgt] { cursor: pointer; }
.pv2-tf-table tr[data-tf-tgt].is-open > td, .pv2-tf-editrow > td { background: var(--bg-subtle); }
.pv2-tf-table tr.is-over > td { background: var(--row-selected); box-shadow: inset 0 2px 0 var(--primary), inset 0 -2px 0 var(--primary); }
.pv2-tf-table tr.is-refused > td { background: var(--danger-soft, #fdecea); cursor: not-allowed; }
.pv2-tf-how { font-size: 12px; color: var(--primary); margin-top: 2px; }
.pv2-tf-hint { font-size: 12px; color: var(--text-muted); font-style: italic; margin-top: 2px; }
.pv2-tf-wires { pointer-events: none; }
.pv2-tf-hit { fill: none; stroke: transparent; stroke-width: 12; pointer-events: stroke; cursor: pointer; }
.pv2-tf-hit:hover + .pv2-tf-wire, .pv2-tf-wire:hover { stroke-width: 2.5; opacity: 1; }
.pv2-tf-ask { position: absolute; z-index: 5; width: 280px; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--bg-card); box-shadow: var(--shadow-md, 0 6px 20px rgba(0,0,0,.14)); }
.pv2-tf-ask-msg { font-size: 13px; line-height: 1.45; }
.pv2-tf-ask-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }

/* =====================================================================================================
   r1630 — EVERY IN-PAGE DOCUMENT FORM: the header (title + its buttons) and the button row stay fixed; only
   the form body scrolls. The page view itself no longer scrolls under a form.
   ===================================================================================================== */
.view.view--form { overflow: hidden; display: flex; flex-direction: column; }
.view--form > .inline-form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; width: 100%; }
.view--form > .inline-form > .card-head { flex: 0 0 auto; }
.view--form > .inline-form > .card-pad { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.view--form #__inl-foot { flex: 0 0 auto; }
.view--form #__inl-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* =====================================================================================================
   r1630 — ONE PAGE INSET FOR MY WORK, HOME AND WORKSPACES. My Work sits in a scene card inset 6px from the top,
   20px from each side and 16px from the bottom; Home put its grid straight into the view, and a workspace page
   only had that inset when it had a scene. The three now read the same token, so their components start the
   same distance from the top and the sides by construction rather than by three numbers kept in step.
   ===================================================================================================== */
:root { --page-inset-top: 6px; --page-inset-x: 20px; --page-inset-bottom: 16px; }
.view--scene > .card { padding: var(--page-inset-top) var(--page-inset-x) var(--page-inset-bottom); }
.view:has(> .home-grid) { padding: var(--page-inset-top) var(--page-inset-x) var(--page-inset-bottom); }
.view > .card.ws-page { padding: var(--page-inset-top) var(--page-inset-x) var(--page-inset-bottom);
  border: 0; border-radius: 0; box-shadow: none; background: transparent; margin: 0; }
.view--scroll:has(> .card.ws-page) { padding: 0; }

/* r1631 — the CF Designer's Action buttons section */
.fb-actions .fb-ab-wrap { overflow-x: auto; margin-top: 8px; }
.fb-actions .fb-ab tr.fb-ab-sys td { color: var(--text-muted); }
.fb-actions .fb-ab td { vertical-align: middle; }
.fb-ab-st { display: flex; flex-wrap: wrap; gap: 6px; }
.fb-ab-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border: 1px solid var(--line); border-radius: 999px; font-size: 12px; white-space: nowrap; }

/* =====================================================================================================
   r1633 — THE INSET WHERE THE COMPONENTS ACTUALLY LAND. Measured in a real browser: My Work's components sit
   44px from each side and 14px below the top menu — its scene card (20 / 6) PLUS its inner section's own padding
   (--v16-pad 24 / 8). r1630 matched only the card, so Home stayed at 20 / 6 and the Workspaces page, whose tile
   grid adds 16 of its own, at 36 / 22. Home and the Workspaces page now use the same sum, built from the same
   parts, so the three cannot drift apart again.
   ===================================================================================================== */
:root {
  --page-content-x: calc(var(--page-inset-x) + var(--v16-pad));
  --page-content-top: calc(var(--page-inset-top) + 8px);
  --page-content-bottom: var(--page-inset-bottom);
}
.main .view:has(> .home-grid) { padding: var(--page-content-top) var(--page-content-x) var(--page-content-bottom); }
/* r1645 — scoped to the page that shows the grid: the marker class outlived the page, and My work took its inset */
.main .view.view--ws-index:has(> .ws-grid) { padding: var(--page-content-top) var(--page-content-x) var(--page-content-bottom); }
.main .view.view--ws-index > .ws-grid { padding: 0; }

/* r1634 — the record detail's header row: Close on the left, "Show full detail ›" on the right */
.record-peek-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex: 0 0 auto; }
.record-peek-head .record-peek-close { margin-left: 0; }
.record-peek-head .mywd2-full { margin-left: auto; }

/* r1643 — the approval section when no flow applies: a sentence and the "+" to add an approver by hand */
.rqp--none .rqp__none { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.rqp--none .rqp__line--add { margin: 0; padding: 0; list-style: none; display: inline-flex; }

/* r1646 — CF Designer › Action buttons as tiles (like fields), and their settings pop-up */
.ab-zone { display: flex; flex-wrap: wrap; gap: 8px; padding: 10px; border: 1px dashed var(--line-strong); border-radius: 10px; min-height: 52px; }
.ab-tile { display: inline-flex; align-items: center; gap: 8px; padding: 6px 8px 6px 6px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); cursor: grab; max-width: 100%; }
.ab-tile--sys { background: var(--bg-subtle); }
.ab-tile .fb-grip { color: var(--text-muted); cursor: grab; }
.ab-tile__l { font-weight: 600; white-space: nowrap; }
.ab-tile__m { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
.ab-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
.ab-tabs .fb-tab { border: 0; background: none; padding: 8px 12px; cursor: pointer; border-bottom: 2px solid transparent; color: var(--text-muted); }
.ab-tabs .fb-tab.is-on { color: var(--text); border-bottom-color: var(--brand); font-weight: 600; }
.ab-stgrp { margin: 8px 0; } .ab-stgrp__t { font-size: 12px; font-weight: 600; margin-bottom: 6px; }
.ab-cond { display: grid; grid-template-columns: 1.2fr 1fr 1.4fr auto; gap: 8px; align-items: center; margin-bottom: 8px; }

/* r1672 — CF Designer › Preview form: the banner that says the form is a preview and saves nothing */
.preview-banner { margin: 0 0 14px; padding: 10px 12px; border-radius: 8px; background: var(--warn-bg, var(--surface-2)); border: 1px solid var(--warn, var(--border)); color: var(--text); font-size: 13px; line-height: 1.45; }
.preview-banner strong { color: var(--warn-fg, var(--text)); }

/* r1702 — SETUP'S CONVERTED LISTS (units, commodities, countries, cities) draw the shared list component's head, which had
   no Setup measurement: its rule line sat higher than on the tab beside it and its title was another size. In Setup's
   list panels it takes the Setup head's measurement — the majority's, 16px 20px and a 14px/600 title (SS-260). Scoped to
   Setup, so the component elsewhere (supplier board, KPI cards) keeps its own. */
.setup-panel .dim-panel .supb-comp__head { padding: 16px 20px; }
.setup-panel .dim-panel .supb-comp__title { font-size: 14px; font-weight: 600; }

/* r1713 — SETUP'S FRAME (r1705's sticky tabs removed: they left the whole page scrolling, and their background also
   repainted the WORKSPACE menu, which shares the .setup-tabs class). Scoped to a view whose direct child is SETUP's tab
   bar, never the workspace tabs: the view stops scrolling; the tab bar keeps its natural height outside any scroller; the
   visible panel fills the rest and is the ONLY thing that scrolls — its scrollbar starts under the tabs. A panel with
   sub-tabs is itself a column: its sub-tab bar stays, the visible sub-panel scrolls under it. */
.view.view--scroll:has(> .setup-tabs:not(.ws-tabs)) { overflow: hidden; padding-bottom: 0; }
.view:has(> .setup-tabs:not(.ws-tabs)) > .setup-tabs { flex: 0 0 auto; }
.view:has(> .setup-tabs:not(.ws-tabs)) > .setup-panel:not([hidden]) { flex: 1 1 auto; min-height: 0; overflow: auto; padding-bottom: 24px; }
.view:has(> .setup-tabs:not(.ws-tabs)) > .setup-panel:not([hidden]):has(> .dim-tabs) { overflow: hidden; display: flex; flex-direction: column; padding-bottom: 0; }
.view:has(> .setup-tabs:not(.ws-tabs)) > .setup-panel > .dim-tabs { flex: 0 0 auto; }
.view:has(> .setup-tabs:not(.ws-tabs)) > .setup-panel:has(> .dim-tabs) > .dim-panel:not([hidden]) { flex: 1 1 auto; min-height: 0; overflow: auto; padding-bottom: 24px; }

/* r1706 — rich text shown as authored: tables keep their own borders and widths (inline styles and attributes win);
   these are only the defaults a pasted table needs to read as one */
.onb-rich table, .rt-view table { border-collapse: collapse; max-width: 100%; }
.onb-rich td, .onb-rich th, .rt-view td, .rt-view th { vertical-align: top; padding: 4px 6px; }
.onb-rich img, .rt-view img { max-width: 100%; height: auto; }

/* r1779 — the CF Designer's placeholder on a RICH-TEXT field (an editable area, not an input), shown while it is empty */
.rt-edit[data-placeholder]:empty::before { content: attr(data-placeholder); color: var(--text-muted); pointer-events: none; }

/* r1794 — A SWITCH FIELD READS LIKE EVERY OTHER FIELD (the product owner's screenshots: "the switches are displayed like total
   nonsense"). A toggle row is name | switch with `justify-content: space-between`, so in a field grid the name sat at the left edge of its
   box and the switch at the right one: on a full-width field some 1,700 px apart, on a half-width one beside the NEXT field. In a field
   grid it is laid out as the CF Designer places a field: its NAME on top, like every label, and under it the SWITCH with its DESCRIPTION
   beside it, at the left of its cell. Switches outside field grids (settings, the designer's own dialogs) keep their row. At the END of the sheet, so it wins by order as well as by specificity over the toggle
   row's own rules (`.toggle-row .tgl-text { display: flex }`). */
.cf-grid > .toggle-row, .form-grid > .toggle-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "name name" "switch help";
  justify-content: stretch; align-items: center; column-gap: 10px; row-gap: 6px; padding: 4px 0 8px;
}
.cf-grid > .toggle-row > .tgl-text, .form-grid > .toggle-row > .tgl-text { display: contents; }
.cf-grid > .toggle-row .tgl-name, .form-grid > .toggle-row .tgl-name,
.cf-grid > .toggle-row > span:first-child:not(.tgl-text), .form-grid > .toggle-row > span:first-child:not(.tgl-text) { grid-area: name; }
.cf-grid > .toggle-row .tgl-text > .help, .form-grid > .toggle-row .tgl-text > .help { grid-area: help; }
.cf-grid > .toggle-row > .switch, .form-grid > .toggle-row > .switch { grid-area: switch; justify-self: start; }

/* r1802 — the Simple → Expert switch on the header's left, right after the form's name (inside the title element) */
.alloc-switch.alloc-switch--head { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 0 16px; vertical-align: middle; font-size: 13px; font-weight: 400; }
.alloc-switch.alloc-switch--head .switch-text { font-size: 13px; font-weight: 400; }
.alloc-switch.alloc-switch--head .switch-text strong { font-weight: 600; }
