/* =========================================================================
   DEX-OS — SHELL & COMPONENTS
   =========================================================================
   Everything references tokens.css. No literal colours, sizes or timings.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--dx-bg-app);
    color: var(--dx-ink-primary);
    font-family: var(--dx-font-sans);
    font-size: var(--dx-text-base);
    line-height: var(--dx-leading-normal);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Money, references, anything scanned in a column. Tabular figures are the
   single highest-value typographic decision in a system like this: without
   them the eye cannot compare amounts down a column. */
.dx-num {
    font-family: var(--dx-font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    letter-spacing: var(--dx-tracking-normal);
}

/* Visible only to screen readers. */
.dx-sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* Keyboard focus, everywhere, without exception. This system will be
   operated by people who never touch a mouse — a finance clerk entering
   two hundred invoices works entirely from the keyboard. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid var(--dx-border-focus);
    outline-offset: 1px;
    border-radius: var(--dx-radius-sm);
}

/* ─────────────────────────────────────────────────────────────────────────
   LAYOUT
   ───────────────────────────────────────────────────────────────────────── */

.dx-app {
    display: grid;
    grid-template-columns: var(--dx-rail-width) 1fr;
    grid-template-rows: var(--dx-topbar-height) 1fr;
    grid-template-areas: "rail topbar" "rail main";
    min-height: 100vh;
}

@media (max-width: 900px) {
    .dx-app {
        grid-template-columns: 1fr;
        grid-template-areas: "topbar" "main";
    }
    .dx-rail { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   MODULE RAIL
   The chrome is where the identity lives — dark, confident, and separate
   from the working surface so the eye never confuses navigation with data.
   ───────────────────────────────────────────────────────────────────────── */

.dx-rail {
    grid-area: rail;
    background: var(--dx-bg-chrome);
    border-right: 1px solid rgba(255, 255, 255, 0.06);
    display: flex;
    flex-direction: column;
    z-index: var(--dx-z-rail);
}

.dx-rail__brand {
    height: var(--dx-topbar-height);
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    padding: 0 var(--dx-space-4);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    flex-shrink: 0;
}

/* The real DEX EMPIRE monogram, not a coloured square with initials in it.
   The artwork carries its own green and its counters are white, both of which
   read correctly on the dark rail, so it needs no plate behind it — a tinted
   background would only muddy the gradient it already has. */
.dx-rail__mark {
    width: 26px; height: 26px;
    display: grid;
    place-items: center;
    flex-shrink: 0;
}

.dx-rail__mark img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.dx-rail__wordmark {
    font-size: var(--dx-text-sm);
    font-weight: var(--dx-weight-semibold);
    color: rgba(255, 255, 255, 0.92);
    letter-spacing: var(--dx-tracking-tight);
}

/* Workspace switcher. Lists what you HOLD, never what exists — enumerating
   business units would disclose the group structure to everyone who logs in. */
.dx-workspace {
    margin: var(--dx-space-3);
    padding: var(--dx-space-2) var(--dx-space-3);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: var(--dx-radius-md);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--dx-space-2);
    transition: background var(--dx-duration-fast) var(--dx-ease);
    width: calc(100% - var(--dx-space-6));
    text-align: left;
    font-family: inherit;
}

.dx-workspace:hover { background: rgba(255, 255, 255, 0.07); }

.dx-workspace__label {
    font-size: var(--dx-text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    color: rgba(255, 255, 255, 0.45);
    display: block;
    margin-bottom: 1px;
}

.dx-workspace__value {
    font-size: var(--dx-text-sm);
    font-weight: var(--dx-weight-medium);
    color: rgba(255, 255, 255, 0.92);
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dx-workspace__chevron { color: rgba(255, 255, 255, 0.35); flex-shrink: 0; }

.dx-rail__nav {
    flex: 1;
    overflow-y: auto;
    padding: var(--dx-space-2) var(--dx-space-3) var(--dx-space-4);
}

.dx-rail__group + .dx-rail__group { margin-top: var(--dx-space-5); }

.dx-rail__grouplabel {
    font-size: var(--dx-text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    color: rgba(255, 255, 255, 0.34);
    padding: 0 var(--dx-space-2) var(--dx-space-2);
    font-weight: var(--dx-weight-semibold);
}

.dx-navitem {
    display: flex;
    align-items: center;
    gap: var(--dx-space-3);
    padding: var(--dx-space-2) var(--dx-space-2);
    border-radius: var(--dx-radius-md);
    color: rgba(255, 255, 255, 0.66);
    text-decoration: none;
    font-size: var(--dx-text-sm);
    transition: background var(--dx-duration-fast) var(--dx-ease),
                color var(--dx-duration-fast) var(--dx-ease);
    position: relative;
}

.dx-navitem:hover {
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.95);
}

.dx-navitem--active {
    background: rgba(28, 159, 104, 0.16);
    color: #fff;
    font-weight: var(--dx-weight-medium);
}

/* Active state carries a shape as well as a colour, so it survives both
   greyscale printing and colour vision deficiency. */
.dx-navitem--active::before {
    content: "";
    position: absolute;
    left: calc(var(--dx-space-2) * -1 - 1px);
    top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 16px;
    border-radius: 0 var(--dx-radius-full) var(--dx-radius-full) 0;
    background: var(--dx-brand-400);
}

.dx-navitem__icon {
    width: 16px; height: 16px;
    flex-shrink: 0;
    opacity: 0.85;
}

.dx-navitem__count {
    margin-left: auto;
    font-size: var(--dx-text-2xs);
    font-weight: var(--dx-weight-semibold);
    background: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.85);
    padding: 1px 6px;
    border-radius: var(--dx-radius-full);
    font-variant-numeric: tabular-nums;
}

.dx-navitem__count--urgent {
    background: var(--dx-danger-500);
    color: #fff;
}

.dx-rail__foot {
    padding: var(--dx-space-3);
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    flex-shrink: 0;
}

.dx-avatar {
    width: 26px; height: 26px;
    border-radius: var(--dx-radius-full);
    background: var(--dx-brand-600);
    color: #fff;
    display: grid;
    place-items: center;
    font-size: var(--dx-text-2xs);
    font-weight: var(--dx-weight-semibold);
    flex-shrink: 0;
}

.dx-rail__user { min-width: 0; }
.dx-rail__username {
    font-size: var(--dx-text-xs);
    color: rgba(255, 255, 255, 0.9);
    font-weight: var(--dx-weight-medium);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dx-rail__userrole {
    font-size: var(--dx-text-2xs);
    color: rgba(255, 255, 255, 0.42);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ─────────────────────────────────────────────────────────────────────────
   TOPBAR
   ───────────────────────────────────────────────────────────────────────── */

.dx-topbar {
    grid-area: topbar;
    background: var(--dx-bg-surface);
    border-bottom: 1px solid var(--dx-border-subtle);
    display: flex;
    align-items: center;
    gap: var(--dx-space-4);
    padding: 0 var(--dx-space-5);
    z-index: var(--dx-z-topbar);
}

.dx-breadcrumb {
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    font-size: var(--dx-text-sm);
    color: var(--dx-ink-tertiary);
    min-width: 0;
}
.dx-breadcrumb a { color: inherit; text-decoration: none; }
.dx-breadcrumb a:hover { color: var(--dx-ink-primary); }
.dx-breadcrumb__sep { color: var(--dx-neutral-300); }
.dx-breadcrumb__current {
    color: var(--dx-ink-primary);
    font-weight: var(--dx-weight-medium);
}

/* ⌘K. Filtered through the same gate as the rail — searching for a module
   you cannot reach returns nothing, which is indistinguishable from a system
   that has no such module. */
.dx-search {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    background: var(--dx-bg-sunken);
    border: 1px solid var(--dx-border-default);
    border-radius: var(--dx-radius-md);
    padding: var(--dx-space-1) var(--dx-space-2) var(--dx-space-1) var(--dx-space-3);
    color: var(--dx-ink-tertiary);
    font-size: var(--dx-text-sm);
    min-width: 230px;
    cursor: pointer;
    transition: border-color var(--dx-duration-fast) var(--dx-ease);
    font-family: inherit;
}
.dx-search:hover { border-color: var(--dx-border-strong); }

.dx-kbd {
    font-family: var(--dx-font-sans);
    font-size: var(--dx-text-2xs);
    color: var(--dx-ink-tertiary);
    background: var(--dx-bg-surface);
    border: 1px solid var(--dx-border-default);
    border-bottom-width: 2px;
    border-radius: var(--dx-radius-sm);
    padding: 1px 5px;
    margin-left: auto;
}

.dx-iconbtn {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border-radius: var(--dx-radius-md);
    border: 1px solid transparent;
    background: transparent;
    color: var(--dx-ink-secondary);
    cursor: pointer;
    position: relative;
    transition: background var(--dx-duration-fast) var(--dx-ease);
}
.dx-iconbtn:hover { background: var(--dx-bg-hover); color: var(--dx-ink-primary); }

.dx-iconbtn__dot {
    position: absolute;
    top: 5px; right: 5px;
    width: 6px; height: 6px;
    border-radius: var(--dx-radius-full);
    background: var(--dx-danger-500);
    border: 1.5px solid var(--dx-bg-surface);
}

/* ─────────────────────────────────────────────────────────────────────────
   MAIN
   ───────────────────────────────────────────────────────────────────────── */

.dx-main {
    grid-area: main;
    padding: var(--dx-space-6);
    overflow-x: auto;
}

.dx-page__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--dx-space-4);
    margin-bottom: var(--dx-space-5);
    flex-wrap: wrap;
}

.dx-page__title {
    font-size: var(--dx-text-lg);
    font-weight: var(--dx-weight-semibold);
    letter-spacing: var(--dx-tracking-tight);
    margin: 0 0 var(--dx-space-1);
    line-height: var(--dx-leading-tight);
}

.dx-page__meta {
    font-size: var(--dx-text-sm);
    color: var(--dx-ink-tertiary);
    margin: 0;
}

.dx-actions { display: flex; gap: var(--dx-space-2); flex-shrink: 0; }

/* ─── Scope banner ────────────────────────────────────────────────────────
   The user must always know WHICH slice of the group they are looking at.
   In a system where the same screen shows different data per entity, an
   ambiguous scope is how someone approves the wrong company's invoice. */
.dx-scope {
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    padding: var(--dx-space-2) var(--dx-space-3);
    background: var(--dx-bg-selected);
    border: 1px solid var(--dx-brand-200);
    border-radius: var(--dx-radius-md);
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-brand);
    margin-bottom: var(--dx-space-4);
}
.dx-scope__path { font-weight: var(--dx-weight-medium); }
.dx-scope__sep { opacity: 0.5; }

/* ─────────────────────────────────────────────────────────────────────────
   CARDS & STATS
   ───────────────────────────────────────────────────────────────────────── */

.dx-card {
    background: var(--dx-bg-surface);
    border: 1px solid var(--dx-border-subtle);
    border-radius: var(--dx-radius-lg);
    overflow: hidden;
}

.dx-card__head {
    padding: var(--dx-space-3) var(--dx-space-4);
    border-bottom: 1px solid var(--dx-border-subtle);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--dx-space-3);
}

.dx-card__title {
    font-size: var(--dx-text-base);
    font-weight: var(--dx-weight-semibold);
    margin: 0;
    letter-spacing: var(--dx-tracking-tight);
}

.dx-statgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--dx-space-3);
    margin-bottom: var(--dx-space-5);
}

.dx-stat {
    background: var(--dx-bg-surface);
    border: 1px solid var(--dx-border-subtle);
    border-radius: var(--dx-radius-lg);
    padding: var(--dx-space-4);
}

.dx-stat__label {
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-tertiary);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    font-weight: var(--dx-weight-medium);
    margin-bottom: var(--dx-space-2);
}

.dx-stat__value {
    font-size: var(--dx-text-xl);
    font-weight: var(--dx-weight-semibold);
    letter-spacing: var(--dx-tracking-tight);
    line-height: var(--dx-leading-tight);
}

.dx-stat__foot {
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-tertiary);
    margin-top: var(--dx-space-1);
}

.dx-delta--up   { color: var(--dx-success-500); font-weight: var(--dx-weight-medium); }
.dx-delta--down { color: var(--dx-danger-500);  font-weight: var(--dx-weight-medium); }

/* ─────────────────────────────────────────────────────────────────────────
   TABLE
   The densest surface in the system, and the one that decides whether the
   whole thing feels usable.
   ───────────────────────────────────────────────────────────────────────── */

.dx-tablewrap { overflow-x: auto; }

.dx-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--dx-text-sm);
}

.dx-table th {
    text-align: left;
    font-size: var(--dx-text-xs);
    font-weight: var(--dx-weight-semibold);
    color: var(--dx-ink-tertiary);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    padding: var(--dx-space-2) var(--dx-space-4);
    border-bottom: 1px solid var(--dx-border-default);
    background: var(--dx-bg-sunken);
    white-space: nowrap;
    position: sticky;
    top: 0;
}

.dx-table td {
    padding: 0 var(--dx-space-4);
    height: var(--dx-row-height);
    border-bottom: 1px solid var(--dx-border-subtle);
    vertical-align: middle;
    color: var(--dx-ink-primary);
}

.dx-table tbody tr {
    transition: background var(--dx-duration-instant) var(--dx-ease);
}
.dx-table tbody tr:hover { background: var(--dx-bg-hover); }
.dx-table tbody tr:last-child td { border-bottom: none; }

.dx-table .dx-right { text-align: right; }

/* An archived row is legible but visibly withdrawn — never hidden, because
   nothing is ever deleted (ADR-05) and staff must be able to see why a
   record no longer appears in their working set. */
.dx-table tr.is-archived td { color: var(--dx-ink-disabled); }
.dx-table tr.is-archived .dx-num { text-decoration: line-through; }

.dx-cell__primary { font-weight: var(--dx-weight-medium); }
.dx-cell__sub {
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-tertiary);
}

/* ─── Masked field (§6.2 Layer 5) ─────────────────────────────────────────
   Deliberately distinct from an empty cell AND from real data. A masked
   salary that looks like a blank is a support ticket; one that looks like a
   value is a misread figure. Fixed width regardless of the underlying
   content, so it never becomes a length oracle. */
.dx-masked {
    display: inline-flex;
    align-items: center;
    gap: var(--dx-space-1);
    background: var(--dx-restricted-bg);
    color: var(--dx-restricted-fg);
    border-radius: var(--dx-radius-sm);
    padding: 1px var(--dx-space-2);
    font-size: var(--dx-text-xs);
    font-weight: var(--dx-weight-medium);
    letter-spacing: 0.08em;
    cursor: help;
}

/* ─────────────────────────────────────────────────────────────────────────
   BADGES
   Every status carries a WORD. Colour is reinforcement, never the message.
   ───────────────────────────────────────────────────────────────────────── */

.dx-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--dx-space-1);
    font-size: var(--dx-text-xs);
    font-weight: var(--dx-weight-medium);
    padding: 2px var(--dx-space-2);
    border-radius: var(--dx-radius-full);
    border: 1px solid transparent;
    white-space: nowrap;
    line-height: 1.4;
}

.dx-badge__dot {
    width: 5px; height: 5px;
    border-radius: var(--dx-radius-full);
    background: currentColor;
    flex-shrink: 0;
}

.dx-badge--success { background: var(--dx-success-50); color: var(--dx-success-700); border-color: color-mix(in srgb, var(--dx-success-500) 22%, transparent); }
.dx-badge--warning { background: var(--dx-warning-50); color: var(--dx-warning-700); border-color: color-mix(in srgb, var(--dx-warning-500) 22%, transparent); }
.dx-badge--danger  { background: var(--dx-danger-50);  color: var(--dx-danger-700);  border-color: color-mix(in srgb, var(--dx-danger-500) 22%, transparent); }
.dx-badge--info    { background: var(--dx-info-50);    color: var(--dx-info-700);    border-color: color-mix(in srgb, var(--dx-info-500) 22%, transparent); }
.dx-badge--neutral { background: var(--dx-bg-sunken);  color: var(--dx-ink-secondary); border-color: var(--dx-border-default); }

/* ─────────────────────────────────────────────────────────────────────────
   BUTTONS
   ───────────────────────────────────────────────────────────────────────── */

.dx-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--dx-space-2);
    height: 32px;
    padding: 0 var(--dx-space-3);
    border-radius: var(--dx-radius-md);
    font-family: inherit;
    font-size: var(--dx-text-sm);
    font-weight: var(--dx-weight-medium);
    cursor: pointer;
    border: 1px solid var(--dx-border-default);
    background: var(--dx-bg-surface);
    color: var(--dx-ink-primary);
    white-space: nowrap;
    transition: background var(--dx-duration-fast) var(--dx-ease),
                border-color var(--dx-duration-fast) var(--dx-ease);
}

.dx-btn:hover { background: var(--dx-bg-hover); border-color: var(--dx-border-strong); }

.dx-btn--primary {
    background: var(--dx-brand-600);
    border-color: var(--dx-brand-600);
    color: #fff;
}
.dx-btn--primary:hover { background: var(--dx-brand-700); border-color: var(--dx-brand-700); }

.dx-btn--subtle { border-color: transparent; background: transparent; color: var(--dx-ink-secondary); }
.dx-btn--subtle:hover { background: var(--dx-bg-hover); color: var(--dx-ink-primary); }

.dx-btn[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* ─────────────────────────────────────────────────────────────────────────
   APPROVAL STRIP — the workflow surface
   ───────────────────────────────────────────────────────────────────────── */

.dx-approval {
    display: flex;
    align-items: center;
    gap: var(--dx-space-3);
    padding: var(--dx-space-3) var(--dx-space-4);
    background: var(--dx-warning-50);
    border: 1px solid color-mix(in srgb, var(--dx-warning-500) 25%, transparent);
    border-radius: var(--dx-radius-lg);
    margin-bottom: var(--dx-space-5);
    flex-wrap: wrap;
}

.dx-approval__text { font-size: var(--dx-text-sm); flex: 1; min-width: 200px; }
.dx-approval__title { font-weight: var(--dx-weight-semibold); }
.dx-approval__meta { color: var(--dx-ink-secondary); font-size: var(--dx-text-xs); }

/* Stage progress — a two-stage chain rendered so the user can see where a
   document actually is, rather than being told "pending". */
.dx-stages { display: flex; align-items: center; gap: var(--dx-space-2); }

.dx-stage {
    display: flex;
    align-items: center;
    gap: var(--dx-space-2);
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-tertiary);
}

.dx-stage__pip {
    width: 18px; height: 18px;
    border-radius: var(--dx-radius-full);
    display: grid; place-items: center;
    border: 1.5px solid var(--dx-border-strong);
    font-size: 9px;
    font-weight: var(--dx-weight-bold);
    background: var(--dx-bg-surface);
    flex-shrink: 0;
}

.dx-stage--done .dx-stage__pip {
    background: var(--dx-success-500);
    border-color: var(--dx-success-500);
    color: #fff;
}
.dx-stage--done { color: var(--dx-ink-secondary); }

.dx-stage--current .dx-stage__pip {
    border-color: var(--dx-warning-500);
    color: var(--dx-warning-700);
}
.dx-stage--current { color: var(--dx-ink-primary); font-weight: var(--dx-weight-medium); }

.dx-stage__line {
    width: 20px; height: 1px;
    background: var(--dx-border-strong);
}

/* ─────────────────────────────────────────────────────────────────────────
   EMPTY STATE
   Where the identity is allowed to show, because there is no data to
   compete with.
   ───────────────────────────────────────────────────────────────────────── */

.dx-empty {
    padding: var(--dx-space-12) var(--dx-space-6);
    text-align: center;
    color: var(--dx-ink-tertiary);
}
.dx-empty__title {
    font-size: var(--dx-text-base);
    font-weight: var(--dx-weight-medium);
    color: var(--dx-ink-secondary);
    margin-bottom: var(--dx-space-1);
}
.dx-empty__body { font-size: var(--dx-text-sm); }

/* ─────────────────────────────────────────────────────────────────────────
   PRINT — §6.2 audits `print` as an action, so it is a real output.
   ───────────────────────────────────────────────────────────────────────── */

@media print {
    .dx-rail, .dx-topbar, .dx-actions, .dx-search { display: none !important; }
    .dx-app { grid-template-columns: 1fr; grid-template-areas: "main"; }
    .dx-main { padding: 0; }
    .dx-card { border-color: #000; break-inside: avoid; }
    .dx-badge { border: 1px solid #000; }
    .dx-crest { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
   CREST — a club logo in a list row.

   Fixed box regardless of the source image, because club crests arrive as
   whatever the club had: 40 KB PNGs, 2 MB JPEGs, wildly different aspect
   ratios. `object-fit: contain` on a fixed square keeps the row height
   uniform, which is the whole point of a dense table — a list whose rows
   change height with the image is unscannable.

   The monogram fallback is not decoration. 30 of 382 clubs have a crest, so
   the fallback is the common case, and an empty cell there would read as a
   rendering fault rather than as missing data.
   ───────────────────────────────────────────────────────────────────────── */

.dx-crest {
    width: 28px;
    height: 28px;
    border-radius: var(--dx-radius-sm);
    flex-shrink: 0;
    display: grid;
    place-items: center;
    overflow: hidden;
    background: var(--dx-bg-sunken);
    border: 1px solid var(--dx-border-subtle);
}

.dx-crest img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Crests are drawn for a white background and many are transparent PNGs.
       On the dark surface a navy crest disappears entirely, so the tile keeps
       a light backing rather than tinting the artwork. */
    background: #fff;
}

.dx-crest--monogram {
    font-size: 10px;
    font-weight: var(--dx-weight-semibold);
    letter-spacing: var(--dx-tracking-wide);
    color: var(--dx-ink-tertiary);
}

.dx-cell__withcrest {
    display: flex;
    align-items: center;
    gap: var(--dx-space-3);
    min-width: 0;
}

.dx-cell__withcrest .dx-cell__primary {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────────────
   CLICKABLE ROWS

   The whole row is the target, not a link inside it — a 2 mm "view" link in a
   40-row table is a precision task repeated all day.

   The anchor covers the first cell and the row carries the affordance, so
   keyboard users still get a real focusable link with a real href rather than
   a JavaScript click handler on a <tr>. A row that only responds to a mouse
   is a row that cannot be reached with Tab.
   ───────────────────────────────────────────────────────────────────────── */

.dx-table tbody tr.is-clickable { cursor: pointer; }
.dx-table tbody tr.is-clickable:hover { background: var(--dx-bg-hover); }

.dx-table tbody tr.is-clickable:focus-within {
    outline: 2px solid var(--dx-accent-500);
    outline-offset: -2px;
}

.dx-rowlink {
    color: inherit;
    text-decoration: none;
    display: block;
}

.dx-rowlink:focus { outline: none; }
.dx-rowlink:hover .dx-cell__primary { color: var(--dx-accent-600); }

/* ─────────────────────────────────────────────────────────────────────────
   DETAIL VIEW
   ───────────────────────────────────────────────────────────────────────── */

.dx-detail {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--dx-space-5) var(--dx-space-6);
}

.dx-detail__label {
    font-size: var(--dx-text-xs);
    color: var(--dx-ink-tertiary);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    margin-bottom: 2px;
}

.dx-detail__value {
    font-size: var(--dx-text-sm);
    color: var(--dx-ink-primary);
}

.dx-detail__value--empty { color: var(--dx-ink-disabled); }

.dx-crest--large { width: 72px; height: 72px; border-radius: var(--dx-radius); }
.dx-crest--large.dx-crest--monogram { font-size: 22px; }

.dx-cardhead {
    display: flex;
    align-items: center;
    gap: var(--dx-space-4);
    margin-bottom: var(--dx-space-5);
}

.dx-sectiontitle {
    font-size: var(--dx-text-xs);
    font-weight: var(--dx-weight-semibold);
    color: var(--dx-ink-tertiary);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    margin: var(--dx-space-6) 0 var(--dx-space-3);
}

/* ─────────────────────────────────────────────────────────────────────────
   FORMS

   Labels sit above their fields rather than beside them. Side-by-side reads
   tidier on a mockup and forces a second eye movement per field; on a form
   with twenty-six of them that is fifty-two.

   Errors sit under the field they belong to and are never colour alone — the
   message is the information, the red is the wayfinding.
   ───────────────────────────────────────────────────────────────────────── */

.dx-formgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--dx-space-4) var(--dx-space-5);
}

.dx-formgrid--full { grid-template-columns: 1fr; }

.dx-formfield { display: flex; flex-direction: column; min-width: 0; }

.dx-formfield label {
    font-size: var(--dx-text-xs);
    font-weight: var(--dx-weight-medium);
    color: var(--dx-ink-tertiary);
    text-transform: uppercase;
    letter-spacing: var(--dx-tracking-wide);
    margin-bottom: 6px;
}

.dx-formfield input,
.dx-formfield select,
.dx-formfield textarea {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    background: var(--dx-bg-sunken);
    border: 1px solid var(--dx-border-default);
    border-radius: var(--dx-radius-sm);
    color: var(--dx-ink-primary);
    font: inherit;
    font-size: var(--dx-text-sm);
}

.dx-formfield textarea { resize: vertical; min-height: 80px; }

.dx-formfield input:focus,
.dx-formfield select:focus,
.dx-formfield textarea:focus {
    outline: 2px solid var(--dx-accent-500);
    outline-offset: -1px;
    border-color: transparent;
}

.dx-formfield.has-error input,
.dx-formfield.has-error select,
.dx-formfield.has-error textarea {
    border-color: var(--dx-danger-500);
}

.dx-formfield__error {
    font-size: var(--dx-text-xs);
    color: var(--dx-danger-600);
    margin-top: 4px;
}

.dx-formerror {
    border-color: color-mix(in srgb, var(--dx-danger-500) 40%, transparent);
    color: var(--dx-danger-600);
    font-size: var(--dx-text-sm);
    margin-bottom: var(--dx-space-4);
}

/* A change that saved. Announced, then gone — a banner that persists across
   navigation stops being read. */
.dx-flash {
    border-color: color-mix(in srgb, var(--dx-success-500) 40%, transparent);
    background: color-mix(in srgb, var(--dx-success-500) 8%, transparent);
    color: var(--dx-success-700);
    font-size: var(--dx-text-sm);
    margin-bottom: var(--dx-space-4);
}

/* ─────────────────────────────────────────────────────────────────────────
   AUDIT TRAIL
   ───────────────────────────────────────────────────────────────────────── */

.dx-diff {
    font-size: var(--dx-text-xs);
    display: flex;
    flex-wrap: wrap;
    gap: var(--dx-space-2);
}

.dx-diff__item {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 2px var(--dx-space-2);
    border: 1px solid var(--dx-border-subtle);
    border-radius: var(--dx-radius-sm);
    background: var(--dx-bg-sunken);
}

.dx-diff__field { color: var(--dx-ink-tertiary); }
.dx-diff__old { color: var(--dx-danger-600); text-decoration: line-through; }
.dx-diff__new { color: var(--dx-success-700); }
