:root {
    color-scheme: dark;

    /* Brand palette -- unchanged. Every surface below is derived from these. */
    --cyan: #20b8d9;
    --green: #0aa07f;
    --magenta: #d71976;
    --amber: #f5b642;
    --red: #ff5d6c;
    --blue: #5277ff;

    --bg: #081110;
    --bg-grid: rgba(32, 184, 217, 0.055);
    --panel: #0f1d1d;
    --panel-2: #142728;
    --panel-3: #1a3132;
    --line: #254044;
    --line-soft: #1b3234;
    --text: #ecfdf7;
    --muted: #93a8a6;
    --faint: #6d8280;
    --input: #081615;
    --shadow: 0 20px 55px rgba(0, 0, 0, 0.32);
    --overlay: rgba(4, 10, 10, 0.66);
    --accent-wash: rgba(32, 184, 217, 0.12);
    --accent-wash-strong: rgba(32, 184, 217, 0.2);
    --skeleton: linear-gradient(90deg, #142728 25%, #1c3436 37%, #142728 63%);

    /* Spacing -- a 4px scale. Use these instead of ad-hoc pixel values. */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;
    --space-10: 40px;
    --space-12: 48px;

    /* Type scale */
    --font-ui: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --font-display: "Rajdhani", var(--font-ui);
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    --text-xs: 11px;
    --text-sm: 12px;
    --text-base: 13px;
    --text-md: 14px;
    --text-lg: 16px;
    --text-xl: 20px;
    --text-2xl: 26px;
    --text-3xl: 32px;

    /* Radii, elevation, motion */
    --radius-sm: 4px;
    --radius: 6px;
    --radius-lg: 10px;
    --radius-xl: 14px;
    --elev-1: 0 1px 2px rgba(0, 0, 0, 0.18);
    --elev-2: 0 4px 12px rgba(0, 0, 0, 0.22);
    --elev-3: 0 12px 32px rgba(0, 0, 0, 0.28);
    --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--cyan);
    --motion: 120ms cubic-bezier(0.2, 0, 0.2, 1);

    --sidebar-w: 244px;
    --sidebar-w-collapsed: 60px;
    --topbar-h: 52px;
}

:root[data-theme="light"] {
    color-scheme: light;
    --bg: #f5f8fa;
    --bg-grid: rgba(0, 94, 111, 0.055);
    --panel: #ffffff;
    --panel-2: #eef5f4;
    --panel-3: #e2ecec;
    --line: #d2e0e1;
    --line-soft: #e4eded;
    --text: #182326;
    --muted: #66777b;
    --faint: #849a9a;
    --input: #ffffff;
    --shadow: 0 18px 42px rgba(18, 35, 38, 0.1);
    --overlay: rgba(24, 35, 38, 0.4);
    --accent-wash: rgba(0, 122, 145, 0.09);
    --accent-wash-strong: rgba(0, 122, 145, 0.16);
    --skeleton: linear-gradient(90deg, #e9f1f1 25%, #f3f8f8 37%, #e9f1f1 63%);
    --elev-1: 0 1px 2px rgba(18, 35, 38, 0.06);
    --elev-2: 0 4px 12px rgba(18, 35, 38, 0.08);
    --elev-3: 0 12px 32px rgba(18, 35, 38, 0.12);
}

* {
    box-sizing: border-box;
}

/*
 * Rajdhani is a condensed display face: excellent for the brand and headings,
 * hard to scan in dense incident tables. Data now renders in a UI face while
 * headings keep the brand voice -- swap --font-ui back to reverse this.
 */
body {
    margin: 0;
    min-height: 100vh;
    background-color: var(--bg);
    color: var(--text);
    font-family: var(--font-ui);
    font-size: var(--text-md);
    line-height: 1.5;
    letter-spacing: 0;
    -webkit-font-smoothing: antialiased;
}

/*
 * Rajdhani is reserved for display scale: the page title and the wordmark. It
 * was previously carrying every heading, eyebrow and dashboard figure too, from
 * 34px down to 11px, sitting beside Inter at the same sizes -- at which point a
 * condensed face stops reading as hierarchy and starts reading as a second font
 * chosen by accident. Below display scale, weight and colour do that work.
 */
h1,
.brand,
.sidebar-brand {
    font-family: var(--font-display);
    letter-spacing: 0.01em;
}

h2,
h3 {
    font-family: var(--font-ui);
    font-weight: 600;
    letter-spacing: 0;
}

@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}

a {
    color: inherit;
}

.app-frame {
    min-height: 100vh;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 12px;
    align-items: center;
    min-height: 58px;
    padding: 8px 18px;
    border-bottom: 1px solid var(--line);
    background: color-mix(in srgb, var(--panel) 92%, transparent);
    backdrop-filter: blur(16px);
}

.guest-topbar {
    position: fixed;
    right: 0;
    left: 0;
}

.topbar-main,
.topbar-actions,
.topbar-user,
.brand,
.button-row {
    display: flex;
    gap: 10px;
    align-items: center;
}

.topbar-main {
    min-width: 0;
}

.topbar-actions {
    justify-content: flex-end;
}

.brand {
    flex: 0 0 auto;
    color: var(--text);
    font-weight: 700;
    text-decoration: none;
}

.brand img {
    width: 116px;
    height: auto;
}

.brand span {
    padding-left: 12px;
    border-left: 1px solid var(--line);
    color: var(--cyan);
    white-space: nowrap;
}

.top-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    min-width: 0;
    overflow: visible;
    padding: 2px;
}

.top-nav-link {
    flex: 0 0 auto;
    padding: 6px 8px;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--muted);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.top-nav-link:hover,
.top-nav-link.active {
    border-color: color-mix(in srgb, var(--cyan) 35%, transparent);
    background: linear-gradient(90deg, color-mix(in srgb, var(--magenta) 18%, transparent), color-mix(in srgb, var(--green) 14%, transparent));
    color: var(--text);
}

.settings-menu {
    position: relative;
    flex: 0 0 auto;
}

.settings-menu summary {
    cursor: pointer;
    list-style: none;
}

.settings-menu summary::-webkit-details-marker {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    .settings-menu::after {
        position: absolute;
        top: 100%;
        right: 0;
        left: 0;
        height: 8px;
        content: "";
    }
}

.settings-menu-list {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 40;
    display: grid;
    min-width: 230px;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    box-shadow: var(--shadow);
}

.settings-menu-link {
    display: grid;
    padding: 10px 12px;
    border-radius: 6px;
    color: var(--muted);
    font-weight: 700;
    text-decoration: none;
}

.settings-menu-link:hover,
.settings-menu-link.active {
    background: color-mix(in srgb, var(--cyan) 14%, transparent);
    color: var(--text);
}

.roster-menu .settings-menu-list {
    right: auto;
    left: 0;
    min-width: 180px;
}

.account-menu {
    position: relative;
    flex: 0 0 auto;
}

.account-menu summary {
    cursor: pointer;
    list-style: none;
}

.account-menu summary::-webkit-details-marker {
    display: none;
}

.topbar-user {
    padding-left: 10px;
    border-left: 1px solid var(--line);
}

.account-summary {
    display: grid;
    gap: 1px;
    min-width: 138px;
    padding: 3px 24px 3px 10px;
    border-radius: 6px;
    position: relative;
}

.account-summary::after {
    position: absolute;
    top: 50%;
    right: 10px;
    width: 7px;
    height: 7px;
    border-right: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
    content: "";
    transform: translateY(-65%) rotate(45deg);
}

.account-menu[open] .account-summary,
.account-summary:hover {
    background: color-mix(in srgb, var(--cyan) 10%, transparent);
}

.account-summary strong,
.account-summary span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.account-summary strong {
    font-size: 13px;
}

.account-summary span {
    font-size: 11px;
}

.account-menu-list {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 45;
    display: grid;
    min-width: 210px;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    box-shadow: var(--shadow);
}

.account-menu-action {
    width: 100%;
    min-height: 38px;
    padding: 8px 10px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text);
    font: inherit;
    font-weight: 700;
    text-align: left;
}

.account-menu-action:hover {
    background: color-mix(in srgb, var(--cyan) 14%, transparent);
    color: var(--cyan);
}

.topbar-user span,
small,
.page-heading p,
.metric span,
label,
.bar-row span {
    color: var(--muted);
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--panel-2);
    color: var(--text);
    font: inherit;
}

.theme-toggle:hover {
    border-color: var(--cyan);
    color: var(--cyan);
}

.theme-icon {
    display: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-width: 2;
}

.theme-icon-moon {
    display: block;
}

:root[data-theme="light"] .theme-icon-sun {
    display: block;
}

:root[data-theme="light"] .theme-icon-moon {
    display: none;
}

.content {
    min-width: 0;
    padding: 28px;
}

.page-heading {
    margin-bottom: 18px;
}

.eyebrow {
    margin: 0 0 6px;
    color: var(--cyan);
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
}

h1,
h2,
h3,
p {
    margin-top: 0;
}

h1 {
    font-size: 34px;
    line-height: 1.1;
}

h2 {
    margin-bottom: 14px;
    font-size: 19px;
}

.panel,
.metric {
    border: 1px solid var(--line);
    border-radius: 8px;
    background: color-mix(in srgb, var(--panel) 96%, transparent);
    box-shadow: var(--shadow);
}

.panel {
    margin-bottom: 18px;
    padding: 18px;
}

.module-toolbar {
    display: flex;
    gap: 16px;
    align-items: center;
    justify-content: space-between;
}

.module-toolbar h2 {
    margin-bottom: 0;
}

.app-modal {
    width: min(720px, calc(100vw - 32px));
    max-width: none;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--text);
}

.app-modal-wide {
    width: min(980px, calc(100vw - 32px));
}

.app-modal::backdrop {
    background: rgba(3, 8, 9, 0.72);
    backdrop-filter: blur(12px);
}

.app-modal-surface {
    max-height: calc(100vh - 48px);
    overflow: auto;
    padding: 20px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    box-shadow: var(--shadow);
}

.modal-title-row {
    display: flex;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.modal-title-row h2 {
    margin-bottom: 0;
}

.modal-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--panel-2);
    color: var(--text);
    font-weight: 800;
}

.modal-close:hover {
    border-color: var(--red);
    color: var(--red);
}

.metrics {
    display: grid;
    grid-template-columns: repeat(6, minmax(150px, 1fr));
    gap: 14px;
    margin-bottom: 18px;
}

.metrics.compact {
    grid-template-columns: repeat(4, minmax(140px, 1fr));
}

.metric {
    display: grid;
    gap: 8px;
    min-height: 100px;
    padding: 16px;
}

.metric strong {
    font-size: 30px;
}

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(260px, 1fr));
    gap: 18px;
}

/* Five export cards in a two-wide grid always left one stranded on its own
   row. Letting them fit means three across on a desk monitor and no orphan. */
.report-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 18px;
}

.report-card {
    display: grid;
    align-content: start;
    gap: var(--space-2);
}

.report-card p {
    margin: 0;
    color: var(--muted);
}

.report-card .button-row {
    margin-top: var(--space-2);
}

.panel-title-row {
    display: flex;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.button-row {
    flex-wrap: wrap;
    justify-content: flex-start;
    margin-bottom: 0;
}

.button-row .btn,
.form-actions .btn,
.panel-title-row .btn,
.toolbar-search .btn,
.top-nav-link {
    flex: 0 0 auto;
    white-space: nowrap;
}

.toolbar-search {
    display: flex;
    flex: 1 1 280px;
    gap: 8px;
    min-width: min(100%, 280px);
}

.toolbar-search input {
    min-width: 180px;
}

.module-toolbar .button-row {
    justify-content: flex-end;
}

.export-menu {
    position: relative;
    flex: 0 0 auto;
}

.export-menu summary {
    cursor: pointer;
    list-style: none;
}

.export-menu summary::-webkit-details-marker {
    display: none;
}

.export-menu-list {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 60;
    display: grid;
    min-width: 120px;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
    box-shadow: var(--shadow);
}

.export-menu-list a {
    padding: 8px 10px;
    border-radius: 6px;
    color: var(--text);
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.export-menu-list a:hover,
.export-menu-list a:focus {
    background: color-mix(in srgb, var(--cyan) 14%, transparent);
    color: var(--cyan);
}

.table-wrap {
    width: 100%;
    overflow-x: auto;
}

.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--text);
    --bs-table-border-color: var(--line);
    --bs-table-striped-color: var(--text);
    --bs-table-active-color: var(--text);
    --bs-table-hover-color: var(--text);
    --bs-table-hover-bg: color-mix(in srgb, var(--cyan) 8%, transparent);
}

.clickable-row {
    cursor: pointer;
}

th {
    color: var(--muted) !important;
    font-size: 12px;
    text-transform: uppercase;
}

td,
th {
    vertical-align: middle;
}

.multiline-cell {
    white-space: pre-line;
}

.handover-form {
    display: grid;
    gap: 14px;
}

.handover-meta-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(160px, 1fr));
    gap: 12px;
    align-items: end;
}

.handover-form-table {
    width: 100%;
    min-width: 980px;
    border-collapse: collapse;
    background: color-mix(in srgb, var(--panel) 92%, var(--input));
}

.handover-form-table th,
.handover-form-table td {
    padding: 8px;
    border: 1px solid var(--line);
    vertical-align: middle;
}

.handover-form-table thead th {
    background: color-mix(in srgb, var(--cyan) 10%, var(--panel));
    color: var(--text) !important;
    font-size: 12px;
    text-transform: uppercase;
}

.handover-section-cell {
    width: 150px;
    background: color-mix(in srgb, var(--panel-2) 82%, var(--input));
    color: var(--text);
    font-weight: 700;
    text-align: center;
}

.handover-label {
    width: 270px;
    color: var(--text) !important;
    font-size: 13px;
    text-transform: none;
}

.handover-form-table textarea {
    min-height: 54px;
    resize: vertical;
}

input,
select,
textarea {
    width: 100%;
    min-height: 38px;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 6px;
    background: var(--input);
    color: var(--text);
    font: inherit;

    /* A control sits inside its label, and `font: inherit` was handing it the
       label's 12px/700 -- which is why typed values and pasted lists came out
       small and bold. Size and weight belong to the value, not to its caption. */
    font-size: var(--text-base);
    font-weight: 400;
}

textarea {
    min-height: 96px;
    resize: vertical;
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--cyan);
    outline: 2px solid color-mix(in srgb, var(--cyan) 18%, transparent);
}

input[readonly],
textarea[readonly] {
    background: color-mix(in srgb, var(--panel-2) 76%, var(--input));
    color: var(--muted);
    cursor: default;
}

label {
    display: grid;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
}

.register-form,
.filter-grid,
.settings-form {
    display: grid;
    grid-template-columns: repeat(4, minmax(160px, 1fr));
    gap: 12px;
    align-items: end;
}

.register-form .wide,
.import-form label {
    grid-column: span 2;
}

/* One field and its actions on a line. A four-column grid used to give the
   input a third of the row and hand the other two thirds to two buttons. */
.search-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

.search-row input {
    flex: 1 1 260px;
    max-width: 420px;
}

/* A button dropped into one of these grids used to inherit a field's width, so
   "Search", "Create" and "Preview import" each stretched to 270px of mostly
   empty slab. An action should be as wide as the words on it. */
.register-form > .btn,
.filter-grid > .btn,
.settings-form > .btn,
.import-form > .btn {
    justify-self: start;
}

.form-note {
    align-self: end;
    margin: 0;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    color: var(--muted);
    background: var(--panel-2);
}

.ioc-form,
.ioc-pairs {
    display: grid;
    gap: 12px;
}

.ioc-pair {
    display: grid;
    grid-template-columns: minmax(180px, 0.8fr) minmax(260px, 1.6fr) auto;
    gap: 12px;
    align-items: end;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: color-mix(in srgb, var(--panel-2) 65%, transparent);
}

.ioc-pair textarea {
    min-height: 42px;
    max-height: 180px;
}

.ioc-remove {
    min-height: 38px;
}

.case-update-summary {
    margin-bottom: 16px;
}

.case-update-edit {
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    grid-column: 1 / -1;
    gap: 10px;
}

.import-form {
    display: grid;
    gap: 12px;
}

.login-screen {
    display: grid;
    grid-template-columns: minmax(320px, 1.2fr) minmax(320px, 430px);
    gap: 42px;
    align-items: center;
    max-width: 1080px;
    min-height: 100vh;
    margin: 0 auto;
    padding: 104px 24px 44px;
}

.login-hero {
    display: grid;
    gap: 18px;
}

.login-mark {
    display: flex;
    gap: 14px;
    align-items: center;
}

.login-mark img {
    width: 220px;
}

.login-mark span {
    padding-left: 14px;
    border-left: 1px solid var(--line);
    color: var(--cyan);
    font-size: 22px;
    font-weight: 700;
}

.login-hero h1 {
    max-width: 720px;
    font-size: 52px;
}

.signal-board {
    display: grid;
    grid-template-columns: repeat(3, minmax(120px, 1fr));
    gap: 10px;
    max-width: 620px;
}

.signal-board div {
    display: grid;
    gap: 3px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel);
}

.signal-board span {
    color: var(--muted);
    font-size: 12px;
}

.signal-board strong {
    color: var(--green);
    font-size: 20px;
}

.login-form {
    display: grid;
    gap: 16px;
    padding: 24px;
}

.btn-primary {
    border-color: var(--green);
    background: linear-gradient(90deg, var(--magenta), var(--green));
}

.btn-primary:hover {
    border-color: var(--cyan);
    background: linear-gradient(90deg, #b81565, #06745f);
}

.btn.btn-outline-light {
    border-color: color-mix(in srgb, var(--text) 34%, var(--line));
    color: var(--text);
}

.btn.btn-outline-light:hover,
.btn.btn-outline-light:focus {
    border-color: var(--cyan);
    background: color-mix(in srgb, var(--cyan) 16%, var(--panel));
    color: var(--text);
}

.soc-badge {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
}

.critical,
.status-escalated {
    background: color-mix(in srgb, var(--red) 18%, transparent);
    color: var(--red);
}

.high,
.status-pending {
    background: color-mix(in srgb, var(--amber) 18%, transparent);
    color: var(--amber);
}

.medium,
.status-in-progress {
    background: color-mix(in srgb, var(--cyan) 16%, transparent);
    color: var(--cyan);
}

.low,
.status-closed {
    background: color-mix(in srgb, var(--green) 18%, transparent);
    color: var(--green);
}

.info,
.status-open,
.status-false-positive {
    background: color-mix(in srgb, var(--blue) 18%, transparent);
    color: color-mix(in srgb, var(--blue) 70%, var(--text));
}

.bar-list {
    display: grid;
    gap: 12px;
}

.bar-row {
    display: grid;
    gap: 6px;
}

.bar-row > div:first-child {
    display: flex;
    justify-content: space-between;
    gap: 10px;
}

.bar-track {
    height: 8px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--input);
}

.bar-track span {
    display: block;
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--magenta), var(--cyan), var(--green));
}

.detail-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(160px, 1fr));
    gap: 12px;
}

.detail-grid div {
    display: grid;
    gap: 4px;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel-2);
}

.detail-grid span {
    color: var(--muted);
    font-size: 12px;
}

.detail-grid strong {
    overflow-wrap: anywhere;
}

.permission-layout {
    display: grid;
    grid-template-columns: 300px 1fr;
    gap: 16px;
}

.permission-override-panel {
    overflow: hidden;
}

.permission-override-layout {
    display: grid;
    grid-template-columns: minmax(260px, 340px) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.permission-user-picker {
    display: grid;
    gap: 12px;
    min-width: 0;
}

.permission-search {
    display: grid;
    gap: 10px;
}

.permission-search .button-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
}

.permission-search .btn {
    width: 100%;
}

.user-results {
    display: grid;
    align-content: start;
    gap: 8px;
    max-height: 420px;
    overflow: auto;
}

.user-result {
    display: grid;
    gap: 4px;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--panel-2);
    text-decoration: none;
}

.permission-editor {
    min-width: 0;
}

.permission-editor-form {
    min-width: 0;
}

.permission-editor-form .panel-title-row h3 {
    margin-bottom: 2px;
}

.empty-state {
    margin: 0;
    padding: 14px;
    border: 1px dashed var(--line);
    border-radius: 8px;
    color: var(--muted);
    background: color-mix(in srgb, var(--panel-2) 52%, transparent);
}

.permission-empty-state {
    min-height: 120px;
    display: grid;
    place-items: center;
    text-align: center;
}

.user-result.selected,
.user-result:hover {
    border-color: var(--cyan);
}

.radio-group {
    display: inline-flex;
    gap: 8px;
    align-items: center;
}

/* The whole cell is the hit area, so a mis-aimed click still toggles the box
   it was aimed at rather than doing nothing. */
.check-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 26px;
    margin: -6px -10px;
    padding: 6px 10px;
    cursor: pointer;
}

.check-cell input {
    width: auto;
    min-height: 0;
}

/* Forty-odd rows of a single checkbox do not need a row height built for
   wrapped prose, and the role columns only ever hold one box each. */
.permission-matrix td,
.permission-matrix th:not(:first-child) {
    padding-top: var(--space-2);
    padding-bottom: var(--space-2);
}

.permission-matrix th:not(:first-child),
.permission-matrix td:not(:first-child) {
    width: 1%;
    text-align: center;
}

/* The group heading belongs over the column it groups, not floating in the
   middle of the roles it says nothing about. */
.category-row th {
    padding-top: var(--space-5);
    border-bottom: 1px solid var(--line);
    color: var(--cyan);
    font-size: var(--text-xs);
    letter-spacing: 0.09em;
    text-align: left;
    text-transform: uppercase;
}

/* A row's name leads and its detail sits under it, rather than the two running
   together into "View dashboarddashboard.view". */
.table td > strong + small {
    display: block;
    margin-top: 2px;
    color: var(--faint);
    font-size: var(--text-xs);
    font-weight: 400;
}

/* A sentence of context under a row's name earns its place, but not the width
   of a whole sentence. It follows the same rule as every other long cell here:
   one line, cut, with the whole of it on hover. */
.table td > strong + small.clamp-2 {
    max-width: 26ch;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* A wide table scrolling sideways is fine -- a clipped Edit button is not. When
   the last column holds actions, it stops travelling with the scroll and stays
   where it can be pressed. */
.table:has(.row-actions) > tbody > tr > td:last-child,
.table:has(.row-actions) > thead > tr > th:last-child {
    position: sticky;
    right: 0;
    z-index: 2;
    background: var(--panel);
}

.table:has(.row-actions) > tbody > tr:hover > td:last-child {
    background: color-mix(in srgb, var(--cyan) 8%, var(--panel));
}

/* Above the body cells, and above the sticky header row it sits in. */
.table:has(.row-actions) > thead > tr > th:last-child {
    z-index: 4;
    background: color-mix(in srgb, var(--panel-2) 88%, var(--bg));
}

/* Only where the detail really is a code. A summary sentence set in monospace
   reads like output, not like prose. */
.permission-matrix td > strong + small,
.permission-override td > strong + small,
.table td > strong + small.code {
    font-family: var(--font-mono);
}

.inline-form {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.inline-form input,
.inline-form select {
    width: auto;
    min-width: 120px;
}

.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.app-flash[hidden] {
    display: none;
}

.ajax-saving {
    opacity: 0.72;
}

.ajax-saved {
    border-color: color-mix(in srgb, var(--green) 45%, var(--line));
}

@media (max-width: 1200px) {
    .topbar {
        grid-template-columns: 1fr;
    }

    .topbar-actions {
        justify-content: space-between;
    }

    .settings-menu-list {
        right: auto;
        left: 0;
    }

    .account-menu-list {
        right: 0;
    }

    .metrics,
    .dashboard-grid,
    .report-grid,
    .register-form,
    .filter-grid,
    .settings-form,
    .handover-meta-grid,
    .detail-grid,
    .permission-layout,
    .permission-override-layout,
    .login-screen {
        grid-template-columns: 1fr;
    }

    .module-toolbar {
        align-items: flex-start;
        flex-direction: column;
    }

    .ioc-pair {
        grid-template-columns: 1fr;
    }

    .register-form .wide {
        grid-column: auto;
    }
}

@media (max-width: 720px) {
    .topbar {
        padding: 10px 14px;
    }

    .topbar-main,
    .topbar-actions,
    .login-mark,
    .panel-title-row {
        align-items: flex-start;
        flex-direction: column;
    }

    .account-menu,
    .account-summary {
        width: 100%;
    }

    .account-menu-list {
        right: auto;
        left: 0;
    }

    .brand img,
    .login-mark img {
        width: 132px;
    }

    .login-hero h1 {
        font-size: 36px;
    }

    .signal-board {
        grid-template-columns: 1fr;
    }

    .content {
        padding: 18px;
    }
}

/* ==========================================================================
   Workspace enhancements
   Additive layer on top of the Mutual Trust Bank palette above. Nothing here
   introduces new colours; everything derives from the existing tokens.
   ========================================================================== */

/* Navigation progress bar -------------------------------------------------- */

.nav-progress {
    position: fixed;
    inset: 0 auto auto 0;
    z-index: 200;
    width: 100%;
    height: 2px;
    transform: scaleX(0);
    transform-origin: 0 50%;
    background: linear-gradient(90deg, var(--magenta), var(--cyan) 60%, var(--green));
    opacity: 0;
    pointer-events: none;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.nav-progress.active {
    opacity: 1;
}

/* Sticky table headers ----------------------------------------------------- */

.table-wrap[data-sticky-table] {
    max-height: min(68vh, 780px);
    overflow: auto;
    border-radius: 6px;
}

.table-wrap[data-sticky-table] thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: color-mix(in srgb, var(--panel-2) 88%, var(--bg));
    box-shadow: inset 0 -1px 0 var(--line);
}

/* A hint that a wide table still has columns off to the right. */
.table-wrap[data-sticky-table]::after {
    content: "";
}

.table-scroller {
    position: relative;
}

.table-scroller[data-overflow-right="true"]::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 44px;
    pointer-events: none;
    border-radius: 0 6px 6px 0;
    background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--bg) 78%, transparent));
}

/* Record counts ------------------------------------------------------------ */

.record-count {
    padding: 3px 10px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: color-mix(in srgb, var(--cyan) 8%, transparent);
    color: var(--muted);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

/* Priority triage stripe --------------------------------------------------- */

.table tbody tr[data-priority] > td:first-child {
    position: relative;
    padding-left: 14px;
}

.table tbody tr[data-priority] > td:first-child::before {
    content: "";
    position: absolute;
    top: 6px;
    bottom: 6px;
    left: 2px;
    width: 3px;
    border-radius: 3px;
    background: var(--line);
}

.table tbody tr[data-priority="P1"] > td:first-child::before {
    background: var(--red);
}

.table tbody tr[data-priority="P2"] > td:first-child::before {
    background: var(--magenta);
}

.table tbody tr[data-priority="P3"] > td:first-child::before {
    background: var(--amber);
}

.table tbody tr[data-priority="P4"] > td:first-child::before {
    background: var(--green);
}

.table tbody tr[data-priority="P5"] > td:first-child::before {
    background: var(--cyan);
}

/* Search shortcut hint ----------------------------------------------------- */

.toolbar-search {
    position: relative;
}

.search-hint {
    position: absolute;
    top: 50%;
    right: 92px;
    transform: translateY(-50%);
    padding: 1px 7px;
    border: 1px solid var(--line);
    border-radius: 4px;
    background: color-mix(in srgb, var(--panel-2) 70%, transparent);
    color: var(--muted);
    font-family: inherit;
    font-size: 11px;
    line-height: 1.5;
    pointer-events: none;
    transition: opacity 0.15s ease;
}

.toolbar-search:focus-within .search-hint,
.toolbar-search input:not(:placeholder-shown) ~ .search-hint {
    opacity: 0;
}

@media (max-width: 900px) {
    .search-hint {
        display: none;
    }
}

/* Row density -------------------------------------------------------------- */

.app-frame[data-density="compact"] .table td,
.app-frame[data-density="compact"] .table th {
    padding-top: 4px;
    padding-bottom: 4px;
    font-size: 13px;
}

.density-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* ==========================================================================
   Application shell
   Sidebar + topbar replace the horizontal nav, which had run out of room:
   six top-level items, three of them nested behind <details> dropdowns.
   ========================================================================== */

.app-shell {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    min-height: 100vh;
    transition: grid-template-columns var(--motion);
}

.app-shell[data-nav="collapsed"] {
    grid-template-columns: var(--sidebar-w-collapsed) minmax(0, 1fr);
}

.sidebar {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    height: 100vh;
    padding: var(--space-3) var(--space-2);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--panel);
    border-right: 1px solid var(--line);
}

.sidebar-brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 36px;
    padding: 0 var(--space-2);
    margin-bottom: var(--space-2);
}

.sidebar-brand img {
    height: 26px;
    width: auto;
    flex-shrink: 0;
}

.nav-group {
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.nav-group-label {
    padding: var(--space-4) var(--space-2) var(--space-1);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--faint);
}

.nav-link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-2);
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--muted);
    font: inherit;
    font-size: var(--text-base);
    font-weight: 500;
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--motion), color var(--motion);
}

.nav-link:hover {
    background: var(--panel-2);
    color: var(--text);
}

.nav-link.active {
    background: var(--accent-wash);
    color: var(--text);
    font-weight: 600;
    box-shadow: inset 2px 0 0 var(--cyan);
}

.nav-link svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.nav-spacer {
    flex: 1;
}

/* Collapsed rail: icons only, labels revealed on hover as a tooltip. */
.app-shell[data-nav="collapsed"] .nav-label,
.app-shell[data-nav="collapsed"] .nav-group-label,
.app-shell[data-nav="collapsed"] .sidebar-brand span {
    display: none;
}

.app-shell[data-nav="collapsed"] .nav-group-label {
    display: block;
    height: var(--space-4);
    padding: 0;
    overflow: hidden;
    text-indent: -999em;
}

.app-shell[data-nav="collapsed"] .nav-link {
    justify-content: center;
}

.app-shell[data-nav="collapsed"] .nav-link:hover::after {
    content: attr(data-label);
    position: absolute;
    left: calc(var(--sidebar-w-collapsed) + var(--space-2));
    z-index: 40;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--panel-3);
    box-shadow: var(--elev-2);
    color: var(--text);
    font-size: var(--text-sm);
    white-space: nowrap;
}

.app-shell[data-nav="collapsed"] .nav-link {
    position: relative;
}

/* Topbar ------------------------------------------------------------------ */

.app-main {
    display: flex;
    min-width: 0;
    flex-direction: column;
}

.app-topbar {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--topbar-h);
    padding: 0 var(--space-5);
    background: color-mix(in srgb, var(--bg) 86%, transparent);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--line);
}

.nav-toggle {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: none;
    color: var(--muted);
    cursor: pointer;
    transition: background var(--motion), color var(--motion);
}

.nav-toggle:hover {
    background: var(--panel-2);
    color: var(--text);
}

.breadcrumbs {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    font-size: var(--text-base);
    color: var(--muted);
}

.breadcrumbs a {
    color: var(--muted);
    text-decoration: none;
}

.breadcrumbs a:hover {
    color: var(--text);
}

.breadcrumbs .crumb-current {
    color: var(--text);
    font-weight: 600;
}

.breadcrumbs .crumb-sep {
    color: var(--faint);
}

.topbar-spacer {
    flex: 1;
}

/* Command palette trigger -- looks like search, opens the palette. */
.palette-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 210px;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--input);
    color: var(--faint);
    font: inherit;
    font-size: var(--text-base);
    cursor: pointer;
    transition: border-color var(--motion), color var(--motion);
}

.palette-trigger:hover {
    border-color: var(--cyan);
    color: var(--muted);
}

.palette-trigger .kbd-hint {
    margin-left: auto;
}

.kbd-hint {
    padding: 1px 5px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--panel-2);
    color: var(--faint);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    line-height: 1.5;
}

/* Command palette --------------------------------------------------------- */

.palette[open] {
    display: block;
}

.palette {
    width: min(560px, calc(100vw - 2 * var(--space-4)));
    max-height: 60vh;
    padding: 0;
    margin-top: 12vh;
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--panel);
    box-shadow: var(--elev-3);
    color: var(--text);
    overflow: hidden;
}

.palette::backdrop {
    background: var(--overlay);
    backdrop-filter: blur(2px);
}

.palette-input {
    width: 100%;
    padding: var(--space-4) var(--space-5);
    border: 0;
    border-bottom: 1px solid var(--line);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: var(--text-lg);
}

.palette-input:focus {
    outline: none;
}

.palette-results {
    max-height: calc(60vh - 58px);
    padding: var(--space-2);
    overflow-y: auto;
}

.palette-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: var(--space-2) var(--space-3);
    border: 0;
    border-radius: var(--radius);
    background: none;
    color: var(--text);
    font: inherit;
    font-size: var(--text-base);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.palette-item[aria-selected="true"] {
    background: var(--accent-wash-strong);
}

.palette-item .palette-group {
    margin-left: auto;
    color: var(--faint);
    font-size: var(--text-xs);
}

.palette-empty {
    padding: var(--space-6);
    color: var(--muted);
    font-size: var(--text-base);
    text-align: center;
}

/* Mobile / tablet: sidebar becomes an overlay drawer. ---------------------- */

.nav-scrim {
    position: fixed;
    inset: 0;
    z-index: 44;
    background: var(--overlay);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion);
}

@media (max-width: 900px) {
    .app-shell,
    .app-shell[data-nav="collapsed"] {
        grid-template-columns: minmax(0, 1fr);
    }

    .sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: 45;
        width: var(--sidebar-w);
        transform: translateX(-100%);
        transition: transform var(--motion);
    }

    .app-shell[data-nav="open"] .sidebar {
        transform: translateX(0);
        box-shadow: var(--elev-3);
    }

    .app-shell[data-nav="open"] .nav-scrim {
        opacity: 1;
        pointer-events: auto;
    }

    .app-shell[data-nav="open"] .nav-label,
    .app-shell[data-nav="open"] .nav-group-label,
    .app-shell[data-nav="open"] .sidebar-brand span {
        display: block;
    }

    .palette-trigger {
        min-width: 0;
    }

    .palette-trigger .palette-trigger-label,
    .palette-trigger .kbd-hint {
        display: none;
    }
}

/* ==========================================================================
   Component primitives
   ========================================================================== */

.content {
    padding: var(--space-6) var(--space-5) var(--space-12);
}

.panel {
    padding: var(--space-5);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--panel);
    box-shadow: var(--elev-1);
}

.panel h2 {
    margin: 0 0 var(--space-4);
    font-size: var(--text-lg);
    font-weight: 600;
}

/* Buttons: one scale, three weights, consistent focus. */
.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border: 1px solid transparent;
    border-radius: var(--radius);
    font-family: var(--font-ui);
    font-size: var(--text-base);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    transition: background var(--motion), border-color var(--motion), color var(--motion);
}

.btn-sm {
    padding: var(--space-1) var(--space-3);
    font-size: var(--text-sm);
}

.btn:focus-visible,
.nav-link:focus-visible,
.palette-item:focus-visible,
.nav-toggle:focus-visible,
.palette-trigger:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

.btn-primary {
    background: var(--cyan);
    border-color: var(--cyan);
    color: #04191d;
}

.btn-primary:hover {
    background: color-mix(in srgb, var(--cyan) 86%, #000);
    border-color: color-mix(in srgb, var(--cyan) 86%, #000);
    color: #04191d;
}

.btn-secondary {
    background: var(--panel-2);
    border-color: var(--line);
    color: var(--text);
}

.btn-secondary:hover {
    background: var(--panel-3);
    color: var(--text);
}

/* For the undo beside an action -- "Clear" next to "Search". It has to be
   reachable, but it is not what anyone came to the page to press. */
.btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--muted);
    font-weight: 500;
}

.btn-ghost:hover {
    background: var(--panel-2);
    color: var(--text);
}

/* Status + priority badges share one shape so severity reads by colour alone. */
.soc-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.soc-badge::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
}

.soc-badge.critical {
    background: color-mix(in srgb, var(--red) 16%, transparent);
    border-color: color-mix(in srgb, var(--red) 38%, transparent);
    color: var(--red);
}

.soc-badge.high {
    background: color-mix(in srgb, var(--magenta) 15%, transparent);
    border-color: color-mix(in srgb, var(--magenta) 36%, transparent);
    color: var(--magenta);
}

.soc-badge.medium {
    background: color-mix(in srgb, var(--amber) 16%, transparent);
    border-color: color-mix(in srgb, var(--amber) 38%, transparent);
    color: var(--amber);
}

.soc-badge.low {
    background: color-mix(in srgb, var(--cyan) 15%, transparent);
    border-color: color-mix(in srgb, var(--cyan) 36%, transparent);
    color: var(--cyan);
}

.soc-badge.info {
    background: color-mix(in srgb, var(--muted) 18%, transparent);
    border-color: color-mix(in srgb, var(--muted) 34%, transparent);
    color: var(--muted);
}

/* Account state, which is not a case state -- a disabled login is a fact to
   notice, not an alarm, so it reads muted rather than red. */
.soc-badge.status-complete,
.soc-badge.status-enabled {
    background: color-mix(in srgb, var(--green) 16%, transparent);
    border-color: color-mix(in srgb, var(--green) 36%, transparent);
    color: var(--green);
}

.soc-badge.status-disabled,
.soc-badge.status-draft,
.soc-badge.status-planned {
    background: color-mix(in srgb, var(--muted) 16%, transparent);
    border-color: color-mix(in srgb, var(--muted) 34%, transparent);
    color: var(--muted);
}

/* An indicator's state is really "has anyone done anything about this yet".
   New is the one that wants an answer, so New is the one that carries warmth;
   Blocked is the finished state and reads calm. */
.soc-badge.status-new {
    background: color-mix(in srgb, var(--amber) 16%, transparent);
    border-color: color-mix(in srgb, var(--amber) 38%, transparent);
    color: var(--amber);
}

.soc-badge.status-monitoring {
    background: color-mix(in srgb, var(--blue) 16%, transparent);
    border-color: color-mix(in srgb, var(--blue) 38%, transparent);
    color: color-mix(in srgb, var(--blue) 72%, var(--text));
}

.soc-badge.status-blocked {
    background: color-mix(in srgb, var(--green) 16%, transparent);
    border-color: color-mix(in srgb, var(--green) 36%, transparent);
    color: var(--green);
}

.soc-badge.status-expired {
    background: color-mix(in srgb, var(--muted) 14%, transparent);
    border-color: color-mix(in srgb, var(--muted) 30%, transparent);
    color: var(--faint);
}

/* A rule pulled out for tuning is not detecting anything tonight, which is
   worth noticing without sounding like an outage. */
.soc-badge.status-running,
.soc-badge.status-tuning {
    background: color-mix(in srgb, var(--amber) 16%, transparent);
    border-color: color-mix(in srgb, var(--amber) 38%, transparent);
    color: var(--amber);
}

/* A row's actions: what you can do to this record, on one line. */
.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: flex-start;
}

.row-actions form {
    margin: 0;
}

.row-editor > summary {
    display: inline-flex;
    cursor: pointer;
    list-style: none;
}

.row-editor > summary::-webkit-details-marker {
    display: none;
}

.row-editor[open] > summary {
    border-color: var(--cyan);
    color: var(--cyan);
}

.row-editor-body {
    display: grid;
    gap: var(--space-4);
    width: max-content;
    min-width: 260px;
    margin-top: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel-2);
}

.row-editor-form {
    display: grid;
    gap: var(--space-2);
    justify-items: start;
}

.row-editor-form label {
    display: grid;
    gap: var(--space-1);
    width: 100%;
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

/* Tables: the theme is driven by our tokens, not Bootstrap's .table-dark,
   which stayed dark even in light mode. */
/* A flat 1150px floor used to make every table a wide table: the five-column
   Users list scrolled sideways and spread its columns over a screen and a half
   for the sake of the twelve-column record tables. A table should fill its
   panel and grow past it only when its own columns need the room. */
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--text);
    width: max-content;
    min-width: 100%;
    margin: 0;
    border-collapse: separate;
    border-spacing: 0;
    color: var(--text);
    font-size: var(--text-base);
}

/* ...and a cell carrying free prose wraps inside a readable column instead of
   dragging the whole table out to the width of its longest sentence. */
.table > tbody > tr > td {
    max-width: 420px;
}

.table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: var(--space-2) var(--space-3);
    background: var(--panel-2);
    border-bottom: 1px solid var(--line);
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;

    /* A th centres itself by default, so any header that was not a sortable
       link -- "Permission", "Actions" -- floated away from the column under it
       while its sortable neighbours sat left. */
    text-align: left;
    text-transform: uppercase;
    white-space: nowrap;
}

.table > tbody > tr > td {
    padding: var(--space-3);
    border-bottom: 1px solid var(--line-soft);
    background: transparent;
    color: var(--text);
    vertical-align: middle;
}

.table > tbody > tr:hover > td {
    background: var(--accent-wash);
}

.table > tbody > tr:last-child > td {
    border-bottom: 0;
}

.table-wrap {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: auto;
}

/* Empty and loading states -------------------------------------------------*/

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-12) var(--space-6);
    color: var(--muted);
    text-align: center;
}

.empty-state h3 {
    margin: 0;
    color: var(--text);
    font-size: var(--text-lg);
}

.empty-state p {
    max-width: 46ch;
    margin: 0;
    font-size: var(--text-base);
}

.skeleton {
    border-radius: var(--radius-sm);
    background: var(--skeleton);
    background-size: 400% 100%;
    animation: skeleton-sweep 1.4s ease-in-out infinite;
}

@keyframes skeleton-sweep {
    0% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0 50%;
    }
}

/* Toasts -------------------------------------------------------------------*/

.toast-stack {
    position: fixed;
    right: var(--space-5);
    bottom: var(--space-5);
    z-index: 60;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    pointer-events: none;
}

.toast {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    max-width: 360px;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--line);
    border-left: 3px solid var(--cyan);
    border-radius: var(--radius);
    background: var(--panel-3);
    box-shadow: var(--elev-3);
    color: var(--text);
    font-size: var(--text-base);
    pointer-events: auto;
    animation: toast-in 160ms cubic-bezier(0.2, 0, 0.2, 1);
}

.toast.danger {
    border-left-color: var(--red);
}

.toast.success {
    border-left-color: var(--green);
}

@keyframes toast-in {
    from {
        opacity: 0;
        transform: translateY(6px);
    }
}

/* The grid backdrop reads as texture on the sign-in screen and as noise
   behind dense tables, so it now lives only on the login route. */
.login-screen {
    background-image:
        linear-gradient(90deg, var(--bg-grid) 1px, transparent 1px),
        linear-gradient(0deg, var(--bg-grid) 1px, transparent 1px);
    background-size: 28px 28px;
}

/* The wordmark has dark lettering baked into the PNG, so it disappears on the
   dark surface. A light plate keeps the brand colours exact and legible. */
.sidebar-brand img,
.guest-topbar .brand img {
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    background: #ffffff;
}

:root[data-theme="light"] .sidebar-brand img,
:root[data-theme="light"] .guest-topbar .brand img {
    padding: 0;
    background: none;
}

/* Toolbars wrap onto a second line at narrow widths instead of overflowing. */
.module-toolbar {
    flex-wrap: wrap;
    gap: var(--space-3);
}

/* ==========================================================================
   Table ergonomics
   ========================================================================== */

.panel-title-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
}

.panel-title-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-left: auto;
}

/* Sortable headers are links: shareable URLs, and they work without script. */
.th-sortable {
    padding: 0 !important;
}

.th-sortable > a {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    color: inherit;
    text-decoration: none;
    white-space: nowrap;
}

.th-sortable > a:hover {
    color: var(--text);
}

.th-sortable .sort-icon {
    opacity: 0.35;
    flex-shrink: 0;
}

.th-sortable:hover .sort-icon {
    opacity: 0.7;
}

.th-sortable.sorted {
    color: var(--text);
}

.th-sortable.sorted .sort-icon {
    opacity: 1;
    color: var(--cyan);
}

.th-sortable > a:focus-visible {
    outline: none;
    box-shadow: inset var(--ring);
}

/* Active filter chips ----------------------------------------------------- */

.filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    max-width: 320px;
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel-2);
    color: var(--text);
    font-size: var(--text-sm);
    text-decoration: none;
    transition: border-color var(--motion), background var(--motion);
}

.filter-chip:hover {
    border-color: var(--red);
    background: var(--panel-3);
    color: var(--text);
}

.filter-chip > span:nth-child(2) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.filter-chip-key {
    color: var(--muted);
    font-weight: 600;
}

.filter-chip-x {
    color: var(--faint);
    font-size: var(--text-md);
    line-height: 1;
}

.filter-chip:hover .filter-chip-x {
    color: var(--red);
}

.filter-chip-clear {
    border-style: dashed;
    background: none;
    color: var(--muted);
}

.filter-chip-clear:hover {
    border-color: var(--cyan);
    color: var(--text);
}

/* Column visibility ------------------------------------------------------- */

.column-menu {
    position: relative;
}

.column-menu summary {
    cursor: pointer;
    list-style: none;
}

.column-menu summary::-webkit-details-marker {
    display: none;
}

.column-menu-list {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    z-index: 25;
    display: grid;
    gap: 1px;
    max-height: 320px;
    min-width: 220px;
    padding: var(--space-2);
    overflow-y: auto;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel);
    box-shadow: var(--elev-3);
}

.column-menu-list label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-sm);
    font-size: var(--text-base);
    font-weight: 500;
    cursor: pointer;
}

.column-menu-list label:hover {
    background: var(--panel-2);
}

.column-menu-list input {
    accent-color: var(--cyan);
}

/* Hidden columns are removed from layout so the table reflows. */
.table [data-col].col-hidden {
    display: none;
}

.empty-row td {
    background: transparent !important;
}

.empty-row:hover td {
    background: transparent !important;
}

/* ==========================================================================
   Self-hosted typography and the handful of Bootstrap classes we still used
   Bootstrap shipped 230 KB of CSS to provide eight class names, and every page
   load announced itself to two third-party CDNs. Both are now served from here.
   ========================================================================== */

@font-face {
    font-family: Inter;
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("/static/vendor/fonts/inter-latin-400-normal.woff2") format("woff2");
}

@font-face {
    font-family: Inter;
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/static/vendor/fonts/inter-latin-500-normal.woff2") format("woff2");
}

@font-face {
    font-family: Inter;
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/static/vendor/fonts/inter-latin-600-normal.woff2") format("woff2");
}

@font-face {
    font-family: Inter;
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/static/vendor/fonts/inter-latin-700-normal.woff2") format("woff2");
}

@font-face {
    font-family: Rajdhani;
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("/static/vendor/fonts/rajdhani-latin-500-normal.woff2") format("woff2");
}

@font-face {
    font-family: Rajdhani;
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("/static/vendor/fonts/rajdhani-latin-600-normal.woff2") format("woff2");
}

@font-face {
    font-family: Rajdhani;
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("/static/vendor/fonts/rajdhani-latin-700-normal.woff2") format("woff2");
}

/* Outline buttons ---------------------------------------------------------- */

.btn-outline-info,
.btn-outline-light,
.btn-outline-danger,
.btn-outline-warning {
    background: transparent;
    border-width: 1px;
    border-style: solid;
}

.btn-outline-info {
    border-color: color-mix(in srgb, var(--cyan) 45%, transparent);
    color: var(--cyan);
}

.btn-outline-info:hover {
    background: color-mix(in srgb, var(--cyan) 14%, transparent);
    border-color: var(--cyan);
    color: var(--cyan);
}

.btn-outline-light {
    border-color: var(--line);
    color: var(--muted);
}

.btn-outline-light:hover {
    background: var(--panel-2);
    border-color: var(--muted);
    color: var(--text);
}

.btn-outline-danger {
    border-color: color-mix(in srgb, var(--red) 45%, transparent);
    color: var(--red);
}

.btn-outline-danger:hover {
    background: color-mix(in srgb, var(--red) 14%, transparent);
    border-color: var(--red);
    color: var(--red);
}

.btn-outline-warning {
    border-color: color-mix(in srgb, var(--amber) 48%, transparent);
    color: var(--amber);
}

.btn-outline-warning:hover {
    background: color-mix(in srgb, var(--amber) 14%, transparent);
    border-color: var(--amber);
    color: var(--amber);
}

.btn-danger {
    background: var(--red);
    border-color: var(--red);
    color: #2a0106;
}

.btn-danger:hover {
    background: color-mix(in srgb, var(--red) 86%, #000);
    border-color: color-mix(in srgb, var(--red) 86%, #000);
    color: #2a0106;
}

/* Alerts ------------------------------------------------------------------- */

.alert {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--line);
    border-left: 3px solid var(--muted);
    border-radius: var(--radius);
    background: var(--panel-2);
    color: var(--text);
    font-size: var(--text-base);
}

.alert-warning {
    border-left-color: var(--amber);
}

.alert-danger {
    border-left-color: var(--red);
}

.alert-success {
    border-left-color: var(--green);
}

.alert-info {
    border-left-color: var(--cyan);
}

.align-middle,
.align-middle > tbody > tr > td,
.align-middle > thead > tr > th {
    vertical-align: middle;
}

.badge {
    display: inline-block;
    padding: 2px var(--space-2);
    border-radius: 999px;
    background: var(--panel-3);
    color: var(--text);
    font-size: var(--text-xs);
    font-weight: 600;
}

/* ==========================================================================
   Dashboard
   ========================================================================== */

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

.metric {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: var(--space-4);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--panel);
    box-shadow: var(--elev-1);
}

.metric > span {
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.metric > strong {
    font-size: var(--text-2xl);
    font-weight: 700;
    line-height: 1.1;
}

.metric > small {
    color: var(--faint);
    font-size: var(--text-sm);
}

/* The only tile that earns colour: severity is what an analyst scans for first. */
.metric-alert {
    border-color: color-mix(in srgb, var(--red) 40%, var(--line));
}

.metric-alert > strong {
    color: var(--red);
}

.dashboard-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-4);
}

.dashboard-grid-wide {
    grid-template-columns: minmax(0, 1fr);
}

.chart-panel .chart-body {
    position: relative;
    height: 260px;
}

.dashboard-grid-wide .chart-panel .chart-body {
    height: 300px;
}

.chart-body canvas {
    width: 100% !important;
    height: 100% !important;
}

.chart-body .empty-state {
    padding: var(--space-8) var(--space-4);
}

/* Proportional bar lists --------------------------------------------------- */

.bar-list {
    display: grid;
    gap: var(--space-3);
}

.bar-row > div:first-child {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-1);
    font-size: var(--text-base);
}

.bar-row strong {
    overflow: hidden;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bar-row span {
    flex-shrink: 0;
    color: var(--text);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

.bar-row span em {
    margin-left: var(--space-1);
    color: var(--faint);
    font-size: var(--text-sm);
    font-style: normal;
    font-weight: 500;
}

.bar-track {
    height: 6px;
    overflow: hidden;
    border-radius: 999px;
    background: var(--panel-2);
}

.bar-track > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--cyan);
    transition: width var(--motion);
}

.bar-track > span[data-series="1"] { background: var(--green); }
.bar-track > span[data-series="2"] { background: var(--amber); }
.bar-track > span[data-series="3"] { background: var(--magenta); }
.bar-track > span[data-series="4"] { background: var(--blue); }
.bar-track > span[data-series="5"] { background: var(--red); }

/* ==========================================================================
   Grouped forms
   ========================================================================== */

.form-section {
    padding: 0;
    margin: 0 0 var(--space-5);
    border: 0;
    border-top: 1px solid var(--line-soft);
    padding-top: var(--space-4);
}

.form-section:first-of-type {
    border-top: 0;
    padding-top: 0;
}

.form-section > legend,
.form-section > summary > span {
    padding: 0;
    color: var(--text);
    font-family: var(--font-display);
    font-size: var(--text-md);
    font-weight: 700;
    letter-spacing: 0.02em;
}

.form-section-hint,
.form-section > summary > em {
    margin: var(--space-1) 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
    font-style: normal;
}

.form-section-body {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: var(--space-3) var(--space-4);
    margin-top: var(--space-3);
}

.form-section-body > label.wide,
.form-section-body > .wide {
    grid-column: 1 / -1;
}

.form-section-body label {
    display: grid;
    gap: var(--space-1);
    align-content: start;
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

.form-section-body label small {
    color: var(--faint);
    font-size: var(--text-xs);
    font-weight: 500;
}

/* A group that only applies in a particular state stays folded away. */
.form-section-collapsible {
    border-top: 1px solid var(--line-soft);
    padding-top: var(--space-4);
}

.form-section-collapsible > summary {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: 0;
    cursor: pointer;
    list-style: none;
}

.form-section-collapsible > summary::-webkit-details-marker {
    display: none;
}

.form-section-collapsible > summary > span::before {
    display: inline-block;
    width: 1em;
    content: "\203A";
    color: var(--muted);
    transition: transform var(--motion);
}

.form-section-collapsible[open] > summary > span::before {
    transform: rotate(90deg);
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    justify-content: flex-end;
    padding-top: var(--space-4);
    border-top: 1px solid var(--line-soft);
}

/* Invalid fields say so before the form is submitted. */
.form-section-body input:user-invalid,
.form-section-body select:user-invalid,
.form-section-body textarea:user-invalid {
    border-color: var(--red);
}

.filter-form .form-section-body {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

/* Grouped forms stack their sections; the columns happen inside each section.
   Scoped to a class because five other forms still use the flat grid. */
.form-grouped {
    display: block;
}

/* ==========================================================================
   MITRE ATT&CK
   ========================================================================== */

.mitre-cell {
    display: flex;
    flex-direction: column;
    gap: 2px;
    line-height: 1.3;
}

.mitre-technique {
    align-self: flex-start;
    padding: 1px var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--panel-2);
    color: var(--cyan);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

.mitre-unmapped {
    color: var(--faint);
}

/* Every tactic is drawn, whether or not it has cases: the empty columns are
   the finding. Intensity is relative to the busiest tactic. */
.mitre-matrix {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: var(--space-2);
}

.mitre-tile {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    justify-content: space-between;
    min-height: 74px;
    padding: var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel-2);
}

.mitre-tile-name {
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: 600;
    line-height: 1.25;
}

.mitre-tile strong {
    font-size: var(--text-lg);
    font-variant-numeric: tabular-nums;
}

.mitre-tile[data-level="0"] strong {
    color: var(--faint);
    font-weight: 500;
}

.mitre-tile[data-level="1"] { background: color-mix(in srgb, var(--cyan) 12%, var(--panel-2)); }
.mitre-tile[data-level="2"] { background: color-mix(in srgb, var(--cyan) 26%, var(--panel-2)); }
.mitre-tile[data-level="3"] { background: color-mix(in srgb, var(--amber) 30%, var(--panel-2)); }
.mitre-tile[data-level="4"] {
    background: color-mix(in srgb, var(--red) 32%, var(--panel-2));
    border-color: color-mix(in srgb, var(--red) 45%, var(--line));
}

/* Reports -------------------------------------------------------------------*/

.period-or {
    color: var(--faint);
    font-size: var(--text-sm);
}

.search-row input[type="month"],
.search-row input[type="date"] {
    flex: 0 0 auto;
    width: auto;
    min-width: 150px;
}

.metric > small {
    color: var(--faint);
    font-size: var(--text-xs);
}

/* A zero in a cross-tab is real information -- "no P1 phishing this month" --
   but it should not compete with the counts that are not zero. */
.cell-zero {
    color: var(--faint);
}

/* Threat hunting ------------------------------------------------------------*/

.hunt-gap-lead {
    margin: 0 0 var(--space-3);
    color: var(--muted);
}

.hunt-gaps {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: var(--space-2);
}

/* The list is already filtered to tactics nothing is watching, so the colour
   here answers the second question only: has anyone been to look? */
.hunt-gap {
    display: grid;
    gap: var(--space-1);
    padding: var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel-2);
}

.hunt-gap[data-state="never"] {
    background: color-mix(in srgb, var(--red) 16%, var(--panel-2));
    border-color: color-mix(in srgb, var(--red) 40%, var(--line));
}

.hunt-gap[data-state="stale"] {
    background: color-mix(in srgb, var(--amber) 14%, var(--panel-2));
    border-color: color-mix(in srgb, var(--amber) 34%, var(--line));
}

.hunt-gap[data-state="recent"] {
    background: color-mix(in srgb, var(--green) 12%, var(--panel-2));
    border-color: color-mix(in srgb, var(--green) 30%, var(--line));
}

.hunt-gap-note {
    color: var(--muted);
    font-size: var(--text-xs);
}

/* "Nothing found" is a result, not a failure, so it reads calm. Findings is the
   one that wants a second look. */
.hunt-outcome {
    font-weight: 600;
}

.hunt-outcome[data-outcome="Findings"] {
    color: var(--amber);
}

.hunt-outcome[data-outcome="Nothing found"] {
    color: var(--green);
}

.hunt-outcome[data-outcome="Inconclusive"] {
    color: color-mix(in srgb, var(--blue) 72%, var(--text));
}

.hunt-outcome[data-outcome=""] {
    color: var(--faint);
    font-weight: 400;
}

/* Repeat indicators ---------------------------------------------------------*/

.repeat-count {
    color: var(--amber);
    font-size: var(--text-lg);
    font-variant-numeric: tabular-nums;
}

.repeat-cases {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
}

.repeat-case {
    padding: 1px var(--space-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--cyan);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    text-decoration: none;
}

.repeat-case:hover {
    border-color: var(--cyan);
    background: var(--accent-wash);
}

/* On a case, "this one is already familiar" is the whole message, so it is the
   only thing in the column that carries a colour. */
.ioc-repeat-flag {
    color: var(--amber);
    font-weight: 600;
    text-decoration: none;
}

.ioc-repeat-flag:hover {
    text-decoration: underline;
}

.ioc-first-flag {
    color: var(--faint);
}

/* Playbooks on a case -------------------------------------------------------*/

.playbook-apply {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

.playbook-apply select {
    width: auto;
    min-width: 220px;
}

.playbook-run + .playbook-run {
    margin-top: var(--space-5);
    padding-top: var(--space-5);
    border-top: 1px solid var(--line-soft);
}

.playbook-run-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: var(--space-3);
}

.playbook-run-head h3 {
    margin: 0;
    font-size: var(--text-md);
}

.playbook-run[data-complete="true"] .playbook-run-head .record-count {
    border-color: color-mix(in srgb, var(--green) 34%, transparent);
    color: var(--green);
}

.playbook-steps {
    display: grid;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

.playbook-step {
    display: flex;
    gap: var(--space-3);
    align-items: baseline;
    padding: var(--space-2) var(--space-2) var(--space-2) 0;
    border-radius: var(--radius);
}

.playbook-step form {
    margin: 0;
}

/* The tick is a button, not a checkbox: pressing it posts and is audited, so it
   must never look like something that toggles freely and might not have saved. */
.playbook-step-toggle {
    display: block;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--input);
    cursor: pointer;
    transition: background var(--motion), border-color var(--motion);
}

.playbook-step-toggle:hover {
    border-color: var(--cyan);
}

.playbook-step[data-done="true"] .playbook-step-toggle {
    position: relative;
    border-color: var(--green);
    background: var(--green);
}

.playbook-step[data-done="true"] .playbook-step-toggle::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 6px;
    width: 4px;
    height: 9px;
    border: solid #04191d;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

.playbook-step-text {
    flex: 1 1 auto;
}

.playbook-step[data-done="true"] .playbook-step-text {
    color: var(--muted);
    text-decoration: line-through;
}

.playbook-step small {
    flex: 0 0 auto;
    color: var(--faint);
    font-size: var(--text-xs);
}

.playbook-empty {
    margin: 0;
    color: var(--muted);
}

/* On the case matrix, colour is already spent on how often a tactic hit us, so
   "nothing is watching this" has to be said in the one channel left: the edge. */
.mitre-tile[data-watched="false"] {
    border-style: dashed;
    border-color: color-mix(in srgb, var(--red) 55%, var(--line));
}

.mitre-detection-note {
    margin: var(--space-4) 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

.mitre-detection-note a {
    color: var(--cyan);
}

/* The case matrix colours the hot tiles, because being hit often is the signal
   there. The coverage matrix inverts that: a tile with nothing watching it is
   the signal, so the blind ones carry the colour and the covered ones go quiet. */
.detection-tile[data-state="covered"] {
    background: color-mix(in srgb, var(--green) 14%, var(--panel-2));
    border-color: color-mix(in srgb, var(--green) 32%, var(--line));
}

.detection-tile[data-state="idle"] {
    background: color-mix(in srgb, var(--amber) 16%, var(--panel-2));
    border-color: color-mix(in srgb, var(--amber) 38%, var(--line));
}

.detection-tile[data-state="blind"] {
    background: color-mix(in srgb, var(--red) 18%, var(--panel-2));
    border-color: color-mix(in srgb, var(--red) 42%, var(--line));
}

.detection-tile[data-state="blind"] strong {
    color: var(--red);
}

.detection-tile-note {
    color: var(--muted);
    font-size: var(--text-xs);
}

.detection-blind {
    margin: var(--space-4) 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

.detection-blind-clear {
    color: var(--green);
}

.mitre-top-heading {
    margin: var(--space-5) 0 var(--space-2);
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.mitre-top {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--space-1) var(--space-4);
    padding: 0;
    margin: 0;
    list-style: none;
}

.mitre-top li {
    display: flex;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-1) 0;
    border-bottom: 1px solid var(--line-soft);
    font-size: var(--text-base);
}

.mitre-top code {
    color: var(--cyan);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

/* ==========================================================================
   Case detail
   ========================================================================== */

.detail-heading {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: flex-start;
    justify-content: space-between;
}

.detail-heading .eyebrow a {
    color: var(--muted);
    text-decoration: none;
}

.detail-heading .eyebrow a:hover {
    color: var(--cyan);
}

.detail-badges {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    margin-top: var(--space-2);
}

.detail-id {
    padding: 2px var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--panel-2);
    color: var(--cyan);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

.detail-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-4);
    margin: 0;
}

.detail-item.wide {
    grid-column: 1 / -1;
}

.detail-item dt {
    margin-bottom: var(--space-1);
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.detail-item dd {
    margin: 0;
    color: var(--text);
    font-size: var(--text-base);
    white-space: pre-wrap;
}

.detail-empty {
    color: var(--faint);
    font-style: italic;
}

.detail-mono {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

.case-link {
    color: var(--cyan);
    text-decoration: none;
}

.case-link:hover {
    text-decoration: underline;
}

/* Timeline ---------------------------------------------------------------- */

.timeline {
    display: grid;
    gap: var(--space-4);
    padding: 0 0 0 var(--space-5);
    margin: 0;
    list-style: none;
}

.timeline-item {
    position: relative;
}

/* The spine is drawn per item, stopping short on the last one. */
.timeline-item::before {
    position: absolute;
    top: 14px;
    bottom: calc(var(--space-4) * -1);
    left: -13px;
    width: 1px;
    background: var(--line);
    content: "";
}

.timeline-item:last-child::before {
    display: none;
}

.timeline-marker {
    position: absolute;
    top: 5px;
    left: -17px;
    width: 9px;
    height: 9px;
    border: 2px solid var(--panel);
    border-radius: 50%;
    background: var(--muted);
}

.timeline-item[data-action="case.created"] .timeline-marker { background: var(--cyan); }
.timeline-item[data-action="case.closed"] .timeline-marker { background: var(--green); }
.timeline-item[data-action="case.reopened"] .timeline-marker { background: var(--amber); }
.timeline-item[data-action="case.deleted"] .timeline-marker { background: var(--red); }

.timeline-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: baseline;
    justify-content: space-between;
    margin: 0;
    font-size: var(--text-base);
}

.timeline-head time {
    color: var(--faint);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.timeline-actor {
    margin: 2px 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

.timeline-change {
    margin: var(--space-2) 0 0;
    color: var(--text);
    font-size: var(--text-sm);
}

.timeline-change span {
    margin: 0 var(--space-1);
    color: var(--faint);
}

.timeline-detail {
    margin: var(--space-1) 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

/* In the detail header the MITRE pair sits inline with the other badges rather
   than stacking as it does in a table cell. */
.detail-badges .mitre-cell {
    flex-direction: row;
    align-items: center;
    gap: var(--space-2);
    padding: 2px var(--space-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel-2);
    font-size: var(--text-sm);
}

.detail-badges .mitre-technique {
    padding: 0;
    background: none;
}

/* Sits above the page rather than inside it: this is about the deployment, not
   about whatever the administrator happened to open. */
.security-banner {
    margin-bottom: var(--space-5);
}

.security-banner code {
    padding: 1px var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--panel-3);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

/* ==========================================================================
   Case notes and evidence
   ========================================================================== */

.note-form {
    display: grid;
    gap: var(--space-3);
    padding-bottom: var(--space-4);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--line-soft);
}

.note-kind {
    display: flex;
    gap: var(--space-2);
}

.note-kind label {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--muted);
    font-size: var(--text-base);
    font-weight: 600;
    cursor: pointer;
}

.note-kind label:has(input:checked) {
    border-color: var(--cyan);
    background: var(--accent-wash);
    color: var(--text);
}

.note-kind input {
    accent-color: var(--cyan);
}

.note-evidence-fields {
    display: grid;
    grid-template-columns: minmax(160px, 1fr) minmax(0, 2fr);
    gap: var(--space-3);
}

.note-evidence-fields label,
.note-form > label {
    display: grid;
    gap: var(--space-1);
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

.note-form .form-actions {
    padding-top: 0;
    border-top: 0;
}

.note-list {
    display: grid;
    gap: var(--space-3);
    padding: 0;
    margin: 0;
    list-style: none;
}

.note-item {
    padding: var(--space-3);
    border: 1px solid var(--line);
    border-left: 3px solid var(--line);
    border-radius: var(--radius);
    background: var(--panel-2);
}

.note-item[data-kind="evidence"] {
    border-left-color: var(--amber);
}

.note-item[data-kind="note"] {
    border-left-color: var(--cyan);
}

.note-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    font-size: var(--text-sm);
}

.note-badge {
    padding: 1px var(--space-2);
    border-radius: 999px;
    background: var(--panel-3);
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.note-head time {
    color: var(--faint);
    font-variant-numeric: tabular-nums;
}

.note-withdraw {
    margin-left: auto;
}

.note-evidence {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    margin: var(--space-2) 0 0;
}

.note-evidence-type {
    color: var(--amber);
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.note-evidence code {
    padding: 1px var(--space-2);
    border-radius: var(--radius-sm);
    background: var(--panel-3);
    color: var(--text);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    overflow-wrap: anywhere;
}

.note-body {
    margin: var(--space-2) 0 0;
    color: var(--text);
    font-size: var(--text-base);
    white-space: pre-wrap;
}

.timeline-item[data-action="case.evidence_added"] .timeline-marker { background: var(--amber); }
.timeline-item[data-action="case.note_added"] .timeline-marker { background: var(--cyan); }
.timeline-item[data-action="case.evidence_withdrawn"] .timeline-marker,
.timeline-item[data-action="case.note_withdrawn"] .timeline-marker { background: var(--red); }

/* Post incident review ----------------------------------------------------- */

.review-read {
    margin-bottom: var(--space-4);
}

.review-edit {
    border-top: 1px solid var(--line-soft);
}

.review-form {
    margin-top: var(--space-3);
}

.review-form .form-section-body {
    grid-template-columns: minmax(0, 1fr);
}

.timeline-item[data-action="case.review_created"] .timeline-marker,
.timeline-item[data-action="case.review_updated"] .timeline-marker { background: var(--green); }

/* ==========================================================================
   Activity feed
   ========================================================================== */

.activity-bell {
    position: relative;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: var(--radius);
    color: var(--muted);
    text-decoration: none;
    transition: background var(--motion), color var(--motion);
}

.activity-bell:hover {
    background: var(--panel-2);
    color: var(--text);
}

.activity-bell:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

.activity-count {
    position: absolute;
    top: -1px;
    right: -3px;
    min-width: 15px;
    padding: 0 3px;
    border: 1.5px solid var(--bg);
    border-radius: 999px;
    background: var(--red);
    color: #2a0106;
    font-size: 9px;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
}

.activity-list {
    display: grid;
    gap: 1px;
    padding: 0;
    margin: 0;
    list-style: none;
}

.activity-item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: baseline;
    justify-content: space-between;
    padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--line-soft);
}

.activity-item:last-child {
    border-bottom: 0;
}

.activity-line {
    margin: 0;
    font-size: var(--text-base);
}

.activity-detail {
    margin: 2px 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

.activity-item time {
    flex-shrink: 0;
    color: var(--faint);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

/* Assignment and follow-ups ------------------------------------------------ */

.assign-form {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

.assign-label {
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

.note-followup-fields label {
    display: grid;
    gap: var(--space-1);
    max-width: 260px;
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: 600;
}

.note-followup-fields small {
    color: var(--faint);
    font-size: var(--text-xs);
    font-weight: 500;
}

.note-item[data-kind="follow_up"] {
    border-left-color: var(--magenta);
}

.note-due {
    margin: var(--space-2) 0 0;
    color: var(--muted);
    font-size: var(--text-sm);
}

.note-due strong {
    color: var(--magenta);
    font-variant-numeric: tabular-nums;
}

.notification-item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: baseline;
    justify-content: space-between;
    padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--line-soft);
}

.notification-item:last-child {
    border-bottom: 0;
}

/* Unread carries a marker rather than a background, so a long list of read
   items does not read as disabled. */
.notification-item.unread {
    box-shadow: inset 2px 0 0 var(--cyan);
}

.notification-item time {
    flex-shrink: 0;
    color: var(--faint);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.timeline-item[data-action="case.followed_up"] .timeline-marker { background: var(--magenta); }
.timeline-item[data-action="case.assigned"] .timeline-marker { background: var(--blue); }

/* Needs attention ---------------------------------------------------------- */

.attention-list {
    display: grid;
    gap: 1px;
    padding: 0;
    margin: 0;
    list-style: none;
}

.attention-item {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--line-soft);
}

.attention-item:last-child {
    border-bottom: 0;
}

/* A missed commitment reads louder than ordinary silence. */
.attention-item.is-overdue {
    box-shadow: inset 2px 0 0 var(--red);
}

.attention-main {
    display: grid;
    gap: var(--space-2);
    min-width: 0;
}

.attention-main .case-link {
    color: var(--text);
    font-size: var(--text-base);
}

.attention-main .case-link strong {
    margin-right: var(--space-2);
    color: var(--cyan);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
}

.attention-meta {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

.attention-owner {
    color: var(--muted);
    font-size: var(--text-sm);
}

.attention-reason {
    flex-shrink: 0;
    color: var(--muted);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
}

.attention-reason.overdue {
    color: var(--red);
    font-weight: 600;
}

.timeline-item[data-action="case.overdue"] .timeline-marker { background: var(--red); }

/* ==========================================================================
   Bulk selection and saved views
   ========================================================================== */

.select-cell,
.table th[data-col="0"]:has(input) {
    width: 34px;
    text-align: center;
}

.select-cell input,
[data-bulk-all] {
    accent-color: var(--cyan);
    cursor: pointer;
}

.table tbody tr.row-selected > td {
    background: var(--accent-wash-strong);
}

/* Sticks to the bottom so the selection stays reachable however far the table
   is scrolled. */
.bulk-bar {
    position: sticky;
    bottom: var(--space-4);
    z-index: 25;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
    border: 1px solid var(--cyan);
    border-radius: var(--radius-lg);
    background: var(--panel-3);
    box-shadow: var(--elev-3);
}

.bulk-count {
    font-size: var(--text-base);
}

.bulk-count strong {
    font-size: var(--text-lg);
    font-variant-numeric: tabular-nums;
}

.bulk-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
}

.saved-views {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    margin-bottom: var(--space-3);
}

.saved-view {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2) var(--space-1) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel-2);
    font-size: var(--text-sm);
}

.saved-view a {
    color: var(--text);
    font-weight: 600;
    text-decoration: none;
}

.saved-view a:hover {
    color: var(--cyan);
}

.saved-view form {
    display: inline-flex;
}

.saved-view button {
    padding: 0 var(--space-1);
    border: 0;
    background: none;
    color: var(--faint);
    cursor: pointer;
    font-size: var(--text-md);
    line-height: 1;
}

.saved-view button:hover {
    color: var(--red);
}

.saved-views-empty {
    color: var(--faint);
    font-size: var(--text-sm);
}

.saved-view-add {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    margin-left: auto;
}

.saved-view-add input {
    width: 190px;
}

/* ==========================================================================
   Module toolbar
   The row mixed two sizes and three weights: a small cyan Export competing with
   the cyan primary, a small outline density toggle appended by script, and
   full-size Filters between them. A toolbar wants one action that looks like the
   action and a set of utilities that look like each other, so the treatment is
   scoped here rather than restated in six view functions.
   ========================================================================== */

.module-toolbar .button-row .btn,
.module-toolbar .button-row .export-menu > summary {
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-base);
    line-height: 1.4;
}

.module-toolbar .button-row .btn:not(.btn-primary),
.module-toolbar .button-row .export-menu > summary {
    border-color: var(--line);
    background: var(--panel-2);
    color: var(--text);
}

.module-toolbar .button-row .btn:not(.btn-primary):hover,
.module-toolbar .button-row .export-menu > summary:hover {
    border-color: var(--muted);
    background: var(--panel-3);
    color: var(--text);
}

/* Clear only appears while filters are on, and undoing them is not a peer of
   the rest -- it stays outlined so it reads as an escape rather than an action. */
.module-toolbar .button-row .btn-clear {
    border-style: dashed;
    background: none;
    color: var(--muted);
}

.module-toolbar .button-row .btn-clear:hover {
    border-color: var(--cyan);
    background: none;
    color: var(--text);
}

/* Search sits with its input, so the pair reads as one control. */
.module-toolbar .toolbar-search {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.module-toolbar .button-row {
    align-items: center;
    gap: var(--space-2);
}

/* Clear is an anchor styled as a button, so it inherits a link underline. */
.module-toolbar .button-row .btn-clear {
    text-decoration: none;
}

/* ==========================================================================
   Data table legibility
   The list tables were letting every cell wrap, so a date became two lines and a
   sender domain three, rows grew to triple height and the grid read as ragged.
   Counts sat left-aligned, which is the one alignment that stops a column of
   numbers being comparable at a glance.
   ========================================================================== */

.table > tbody > tr > td,
.table > thead > tr > th {
    white-space: nowrap;
}

/* Long free text truncates rather than reflowing the row; the full value stays
   available through the title the client attaches. */
.table > tbody > tr > td {
    max-width: 280px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Cells that are meant to be read in full, like a list of indicators. */
.table > tbody > tr > td.multiline-cell {
    max-width: 360px;
    overflow: visible;
    white-space: pre-line;
}

/* Numbers line up on their last digit so a column can be scanned. */
.table > tbody > tr > td.numeric-cell,
.table > thead > tr > th.numeric-cell {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.table > thead > tr > th.numeric-cell .th-sortable > a,
.table > thead > tr > th.numeric-cell > a {
    justify-content: flex-end;
}

/* Row actions stay on one line and never get clipped by the column. */
.row-actions {
    flex-wrap: nowrap;
    justify-content: flex-end;
    gap: var(--space-2);
}

.table > tbody > tr > td:has(.row-actions) {
    max-width: none;
    overflow: visible;
    text-align: right;
}

/* Several "Add ..." controls are anchors wearing button classes, so they arrive
   underlined while the equivalent <button> elsewhere does not. */
a.btn {
    text-decoration: none;
}

/* ==========================================================================
   One voice below display scale
   The eyebrow, the form legend and the dashboard figures were each reaching for
   the display face at UI sizes. An eyebrow reads as an eyebrow because it is
   small, uppercase and tracked out -- not because of its typeface -- and a
   figure on the dashboard should look like the same kind of number as the one
   in the table beneath it.
   ========================================================================== */

.eyebrow,
.form-section > legend,
.form-section > summary > span {
    font-family: var(--font-ui);
    letter-spacing: 0.06em;
}

.form-section > legend,
.form-section > summary > span {
    letter-spacing: 0;
}

/* Figures match the tables: same face, same tabular figures, so a count on the
   dashboard and the same count in a list are recognisably the same thing. */
.metric > strong,
.mitre-tile strong,
.bulk-count strong {
    font-family: var(--font-ui);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

/* ==========================================================================
   Module tabs
   ========================================================================== */

.module-tabs {
    display: flex;
    gap: var(--space-1);
    margin: 0 0 var(--space-4);
    border-bottom: 1px solid var(--line);
}

.module-tab {
    padding: var(--space-2) var(--space-4);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    color: var(--muted);
    font-size: var(--text-base);
    font-weight: 600;
    text-decoration: none;
    transition: color var(--motion), border-color var(--motion);
}

.module-tab:hover {
    color: var(--text);
}

.module-tab.active {
    border-bottom-color: var(--cyan);
    color: var(--text);
}

.module-tab:focus-visible {
    outline: none;
    border-radius: var(--radius-sm);
    box-shadow: var(--ring);
}

/* The heading and its tabs are one block, so the gap under the title closes. */
.page-heading + .module-tabs {
    margin-top: calc(var(--space-4) * -1);
}
