﻿/* ============================================================================
   MKI Management - design system

   One place for the look of the whole back office. Everything below is built
   from the tokens in :root, so a colour or a radius is changed once here and
   follows through every screen.
   ========================================================================== */

:root {
    /* brand */
    --brand: #2563eb;
    --brand-strong: #1d4ed8;
    --brand-soft: #eff4ff;
    --brand-softer: #f6f9ff;
    --brand-ring: rgba(37, 99, 235, .22);

    /* semantic */
    --ok: #15a35b;
    --ok-soft: #e9f8f0;
    --warn: #d97706;
    --warn-soft: #fef4e6;
    --bad: #dc2626;
    --bad-soft: #fdeeee;
    --info: #0891b2;
    --info-soft: #e6f6fa;

    /* neutrals */
    --ink: #182031;
    --ink-2: #4a5568;
    --ink-3: #78849a;
    --ink-4: #9aa4b6;
    --line: #e4e8ef;
    --line-soft: #eef1f6;
    --surface: #ffffff;
    --surface-2: #fafbfd;
    --canvas: #f4f6fa;

    /* sidebar */
    --sidebar-width: 258px;
    --sidebar-bg: #101827;
    --sidebar-bg-2: #0b111c;
    --sidebar-hover: rgba(255, 255, 255, .06);
    --sidebar-fg: #c3ccdb;
    --sidebar-fg-muted: #6f7d93;
    --sidebar-accent: #4d8bff;

    --topbar-h: 58px;

    /* shape */
    --r-xs: 5px;
    --r-sm: 7px;
    --r: 10px;
    --r-lg: 14px;
    --r-pill: 999px;

    /* elevation */
    --shadow-xs: 0 1px 2px rgba(16, 24, 40, .05);
    --shadow-sm: 0 1px 3px rgba(16, 24, 40, .07), 0 1px 2px rgba(16, 24, 40, .04);
    --shadow-md: 0 4px 14px rgba(16, 24, 40, .09);
    --shadow-lg: 0 14px 40px rgba(16, 24, 40, .14);

    /* motion */
    --t-fast: 110ms cubic-bezier(.4, 0, .2, 1);
    --t: 180ms cubic-bezier(.4, 0, .2, 1);

    /* keeps the old variable names working */
    --content-bg: var(--canvas);
    --border: var(--line);
    --sidebar-bg-hover: var(--sidebar-hover);
}

*, *::before, *::after {
    box-sizing: border-box;
}

html, body {
    height: 100%;
}

body {
    background: var(--canvas);
    font-family: "Segoe UI Variable Text", "Segoe UI", -apple-system, BlinkMacSystemFont,
                 "Helvetica Neue", Roboto, "Noto Sans", "Microsoft YaHei", sans-serif;
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

::selection {
    background: var(--brand-ring);
}

a {
    color: var(--brand);
    text-decoration: none;
    transition: color var(--t-fast);
}

a:hover {
    color: var(--brand-strong);
    text-decoration: underline;
}

/* Anything focused by keyboard gets the same ring; a mouse press never shows it. */
:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--brand-ring);
    border-radius: var(--r-xs);
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ---------- top progress bar ------------------------------------------- */

.route-progress {
    position: fixed;
    top: 0;
    left: 0;
    height: 3px;
    width: 0;
    z-index: 2000;
    background: linear-gradient(90deg, var(--brand), #22d3ee);
    box-shadow: 0 0 10px rgba(37, 99, 235, .6);
    opacity: 0;
    transition: width 200ms ease, opacity 200ms ease;
    pointer-events: none;
}

.route-progress.is-active {
    opacity: 1;
}

/* ---------- shell ------------------------------------------------------- */

.app-shell {
    min-height: 100vh;
}

.app-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: var(--sidebar-width);
    background: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-2) 100%);
    color: var(--sidebar-fg);
    display: flex;
    flex-direction: column;
    z-index: 1040;
    transition: transform var(--t);
    box-shadow: inset -1px 0 0 rgba(255, 255, 255, .05);
}

.app-main {
    margin-left: var(--sidebar-width);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.app-content {
    flex: 1 1 auto;
    padding: 22px 26px 32px;
    animation: content-in 240ms cubic-bezier(.4, 0, .2, 1);
}

@keyframes content-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.app-footer {
    padding: 14px 26px;
    color: var(--ink-4);
    font-size: 12px;
    border-top: 1px solid var(--line);
    background: var(--surface);
}

/* ---------- sidebar ----------------------------------------------------- */

.sidebar-brand {
    height: var(--topbar-h);
    display: flex;
    align-items: center;
    padding: 0 18px;
    border-bottom: 1px solid rgba(255, 255, 255, .06);
    flex: 0 0 auto;
}

.sidebar-brand a {
    color: #fff;
    text-decoration: none;
    font-weight: 600;
    font-size: 15px;
    letter-spacing: -.01em;
    display: flex;
    align-items: center;
    gap: 10px;
}

.sidebar-brand a:hover {
    text-decoration: none;
}

.sidebar-brand i {
    color: var(--sidebar-accent);
    font-size: 19px;
    transition: transform var(--t);
}

.sidebar-brand a:hover i {
    transform: rotate(-8deg) scale(1.08);
}

.sidebar-user {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 15px 18px;
    border-bottom: 1px solid rgba(255, 255, 255, .06);
    flex: 0 0 auto;
}

.sidebar-avatar,
.topbar-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--sidebar-accent), #7c5cff);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    flex: 0 0 auto;
    box-shadow: 0 2px 8px rgba(77, 139, 255, .35);
}

.topbar-avatar {
    width: 28px;
    height: 28px;
    font-size: 12.5px;
    box-shadow: none;
}

.sidebar-user-text {
    min-width: 0;
}

.sidebar-greeting {
    font-size: 10.5px;
    color: var(--sidebar-fg-muted);
    text-transform: uppercase;
    letter-spacing: .06em;
}

.sidebar-username {
    color: #fff;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 10px 10px 24px;
}

.sidebar-nav::-webkit-scrollbar { width: 8px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, .1);
    border-radius: var(--r-pill);
    border: 2px solid transparent;
    background-clip: padding-box;
}
.sidebar-nav:hover::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .18); background-clip: padding-box; }

.menu-section-title {
    padding: 16px 10px 6px;
    font-size: 10.5px;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--sidebar-fg-muted);
    font-weight: 600;
}

.menu-group-list,
.menu-child-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.menu-group-toggle,
.menu-leaf {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--sidebar-fg);
    text-decoration: none;
    border-radius: var(--r-sm);
    transition: background var(--t-fast), color var(--t-fast);
    overflow: hidden;
}

.menu-group-toggle {
    padding: 9px 10px;
    font-size: 13.5px;
    margin: 1px 0;
}

.menu-leaf {
    padding: 8px 10px 8px 38px;
    font-size: 13px;
    margin: 1px 0;
}

.menu-group-toggle:hover,
.menu-leaf:hover {
    background: var(--sidebar-hover);
    color: #fff;
    text-decoration: none;
}

.menu-group-toggle:active,
.menu-leaf:active {
    background: rgba(255, 255, 255, .1);
}

/* Set by ui.js on the link that was clicked. It holds the pressed look until the
   next page arrives, so the answer to "did that register, and which one did I
   press" is on the item itself rather than only in the bar at the top. */
.menu-leaf.is-navigating,
.menu-group-toggle.is-navigating {
    background: rgba(77, 139, 255, .16);
    color: #fff;
}

.menu-leaf.is-navigating .menu-icon,
.menu-group-toggle.is-navigating .menu-icon {
    color: var(--sidebar-accent);
}

.menu-icon {
    font-size: 15px;
    color: var(--sidebar-fg-muted);
    width: 18px;
    text-align: center;
    flex: 0 0 auto;
    transition: color var(--t-fast);
}

.menu-group-toggle:hover .menu-icon,
.menu-leaf:hover .menu-icon {
    color: var(--sidebar-accent);
}

.menu-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.menu-caret {
    font-size: 10px;
    color: var(--sidebar-fg-muted);
    transition: transform var(--t);
}

.menu-group-toggle.collapsed .menu-caret {
    transform: rotate(-90deg);
}

.menu-child-list {
    margin: 2px 0 6px;
}

/* The active screen: brand tint, white text, and an accent bar down the left. */
.menu-leaf.active,
.menu-group-toggle.standalone.active {
    background: rgba(77, 139, 255, .16);
    color: #fff;
    font-weight: 600;
}

.menu-leaf.active::before,
.menu-group-toggle.standalone.active::before {
    content: "";
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 var(--r-pill) var(--r-pill) 0;
    background: var(--sidebar-accent);
}

.menu-leaf.active .menu-icon,
.menu-group-toggle.standalone.active .menu-icon {
    color: var(--sidebar-accent);
}

.menu-leaf.pending,
.menu-group-toggle.pending {
    color: var(--sidebar-fg-muted);
}

.menu-pending-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #4c596d;
    flex: 0 0 auto;
}

.menu-empty {
    padding: 16px 10px;
    color: var(--sidebar-fg-muted);
    font-size: 13px;
}

/* ---------- topbar ------------------------------------------------------ */

.app-topbar {
    height: var(--topbar-h);
    background: rgba(255, 255, 255, .88);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--line);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 22px 0 14px;
    position: sticky;
    top: 0;
    z-index: 1030;
    transition: box-shadow var(--t);
}

body.is-scrolled .app-topbar {
    box-shadow: var(--shadow-sm);
}

.topbar-toggle {
    color: var(--ink-2);
    font-size: 20px;
    padding: 4px 8px;
    border-radius: var(--r-sm);
    text-decoration: none;
    transition: background var(--t-fast), color var(--t-fast);
}

.topbar-toggle:hover {
    background: var(--line-soft);
    color: var(--ink);
}

.topbar-title {
    font-weight: 650;
    font-size: 16px;
    letter-spacing: -.01em;
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topbar-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

.legacy-switch {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.user-menu {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--ink);
    text-decoration: none;
    padding: 4px 8px;
    border-radius: var(--r-pill);
    transition: background var(--t-fast);
}

.user-menu:hover {
    background: var(--line-soft);
    color: var(--ink);
    text-decoration: none;
}

.user-menu::after {
    margin-left: 2px;
    color: var(--ink-4);
}

/* ---------- buttons ----------------------------------------------------- */

.btn {
    --btn-fg: var(--ink);
    --btn-bg: transparent;
    --btn-border: transparent;
    --btn-shadow: none;
    position: relative;
    font-size: 13px;
    font-weight: 550;
    line-height: 1.4;
    padding: 7px 14px;
    border-radius: var(--r-sm);
    border: 1px solid var(--btn-border);
    color: var(--btn-fg);
    background: var(--btn-bg);
    box-shadow: var(--btn-shadow);
    transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast),
                box-shadow var(--t-fast), transform var(--t-fast);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    white-space: nowrap;
}

.btn:hover {
    transform: translateY(-1px);
}

/* The press is the whole acknowledgement, and it lands on mouse-down, before
   any request starts. Nothing decorative is layered on top: a button that goes
   on to do slow work says so with the spinner in .btn.is-busy, and one that
   changes the page says so with the progress bar. */
.btn:active {
    transform: translateY(0) scale(.985);
    filter: brightness(.95);
    transition-duration: 40ms;
}

.btn:focus-visible {
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.btn-sm {
    font-size: 12px;
    padding: 5px 10px;
    border-radius: var(--r-xs);
}

.btn-lg {
    font-size: 14.5px;
    padding: 10px 20px;
    border-radius: var(--r);
}

.btn .bi {
    font-size: 1.05em;
    line-height: 1;
}

.btn-primary {
    --btn-fg: #fff;
    --btn-bg: var(--brand);
    --btn-border: var(--brand);
    --btn-shadow: 0 1px 2px rgba(37, 99, 235, .3);
}

.btn-primary:hover {
    --btn-bg: var(--brand-strong);
    --btn-border: var(--brand-strong);
    --btn-shadow: 0 4px 12px rgba(37, 99, 235, .32);
    color: #fff;
}

.btn-secondary {
    --btn-fg: #fff;
    --btn-bg: #566076;
    --btn-border: #566076;
}

.btn-secondary:hover { --btn-bg: #454e61; --btn-border: #454e61; color: #fff; }

.btn-success {
    --btn-fg: #fff;
    --btn-bg: var(--ok);
    --btn-border: var(--ok);
    --btn-shadow: 0 1px 2px rgba(21, 163, 91, .3);
}

.btn-success:hover { --btn-bg: #128a4d; --btn-border: #128a4d; color: #fff; }

.btn-danger {
    --btn-fg: #fff;
    --btn-bg: var(--bad);
    --btn-border: var(--bad);
    --btn-shadow: 0 1px 2px rgba(220, 38, 38, .3);
}

.btn-danger:hover { --btn-bg: #b91c1c; --btn-border: #b91c1c; color: #fff; }

.btn-warning {
    --btn-fg: #fff;
    --btn-bg: var(--warn);
    --btn-border: var(--warn);
}

.btn-warning:hover { --btn-bg: #b45309; --btn-border: #b45309; color: #fff; }

.btn-outline-primary {
    --btn-fg: var(--brand);
    --btn-bg: var(--surface);
    --btn-border: #bcd0f7;
}

.btn-outline-primary:hover {
    --btn-fg: var(--brand-strong);
    --btn-bg: var(--brand-soft);
    --btn-border: var(--brand);
}

.btn-outline-secondary {
    --btn-fg: var(--ink-2);
    --btn-bg: var(--surface);
    --btn-border: var(--line);
    --btn-shadow: var(--shadow-xs);
}

.btn-outline-secondary:hover {
    --btn-fg: var(--ink);
    --btn-bg: var(--surface-2);
    --btn-border: #cfd6e2;
    --btn-shadow: var(--shadow-sm);
}

.btn-outline-danger {
    --btn-fg: var(--bad);
    --btn-bg: var(--surface);
    --btn-border: #f2c4c4;
}

.btn-outline-danger:hover {
    --btn-fg: #fff;
    --btn-bg: var(--bad);
    --btn-border: var(--bad);
}

.btn-outline-warning {
    --btn-fg: #92590a;
    --btn-bg: var(--surface);
    --btn-border: #f0d08a;
}

.btn-outline-warning:hover {
    --btn-fg: #fff;
    --btn-bg: #b45309;
    --btn-border: #b45309;
}

.btn-outline-success {
    --btn-fg: var(--ok);
    --btn-bg: var(--surface);
    --btn-border: #bce4cf;
}

.btn-outline-success:hover {
    --btn-fg: #fff;
    --btn-bg: var(--ok);
    --btn-border: var(--ok);
}

.btn-link {
    --btn-fg: var(--brand);
    box-shadow: none;
    text-decoration: none;
}

.btn-link:hover {
    --btn-fg: var(--brand-strong);
    text-decoration: underline;
    transform: none;
}

.btn:disabled,
.btn.disabled {
    opacity: .55;
    transform: none !important;
    box-shadow: none;
    cursor: not-allowed;
}

/* Busy state: the label stays put so the button does not resize, and a spinner
   sits on top of it. ui.js also sets disabled, which is what blocks the second click. */
.btn.is-busy {
    color: transparent !important;
    pointer-events: none;
    position: relative;
}

.btn.is-busy > * {
    visibility: hidden;
}

.btn.is-busy::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 15px;
    height: 15px;
    margin: -7.5px 0 0 -7.5px;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-right-color: transparent;
    color: var(--btn-fg);
    visibility: visible;
    animation: spin 620ms linear infinite;
}

.btn-primary.is-busy::after,
.btn-danger.is-busy::after,
.btn-success.is-busy::after,
.btn-secondary.is-busy::after,
.btn-warning.is-busy::after { color: #fff; }

@keyframes spin {
    to { transform: rotate(360deg); }
}

.btn-icon {
    padding: 6px 8px;
    line-height: 1;
}

/* ---------- forms ------------------------------------------------------- */

.form-control,
.form-select {
    font-size: 13px;
    padding: 7px 11px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    color: var(--ink);
    background-color: var(--surface);
    transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}

/* Bootstrap draws the select's arrow inside the right padding; the 11px above put it on top
   of the text, so a short select ("Select...", "CA") clipped its words. */
.form-select {
    padding-right: 32px;
    min-width: 7.5rem;
}

.form-control:hover:not(:focus),
.form-select:hover:not(:focus) {
    border-color: #cfd6e2;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
    background-color: var(--surface);
}

.form-control::placeholder {
    color: var(--ink-4);
}

.form-control-sm, .form-select-sm {
    font-size: 12px;
    padding: 5px 9px;
}

.form-select-sm {
    padding-right: 28px;
}

.form-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-2);
    margin-bottom: 4px;
}

.form-text {
    font-size: 11.5px;
    color: var(--ink-3);
}

.form-check-input {
    border-color: #c3cbd9;
    transition: background-color var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}

.form-check-input:checked {
    background-color: var(--brand);
    border-color: var(--brand);
}

.form-check-input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.form-check-label {
    font-size: 13px;
}

.form-check-label .small {
    margin-left: 6px;
}

.input-group-text {
    font-size: 12.5px;
    background: var(--surface-2);
    border-color: var(--line);
    color: var(--ink-3);
}

.validation-summary-errors,
.field-validation-error,
.text-danger {
    color: var(--bad) !important;
}

.validation-summary-errors ul {
    margin: 0;
    padding-left: 18px;
}

code {
    font-family: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
    font-size: .92em;
    color: var(--ink);
    background: var(--line-soft);
    border: 1px solid var(--line);
    border-radius: var(--r-xs);
    padding: 1px 5px;
}

/* ---------- cards ------------------------------------------------------- */

.content-card {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-xs);
    transition: box-shadow var(--t);
}

/* Not overflow:hidden - that would clip the export menu against the bottom of a
   short card. The inner pieces round their own corners instead. */
.content-card > :first-child {
    border-top-left-radius: var(--r);
    border-top-right-radius: var(--r);
}

.content-card > :last-child {
    border-bottom-left-radius: var(--r);
    border-bottom-right-radius: var(--r);
}

.content-card:hover {
    box-shadow: var(--shadow-sm);
}

.card-header {
    background: var(--surface);
    border-bottom: 1px solid var(--line-soft);
    font-weight: 650;
    font-size: 13.5px;
    letter-spacing: -.005em;
    padding: 12px 16px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
}

.card-header .bi {
    color: var(--ink-3);
    margin-right: 5px;
}

.card-header .fw-normal {
    font-size: 12px;
    margin-left: 6px;
    color: var(--ink-3);
}

.card-header .float-end {
    margin-left: auto;
    float: none !important;
    font-size: 12.5px;
}

.card-body {
    padding: 16px;
}

.placeholder-icon {
    font-size: 42px;
    color: #c3cbd9;
}

/* ---------- alerts ------------------------------------------------------ */

.alert {
    border: 1px solid transparent;
    border-radius: var(--r);
    font-size: 13px;
    padding: 11px 15px;
    box-shadow: var(--shadow-xs);
    animation: alert-in 260ms cubic-bezier(.4, 0, .2, 1);
}

@keyframes alert-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

.alert-success { background: var(--ok-soft);   border-color: #b7e6cd; color: #0d6b3b; }
.alert-danger  { background: var(--bad-soft);  border-color: #f4c7c7; color: #a01c1c; }
.alert-warning { background: var(--warn-soft); border-color: #f6dcb0; color: #8a4b06; }
.alert-info    { background: var(--info-soft); border-color: #b6e4ee; color: #086b81; }

/* ---------- badges ------------------------------------------------------ */

.badge {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .01em;
    padding: 3.5px 8px;
    border-radius: var(--r-pill);
}

.badge.text-bg-success { background: var(--ok-soft) !important;   color: #0d6b3b !important; }
.badge.text-bg-warning { background: var(--warn-soft) !important; color: #8a4b06 !important; }
.badge.text-bg-danger  { background: var(--bad-soft) !important;  color: #a01c1c !important; }
.badge.text-bg-primary { background: var(--brand-soft) !important; color: var(--brand-strong) !important; }
.badge.text-bg-secondary { background: var(--line-soft) !important; color: var(--ink-2) !important; }

/* ---------- dropdowns --------------------------------------------------- */

.dropdown-menu {
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-lg);
    padding: 6px;
    font-size: 13px;
    animation: menu-in 140ms cubic-bezier(.4, 0, .2, 1);
}

@keyframes menu-in {
    from { opacity: 0; translate: 0 -4px; scale: .98; }
    to   { opacity: 1; translate: none;   scale: none; }
}

/* The confirmation modal (ui.js mkiConfirm): one plain question, two buttons that say what they do. */
.mki-confirm .modal-body {
    font-size: 14px;
    line-height: 1.5;
    white-space: pre-line;
}

.mki-confirm .modal-footer {
    gap: 8px;
}

.mki-confirm .modal-footer .btn {
    min-width: 110px;
}

.dropdown-item {
    border-radius: var(--r-xs);
    padding: 7px 10px;
    font-size: 13px;
    color: var(--ink);
    transition: background var(--t-fast), color var(--t-fast);
}

.dropdown-item:hover,
.dropdown-item:focus {
    background: var(--brand-soft);
    color: var(--brand-strong);
}

.dropdown-divider {
    margin: 5px 2px;
    border-color: var(--line-soft);
}

/* ---------- tables ------------------------------------------------------ */

.table {
    color: var(--ink);
    margin-bottom: 0;
}

.data-table {
    font-size: 13px;
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
}

.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--surface-2);
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 700;
    white-space: nowrap;
    border-bottom: 1px solid var(--line);
    border-top: 0;
    padding: 9px 13px;
}

.data-table td {
    padding: 8px 13px;
    vertical-align: middle;
    border-bottom: 1px solid var(--line-soft);
    background: transparent;
}

.data-table tbody tr {
    transition: background var(--t-fast), box-shadow var(--t-fast);
}

/* The row highlight the old system never had. */
.data-table tbody tr:hover td {
    background: var(--brand-softer);
}

.data-table tbody tr:hover td:first-child {
    box-shadow: inset 3px 0 0 var(--brand);
}

.data-table tbody tr:last-child td {
    border-bottom: 0;
}

.data-table .text-end {
    font-variant-numeric: tabular-nums;
}

.data-table a {
    font-weight: 550;
}

.table-responsive {
    border-radius: 0 0 var(--r) var(--r);
}

/* Sortable headers, wired by datagrid.js */
.data-table thead th.grid-sortable {
    cursor: pointer;
    user-select: none;
    transition: color var(--t-fast), background var(--t-fast);
}

.data-table thead th.grid-sortable:hover {
    color: var(--brand);
    background: var(--brand-soft);
}

.data-table thead th.grid-sortable::after {
    content: "\F0DC";
    font-family: bootstrap-icons;
    font-size: 9px;
    margin-left: 5px;
    opacity: .25;
    vertical-align: middle;
}

.data-table thead th.grid-asc::after  { content: "\F0DD"; opacity: 1; color: var(--brand); }
.data-table thead th.grid-desc::after { content: "\F0D8"; opacity: 1; color: var(--brand); }

/* ---------- grid toolbar (search / rows / export) ----------------------- */

.grid-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line-soft);
    background: var(--surface);
}

.grid-search {
    position: relative;
    flex: 1 1 160px;
    min-width: 130px;
    max-width: 320px;
}

.grid-search .bi {
    position: absolute;
    left: 11px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ink-4);
    font-size: 13px;
    pointer-events: none;
    transition: color var(--t-fast);
}

.grid-search:focus-within .bi {
    color: var(--brand);
}

.grid-search input {
    width: 100%;
    padding: 6px 30px 6px 31px;
    font-size: 12.5px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--surface-2);
    transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}

.grid-search input:focus {
    outline: none;
    background: var(--surface);
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-ring);
}

.grid-search-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: transparent;
    color: var(--ink-4);
    font-size: 13px;
    line-height: 1;
    padding: 3px 5px;
    border-radius: 50%;
    cursor: pointer;
    display: none;
    transition: background var(--t-fast), color var(--t-fast);
}

.grid-search-clear:hover { background: var(--line-soft); color: var(--ink); }
.grid-search.has-text .grid-search-clear { display: block; }

.grid-toolbar-spacer {
    flex: 1 1 auto;
}

.grid-count {
    font-size: 11.5px;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.grid-count b {
    color: var(--ink);
    font-weight: 650;
}

.grid-rows-label {
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
}

.grid-rows-select {
    font-size: 12px;
    padding: 4px 24px 4px 9px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background-color: var(--surface);
    color: var(--ink);
    cursor: pointer;
}

/* Set by datagrid.js: filtered out by the search, or on another page. */
.data-table tbody tr.grid-filtered-out,
.data-table tbody tr.grid-page-hidden {
    display: none;
}

.grid-rows-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
}

.grid-toolbar .dropdown-item {
    display: flex;
    align-items: center;
    gap: 8px;
}

.grid-toolbar .dropdown-item .bi {
    color: var(--ink-3);
    font-size: 14px;
}

.grid-no-match td {
    padding: 26px 14px !important;
    text-align: center;
    color: var(--ink-3);
}

.grid-no-match .bi {
    display: block;
    font-size: 26px;
    margin-bottom: 6px;
    color: #c3cbd9;
}

/* client-side pager, styled to match the server one */
.grid-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-top: 1px solid var(--line-soft);
    background: var(--surface);
}

/* ---------- pagination -------------------------------------------------- */

.pager-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-top: 1px solid var(--line-soft);
    background: var(--surface);
}

.pager-summary {
    font-size: 11.5px;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

.pagination {
    gap: 3px;
}

.page-link {
    border: 1px solid transparent;
    border-radius: var(--r-sm) !important;
    color: var(--ink-2);
    font-size: 12.5px;
    font-weight: 550;
    padding: 5px 10px;
    min-width: 30px;
    text-align: center;
    transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}

.page-link:hover {
    background: var(--brand-soft);
    border-color: #cddffb;
    color: var(--brand-strong);
    transform: translateY(-1px);
}

.page-item.active .page-link {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    box-shadow: 0 1px 3px rgba(37, 99, 235, .35);
}

.page-item.disabled .page-link {
    color: var(--ink-4);
    background: transparent;
    border-color: transparent;
}

/* ---------- today's orders, one line per warehouse ----------------------- */

/* The strip is not a link itself: each stuck state has its own button on the
   right, leading to the page where that state is cleared. Two flex items: the
   icon with its sentence, and the buttons. On a narrow screen the buttons drop
   under the sentence and wrap among themselves; the sentence keeps its icon. */
.attention-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    padding: 10px 12px 10px 16px;
    margin-bottom: 14px;
    border-radius: var(--r);
    background: var(--warn-soft);
    border: 1px solid #f3d9a8;
    color: #8a4b06;
    font-size: 13.5px;
    box-shadow: var(--shadow-xs);
}

.attention-lead {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1 1 320px;
    min-width: 0;
}

.attention-lead > .bi {
    font-size: 17px;
    flex: 0 0 auto;
    color: var(--warn);
}

.attention-text {
    min-width: 0;
}

.attention-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
}

.attention-go {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .7);
    border: 1px solid #e6bd76;
    color: inherit;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none;
    transition: background var(--t), border-color var(--t), box-shadow var(--t);
}

.attention-go:hover {
    color: #6f3c05;
    background: #fff;
    border-color: #d9a856;
    box-shadow: var(--shadow-xs);
    text-decoration: none;
}

.attention-go .bi {
    font-size: 14px;
}

.wh-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(285px, 1fr));
    align-items: stretch;
    gap: 12px;
}

.wh-tile {
    display: flex;
    align-items: center;
    min-height: 62px;
    gap: 11px;
    padding: 11px 14px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-xs);
    color: var(--ink);
    text-decoration: none;
    transition: box-shadow var(--t), transform var(--t), border-color var(--t);
}

.wh-tile:hover {
    color: var(--ink);
    text-decoration: none;
    border-color: #d5dded;
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
}

.wh-tile:hover .wh-go {
    transform: translateX(3px);
    color: var(--brand);
}

.wh-body {
    flex: 1 1 auto;
    min-width: 0;
}

.wh-head {
    display: flex;
    align-items: baseline;
    gap: 7px;
}

.wh-code {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -.01em;
}

.wh-name {
    font-size: 11.5px;
    color: var(--ink-4);
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wh-state {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.wh-meter {
    display: block;
    height: 4px;
    margin: 7px 0 6px;
    border-radius: var(--r-pill);
    background: var(--line-soft);
    overflow: hidden;
}

.wh-meter > span {
    display: block;
    height: 100%;
    border-radius: inherit;
    transition: width var(--t);
}

.wh-counts {
    display: block;
    font-size: 11.5px;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
    line-height: 1.45;
}

.wh-counts b {
    color: var(--ink);
    font-weight: 650;
}

.wh-sep {
    margin: 0 5px;
    color: var(--ink-4);
}

.wh-go {
    flex: 0 0 auto;
    font-size: 17px;
    color: var(--ink-4);
    transition: transform var(--t), color var(--t);
}

/* ---- the status lamp ----
   A solid dot with a pale ring of the same colour around it, the same shape the
   carrier panels use. Every state is this lamp in a different colour; the ring is
   the only part that moves. Both take the colour from currentColor, so a state
   only has to set `color` once. */

.wh-lamp {
    position: relative;
    width: 11px;
    height: 11px;
    flex: 0 0 auto;
    margin: 0 5px;
    border-radius: 50%;
    background: currentColor;
}

.wh-lamp::before {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: 50%;
    background: currentColor;
    opacity: .22;
}

/* The ring itself breathes, between a little smaller and its own full size. An
   earlier version grew a third ring outside this one, which made the lamp nearly
   twice as wide while it played. Nothing here ever exceeds the ring above. */
.wh-tile:not(.wh-idle) .wh-lamp::before {
    animation: wh-pulse 2.6s ease-in-out infinite;
}

.wh-waiting .wh-lamp::before { animation-duration: 2s; }

@keyframes wh-pulse {
    0%, 100% { transform: scale(.68); opacity: .12; }
    50%      { transform: scale(1);   opacity: .34; }
}

.wh-waiting  { color: var(--bad); }
.wh-active   { color: var(--brand); }
.wh-done     { color: var(--ok); }
.wh-idle     { color: var(--ink-4); }

.wh-waiting .wh-meter > span { background: var(--bad); }
.wh-active  .wh-meter > span { background: var(--brand); }
.wh-done    .wh-meter > span { background: var(--ok); }
.wh-idle    .wh-meter > span { background: var(--ink-4); }

.wh-waiting .wh-state { color: var(--bad); }
.wh-active  .wh-state { color: var(--brand); }
.wh-done    .wh-state { color: var(--ok); }
.wh-idle    .wh-state { color: var(--ink-4); }

.wh-tile .wh-code,
.wh-tile .wh-counts b {
    color: var(--ink);
}

.section-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

/* ---------- dashboard status cards -------------------------------------- */

.status-table {
    font-size: 13px;
    margin-bottom: 0;
}

.status-table thead th {
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 700;
    border-bottom: 1px solid var(--line);
    padding: 9px 12px;
}

.status-table td {
    padding: 8px 12px;
    vertical-align: middle;
    border-bottom: 1px solid var(--line-soft);
    transition: background var(--t-fast);
}

.status-table tbody tr:hover td {
    background: var(--brand-softer);
}

.status-table tr:last-child td {
    border-bottom: 0;
}

.status-dot-cell {
    width: 26px;
    padding-right: 0 !important;
}

.status-dot {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    position: relative;
}

.status-dot::after {
    content: "";
    position: absolute;
    inset: -3px;
    border-radius: 50%;
    background: inherit;
    opacity: .2;
}

.status-green { background: var(--ok); }
.status-red   { background: var(--bad); }
.status-blue  { background: var(--brand); }

.status-label {
    color: var(--ink-2);
}

.status-count {
    text-align: right;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    padding-right: 14px !important;
}

/* "x48" beside a collapsed notification: how many times it has been reported. */
.repeat-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: var(--r-pill);
    background: var(--warn-soft);
    border: 1px solid #f0d3a4;
    color: #8a4b06;
    font-size: 11px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    vertical-align: 1px;
    white-space: nowrap;
}

.notification-list .list-group-item {
    border-color: var(--line-soft);
    font-size: 13px;
    padding: 10px 16px;
    transition: background var(--t-fast);
}

.notification-list .list-group-item:hover {
    background: var(--brand-softer);
}

/* ---------- the dashboard fills the window ------------------------------
   The strip, the warehouse row and the notifications keep their own height;
   the search card takes whatever is left, so the page ends exactly at the
   bottom of the window rather than a little above or below it. When the
   strip is showing, the search card gives up that much. On a short screen
   the card stops at its natural height and the page scrolls as usual. */

.app-content-fill {
    display: flex;
    flex-direction: column;
}

.dashboard {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
    min-height: 0;
}

.dashboard > * {
    flex: 0 0 auto;
}

.dashboard .attention-strip {
    margin-bottom: 0;
}

.dashboard > .dashboard-fill {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

.dashboard-fill > .find-order-card {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* ---------- find an order (the dashboard search box) --------------------- */

.find-order-card {
    padding: 20px 22px 18px;
}

.find-order-label {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    margin-bottom: 10px;
    font-size: 15px;
    font-weight: 650;
    color: var(--ink);
}

.find-order-label span {
    font-size: 12.5px;
    font-weight: 400;
    color: var(--ink-3);
}

.find-order-row {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.find-order-field {
    position: relative;
    flex: 1 1 320px;
    min-width: 0;
}

.find-order-field > .bi {
    position: absolute;
    left: 17px;
    top: 50%;
    translate: 0 -50%;
    font-size: 18px;
    color: var(--ink-4);
    pointer-events: none;
    transition: color var(--t-fast);
}

.find-order-field:focus-within > .bi {
    color: var(--brand);
}

/* A big target: this is the first thing on the page and the thing used most. */
.find-order-input {
    width: 100%;
    height: 54px;
    padding: 0 16px 0 48px;
    font-size: 17px;
    font-weight: 500;
    color: var(--ink);
    background: var(--surface);
    border: 1.5px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-xs);
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}

.find-order-input::placeholder {
    color: var(--ink-4);
    font-weight: 400;
}

.find-order-input:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 4px var(--brand-ring);
}

.find-order-btn {
    height: 54px;
    padding: 0 22px 0 26px;
    font-size: 15px;
    font-weight: 600;
    border-radius: var(--r);
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
}

.find-order-btn .bi {
    font-size: 22px;
    line-height: 1;
}

@media (max-width: 575.98px) {
    .find-order-btn { width: 100%; }
}

/* ---------- the hero variant on the dashboard ---------------------------
   The sign-in page's stage, brought inside: the same deep navy, the same
   surveyor's grid and warm light (the scanner beam was tried and dropped -
   nothing on this card moves). The fields are dark-surface too, as on that
   page, with a white placeholder. The title stays pinned to the
   top of the card however tall it gets; the box sits on the card's own centre
   line, half the card wide, the way a search engine's front page does it. The
   results page keeps the plain white version above. */

.find-order-hero {
    position: relative;
    overflow: hidden;          /* clips the beam; nothing in here drops a menu */
    isolation: isolate;
    background: linear-gradient(165deg, #16233a 0%, #101827 45%, #0b111c 100%);
    border-color: rgba(148, 178, 235, .14);
    color: #e9eff8;
    box-shadow: 0 10px 30px rgba(6, 12, 24, .28);
}

.find-order-hero .hero-grid {
    position: absolute;
    inset: 0;
    z-index: -3;
    background-image:
        linear-gradient(rgba(148, 178, 235, .055) 1px, transparent 1px),
        linear-gradient(90deg, rgba(148, 178, 235, .055) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: linear-gradient(180deg, #000 0%, #000 60%, transparent 100%);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 60%, transparent 100%);
}

.find-order-hero .hero-glow {
    position: absolute;
    top: -60%;
    left: -8%;
    width: 46%;
    aspect-ratio: 1;
    z-index: -2;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(61, 116, 224, .30) 0%, rgba(61, 116, 224, 0) 68%);
    filter: blur(6px);
}

.find-order-hero .find-order-card {
    padding: 18px 22px;
    justify-content: flex-start;
}

.find-order-hero .find-order {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

/* A headline, not a field label: the dashboard's copy says what this box is
   for, and the line under it, in the sign-in page's muted blue, says what
   can be done from it. Stacked, pinned to the top-left of the card. */
.find-order-hero .find-order-label {
    display: block;
    color: #fff;
    margin-bottom: 0;
    font-size: 19px;
    font-weight: 650;
    line-height: 26px;
    letter-spacing: -.01em;
}

.find-order-hero .find-order-label span {
    display: block;
    margin-top: 4px;
    font-size: 13px;
    line-height: 18px;
    font-weight: 400;
    color: #93a6c2;
}

/* The headline block above is 48px tall and the row sits 12px under it, so
   60px of bottom padding balances that out: the box lands on the card's own
   centre line, not the centre of what is left under the headline. */
.find-order-hero .find-order-row {
    flex: 1 1 auto;
    align-content: center;
    justify-content: center;
    width: 50%;
    min-width: 320px;
    max-width: 100%;
    margin: 12px auto 0;
    padding: 0 0 60px;
}

.find-order-hero .find-order-field {
    flex: 1 1 220px;
}

.find-order-hero .find-order-field > .bi {
    color: #62728c;
}

.find-order-hero .find-order-field:focus-within > .bi {
    color: #4d8bff;
}

/* The sign-in page's field: translucent on the dark ground, a faint blue edge,
   the brand blue only when it has focus. */
/* Solid, pre-blended outline and a fill clipped at the padding edge, for the
   same reason as the sign-in fields: translucent border over translucent fill
   doubles up on the rounded corners. */
.find-order-hero .find-order-input {
    background: rgba(255, 255, 255, .045);
    background-clip: padding-box;
    border: 1px solid #283449;
    color: #e9eff8;
    box-shadow: none;
    font-weight: 450;
}

.find-order-hero .find-order-input:hover:not(:focus) {
    border-color: #3a4966;
}

.find-order-hero .find-order-input:focus {
    background: rgba(255, 255, 255, .07);
    border-color: #4d8bff;
    box-shadow: 0 0 0 3px rgba(77, 139, 255, .2);
    color: #fff;
}

/* Between the sign-in page's #62728c (too dim here) and plain white (too loud). */
.find-order-hero .find-order-input::placeholder {
    color: #b4c0d3;
}

/* Chrome's native clear button is drawn dark and vanishes on this ground. */
.find-order-hero .find-order-input::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}

.find-order-hero .find-order-input:-webkit-autofill,
.find-order-hero .find-order-input:-webkit-autofill:hover,
.find-order-hero .find-order-input:-webkit-autofill:focus {
    -webkit-text-fill-color: #e9eff8;
    -webkit-box-shadow: 0 0 0 1000px #131c2b inset;
    caret-color: #e9eff8;
}

.find-order-hero .find-order-btn {
    --btn-shadow: 0 6px 18px rgba(37, 99, 235, .35);
}

@media (max-width: 767.98px) {
    .find-order-hero .find-order-row {
        width: 100%;
        min-width: 0;
    }
}

/* ---------- the order page ---------------------------------------------
   One page per order. The header is the system's navy: identity, one overall
   state, the actions that state allows, and the facts as a strip of tiles. The
   timeline runs the full width, one equal slot per step with an arrow between,
   so it reads as a path. Below it the lines and shipping on the left, NAV,
   related records and activity on the right. Tones use the six semantic
   colours as ink and dots, never as pastel fills. */

.od-page {
    --od-navy: #16233a;
    --od-navy-2: #101827;
    --od-navy-3: #0b111c;
    --od-on-navy: #e9eff8;
    --od-on-navy-2: #b4c0d3;
    --od-on-navy-3: #7f8da6;
    --od-hairline: rgba(148, 178, 235, .16);
    --od-ok: #34c77b;
    --od-warn: #f0a63a;
    --od-bad: #f36c6c;
    --od-info: #38bdf8;
    --od-brand: #5b93ff;
}

/* ---- header ---- */

.od-head {
    position: relative;
    isolation: isolate;
    z-index: 3;                              /* its menus open over the cards below, not under them */
    overflow: visible;                       /* the More menu drops below it */
    background: linear-gradient(165deg, var(--od-navy) 0%, var(--od-navy-2) 45%, var(--od-navy-3) 100%);
    border-color: var(--od-hairline);
    color: var(--od-on-navy);
    box-shadow: 0 10px 30px rgba(6, 12, 24, .28);
}

/* The dashboard hero's grid and glow, clipped to the card by this wrapper. */
.od-head-bg {
    position: absolute;
    inset: 0;
    border-radius: inherit;
    overflow: hidden;
    pointer-events: none;
    z-index: -1;
}

.od-head-bg .hero-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgba(148, 178, 235, .055) 1px, transparent 1px),
        linear-gradient(90deg, rgba(148, 178, 235, .055) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: linear-gradient(180deg, #000 0%, #000 60%, transparent 100%);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 60%, transparent 100%);
}

.od-head-bg .hero-glow {
    position: absolute;
    top: -120%;
    left: -6%;
    width: 38%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(61, 116, 224, .32) 0%, rgba(61, 116, 224, 0) 68%);
    filter: blur(6px);
}

.od-head .card-body {
    padding: 20px 24px 18px;
}

.od-head-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 18px;
}

.od-id {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    flex: 1 1 320px;
    min-width: 0;
}

.od-number {
    font-family: ui-monospace, Consolas, "SF Mono", monospace;
    font-size: 26px;
    font-weight: 600;
    letter-spacing: .02em;
    color: #fff;
    text-shadow: 0 1px 0 rgba(0, 0, 0, .25);
}

.od-kind,
.od-state {
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    padding: 5px 11px;
    border-radius: var(--r-pill);
    border: 1px solid transparent;
}

.od-head .badge.od-kind {
    background: rgba(255, 255, 255, .08) !important;
    border-color: rgba(255, 255, 255, .18);
    color: var(--od-on-navy) !important;
}

.od-head .badge.od-state {
    background: rgba(255, 255, 255, .06) !important;
    color: var(--od-on-navy) !important;
}

.od-head .badge.od-state::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin: 0 7px 1px 0;
    background: currentColor;
}

.od-head .badge.od-state.text-bg-success   { color: var(--od-ok) !important;    border-color: rgba(52, 199, 123, .45); }
.od-head .badge.od-state.text-bg-primary   { color: var(--od-brand) !important; border-color: rgba(91, 147, 255, .5); }
.od-head .badge.od-state.text-bg-info      { color: var(--od-info) !important;  border-color: rgba(56, 189, 248, .45); }
.od-head .badge.od-state.text-bg-warning   { color: var(--od-warn) !important;  border-color: rgba(240, 166, 58, .5); }
.od-head .badge.od-state.text-bg-danger    { color: var(--od-bad) !important;   border-color: rgba(243, 108, 108, .5); }
.od-head .badge.od-state.text-bg-secondary { color: var(--od-on-navy-2) !important; border-color: rgba(255, 255, 255, .2); }

.od-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    justify-content: flex-end;
    flex: 0 1 auto;
    max-width: 100%;
}

.od-actions form {
    display: inline;
}

/* Buttons sit on navy: outlines go light, fills keep their colour but lose the glow. */
.od-head .btn {
    --btn-shadow: none;
    font-weight: 500;
}

.od-head .btn-outline-secondary {
    --btn-fg: var(--od-on-navy);
    --btn-bg: rgba(255, 255, 255, .04);
    --btn-border: rgba(255, 255, 255, .28);
    color: var(--od-on-navy);
    background: rgba(255, 255, 255, .04);
    border-color: rgba(255, 255, 255, .28);
}

.od-head .btn-outline-secondary:hover,
.od-head .btn-outline-secondary:focus-visible,
.od-head .btn-outline-secondary.show {
    color: #fff;
    background: rgba(255, 255, 255, .12);
    border-color: rgba(255, 255, 255, .45);
}

.od-head .btn-outline-danger {
    color: var(--od-bad);
    background: rgba(243, 108, 108, .06);
    border-color: rgba(243, 108, 108, .45);
}

.od-head .btn-outline-danger:hover:not(:disabled) {
    color: #fff;
    background: var(--bad);
    border-color: var(--bad);
}

/* Amber and blue outlines were never restyled for the navy header: the base button text is
   dark ink, so "Release hold" showed only its badge until hovered. */
.od-head .btn-outline-warning {
    color: #f5c452;
    background: rgba(245, 196, 82, .08);
    border-color: rgba(245, 196, 82, .5);
}

.od-head .btn-outline-warning:hover:not(:disabled),
.od-head .btn-outline-warning:focus-visible {
    color: #1b2333;
    background: #f5c452;
    border-color: #f5c452;
}

.od-head .btn-outline-primary {
    color: #9cc0ff;
    background: rgba(156, 192, 255, .08);
    border-color: rgba(156, 192, 255, .5);
}

.od-head .btn-outline-primary:hover:not(:disabled),
.od-head .btn-outline-primary:focus-visible {
    color: #fff;
    background: var(--brand);
    border-color: var(--brand);
}

.od-head .btn:disabled {
    opacity: .45;
}

.od-head .dropdown-menu {
    color: var(--ink);
}

.od-actions .dropdown-item {
    background: none;
    border: 0;
    width: 100%;
    text-align: left;
}

/* The current load in the picking-list dropdown. Bootstrap's .active would paint the text
   white, and .od-actions .dropdown-item strips the blue behind it, so it went invisible. */
.od-actions .dropdown-item.od-load-current {
    background: var(--brand-soft);
    color: var(--brand-strong);
    font-weight: 600;
}

.od-load-tag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    vertical-align: 1px;
}

.od-load-meta {
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
}

.od-actions .dropdown-item.od-load-current .od-load-meta {
    color: var(--brand-strong);
    opacity: .8;
}

.od-reason {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin-top: 16px;
    padding: 10px 14px;
    border-radius: var(--r-sm);
    font-size: 13.5px;
    line-height: 1.45;
    background: rgba(255, 255, 255, .05);
    border: 1px solid var(--od-hairline);
    border-left: 3px solid var(--od-on-navy-3);
    color: var(--od-on-navy);
}

.od-reason > .bi {
    flex: 0 0 auto;
    margin-top: 2px;
    color: var(--od-on-navy-2);
}

.od-reason.tone-success { border-left-color: var(--od-ok); }
.od-reason.tone-primary { border-left-color: var(--od-brand); }
.od-reason.tone-info    { border-left-color: var(--od-info); }
.od-reason.tone-warning { border-left-color: var(--od-warn); }
.od-reason.tone-danger  { border-left-color: var(--od-bad); }

.od-hint {
    color: var(--od-on-navy-2);
}

.od-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    margin: 18px 0 0;
    border-top: 1px solid var(--od-hairline);
    padding-top: 14px;
}

.od-facts > div {
    min-width: 0;
    padding: 0 22px 0 0;
    margin-right: 22px;
    border-right: 1px solid var(--od-hairline);
}

.od-facts > div:last-child {
    border-right: 0;
    margin-right: 0;
    padding-right: 0;
}

.od-facts dt {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--od-on-navy-3);
    margin-bottom: 2px;
}

.od-facts dd {
    margin: 0;
    font-size: 14px;
    font-weight: 500;
    color: #fff;
}

.od-facts dd .text-muted {
    color: var(--od-on-navy-2) !important;
    font-weight: 400;
    margin-left: 4px;
}

/* ---- timeline: one equal slot per step, arrows between ---- */

.od-timeline .card-body {
    padding: 22px 20px 18px;
}

.od-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(var(--steps, 8), minmax(0, 1fr));
    gap: 0;
}

.od-step {
    position: relative;
    min-width: 0;
    padding: 0 18px 0 6px;
}

/* The path: a line from each node to the next. */
.od-step::before {
    content: "";
    position: absolute;
    top: 17px;
    left: 40px;
    right: -8px;
    height: 2px;
    background: var(--line);
}

.od-step:last-child::before {
    display: none;
}

.od-step-node {
    position: relative;
    z-index: 1;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 15px;
    background: var(--surface);
    border: 2px solid var(--line);
    color: var(--ink-4);
    box-shadow: 0 0 0 4px var(--surface);
}

.od-step-body {
    margin-top: 10px;
}

.od-step-idx {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-4);
    font-variant-numeric: tabular-nums;
}

.od-step-title {
    display: block;
    font-size: 13.5px;
    font-weight: 650;
    color: var(--ink);
    letter-spacing: -.005em;
    margin-top: 1px;
}

.od-step .od-when,
.od-step .od-detail {
    display: block;
    font-size: 12px;
    line-height: 1.4;
    color: var(--ink-3);
    overflow-wrap: anywhere;
}

.od-step .od-when {
    margin-top: 3px;
    color: var(--ink-2);
}

.od-step .od-detail {
    margin-top: 2px;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* done: navy, the path behind it is navy too */
.od-done .od-step-node {
    background: var(--od-navy);
    border-color: var(--od-navy);
    color: #fff;
}

.od-done::before {
    background: var(--od-navy);
}

/* now: brand ring, the step the order is on */
.od-now .od-step-node {
    background: var(--brand);
    border-color: var(--brand);
    color: #fff;
    box-shadow: 0 0 0 4px var(--surface), 0 0 0 6px var(--brand-ring);
}

.od-now .od-step-title {
    color: var(--brand-strong);
}

/* hold: amber */
.od-hold .od-step-node {
    background: var(--surface);
    border-color: var(--warn);
    color: var(--warn);
}

.od-hold .od-step-title {
    color: #8a4b06;
}

/* bad: red */
.od-bad .od-step-node {
    background: var(--bad);
    border-color: var(--bad);
    color: #fff;
}

.od-bad .od-step-title {
    color: #a01c1c;
}

/* skip: dashed, greyed */
.od-skip .od-step-node {
    border-style: dashed;
    color: var(--ink-4);
}

.od-skip .od-step-title {
    color: var(--ink-4);
    text-decoration: line-through;
    text-decoration-color: rgba(154, 164, 182, .7);
}

.od-skip .od-when,
.od-skip .od-detail {
    color: var(--ink-4);
}

/* pending: outline only */
.od-pending .od-step-title {
    color: var(--ink-3);
}

@media (max-width: 1199.98px) {
    .od-steps {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        row-gap: 22px;
    }

    .od-step:nth-child(4n)::before {
        display: none;
    }
}

@media (max-width: 575.98px) {
    .od-steps {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .od-step:nth-child(2n)::before {
        display: none;
    }
}

/* ---- cards below ---- */

.od-page .card-header {
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-2);
    padding: 11px 16px;
}

.od-page .card-header .bi {
    color: var(--od-brand);
}

.od-page .card-header .fw-normal {
    text-transform: none;
    letter-spacing: 0;
    font-size: 12px;
}

.od-page .card-header .float-end {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
}

/* Status pills: a coloured dot and ink, not a pastel block. */
.od-page .badge[class*="text-bg-"] {
    background: var(--surface-2) !important;
    border: 1px solid var(--line);
    color: var(--ink-2) !important;
    font-weight: 500;
    padding: 3px 9px 3px 7px;
    border-radius: var(--r-pill);
}

.od-page .badge[class*="text-bg-"]::before {
    content: "";
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    margin: 0 6px 1px 0;
    background: var(--ink-4);
}

.od-page .badge.text-bg-success::before   { background: var(--ok); }
.od-page .badge.text-bg-primary::before   { background: var(--brand); }
.od-page .badge.text-bg-info::before      { background: var(--info); }
.od-page .badge.text-bg-warning::before   { background: var(--warn); }
.od-page .badge.text-bg-danger::before    { background: var(--bad); }
.od-page .badge.text-bg-success           { color: #0d6b3b !important; }
.od-page .badge.text-bg-danger            { color: #a01c1c !important; }

/* the header keeps its own pills */
.od-head .badge[class*="text-bg-"] {
    border-radius: var(--r-pill);
    padding: 5px 11px;
}

.od-head .badge[class*="text-bg-"]::before {
    background: currentColor;
    width: 7px;
    height: 7px;
    margin-right: 7px;
}

.od-head .badge.od-kind::before {
    display: none;
}

/* Which side of the page a number belongs to: this load at the warehouse, or the whole
   order in NAV. The group header row on Lines and the badge on card titles say it; the
   thin rule after "On hand" separates the two column groups. */
.od-scope-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 2px 9px;
    border-radius: 999px;
    background: #e7eefc;
    color: #24478f;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    vertical-align: middle;
}

.od-lines thead .od-scope-row th {
    font-size: 10px;
    letter-spacing: .08em;
    padding: 5px 13px;
    border-bottom: 0;
    background: var(--surface);
}

.od-lines thead .od-scope-row th .bi {
    margin-right: 4px;
}

.od-lines thead .od-scope-wh {
    color: #1e6b3a;
    background: #edf7f0;
}

.od-lines thead .od-scope-nav {
    color: #5a6478;
    background: #f1f3f7;
}

.od-lines th.od-scope-end,
.od-lines td.od-scope-end {
    border-right: 2px solid var(--line);
}

.od-lines .od-line-actions {
    width: 58px;
    white-space: nowrap;
    text-align: center;
}

.od-lines .od-line-actions .btn-link {
    color: var(--ink-3);
    font-size: 14px;
    line-height: 1;
    vertical-align: middle;
}

.od-lines .od-line-actions .btn-link:hover {
    color: var(--brand-strong);
}

.od-lines .od-line-actions .btn-link.text-danger:hover {
    color: var(--bad) !important;
}

.od-lines tr.od-notinload td {
    color: var(--ink-3);
    background: #fafbfd;
}

.od-lines tr.od-divider td {
    padding: 6px 13px !important;
    font-size: 11.5px;
    color: var(--ink-3);
    background: #f1f3f7;
    border-top: 2px solid var(--line);
}

.od-allloads {
    padding: 9px 14px;
    border-top: 1px solid var(--line-soft);
    font-size: 12.5px;
    color: var(--ink-2);
    background: #fafbfd;
}

.od-allloads .bi {
    margin-right: 4px;
    color: var(--ink-3);
}

/* Totals by order: this order's row is marked, and a Posted / Invoiced figure that does not
   match Shipped is tinted so the mismatch is seen before the invoice button is pressed. */
.od-totals td,
.od-totals th {
    font-variant-numeric: tabular-nums;
}

.od-totals-this td {
    background: var(--surface-2);
}

.od-totals-off {
    background: #fff4d6 !important;
    color: #8a5a00;
    font-weight: 600;
}

/* The Total row is <th> for weight, but takes the body cells' padding and size so its
   numbers sit exactly under the rows above (Bootstrap's own th padding is narrower). */
.od-totals-sum th {
    padding: 8px 13px;
    font-size: inherit;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink);
    border-top: 2px solid var(--line);
    border-bottom: 0;
    background: var(--surface);
    vertical-align: middle;
}

.od-lines td,
.od-lines th {
    white-space: nowrap;
    vertical-align: middle;
}

.od-lines td:first-child {
    white-space: normal;
    min-width: 160px;
}

.od-lines tbody tr:nth-child(even) td {
    background: var(--surface-2);
}

.od-lines td.text-end {
    font-variant-numeric: tabular-nums;
}

/* ---- facts lists ---- */

.od-kv {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 7px 16px;
    margin: 0;
    font-size: 13px;
}

.od-kv dt {
    color: var(--ink-3);
    font-weight: 500;
}

.od-kv dd {
    margin: 0;
    color: var(--ink);
    overflow-wrap: anywhere;
}

/* ---- shipping: two address tiles, a tile row of freight facts, the labels ---- */

.od-ship {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
}

.od-addr {
    display: flex;
    gap: 14px;
    padding: 16px;
    border-radius: var(--r);
    border: 1px solid var(--line);
    background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%);
    box-shadow: var(--shadow-xs);
    min-width: 0;
}

.od-addr-icon {
    flex: 0 0 40px;
    width: 40px;
    height: 40px;
    border-radius: 11px;
    display: grid;
    place-items: center;
    font-size: 17px;
    color: #fff;
    background: linear-gradient(160deg, var(--od-navy) 0%, var(--od-navy-3) 100%);
    box-shadow: 0 4px 12px rgba(16, 35, 58, .28);
}

.od-addr-bill .od-addr-icon {
    background: linear-gradient(160deg, #3b4a63 0%, #232e42 100%);
}

.od-addr-body {
    min-width: 0;
    flex: 1 1 auto;
}

.od-addr-label {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.od-addr-label span {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 500;
    color: var(--ink-4);
    margin-left: 6px;
}

.od-addr-name {
    font-size: 15px;
    font-weight: 650;
    color: var(--ink);
    letter-spacing: -.01em;
    margin-top: 3px;
    overflow-wrap: anywhere;
}

.od-addr-lines {
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--ink-2);
    margin-top: 2px;
    overflow-wrap: anywhere;
}

.od-addr-empty {
    font-size: 13.5px;
    color: var(--ink-3);
    margin-top: 4px;
}

.od-addr-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
}

.od-addr-meta span {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    padding: 3px 9px;
    border-radius: var(--r-pill);
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink-2);
}

.od-addr-meta span .bi {
    color: var(--od-brand);
}

.od-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
    gap: 10px;
    margin-top: 14px;
}

.od-tile {
    padding: 10px 12px;
    border-radius: var(--r-sm);
    border: 1px solid var(--line-soft);
    background: var(--surface-2);
    min-width: 0;
}

.od-tile dt {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.od-tile dd {
    margin: 2px 0 0;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--ink);
    overflow-wrap: anywhere;
}

.od-tile dd .text-muted {
    font-weight: 400;
}

.od-note {
    margin-top: 14px;
    padding: 10px 14px;
    border-radius: var(--r-sm);
    border: 1px dashed var(--line);
    background: var(--surface-2);
    color: var(--ink-3);
    font-size: 13px;
}

.od-labels {
    margin-top: 14px;
    border: 1px solid var(--line-soft);
    border-radius: var(--r-sm);
    overflow: hidden;
}

.od-labels .table {
    margin: 0;
}

.od-labels thead th {
    background: var(--surface-2);
}

.od-labels .od-tracking {
    font-family: ui-monospace, Consolas, "SF Mono", monospace;
    font-size: 12.5px;
    letter-spacing: .02em;
}

@media (max-width: 767.98px) {
    .od-ship {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ---- long lists: ten rows, then View all ---- */

.od-more {
    display: none !important;
}

.od-expanded .od-more {
    display: revert !important;
}

.od-viewall {
    display: flex;
    justify-content: center;
    padding: 8px 12px;
    border-top: 1px solid var(--line-soft);
    background: var(--surface-2);
}

.od-viewall .btn {
    font-size: 12.5px;
    font-weight: 500;
}

.od-expanded .od-viewall .od-viewall-more,
.od-viewall .od-viewall-less {
    display: none;
}

.od-expanded .od-viewall .od-viewall-less {
    display: inline;
}

/* ---- related ---- */

.od-related-title {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: 5px;
}

.od-related-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    font-size: 13px;
    padding: 5px 0;
    border-bottom: 1px dashed var(--line-soft);
}

.od-related-row:last-of-type {
    border-bottom: 0;
}

/* ---- activity: a thin rail with a dot per event ---- */

.od-activity .list-group-item {
    position: relative;
    border-color: var(--line-soft);
    padding: 9px 16px 9px 34px;
    font-size: 13px;
}

.od-activity .list-group-item::before {
    content: "";
    position: absolute;
    left: 18px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--line-soft);
}

.od-activity .list-group-item:first-child::before { top: 16px; }
.od-activity .list-group-item:last-child::before  { bottom: calc(100% - 16px); }

.od-event::after {
    content: "";
    position: absolute;
    left: 14px;
    top: 13px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--ink-4);
    box-shadow: 0 0 0 3px var(--surface);
}

.od-event.tone-success::after   { background: var(--ok); }
.od-event.tone-primary::after   { background: var(--brand); }
.od-event.tone-warning::after   { background: var(--warn); }
.od-event.tone-danger::after    { background: var(--bad); }
.od-event.tone-info::after      { background: var(--info); }
.od-event.tone-secondary::after { background: var(--ink-4); }

.od-event-when {
    font-size: 11.5px;
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

.od-event-text {
    overflow-wrap: anywhere;
    color: var(--ink-2);
}

.od-event-text b {
    color: var(--ink);
    font-weight: 600;
}

/* ---------- operation log ------------------------------------------------ */

.oplog td {
    vertical-align: top;
}

.oplog-message {
    max-width: 420px;
    overflow-wrap: anywhere;
}

.oplog-details td {
    background: var(--surface-2);
}

.oplog-details pre {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 12px;
    color: var(--ink-2);
    max-height: 240px;
    overflow: auto;
}

/* ---------- stat tiles -------------------------------------------------- */

.stat-tile {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    padding: 13px 15px;
    height: 100%;
    box-shadow: var(--shadow-xs);
    position: relative;
    overflow: hidden;
    transition: box-shadow var(--t), transform var(--t), border-color var(--t);
}

.stat-tile::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--brand);
    opacity: .8;
}

.stat-tile:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-2px);
    border-color: #d5dded;
}

.stat-label {
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.stat-value {
    font-size: 25px;
    font-weight: 680;
    line-height: 1.25;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
}

.stat-teal::before { background: #12b39a; }
.stat-blue::before { background: var(--brand); }
.stat-red::before  { background: var(--bad); }

.stat-teal .stat-value { color: #0f9b85; }
.stat-blue .stat-value { color: var(--brand-strong); }
.stat-red  .stat-value { color: var(--bad); }

.stat-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(136px, 1fr));
    gap: 12px;
}

.stat-tiles .stat-tile {
    padding: 11px 13px;
}

.stat-tiles .stat-value {
    font-size: 22px;
}

/* ---------- the employees page ----------------------------------------- */

/* One strip: who the viewer is looking at, the numbers, and the add button. */
.emp-summary {
    display: flex;
    align-items: center;
    gap: 22px;
    padding: 14px 18px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-xs);
    flex-wrap: wrap;
}

.emp-scope {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-right: 22px;
    border-right: 1px solid var(--line-soft);
    min-width: 200px;
}

.emp-scope-icon {
    width: 40px;
    height: 40px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    background: linear-gradient(160deg, #1c2b45, #0f1727);
    color: #dbe5f5;
    font-size: 18px;
    flex: 0 0 auto;
}

.emp-scope-title {
    font-weight: 700;
    font-size: 14.5px;
    color: var(--ink);
    letter-spacing: -.01em;
}

.emp-scope-sub {
    font-size: 11.5px;
    color: var(--ink-3);
}

/* Equal columns, so the numbers line up whatever the label underneath says. */
.emp-stats {
    display: grid;
    grid-template-columns: repeat(auto-fill, 126px);
    gap: 8px 0;
    flex: 1 1 auto;
}

.emp-stat {
    min-width: 0;
}

.emp-stat-value {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}

.emp-stat-label {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ink-3);
    white-space: nowrap;
}

.emp-stat.is-muted .emp-stat-value {
    color: var(--ink-3);
}

.emp-stat.is-warm .emp-stat-value {
    color: #b7791f;
}

.emp-stat.is-hot .emp-stat-value {
    color: var(--bad);
}

.emp-add {
    margin-left: auto;
}

/* The filters, once datagrid.js has moved them into the toolbar. */
.emp-tools {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

.emp-tool {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 11.5px;
    color: var(--ink-3);
    white-space: nowrap;
}

@media (max-width: 767.98px) {
    .emp-scope {
        border-right: 0;
        padding-right: 0;
        width: 100%;
    }

    .emp-add {
        margin-left: 0;
    }
}

/* ---------- detail lists ------------------------------------------------ */

.detail-list {
    display: grid;
    grid-template-columns: 124px 1fr;
    gap: 8px 14px;
    margin: 0;
    font-size: 13px;
}

.detail-list dt {
    color: var(--ink-3);
    font-weight: 600;
    font-size: 12px;
    padding-top: 1px;
}

.detail-list dd {
    margin: 0;
    color: var(--ink);
}

/* ---------- org chart --------------------------------------------------- */

.org-tree, .org-tree ul {
    list-style: none;
    margin: 0;
    padding-left: 18px;
}

.org-tree > li {
    padding-left: 0;
}

.org-tree li {
    position: relative;
    padding: 4px 0 4px 16px;
}

.org-tree li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 20px;
    width: 12px;
    border-top: 1px solid var(--line);
}

.org-tree ul {
    border-left: 1px solid var(--line);
}

.org-node {
    display: inline-block;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    padding: 7px 13px;
    box-shadow: var(--shadow-xs);
    transition: box-shadow var(--t), transform var(--t), border-color var(--t);
}

.org-node:hover {
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
    border-color: #cddffb;
}

.org-name {
    font-weight: 650;
    font-size: 13px;
}

.org-title {
    font-size: 11.5px;
    color: var(--ink-3);
}

/* ---------- editable lists / permissions -------------------------------- */

.drag-handle {
    cursor: grab;
    color: var(--ink-4);
    transition: color var(--t-fast);
}

.drag-handle:hover { color: var(--ink-2); }

tr.dragging {
    opacity: .4;
}

.editable-name {
    cursor: text;
    border-bottom: 1px dashed #c6cddb;
    transition: border-color var(--t-fast), color var(--t-fast);
}

.editable-name:hover {
    border-bottom-color: var(--brand);
    color: var(--brand);
}

.permission-group {
    margin-bottom: 14px;
}

.permission-group:last-child {
    margin-bottom: 0;
}

.permission-group-title {
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 700;
    margin-bottom: 6px;
}

/* ---------- login ------------------------------------------------------- */
/*
   Two panels: a warehouse stage on the left, the sign-in card on the right.
   Below 992px the stage is dropped entirely and the card stands on the same
   dark ground, so a phone is not asked to render scenery it has no room for.
*/

.login-body {
    min-height: 100vh;
    background: #0c131f;
}

.login-split {
    min-height: 100vh;
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(430px, .85fr);
}

/* ---- left: the stage ---- */

.login-stage {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 60px 56px 34px;
    background: linear-gradient(165deg, #16233a 0%, #101827 45%, #0b111c 100%);
    isolation: isolate;
}

/* a surveyor's grid, so the flat areas are not dead space */
.login-stage-grid {
    position: absolute;
    inset: 0;
    z-index: -3;
    background-image:
        linear-gradient(rgba(148, 178, 235, .055) 1px, transparent 1px),
        linear-gradient(90deg, rgba(148, 178, 235, .055) 1px, transparent 1px);
    background-size: 46px 46px;
    mask-image: linear-gradient(180deg, #000 0%, #000 55%, transparent 88%);
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 55%, transparent 88%);
}

/* one warm light source, high and to the left */
.login-stage-glow {
    position: absolute;
    top: -18%;
    left: -12%;
    width: 78%;
    aspect-ratio: 1;
    z-index: -2;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(61, 116, 224, .28) 0%, rgba(61, 116, 224, 0) 68%);
    filter: blur(6px);
}

/* the racking itself, anchored to the bottom edge */
.login-stage-scene {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 62%;
    z-index: -1;
    background: url("../img/warehouse.svg") center bottom / cover no-repeat;
    opacity: .8;
    mask-image: linear-gradient(180deg, transparent 0%, #000 30%);
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 30%);
}

/* Keeps the headline readable over whatever the racking happens to be doing. */
.login-stage-scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg,
        rgba(11, 17, 28, .82) 0%,
        rgba(11, 17, 28, .55) 34%,
        rgba(11, 17, 28, 0) 58%,
        rgba(11, 17, 28, 0) 80%,
        rgba(8, 13, 21, .88) 100%);
}

/* one slow pass of a scanner beam - the only thing on this page that moves */
.login-stage-scan {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 62%;
    z-index: -1;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(120, 175, 255, .00) 42%,
        rgba(140, 190, 255, .16) 50%,
        rgba(120, 175, 255, .00) 58%,
        transparent 100%);
    /* 6.5s round trip, linear on purpose - an eased sweep reads as a swoosh,
       a steady one reads as a scanner.

       Two details that are easy to get wrong here:

       The travel is +/-70%, not +/-100%. Only the middle band of this element
       is actually lit, so at +/-100% the lit part spends the first and last
       quarter of the journey off-screen; the beam was visible for 2.6s of a
       6.5s cycle and dark for 3.9s. At +/-70% almost the whole journey counts.

       The delay is negative, which starts the cycle already inside the pass
       instead of at the head of the pause, so the beam crosses within a moment
       of the page appearing. Without it, anyone whose browser fills in their
       credentials is signed in and gone before the first sweep ever begins. */
    animation: stage-scan 6.5s linear -1.87s infinite;
}

@keyframes stage-scan {
    0%, 22%  { transform: translateX(-70%); }
    100%     { transform: translateX(70%); }
}

.login-stage-copy {
    position: relative;
    animation: stage-copy-in 520ms cubic-bezier(.4, 0, .2, 1) both;
}

@keyframes stage-copy-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Sized to keep the 52-character headline on one line from 992px up, where the
   stage is narrowest (562px minus padding). Measured, not guessed; a longer
   headline needs this coefficient lowered again. */
.login-stage-copy h1 {
    margin: 22px 0 14px;
    font-size: clamp(15px, 1.6vw, 30px);
    font-weight: 680;
    line-height: 1.2;
    letter-spacing: -.02em;
    color: #fff;
    white-space: nowrap;
}

.login-stage-copy p {
    margin: 0;
    font-size: clamp(12.5px, 1.05vw, 15px);
    line-height: 1.6;
    color: #93a3bd;
}


/* ---- right: the card ---- */

.login-panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 32px;
    background: linear-gradient(180deg, #0e1623 0%, #0a101a 100%);
    border-left: 1px solid rgba(148, 178, 235, .07);
}

/* No panel behind the fields - they sit straight on the dark ground, so
   everything inside needs its dark-surface treatment below. */
.login-card {
    width: 100%;
    max-width: 340px;
    animation: login-in 340ms cubic-bezier(.4, 0, .2, 1) both;
}

.login-panel .form-label {
    color: #93a6c2;
    font-size: 11.5px;
    letter-spacing: .02em;
}

/* The outline is a solid colour (the old translucent one, pre-blended onto the
   panel) and the fill stops at the padding edge: a translucent border painted
   over a translucent fill doubles up on the curved corners and looks thicker
   there than on the straight runs. */
.login-panel .form-control {
    background-color: rgba(255, 255, 255, .045);
    background-clip: padding-box;
    border-color: #253044;
    color: #e9eff8;
    padding: 9px 12px;
}

.login-panel .form-control:hover:not(:focus) {
    border-color: #384661;
}

.login-panel .form-control:focus {
    background-color: rgba(255, 255, 255, .07);
    border-color: #4d8bff;
    box-shadow: 0 0 0 3px rgba(77, 139, 255, .2);
    color: #fff;
}

.login-panel .form-control::placeholder {
    color: #62728c;
}

/* Chrome paints its own near-white fill over an autofilled field and ignores
   background-color. A large inset shadow is the only way to cover it, so this
   one has to be an opaque colour rather than the translucent one above. */
.login-panel .form-control:-webkit-autofill,
.login-panel .form-control:-webkit-autofill:hover,
.login-panel .form-control:-webkit-autofill:focus {
    -webkit-text-fill-color: #e9eff8;
    -webkit-box-shadow: 0 0 0 1000px #131c2b inset;
    caret-color: #e9eff8;
}

.login-panel .btn-primary {
    padding: 10px 16px;
    font-size: 13.5px;
}

/* Bootstrap's light alert colours disappear against this background. */
.login-panel .alert-danger {
    background: rgba(220, 38, 38, .13);
    border-color: rgba(248, 113, 113, .34);
    color: #ffb3b3;
}

.login-panel .alert-warning {
    background: rgba(217, 119, 6, .14);
    border-color: rgba(251, 191, 36, .32);
    color: #ffd49b;
}

.login-panel .text-danger {
    color: #ff9d9d !important;
}

@keyframes login-in {
    from { opacity: 0; transform: translateY(14px) scale(.985); }
    to   { opacity: 1; transform: none; }
}

.login-heading {
    font-size: 22px;
    font-weight: 680;
    letter-spacing: -.02em;
    margin: 0 0 24px;
    color: #fff;
}

.login-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 650;
    font-size: 19px;
    letter-spacing: -.015em;
}

.login-brand i {
    color: var(--brand);
    font-size: 23px;
}

.login-brand-light {
    color: #fff;
}

.login-brand-light i {
    color: #6ea3ff;
}

/* Only shown once the stage is gone, so the page still says what it is. */
.login-brand-compact {
    display: none;
    margin-bottom: 24px;
    color: #fff;
}

.login-brand-compact i {
    color: #6ea3ff;
}

.reset-form {
    max-width: 400px;
}

@media (max-width: 991.98px) {
    .login-split {
        grid-template-columns: 1fr;
    }

    .login-stage {
        display: none;
    }

    .login-panel {
        background:
            radial-gradient(900px 420px at 50% -10%, rgba(61, 116, 224, .22) 0%, transparent 60%),
            linear-gradient(165deg, #16233a 0%, #0b111c 100%);
    }

    .login-brand-compact {
        display: flex;
        justify-content: center;
    }
}

/* ---------- responsive -------------------------------------------------- */

.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(8, 12, 20, .5);
    backdrop-filter: blur(2px);
    z-index: 1035;
}

@media (max-width: 991.98px) {
    .app-sidebar {
        transform: translateX(-100%);
        box-shadow: var(--shadow-lg);
    }

    body.sidebar-open .app-sidebar {
        transform: translateX(0);
    }

    body.sidebar-open .sidebar-backdrop {
        display: block;
        animation: fade-in 180ms ease;
    }

    .app-main {
        margin-left: 0;
    }

    .app-content {
        padding: 16px 14px 24px;
    }
}

@keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ---------- print / PDF ------------------------------------------------- */

@media print {
    .app-sidebar,
    .app-topbar,
    .app-footer,
    .sidebar-backdrop,
    .route-progress,
    .grid-toolbar,
    .grid-pager,
    .pager-bar,
    .alert-dismissible .btn-close,
    .btn {
        display: none !important;
    }

    /* Filter bars are noise on paper, but some screens keep their actual content
       inside a form, so only the obvious filter rows go. */
    form.filter-bar,
    .card-body > form:only-child:has(.form-label) {
        display: none !important;
    }

    body {
        background: #fff;
        font-size: 11px;
    }

    .app-main {
        margin-left: 0;
    }

    .app-content {
        padding: 0;
        animation: none;
    }

    .content-card {
        border: 1px solid #ccc;
        box-shadow: none;
        break-inside: auto;
    }

    .card-header {
        background: #f2f2f2 !important;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .data-table thead th {
        position: static;
        background: #f2f2f2 !important;
        color: #000;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .data-table tbody tr:hover td {
        background: transparent;
        box-shadow: none;
    }

    /* Printing means printing everything, not just the page the reader is on. */
    .data-table tbody tr.grid-page-hidden {
        display: table-row !important;
    }

    .data-table tbody tr.grid-filtered-out {
        display: none !important;
    }

    .table-responsive {
        overflow: visible !important;
    }

    a {
        color: #000;
        text-decoration: none;
    }

    /* A printed title, since the topbar is gone. */
    .app-content::before {
        content: attr(data-print-title);
        display: block;
        font-size: 15px;
        font-weight: 700;
        margin-bottom: 10px;
    }
}

/* ---------- the launch notice ------------------------------------------ */

.announce .modal-header {
    background: linear-gradient(165deg, #16233a 0%, #101827 45%, #0b111c 100%);
    color: #fff;
    border-bottom: 0;
    padding: 20px 24px;
}

.announce-kicker {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #b4c0d3;
    margin-bottom: 4px;
}

.announce .modal-title {
    font-size: 20px;
    font-weight: 650;
}

.announce .modal-body {
    padding: 22px 24px 8px;
    font-size: 14px;
    line-height: 1.55;
}

.announce-list {
    padding-left: 20px;
    margin-bottom: 14px;
}

.announce-list li {
    margin-bottom: 8px;
}

.announce .modal-footer {
    border-top: 0;
    padding: 8px 24px 20px;
    justify-content: center;
}

/* ---------- the orders list ------------------------------------------------ */

/* Filters: one big search line, one quiet line of controls, then the tags. */
.ol-filters .card-body {
    padding: 18px 20px 16px;
}

.ol-search {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
}

.ol-search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ink-4);
    font-size: 15px;
    pointer-events: none;
}

.ol-search-input {
    height: 44px;
    padding-left: 40px;
    padding-right: 38px;
    font-size: 14.5px;
    border-radius: var(--r);
}

.ol-search-clear {
    position: absolute;
    right: 112px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--ink-4);
    font-size: 12px;
    padding: 6px;
}

.ol-search-clear:hover {
    color: var(--ink);
}

.ol-search-btn {
    height: 44px;
    padding: 0 22px;
    border-radius: var(--r);
    flex: 0 0 auto;
}

.ol-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 18px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--line-soft);
}

.ol-control {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    font-size: 12.5px;
    color: var(--ink-3);
}

.ol-control > span {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.ol-control .form-select,
.ol-control .form-control {
    width: auto;
    min-width: 120px;
    border-color: transparent;
    background-color: var(--surface-2);
    color: var(--ink);
    font-weight: 500;
}

.ol-control .form-select:hover,
.ol-control .form-control:hover {
    border-color: var(--line);
}

.ol-control .form-select:focus,
.ol-control .form-control:focus {
    border-color: var(--brand);
    background-color: var(--surface);
}

.ol-control-dates .form-control {
    min-width: 0;
    width: 140px;
}

.ol-dates-arrow {
    color: var(--ink-4);
    font-size: 12px;
}

.ol-window {
    margin-left: auto;
    font-size: 12.5px;
    color: var(--ink-3);
}

.ol-window .bi {
    margin-right: 4px;
}

.ol-clear {
    font-size: 12.5px;
    color: var(--ink-2);
    text-decoration: none;
}

.ol-clear:hover {
    color: var(--bad);
}

.ol-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 14px;
}

@media (max-width: 767.98px) {
    .ol-window {
        margin-left: 0;
        width: 100%;
    }
}

.ol-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px;
    border-radius: var(--r-pill);
    border: 1px solid var(--line);
    background: var(--surface);
    color: var(--ink-2);
    font-size: 12.5px;
    text-decoration: none;
    transition: background var(--t-fast), border-color var(--t-fast);
}

.ol-tag b {
    font-weight: 600;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
}

.ol-tag:hover {
    background: var(--brand-softer);
    border-color: var(--brand-ring);
    color: var(--brand-strong);
}

.ol-tag.active {
    background: #16233a;
    border-color: #16233a;
    color: #fff;
}

.ol-tag.active b {
    color: #fff;
}

.ol-tag.tone-danger {
    color: #a01c1c;
}

.ol-table td,
.ol-table th {
    vertical-align: middle;
}

.ol-customer,
.ol-po,
.ol-tracking {
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ol-tracking {
    font-family: ui-monospace, Consolas, "SF Mono", monospace;
    font-size: 12px;
}

.ol-kind {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.ol-kind-ltl { color: #6d28d9; }
.ol-kind-ba, .ol-kind-tyger { color: #0e7490; }
.ol-kind-dropship { color: var(--brand-strong); }

.ol-flag {
    font-size: 12.5px;
    font-weight: 500;
}

.ol-flag::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin: 0 6px 1px 0;
    background: var(--ink-4);
}

.ol-flag.tone-success::before { background: var(--ok); }
.ol-flag.tone-warning::before { background: var(--warn); }
.ol-flag.tone-danger::before  { background: var(--bad); }
.ol-flag.tone-success { color: #0d6b3b; }
.ol-flag.tone-warning { color: #8a4b06; }
.ol-flag.tone-danger  { color: #a01c1c; }
.ol-flag.tone-secondary { color: var(--ink-3); }

.ol-cancelled td {
    color: var(--ink-4);
}

.ol-cancelled td a {
    color: var(--ink-3);
}
