/* ═══════════════════════════════════════════════════════════════
   THREAT SENTINEL — STYLESHEET  ·  CONSOLE LAYOUT
   Single stylesheet for every page (dashboard pages + playbooks).
   Standalone: does not require nemesis-blue.css or ti-shared.css.

   This is the console variant of the site. The difference to the
   classic layout is confined to the chrome:

     · the top navbar became a left rail with grouped sections
     · a command bar carries breadcrumb, global search and status
     · the work area is its own scroll container, not the document
     · a status bar is pinned to the bottom of the viewport

   Everything below § 6 is unchanged from the classic stylesheet, so
   the markup the loaders in ts-data.js emit renders identically.

   Contents
     1  Design tokens
     2  Reset / base
     3  Console shell (rail, command bar, work area, status bar)
     4  Sub-navigation (sticky chip bar)
     5  Page shell
     6  Stat tiles
     7  Toolbar + form controls
     8  Data tables
     9  Badges
    10  Loading / error / stamp states
    11  Home page
    12  Security news
    13  Resources
    14  Playbook index
    15  Playbook detail pages
    16  Footer
    17  Utilities
    18  Responsive
    19  Print
═══════════════════════════════════════════════════════════════ */

/* ──────────────────────────────────────────────────────────────
   1. DESIGN TOKENS
────────────────────────────────────────────────────────────── */
:root {
	/* Surfaces */
	--bg:          #0b0e14;
	--bg-sunken:   #080b10;
	--surface:     #121722;
	--surface-2:   #171d2a;
	--surface-hi:  #1d2534;

	/* Lines */
	--border:      #222a3a;
	--border-soft: #1a2130;
	--border-hi:   #313c52;

	/* Text */
	--text:        #dee4ee;
	--text-strong: #ffffff;
	--text-muted:  #8b95a9;
	--text-faint:  #616c81;

	/* Accent */
	--accent:      #4c8dff;
	--accent-hi:   #7aacff;
	--accent-dim:  rgba(76,141,255,.13);
	--accent-line: rgba(76,141,255,.35);

	/* Severity / status */
	--sev-crit:    #f0506e;
	--sev-high:    #ff8a3d;
	--sev-med:     #f2c14e;
	--sev-low:     #4fbf87;
	--sev-info:    #4c8dff;
	--sev-crit-bg: rgba(240,80,110,.11);
	--sev-high-bg: rgba(255,138,61,.11);
	--sev-med-bg:  rgba(242,193,78,.11);
	--sev-low-bg:  rgba(79,191,135,.11);

	/* Typography */
	--font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
	        "Helvetica Neue", Arial, sans-serif;
	--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
	        "Liberation Mono", monospace;

	/* Metrics */
	--subnav-h:    44px;   /* sticky chip bar inside the work area */
	--radius:      6px;
	--radius-sm:   4px;
	--page-max:    1500px;
	--page-pad:    28px;

	/* Console shell */
	--rail-w:      236px;   /* expanded left rail            */
	--rail-w-min:   58px;   /* collapsed to icons only       */
	--bar-h:        52px;   /* command bar                   */
	--status-h:     28px;   /* pinned status bar             */

	color-scheme: dark;

	/* ── Legacy aliases ──
	   ts-data.js and some retained playbook markup still reference the
	   old LCARS colour variables. Mapping them here keeps everything
	   rendering correctly without touching that markup. */
	--cool:      var(--accent);
	--moonbeam:  var(--text-strong);
	--evening:   var(--accent);
	--cardinal:  var(--sev-crit);
	--tangerine: var(--sev-high);
	--honey:     var(--sev-med);

	/* Additional accents — cards, resource groups, feed sources */
	--grape:     #a274ff;
	--teal:      #2bb8a8;

	/* Chrome that is not a plain surface colour. These must exist in
	   both themes: the navbar background is translucent, so a missing
	   value leaves the bar fully transparent. */
	--nav-bg:    rgba(11,14,20,.88);
	--subnav-bg: rgba(11,14,20,.92);
	--scroll-hi: #3e4b63;

	/* Console chrome. The rail and the status bar are opaque — they do
	   not scroll with the content, so there is nothing to blur behind. */
	--rail-bg:   #0e131d;
	--bar-bg:    rgba(11,14,20,.90);
	--status-bg: #0e131d;
}

/* ──────────────────────────────────────────────────────────────
   1b. LIGHT THEME
   Activated by data-theme="light" on <html>. Overrides tokens only —
   no component rule is duplicated, so the dark theme above is
   untouched and remains the default.

   Contrast against #ffffff (WCAG 2.1, normal text needs 4.5):
     text        15.6    text-strong 19.3    text-muted  6.3
     text-faint   5.0    accent       4.6    accent-hi   7.2
     sev-crit     5.5    sev-high     5.0    sev-med     5.6
     sev-low      5.0    grape        6.5
────────────────────────────────────────────────────────────── */
[data-theme="light"] {
	/* Surfaces — a faint blue-grey tint keeps it from glaring */
	--bg:          #ffffff;
	--bg-sunken:   #f4f7fb;
	--surface:     #fbfcfe;
	--surface-2:   #f2f5fa;
	--surface-hi:  #e8edf5;

	/* Lines */
	--border:      #dbe2ec;
	--border-soft: #e8ecf3;
	--border-hi:   #bcc6d6;

	/* Text */
	--text:        #1c2432;
	--text-strong: #0b0e14;
	--text-muted:  #56607a;
	--text-faint:  #667081;

	/* Accent — darkened so it carries on white */
	--accent:      #1f6feb;
	--accent-hi:   #1552b8;
	--accent-dim:  rgba(31,111,235,.09);
	--accent-line: rgba(31,111,235,.30);

	/* Severity — darkened for legibility; amber especially,
	   the dark-theme yellow would be unreadable on white */
	--sev-crit:    #c62a48;
	--sev-high:    #b4530a;
	--sev-med:     #87620a;
	--sev-low:     #15803d;
	--sev-info:    #1f6feb;
	--sev-crit-bg: rgba(198,42,72,.08);
	--sev-high-bg: rgba(180,83,10,.08);
	--sev-med-bg:  rgba(135,98,10,.09);
	--sev-low-bg:  rgba(21,128,61,.08);

	--grape:       #6d3ecf;
	--teal:        #0f7a70;

	/* Chrome */
	--nav-bg:      rgba(255,255,255,.85);
	--subnav-bg:   rgba(255,255,255,.90);
	--scroll-hi:   #9aa6b8;

	--rail-bg:     #f7f9fc;
	--bar-bg:      rgba(255,255,255,.90);
	--status-bg:   #f7f9fc;

	color-scheme: light;
}

/* The dropdown arrow is a background image and cannot inherit currentColor */
[data-theme="light"] .ti-qf-select,
[data-theme="light"] .ts-select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%2356607a' d='M0 0h10L5 6z'/%3E%3C/svg%3E");
}

/* Selection and hover tints are keyed to the dark accent */
[data-theme="light"] ::selection { background: rgba(31,111,235,.18); color: var(--text-strong); }
[data-theme="light"] .ti-table tbody tr:hover td { background: rgba(31,111,235,.045); }

/* Cards sit on a white page, so they need a little more definition */
[data-theme="light"] .ts-card,
[data-theme="light"] .ts-stat,
[data-theme="light"] .ts-toolbar,
[data-theme="light"] .ts-table-wrap,
[data-theme="light"] .news-card,
[data-theme="light"] .res-link,
[data-theme="light"] .pb-card {
	box-shadow: 0 1px 2px rgba(16,24,40,.04);
}

/* ──────────────────────────────────────────────────────────────
   1c. THEME TOGGLE BUTTON
────────────────────────────────────────────────────────────── */
/* Also used for the rail collapse button — same shape, same states. */
.ts-theme-btn,
.ts-icon-btn {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	background: transparent;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text-muted);
	cursor: pointer;
	transition: color .13s, border-color .13s, background .13s;
}
.ts-theme-btn:hover,
.ts-icon-btn:hover {
	color: var(--text-strong);
	border-color: var(--border-hi);
	background: var(--surface-2);
}

.ts-theme-btn svg,
.ts-icon-btn svg { width: 16px; height: 16px; display: block; }
.ts-theme-btn .ts-icon-sun  { display: none; }
.ts-theme-btn .ts-icon-moon { display: block; }
[data-theme="light"] .ts-theme-btn .ts-icon-sun  { display: block; }
[data-theme="light"] .ts-theme-btn .ts-icon-moon { display: none; }

/* ──────────────────────────────────────────────────────────────
   2. RESET / BASE
────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
	font-size: 16px;
	scroll-behavior: smooth;
	background: var(--bg);
	-webkit-text-size-adjust: 100%;
}

/* The console shell fills the viewport and scrolls internally, so the
   document itself must not scroll — otherwise the page gets a second
   scrollbar next to the one inside the work area. Below 780px the
   shell falls back to normal document flow and this is undone (§ 18). */
html, body { height: 100%; overflow: hidden; }

body {
	margin: 0;
	font-family: var(--font);
	font-size: .9375rem;      /* 15px */
	line-height: 1.6;
	color: var(--text);
	background: var(--bg);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hi); text-decoration: underline; }

h1, h2, h3, h4, h5 {
	margin: 0;
	color: var(--text-strong);
	font-weight: 600;
	line-height: 1.25;
	letter-spacing: -.01em;
}

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }

hr { border: none; border-top: 1px solid var(--border-soft); margin: 1.75rem 0; }

code, kbd, samp { font-family: var(--mono); font-size: .875em; }

img { max-width: 100%; height: auto; }

::selection { background: rgba(76,141,255,.3); color: #fff; }

:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
	border-radius: var(--radius-sm);
}

/* Scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border-hi) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
	background: var(--border-hi);
	border: 2px solid var(--bg);
	border-radius: 99px;
}
*::-webkit-scrollbar-thumb:hover { background: var(--scroll-hi); }

/* Skip link */
/* Fixed rather than absolute: html/body are overflow:hidden for the
   shell, which would clip an absolutely positioned skip link. */
.ts-skip {
	position: fixed;
	left: -9999px;
	top: 0;
	z-index: 200;
	background: var(--accent);
	color: #fff;
	padding: .5rem .9rem;
	border-radius: 0 0 var(--radius) 0;
	font-size: .8125rem;
}
.ts-skip:focus { left: 0; text-decoration: none; }

/* ══════════════════════════════════════════════════════════════
   3. CONSOLE SHELL

   A CSS grid that fills the viewport:

       ┌────────┬───────────────────────┐
       │        │  command bar          │
       │  rail  ├───────────────────────┤
       │        │  work  (scrolls)      │
       ├────────┴───────────────────────┤
       │  status bar                    │
       └────────────────────────────────┘

   Only the work area scrolls. The rail can collapse to icons, and
   below 780px it turns into an overlay that slides in from the left.
══════════════════════════════════════════════════════════════ */
.ts-shell {
	display: grid;
	grid-template-columns: var(--rail-w) minmax(0, 1fr);
	grid-template-rows: var(--bar-h) minmax(0, 1fr) var(--status-h);
	grid-template-areas:
		"rail bar"
		"rail work"
		"status status";
	height: 100vh;
	height: 100dvh;
	transition: grid-template-columns .16s ease;
}
.ts-shell.is-collapsed { grid-template-columns: var(--rail-w-min) minmax(0, 1fr); }

/* ── Rail ──────────────────────────────────────────────────── */
.ts-rail {
	grid-area: rail;
	display: flex;
	flex-direction: column;
	min-height: 0;
	background: var(--rail-bg);
	border-right: 1px solid var(--border);
	overflow: hidden;
}

.ts-brand {
	display: flex;
	align-items: center;
	gap: .6rem;
	flex-shrink: 0;
	height: var(--bar-h);
	padding: 0 .85rem;
	border-bottom: 1px solid var(--border-soft);
	color: var(--text-strong);
	font-weight: 650;
	font-size: .9375rem;
	letter-spacing: -.01em;
	white-space: nowrap;
	overflow: hidden;
}
.ts-brand:hover { color: var(--text-strong); text-decoration: none; }
/* Pulse Shield — the same drawing as favicon.svg, inlined so it picks
   up the accent colour of whichever theme is active. */
.ts-brand-mark {
	width: 22px; height: 22px;
	flex-shrink: 0;
	margin-left: 1px;
	color: var(--accent);
}
.ts-brand-text { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.ts-brand-sub {
	color: var(--text-faint);
	font-weight: 500;
	font-size: .625rem;
	text-transform: uppercase;
	letter-spacing: .13em;
}

/* The link list. Scrolls on short viewports so the rail foot stays put. */
.ts-nav-links {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	padding: .55rem .5rem 1rem;
	scrollbar-width: thin;
}

.ts-nav-group {
	padding: .85rem .55rem .3rem;
	font-size: .625rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .13em;
	color: var(--text-faint);
	white-space: nowrap;
	overflow: hidden;
}
.ts-nav-group:first-child { padding-top: .15rem; }

.ts-nav-link {
	position: relative;
	display: flex;
	align-items: center;
	gap: .6rem;
	padding: .42rem .55rem;
	border-radius: var(--radius-sm);
	color: var(--text-muted);
	font-size: .8125rem;
	font-weight: 500;
	white-space: nowrap;
	overflow: hidden;
	transition: color .13s, background .13s;
}
.ts-nav-link svg {
	width: 15px; height: 15px;
	flex-shrink: 0;
	margin-left: 1px;
	opacity: .85;
}
.ts-nav-link:hover {
	color: var(--text);
	background: var(--surface-2);
	text-decoration: none;
}
.ts-nav-link.is-active {
	color: var(--text-strong);
	background: var(--accent-dim);
}
.ts-nav-link.is-active svg { color: var(--accent); opacity: 1; }
.ts-nav-link.is-active::before {
	content: "";
	position: absolute;
	left: 0; top: 50%;
	transform: translateY(-50%);
	width: 2px; height: 16px;
	border-radius: 0 2px 2px 0;
	background: var(--accent);
}

/* Rail foot — collapse and theme, side by side */
.ts-rail-foot {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: .4rem;
	padding: .5rem .6rem;
	border-top: 1px solid var(--border-soft);
}

/* ── Collapsed rail ────────────────────────────────────────── */
.is-collapsed .ts-brand-text,
.is-collapsed .ts-nav-link span,
.is-collapsed .ts-nav-group { display: none; }
.is-collapsed .ts-brand      { justify-content: center; padding: 0; gap: 0; }
.is-collapsed .ts-brand-mark { margin-left: 0; }
.is-collapsed .ts-nav-link   { justify-content: center; padding: .5rem 0; }
.is-collapsed .ts-nav-link svg { margin-left: 0; }
.is-collapsed .ts-nav-links  { padding: .55rem .35rem 1rem; }
.is-collapsed .ts-rail-foot  { flex-direction: column; padding: .5rem .35rem; }

/* ── Command bar ───────────────────────────────────────────── */
.ts-bar {
	grid-area: bar;
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: 0 var(--page-pad) 0 1.1rem;
	background: var(--bar-bg);
	backdrop-filter: saturate(160%) blur(12px);
	-webkit-backdrop-filter: saturate(160%) blur(12px);
	border-bottom: 1px solid var(--border);
	min-width: 0;
}

.ts-crumb {
	display: flex;
	align-items: center;
	gap: .5rem;
	font-size: .8125rem;
	color: var(--text-faint);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	min-width: 0;
}
.ts-crumb strong { color: var(--text-strong); font-weight: 600; }
.ts-crumb-sep { color: var(--border-hi); }

/* Global search — jumps to the lookup page with the query prefilled */
.ts-bar-search {
	position: relative;
	display: flex;
	align-items: center;
	margin-left: auto;
	flex: 0 1 380px;
	min-width: 0;
}
.ts-bar-search svg {
	position: absolute;
	left: .6rem;
	width: 14px; height: 14px;
	color: var(--text-faint);
	pointer-events: none;
}
.ts-bar-search input {
	width: 100%;
	font-family: inherit;
	font-size: .8125rem;
	color: var(--text);
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: .34rem 2.1rem .34rem 1.95rem;
	outline: none;
	transition: border-color .13s, background .13s;
}
.ts-bar-search input::placeholder { color: var(--text-faint); }
.ts-bar-search input:focus { border-color: var(--accent-line); background: var(--surface); }
.ts-kbd {
	position: absolute;
	right: .45rem;
	font-family: var(--mono);
	font-size: .6875rem;
	color: var(--text-faint);
	border: 1px solid var(--border);
	border-radius: 3px;
	padding: 0 .28rem;
	line-height: 1.35;
	pointer-events: none;
}
.ts-bar-search input:focus + .ts-kbd { opacity: 0; }

/* Live pill */
.ts-live {
	display: inline-flex;
	align-items: center;
	gap: .4rem;
	flex-shrink: 0;
	font-family: var(--mono);
	font-size: .6875rem;
	color: var(--text-muted);
	border: 1px solid var(--border);
	border-radius: 99px;
	padding: .16rem .55rem;
	white-space: nowrap;
}
.ts-dot {
	width: 6px; height: 6px;
	border-radius: 50%;
	background: var(--sev-low);
	box-shadow: 0 0 0 3px rgba(79,191,135,.16);
	flex-shrink: 0;
}

/* Hamburger — only visible once the rail becomes an overlay */
.ts-nav-toggle {
	display: none;
	flex-shrink: 0;
	background: none;
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text-muted);
	padding: .3rem .55rem;
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
}
.ts-nav-toggle:hover { color: var(--text); border-color: var(--border-hi); }

/* ── Work area — the only scrolling region ─────────────────── */
.ts-work {
	grid-area: work;
	min-width: 0;
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	overscroll-behavior: contain;
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--subnav-h) + 12px);
}
.ts-work.no-subnav { scroll-padding-top: 16px; }

/* ── Status bar ────────────────────────────────────────────── */
.ts-status {
	grid-area: status;
	display: flex;
	align-items: center;
	gap: .7rem;
	padding: 0 var(--page-pad);
	background: var(--status-bg);
	border-top: 1px solid var(--border);
	font-family: var(--mono);
	font-size: .6875rem;
	color: var(--text-faint);
	white-space: nowrap;
	overflow: hidden;
}
.ts-status-item { display: inline-flex; align-items: center; gap: .4rem; }
.ts-status-item a { color: var(--text-muted); }
.ts-status-item a:hover { color: var(--accent); }
.ts-status-sep { color: var(--border-hi); }
.ts-status-right { margin-left: auto; display: inline-flex; align-items: center; gap: .7rem; }

/* Rail scrim — only ever visible in overlay mode (§ 18) */
.ts-scrim {
	display: none;
	position: fixed;
	inset: 0;
	z-index: 89;
	background: rgba(0,0,0,.45);
}

/* ──────────────────────────────────────────────────────────────
   4. SUB-NAVIGATION  (sticky chip bar — resources + playbooks)
────────────────────────────────────────────────────────────── */
/* Sticks to the top of the work area, not the viewport — the command
   bar is outside the scroll container and never overlaps it. */
.ts-subnav {
	position: sticky;
	top: 0;
	z-index: 90;
	min-height: var(--subnav-h);
	background: var(--subnav-bg);
	backdrop-filter: saturate(160%) blur(12px);
	-webkit-backdrop-filter: saturate(160%) blur(12px);
	border-bottom: 1px solid var(--border-soft);
}
.ts-subnav-inner {
	max-width: var(--page-max);
	margin: 0 auto;
	padding: .4rem var(--page-pad);
	display: flex;
	align-items: center;
	gap: .35rem;
	overflow-x: auto;
	scrollbar-width: none;
}
.ts-subnav-inner::-webkit-scrollbar { display: none; }

.ts-chip {
	flex-shrink: 0;
	background: transparent;
	border: 1px solid transparent;
	border-radius: 99px;
	color: var(--text-muted);
	font-family: inherit;
	font-size: .75rem;
	font-weight: 500;
	padding: .28rem .7rem;
	white-space: nowrap;
	cursor: pointer;
	transition: color .13s, background .13s, border-color .13s;
}
.ts-chip:hover {
	color: var(--text);
	background: var(--surface-2);
	text-decoration: none;
}
.ts-chip.is-active {
	color: var(--accent-hi);
	background: var(--accent-dim);
	border-color: var(--accent-line);
}
.ts-subnav-spacer { flex: 1 1 auto; min-width: .5rem; }

.ts-subnav-tools {
	display: flex;
	align-items: center;
	gap: .4rem;
	flex-shrink: 0;
}
.ts-subnav-link {
	font-size: .75rem;
	color: var(--text-faint);
	white-space: nowrap;
}
.ts-subnav-link:hover { color: var(--accent); text-decoration: none; }

/* ──────────────────────────────────────────────────────────────
   5. PAGE SHELL
────────────────────────────────────────────────────────────── */
.ts-page {
	max-width: var(--page-max);
	margin: 0 auto;
	padding: 1.75rem var(--page-pad) 3.5rem;
}
.ts-page--narrow { max-width: 1000px; }

.ts-page-head { margin-bottom: 1.5rem; }

.ts-eyebrow {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .12em;
	color: var(--accent);
	margin-bottom: .4rem;
}

.ts-page-head h1 { font-size: 1.625rem; margin-bottom: .4rem; }

.ts-lede {
	max-width: 78ch;
	color: var(--text-muted);
	font-size: .875rem;
	margin: 0;
}

.ts-section-head {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: .75rem;
	margin: 2.25rem 0 .9rem;
	padding-bottom: .5rem;
	border-bottom: 1px solid var(--border-soft);
}
.ts-section-head:first-child { margin-top: 0; }
.ts-section-head h2 { font-size: 1rem; letter-spacing: 0; }

/* A section heading can double as an accordion trigger (§ 15 supplies
   the shared .ti-acc-trigger behaviour). align-items is baseline here,
   so the arrow needs centring of its own. */
.ts-section-head.ti-acc-trigger { align-items: center; }
.ts-section-head.ti-acc-trigger .ti-arr { align-self: center; }
.ts-section-head .ts-count {
	font-size: .75rem;
	color: var(--text-faint);
	font-variant-numeric: tabular-nums;
}

.ts-prose { max-width: 80ch; color: var(--text-muted); font-size: .875rem; }
.ts-prose strong { color: var(--text); font-weight: 600; }

/* ──────────────────────────────────────────────────────────────
   6. STAT TILES
────────────────────────────────────────────────────────────── */
.ts-stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: .6rem;
	margin-bottom: 1.5rem;
}
.ts-stat {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: .8rem .95rem;
}
.ts-stat-label {
	font-size: .6875rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: .07em;
	color: var(--text-faint);
	margin-bottom: .3rem;
}
.ts-stat-val {
	font-size: 1.5rem;
	font-weight: 650;
	line-height: 1.15;
	color: var(--text-strong);
	font-variant-numeric: tabular-nums;
	letter-spacing: -.02em;
	overflow-wrap: anywhere;
}
.ts-stat-val.is-err { color: var(--sev-crit); font-size: 1rem; }
.ts-stat-note { font-size: .6875rem; color: var(--text-faint); margin-top: .2rem; }

/* ──────────────────────────────────────────────────────────────
   7. TOOLBAR + FORM CONTROLS
────────────────────────────────────────────────────────────── */
.ts-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem .6rem;
	padding: .7rem .75rem;
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	margin-bottom: .85rem;
}
.ts-toolbar + .ts-toolbar { margin-top: -.35rem; }

.ts-tb-label {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	white-space: nowrap;
}
.ts-tb-sep {
	width: 1px;
	align-self: stretch;
	min-height: 1.2rem;
	background: var(--border);
	margin: 0 .2rem;
}
.ts-tb-spacer { flex: 1 1 auto; }

/* Legacy wrappers emitted by the old markup carry no layout of their own */
.ti-search-wrap, .ti-qf-wrap { display: contents; }
.ti-qf-sep { display: none; }

.ti-search, .ts-input {
	flex: 1 1 240px;
	min-width: 190px;
	max-width: 460px;
	background: var(--bg-sunken);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text);
	font-family: inherit;
	font-size: .8125rem;
	padding: .42rem .65rem;
	outline: none;
	transition: border-color .13s, box-shadow .13s;
}
.ti-search::placeholder, .ts-input::placeholder { color: var(--text-faint); }
.ti-search:focus, .ts-input:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-dim);
}

.ti-qf-btn, .ts-btn, .ti-reset-btn, .ti-load-more, .pb-cl-reset {
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text-muted);
	font-family: inherit;
	font-size: .75rem;
	font-weight: 500;
	padding: .35rem .7rem;
	cursor: pointer;
	white-space: nowrap;
	transition: color .13s, background .13s, border-color .13s;
}
.ti-qf-btn:hover, .ts-btn:hover, .ti-reset-btn:hover,
.ti-load-more:hover, .pb-cl-reset:hover {
	color: var(--text-strong);
	background: var(--surface-hi);
	border-color: var(--border-hi);
}
.ti-qf-btn.active, .ts-btn.is-active {
	color: var(--accent-hi);
	background: var(--accent-dim);
	border-color: var(--accent-line);
}
.ti-reset-btn {
	background: transparent;
	color: var(--text-faint);
	font-size: .6875rem;
	text-transform: uppercase;
	letter-spacing: .07em;
}
.ti-load-more {
	display: inline-block;
	margin-top: .85rem;
	padding: .45rem 1.1rem;
	font-size: .8125rem;
}

/* Severity-tinted quick filters */
.ti-qf-btn.qf-crit { color: var(--sev-crit); border-color: rgba(240,80,110,.28); }
.ti-qf-btn.qf-high { color: var(--sev-high); border-color: rgba(255,138,61,.28); }
.ti-qf-btn.qf-med  { color: var(--sev-med);  border-color: rgba(242,193,78,.28); }
.ti-qf-btn.qf-crit.active { background: var(--sev-crit-bg); border-color: rgba(240,80,110,.5); color: var(--sev-crit); }
.ti-qf-btn.qf-high.active { background: var(--sev-high-bg); border-color: rgba(255,138,61,.5); color: var(--sev-high); }
.ti-qf-btn.qf-med.active  { background: var(--sev-med-bg);  border-color: rgba(242,193,78,.5); color: var(--sev-med); }

/* Container for dynamically generated quick filters — display:contents
   so the buttons take part in the toolbar's flex layout directly */
.ts-quick-vendors { display: contents; }

/* Count badge inside a quick-filter button */
.ts-qf-count {
	display: inline-block;
	margin-left: .3rem;
	padding: 0 .3rem;
	border-radius: 99px;
	background: var(--surface-hi);
	color: var(--text-faint);
	font-size: .6875rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}
.ti-qf-btn.active .ts-qf-count {
	background: var(--accent-line);
	color: var(--text-strong);
}

.ti-qf-select, .ts-select {
	background: var(--bg-sunken);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text-muted);
	font-family: inherit;
	font-size: .75rem;
	padding: .35rem 1.6rem .35rem .55rem;
	cursor: pointer;
	outline: none;
	max-width: 200px;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%238b95a9' d='M0 0h10L5 6z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right .55rem center;
}
.ti-qf-select:focus, .ts-select:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-dim);
}
.ti-qf-select option, .ts-select option { background: var(--surface); color: var(--text); }

/* ──────────────────────────────────────────────────────────────
   8. DATA TABLES
   NOTE: neither .ts-table-wrap nor .ts-table-scroll may use
   overflow:hidden/auto on wide screens — any scroll or clip
   ancestor kills `position: sticky` on the table header.
   Horizontal scrolling is therefore only switched on below 900px,
   where the sticky header is disabled anyway (see § 18).
────────────────────────────────────────────────────────────── */
.ts-table-wrap {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
}
.ts-table-scroll { overflow-x: visible; }

.ti-table { width: 100%; border-collapse: collapse; font-size: .8125rem; }

.ti-table thead th {
	position: sticky;
	top: 0;               /* sticks inside .ts-work, which is the scroller */
	z-index: 5;
	background: var(--surface-2);
	color: var(--text-muted);
	text-align: left;
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .07em;
	white-space: nowrap;
	padding: .55rem .8rem;
	border-bottom: 1px solid var(--border);
	user-select: none;
}
.ti-table th[data-rs], .ti-table th[data-ks], .ti-table th[data-cs] { cursor: pointer; }
.ti-table th[data-rs]:hover, .ti-table th[data-ks]:hover, .ti-table th[data-cs]:hover {
	color: var(--text-strong);
	background: var(--surface-hi);
	opacity: 1;
}
.ti-table .ts-sort-idle { opacity: .35; font-size: .85em; }

.ti-table td {
	padding: .55rem .8rem;
	border-bottom: 1px solid var(--border-soft);
	vertical-align: top;
	line-height: 1.45;
}
.ti-table tbody tr:last-child td { border-bottom: none; }
.ti-table tbody tr:hover td { background: rgba(76,141,255,.055); }

.ti-table a { color: var(--accent); }
.ti-table a:hover { color: var(--accent-hi); }

/* Identifiers and dates read better in mono */
.ts-mono, .ti-table .ts-cve {
	font-family: var(--mono);
	font-size: .78125rem;
	letter-spacing: -.01em;
}
.ti-table .ts-cve { font-weight: 600; }
.ti-table .ts-date { white-space: nowrap; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.ti-table .ts-victim { font-weight: 600; color: var(--text-strong); }
.ti-table .ts-victim:hover { color: var(--accent-hi); }
.ti-table .ts-dim { color: var(--text-muted); }

/* Rounded corners without a clipping ancestor */
.ti-table thead tr th:first-child { border-top-left-radius:  var(--radius); }
.ti-table thead tr th:last-child  { border-top-right-radius: var(--radius); }
.ti-table tbody tr:last-child td:first-child { border-bottom-left-radius:  var(--radius); }
.ti-table tbody tr:last-child td:last-child  { border-bottom-right-radius: var(--radius); }

/* ── EPSS cell ────────────────────────────────────────────────
   Probability plus a proportional bar. The bar uses a square-root
   scale in the JS because EPSS values cluster heavily near zero —
   on a linear scale almost every bar would be invisible. */
.ts-epss {
	display: inline-flex;
	flex-direction: column;
	gap: .22rem;
	min-width: 62px;
}
.ts-epss-val {
	font-family: var(--mono);
	font-size: .78125rem;
	font-weight: 600;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	color: var(--text-muted);
}
.ts-epss-bar {
	display: block;
	height: 3px;
	width: 100%;
	background: var(--surface-hi);
	border-radius: 99px;
	overflow: hidden;
}
.ts-epss-bar i {
	display: block;
	height: 100%;
	border-radius: 99px;
	background: var(--text-faint);
}
.ts-epss.is-low  .ts-epss-val { color: var(--text-faint); }
.ts-epss.is-mid  .ts-epss-val { color: var(--sev-high); }
.ts-epss.is-mid  .ts-epss-bar i { background: var(--sev-high); }
.ts-epss.is-high .ts-epss-val { color: var(--sev-crit); }
.ts-epss.is-high .ts-epss-bar i { background: var(--sev-crit); }

/* Note emitted by the loaders directly after the table */
.ts-table-note {
	font-size: .75rem;
	color: var(--text-faint);
	margin: .6rem 0 0;
}

/* ──────────────────────────────────────────────────────────────
   9. BADGES
────────────────────────────────────────────────────────────── */
.badge, .ts-badge {
	display: inline-block;
	padding: .1rem .45rem;
	border-radius: 99px;
	border: 1px solid transparent;
	font-size: .6875rem;
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}
.b-red   { color: var(--sev-crit); background: var(--sev-crit-bg); border-color: rgba(240,80,110,.3); }
.b-org   { color: var(--sev-high); background: var(--sev-high-bg); border-color: rgba(255,138,61,.3); }
.b-yel   { color: var(--sev-med);  background: var(--sev-med-bg);  border-color: rgba(242,193,78,.3); }
.b-green { color: var(--sev-low);  background: var(--sev-low-bg);  border-color: rgba(79,191,135,.3); }
.b-blue  { color: var(--text-faint); background: var(--surface-hi); border-color: var(--border); }

/* ──────────────────────────────────────────────────────────────
   10. LOADING / ERROR / STAMP
────────────────────────────────────────────────────────────── */
.ti-loading {
	padding: 2.5rem 1rem;
	text-align: center;
	color: var(--text-faint);
	font-size: .875rem;
}
.ti-error {
	padding: 1rem;
	border: 1px solid rgba(240,80,110,.3);
	background: rgba(240,80,110,.07);
	border-radius: var(--radius);
	color: var(--sev-crit);
	font-size: .8125rem;
	margin: 0;
}
.ti-error a { color: var(--sev-crit); text-decoration: underline; }
.ti-empty {
	padding: 2.5rem 1rem;
	text-align: center;
	color: var(--text-faint);
	font-size: .875rem;
}
.ti-stamp {
	font-size: .75rem;
	color: var(--text-faint);
	margin: 0;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/* ──────────────────────────────────────────────────────────────
   11. HOME PAGE
────────────────────────────────────────────────────────────── */
.ts-hero {
	padding: 1rem 0 1.75rem;
	border-bottom: 1px solid var(--border-soft);
	margin-bottom: 1.75rem;
}
.ts-hero h1 {
	font-size: clamp(1.75rem, 3.4vw, 2.25rem);
	letter-spacing: -.02em;
	margin-bottom: .6rem;
}
.ts-hero p {
	max-width: 72ch;
	color: var(--text-muted);
	font-size: 1rem;
	margin: 0;
}
.ts-hero-sources {
	display: flex;
	flex-wrap: wrap;
	gap: .4rem;
	margin-top: 1.1rem;
}
.ts-source-tag {
	font-size: .6875rem;
	font-weight: 500;
	color: var(--text-faint);
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: 99px;
	padding: .2rem .6rem;
}

.ts-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: .75rem;
	margin-bottom: 1rem;
}
.ts-card {
	display: block;
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: 1rem 1.1rem;
	color: inherit;
	transition: border-color .14s, background .14s, transform .14s;
}
a.ts-card:hover {
	border-color: var(--border-hi);
	background: var(--surface-2);
	text-decoration: none;
	transform: translateY(-1px);
}
.ts-card h3 {
	font-size: .9375rem;
	margin-bottom: .35rem;
	display: flex;
	align-items: center;
	gap: .45rem;
}
a.ts-card:hover h3 { color: var(--accent-hi); }
.ts-card p { font-size: .8125rem; color: var(--text-muted); margin: 0; line-height: 1.55; }
.ts-card-dot {
	width: 7px; height: 7px;
	border-radius: 2px;
	background: var(--accent);
	flex-shrink: 0;
}
.ts-card-dot.dot-crit { background: var(--sev-crit); }
.ts-card-dot.dot-high { background: var(--sev-high); }
.ts-card-dot.dot-med  { background: var(--sev-med); }
.ts-card-dot.dot-low  { background: var(--sev-low); }
.ts-card-dot.dot-alt  { background: var(--grape); }
.ts-card-dot.dot-teal { background: var(--teal); }

.ts-note {
	border-left: 2px solid var(--border-hi);
	padding: .1rem 0 .1rem .95rem;
	margin: 1.75rem 0 0;
	color: var(--text-faint);
	font-size: .8125rem;
	line-height: 1.65;
	max-width: 90ch;
}

/* ──────────────────────────────────────────────────────────────
   11b. DASHBOARD  (index.html)

   A 12-column panel grid. Every panel fills itself independently, so
   a slow or failing source never blocks the rest of the board.

   Every row adds up to exactly 12. That is not decoration: a row that
   sums to less leaves grid cells free, and the next panel is pulled
   up into the gap — which is what made the first version look like
   its panels had been shuffled.

       row 1   metrics          3 · 3 · 3 · 3
       row 2   breakdowns       4 · 4 · 4
       row 3   priority queue   12
       row 4   research / news  6 · 6
       row 5   entry points     12

   .ts-panel and .ts-bar-row come from § 12b and are shared with the
   ransomware breakdown — the dashboard adds only the panel header,
   the metric tile and the two compact list styles below.
────────────────────────────────────────────────────────────── */
.ts-dash {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	gap: .75rem;
	/* stretch, not start: two panels sharing a row are the same height */
	align-items: stretch;
}
.ts-dash > .col-3  { grid-column: span 3; }
.ts-dash > .col-4  { grid-column: span 4; }
.ts-dash > .col-6  { grid-column: span 6; }
.ts-dash > .col-12 { grid-column: span 12; }

/* Panels in the grid carry their own header, so the padding moves
   into the parts rather than sitting on the panel itself. A column
   flexbox lets one child absorb the height the row was stretched to. */
.ts-dash .ts-panel {
	padding: 0;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.ts-panel-head {
	display: flex;
	align-items: baseline;
	gap: .6rem;
	flex-shrink: 0;
	padding: .65rem 1rem .55rem;
	border-bottom: 1px solid var(--border-soft);
}
.ts-panel-head .ts-panel-title {
	border: none;
	padding: 0;
	margin: 0;
	flex-shrink: 0;
}

/* The whole heading is the link to the section it summarises */
a.ts-panel-title {
	display: inline-flex;
	align-items: center;
	gap: .35rem;
	color: var(--text-faint);
}
a.ts-panel-title:hover { color: var(--accent); text-decoration: none; }
a.ts-panel-title .ts-panel-go {
	font-size: .875em;
	opacity: .6;
	transition: transform .13s, opacity .13s;
}
a.ts-panel-title:hover .ts-panel-go { opacity: 1; transform: translateX(2px); }
.ts-panel-sub {
	font-size: .75rem;
	color: var(--text-faint);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.ts-panel-actions { margin-left: auto; flex-shrink: 0; }
.ts-panel-actions a { font-size: .75rem; color: var(--text-faint); white-space: nowrap; }
.ts-panel-actions a:hover { color: var(--accent); text-decoration: none; }

.ts-panel-body { padding: .8rem 1rem 1rem; }
/* Tables bring their own cell padding and their own header rule */
.ts-panel-body.is-flush { padding: 0; }
.ts-panel-body.is-flush .ts-table-note { padding: .55rem 1rem; margin: 0; }

/* Takes up whatever height the row was stretched to. Used on the two
   list panels that share a row with a taller neighbour, so the pair
   ends up exactly the same height instead of one leaving a gap.
   min-height:0 is what allows the scroll — without it a flex child
   refuses to shrink below its content. */
.ts-panel-body.is-fill {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* ── Metric tile ──────────────────────────────────────────────
   No trend arrow unless the trend is measured. Three of the four
   tiles can derive a real daily series from the records they already
   loaded; the fourth simply has no history to show and says so. */
.ts-metric { padding: .8rem 1rem .9rem; }
.ts-metric-label {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	margin-bottom: .35rem;
}
.ts-metric-val {
	font-size: 1.75rem;
	font-weight: 650;
	line-height: 1.1;
	color: var(--text-strong);
	font-variant-numeric: tabular-nums;
	letter-spacing: -.02em;
}
.ts-metric-val.is-err { color: var(--sev-crit); font-size: 1rem; font-weight: 600; }
.ts-metric-note {
	font-size: .6875rem;
	color: var(--text-faint);
	margin-top: .25rem;
	line-height: 1.5;
}

/* Sparkline — one bar per day, oldest on the left */
.ts-spark {
	display: flex;
	align-items: flex-end;
	gap: 2px;
	height: 24px;
	margin-top: .55rem;
}
.ts-spark i {
	flex: 1;
	min-height: 2px;
	border-radius: 1px;
	background: var(--accent-dim);
	border-bottom: 2px solid var(--accent-line);
}
.ts-spark i.is-last { background: var(--accent-line); border-bottom-color: var(--accent); }

/* ── Compact feed list ────────────────────────────────────────
   The card grid used on the news and research pages is too tall for
   a dashboard panel, so the same items render as rows here. */
.ts-feed-item {
	display: block;
	padding: .55rem 1rem;
	border-bottom: 1px solid var(--border-soft);
	color: inherit;
}
.ts-feed-item:last-child { border-bottom: none; }
.ts-feed-item:hover { background: var(--surface-2); text-decoration: none; }
.ts-feed-meta {
	display: flex;
	align-items: baseline;
	gap: .45rem;
	font-size: .6875rem;
	color: var(--text-faint);
	margin-bottom: .15rem;
}
.ts-feed-src { font-weight: 600; color: var(--text-muted); }
.ts-feed-title {
	font-size: .8125rem;
	line-height: 1.45;
	color: var(--text);
}
.ts-feed-item:hover .ts-feed-title { color: var(--accent-hi); }

/* ── Source health rows ───────────────────────────────────────
   Status is measured, not decorative: an endpoint is OK when it
   answered, and the age is the age of the newest record it returned. */
.ts-src-row {
	display: flex;
	align-items: center;
	gap: .55rem;
	padding: .3rem 0;
	font-size: .8125rem;
	border-bottom: 1px solid var(--border-soft);
}
.ts-src-row:last-child { border-bottom: none; }
.ts-src-name { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ts-src-age {
	margin-left: auto;
	flex-shrink: 0;
	font-family: var(--mono);
	font-size: .75rem;
	color: var(--text-faint);
	font-variant-numeric: tabular-nums;
}

/* Card grid nested inside a dashboard panel.

   auto-fit rather than auto-fill: at full page width auto-fill would
   lay out six tracks and leave the four cards huddled at 215px on the
   left. auto-fit collapses the empty tracks so the four spread across
   the row. */
.ts-dash .ts-cards {
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	margin-bottom: 0;
}
.ts-dash .ts-card { padding: .8rem .9rem; }
.ts-dash .ts-card h3 { font-size: .875rem; }
.ts-dash .ts-card p { font-size: .78125rem; }

/* Skeleton shown until a panel has its data */
.ts-skel {
	font-size: .8125rem;
	color: var(--text-faint);
	padding: .3rem 0;
}
.ts-panel-body.is-flush .ts-skel { padding: .8rem 1rem; }

/* ── Dashboard responsive ─────────────────────────────────────
   Every step keeps rows summing to 12, for the reason given at the
   top of this section. The rail already narrows at 1180px (§ 18). */
@media (max-width: 1200px) {
	/* The paired panels go full width first. The three breakdowns stay
	   side by side as long as they are legible — they are short bar
	   lists, and standing them on top of each other is exactly the
	   stacking this layout was rebuilt to avoid. */
	.ts-dash > .col-6 { grid-column: span 12; }
}
@media (max-width: 1000px) {
	.ts-dash > .col-3 { grid-column: span 6; }
	.ts-dash > .col-4 { grid-column: span 12; }
}
@media (max-width: 760px) {
	.ts-dash > [class*="col-"] { grid-column: span 12; }
	/* Nothing shares a row any more, so nothing needs to be stretched
	   to match a neighbour — let the lists show their full height. */
	.ts-panel-body.is-fill { overflow-y: visible; }
}

/* ──────────────────────────────────────────────────────────────
   12. SECURITY NEWS
────────────────────────────────────────────────────────────── */
.news-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
	gap: .6rem;
}
.news-card {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-left: 3px solid var(--accent);
	border-radius: var(--radius);
	transition: border-color .14s, background .14s;
}
.news-card:hover { background: var(--surface-2); border-color: var(--border-hi); }
.news-card > a {
	display: block;
	padding: .8rem .95rem;
	color: inherit;
	text-decoration: none;
}
.news-card > a:hover { text-decoration: none; }
.news-src {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	margin-bottom: .3rem;
}
.news-title {
	font-size: .875rem;
	font-weight: 600;
	color: var(--text);
	line-height: 1.45;
}
.news-card a:hover .news-title { color: var(--accent-hi); }
.news-summary {
	font-size: .8125rem;
	line-height: 1.55;
	color: var(--text-muted);
	margin-top: .4rem;
	/* Three lines is enough to judge relevance without the card
	   growing to the length of the abstract */
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.news-date {
	font-size: .75rem;
	color: var(--text-faint);
	margin-top: .4rem;
	font-variant-numeric: tabular-nums;
}
/* Per-source accent */
.news-card.src-krebs  { border-left-color: var(--sev-crit); }
.news-card.src-thn    { border-left-color: var(--sev-high); }
.news-card.src-bc     { border-left-color: var(--accent); }
.news-card.src-bsi    { border-left-color: var(--sev-med); }
.news-card.src-cisa   { border-left-color: var(--sev-crit); }
.news-card.src-isc    { border-left-color: var(--grape); }
.news-card.src-talos  { border-left-color: var(--sev-high); }
.news-card.src-heise  { border-left-color: var(--sev-low); }
.news-card.src-sophos { border-left-color: var(--accent); }
/* Research sources */
.news-card.src-dfir      { border-left-color: var(--sev-crit); }
.news-card.src-unit42    { border-left-color: var(--sev-high); }
.news-card.src-redcanary { border-left-color: var(--sev-crit); }
.news-card.src-huntress  { border-left-color: var(--teal); }
.news-card.src-msft      { border-left-color: var(--accent); }
/* Filter chips take the same source colour */
.ti-qf-btn.src-krebs, .ti-qf-btn.src-cisa   { color: var(--sev-crit); border-color: rgba(240,80,110,.28); }
.ti-qf-btn.src-thn,   .ti-qf-btn.src-talos  { color: var(--sev-high); border-color: rgba(255,138,61,.28); }
.ti-qf-btn.src-bsi                          { color: var(--sev-med);  border-color: rgba(242,193,78,.28); }
.ti-qf-btn.src-heise                        { color: var(--sev-low);  border-color: rgba(79,191,135,.28); }
.ti-qf-btn.src-isc                          { color: var(--grape);         border-color: rgba(162,116,255,.28); }
.ti-qf-btn.src-dfir, .ti-qf-btn.src-redcanary { color: var(--sev-crit); border-color: rgba(240,80,110,.28); }
.ti-qf-btn.src-unit42                         { color: var(--sev-high); border-color: rgba(255,138,61,.28); }
.ti-qf-btn.src-huntress                       { color: var(--teal);     border-color: rgba(43,184,168,.30); }

/* ──────────────────────────────────────────────────────────────
   13. RESOURCES
────────────────────────────────────────────────────────────── */
/* Offset for native hash navigation. Inside the work area only the
   sub-navigation is sticky — the command bar is outside the scroller. */
.res-group { margin-bottom: 2rem; scroll-margin-top: calc(var(--subnav-h) + 16px); }
.res-group-title {
	font-size: 1rem;
	font-weight: 600;
	color: var(--text-strong);
	letter-spacing: -.01em;
	border-bottom: 1px solid var(--border-soft);
	padding-bottom: .5rem;
	margin-bottom: .8rem;
}
.res-links {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: .5rem;
}
.res-link {
	display: flex;
	flex-direction: column;
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-left: 3px solid var(--accent);
	border-radius: var(--radius);
	padding: .7rem .85rem;
	text-decoration: none;
	transition: background .14s, border-color .14s;
}
.res-link:hover { background: var(--surface-2); border-color: var(--border-hi); text-decoration: none; }
.res-link-name { font-size: .875rem; font-weight: 600; color: var(--text); }
.res-link:hover .res-link-name { color: var(--accent-hi); }
.res-link-desc { font-size: .78125rem; color: var(--text-muted); margin-top: .2rem; line-height: 1.45; }

.res-link.cat-framework  { border-left-color: var(--grape); }
.res-link.cat-intel      { border-left-color: var(--sev-crit); }
.res-link.cat-vuln       { border-left-color: var(--sev-high); }
.res-link.cat-tools      { border-left-color: var(--sev-med); }
.res-link.cat-news       { border-left-color: var(--accent); }
.res-link.cat-dfir       { border-left-color: var(--sev-low); }
.res-link.cat-governance { border-left-color: var(--grape); }
.res-link.cat-training   { border-left-color: var(--sev-med); }
.res-link.cat-osint      { border-left-color: var(--teal); }
.res-link.cat-leaks      { border-left-color: var(--sev-crit); }

/* ──────────────────────────────────────────────────────────────
   12b. BREAKDOWN PANELS AND BARS
────────────────────────────────────────────────────────────── */
.ts-split {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
	gap: .75rem;
}
.ts-panel {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: .9rem 1rem 1rem;
}
.ts-panel-title {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	border-bottom: 1px solid var(--border-soft);
	padding-bottom: .4rem;
	margin-bottom: .7rem;
}

/* One row per value: label, proportional bar, count, share.
   Selectable rows are rendered as <button>, so the reset below
   removes the browser's default button appearance. */
.ts-bar-row {
	display: grid;
	grid-template-columns: minmax(90px, 9rem) 1fr 2.6rem 2.4rem;
	align-items: center;
	gap: .6rem;
	width: 100%;
	padding: .28rem .4rem;
	margin-left: -.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-sm);
	background: none;
	font: inherit;
	font-size: .8125rem;
	text-align: left;
	color: inherit;
}

/* Clickable rows behave like filters */
.ts-bar-row.is-clickable { cursor: pointer; transition: background .12s, border-color .12s; }
.ts-bar-row.is-clickable:hover { background: var(--surface-2); border-color: var(--border); }
.ts-bar-row.is-clickable:hover .ts-bar-label { color: var(--text-strong); }

.ts-bar-row.is-active {
	background: var(--accent-dim);
	border-color: var(--accent-line);
}
.ts-bar-row.is-active .ts-bar-label { color: var(--accent-hi); font-weight: 600; }
.ts-bar-row.is-active .ts-bar-track i { background: var(--accent-hi); }
/* A selected row stays legible even when it is a muted bucket */
.ts-bar-row.is-active.is-muted .ts-bar-label,
.ts-bar-row.is-active.is-muted .ts-bar-val { color: var(--accent-hi); font-style: normal; }
.ts-bar-row.is-active.is-muted .ts-bar-track i { background: var(--accent-hi); }
.ts-bar-label {
	color: var(--text);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.ts-bar-track {
	height: 8px;
	background: var(--surface-hi);
	border-radius: 99px;
	overflow: hidden;
}
.ts-bar-track i {
	display: block;
	height: 100%;
	border-radius: 99px;
	background: var(--accent);
}
.ts-bar-val {
	text-align: right;
	font-family: var(--mono);
	font-size: .78125rem;
	font-weight: 600;
	color: var(--text);
	font-variant-numeric: tabular-nums;
}
.ts-bar-pct {
	text-align: right;
	font-size: .75rem;
	color: var(--text-faint);
	font-variant-numeric: tabular-nums;
}

/* Rows that stand for missing or pooled data are visually demoted —
   they are context, not a ranking position */
.ts-bar-row.is-muted .ts-bar-label,
.ts-bar-row.is-muted .ts-bar-val { color: var(--text-faint); font-style: italic; }
.ts-bar-row.is-muted .ts-bar-track i { background: var(--border-hi); }

@media (max-width: 560px) {
	.ts-bar-row { grid-template-columns: minmax(80px, 7rem) 1fr 2.2rem 2.2rem; gap: .4rem; }
}

/* ──────────────────────────────────────────────────────────────
   13b. INDICATOR LOOKUP
────────────────────────────────────────────────────────────── */
.ioc-box {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: 1rem 1.1rem 1.1rem;
	margin-bottom: 1.5rem;
}
.ioc-label {
	display: block;
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	margin-bottom: .45rem;
}
.ioc-input-row {
	display: flex;
	gap: .5rem;
	align-items: stretch;
	flex-wrap: wrap;
}
.ioc-input {
	/* The field has to take the full remaining width: indicators are
	   long — a SHA-256 hash is 64 characters, URLs are worse. */
	flex: 1 1 auto;
	width: 100%;
	min-width: 0;
	background: var(--bg-sunken);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text);
	font-family: var(--mono);
	font-size: .9375rem;
	padding: .65rem .8rem;
	outline: none;
	transition: border-color .13s, box-shadow .13s;
}
/* Buttons keep their natural width, the input absorbs the rest */
.ioc-input-row .ti-reset-btn { flex: 0 0 auto; padding-inline: 1rem; }
.ioc-input::placeholder {
	color: var(--text-faint);
	font-family: var(--font);
	font-size: .875rem;
}
.ioc-input:focus {
	border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-dim);
}

.ioc-type {
	display: flex;
	align-items: center;
	gap: .55rem;
	flex-wrap: wrap;
	margin-top: .7rem;
	min-height: 1.2rem;
}
.ioc-type:empty { margin-top: 0; min-height: 0; }
.ioc-type-tag {
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .04em;
	padding: .12rem .55rem;
	border-radius: 99px;
	color: var(--sev-low);
	background: var(--sev-low-bg);
	border: 1px solid rgba(79,191,135,.35);
}
.ioc-type-tag.is-unknown {
	color: var(--sev-crit);
	background: var(--sev-crit-bg);
	border-color: rgba(240,80,110,.35);
}
.ioc-value {
	font-family: var(--mono);
	font-size: .8125rem;
	color: var(--text);
	background: var(--surface-hi);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: .1rem .45rem;
	overflow-wrap: anywhere;
}
.ioc-hint {
	font-size: .6875rem;
	color: var(--text-faint);
	font-style: italic;
}

.ioc-group { margin-bottom: 1.6rem; }
.ioc-group-title {
	font-size: .6875rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--text-faint);
	border-bottom: 1px solid var(--border-soft);
	padding-bottom: .35rem;
	margin-bottom: .65rem;
}
/* Each service is its own button — without the gap they run together
   into one unreadable line of blue text */
.ioc-links {
	display: flex;
	flex-wrap: wrap;
	gap: .45rem;
	align-items: flex-start;
}
.ioc-link {
	display: inline-block;
	background: var(--surface);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text);
	font-size: .8125rem;
	font-weight: 500;
	padding: .35rem .75rem;
	text-decoration: none;
	transition: color .13s, background .13s, border-color .13s;
}
.ioc-link::after {
	content: " ↗";
	color: var(--text-faint);
	font-size: .75em;
}
.ioc-link:hover {
	color: #fff;
	background: var(--accent);
	border-color: var(--accent);
	text-decoration: none;
}
.ioc-link:hover::after { color: rgba(255,255,255,.7); }

/* ──────────────────────────────────────────────────────────────
   14. PLAYBOOK INDEX
────────────────────────────────────────────────────────────── */
.pb-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: .85rem;
}
.pb-card {
	display: flex;
	flex-direction: column;
	gap: .7rem;
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-top: 3px solid var(--accent);
	border-radius: var(--radius);
	padding: 1.05rem 1.15rem 1.15rem;
	transition: border-color .14s, background .14s;
}
.pb-card:hover { background: var(--surface-2); border-color: var(--border-hi); }
.pb-card.sev-critical { border-top-color: var(--sev-crit); }
.pb-card.sev-high     { border-top-color: var(--sev-high); }
.pb-card.sev-medium   { border-top-color: var(--sev-med); }
.pb-card:hover.sev-critical { border-top-color: var(--sev-crit); }
.pb-card:hover.sev-high     { border-top-color: var(--sev-high); }
.pb-card:hover.sev-medium   { border-top-color: var(--sev-med); }

.pb-card-header { display: flex; justify-content: space-between; align-items: center; gap: .5rem; }
.pb-sev-tag {
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .04em;
	padding: .1rem .5rem;
	border: 1px solid;
	border-radius: 99px;
}
.pb-sev-tag.sev-critical { color: var(--sev-crit); border-color: rgba(240,80,110,.4); background: var(--sev-crit-bg); }
.pb-sev-tag.sev-high     { color: var(--sev-high); border-color: rgba(255,138,61,.4); background: var(--sev-high-bg); }
.pb-sev-tag.sev-medium   { color: var(--sev-med);  border-color: rgba(242,193,78,.4); background: var(--sev-med-bg); }
.pb-wip-badge {
	font-size: .6875rem;
	color: var(--text-faint);
	border: 1px dashed var(--border-hi);
	border-radius: 99px;
	padding: .1rem .5rem;
}

.pb-card h3 { font-size: .9375rem; }
.pb-card-desc { font-size: .8125rem; color: var(--text-muted); line-height: 1.55; margin: 0; }

.pb-phases { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: auto; }
.pb-phase {
	font-size: .6875rem;
	color: var(--text-faint);
	background: var(--surface-hi);
	border: 1px solid var(--border);
	border-radius: 99px;
	padding: .08rem .5rem;
}
.pb-open-btn {
	display: block;
	width: 100%;
	background: var(--surface-hi);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	color: var(--text);
	font-family: inherit;
	font-size: .8125rem;
	font-weight: 500;
	padding: .45rem .8rem;
	cursor: pointer;
	text-align: center;
	text-decoration: none;
	transition: background .14s, border-color .14s, color .14s;
}
.pb-open-btn:hover {
	background: var(--accent);
	border-color: var(--accent);
	color: #fff;
	text-decoration: none;
}
.pb-open-btn.wip {
	opacity: .45;
	cursor: not-allowed;
	pointer-events: none;
}

/* Language toggle (segmented control) */
.pb-lang-toggle {
	display: inline-flex;
	background: var(--surface-2);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 2px;
	gap: 2px;
	flex-shrink: 0;
}
.pb-lang-btn {
	background: transparent;
	border: none;
	border-radius: 3px;
	color: var(--text-faint);
	font-family: inherit;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .04em;
	padding: .2rem .6rem;
	cursor: pointer;
	transition: background .13s, color .13s;
}
.pb-lang-btn:hover { color: var(--text); }
.pb-lang-btn.active { background: var(--accent); color: #fff; }

/* Language visibility on the playbook index page */
.pb-section-en .pb-de,
.pb-section-de .pb-en { display: none !important; }

/* ──────────────────────────────────────────────────────────────
   15. PLAYBOOK DETAIL PAGES
────────────────────────────────────────────────────────────── */

/* Language visibility (body-class driven).
   Scoped to body.pb-detail so it cannot affect the playbook index,
   which uses the .pb-section-en / .pb-section-de mechanism instead. */
body.pb-detail .pb-de { display: none !important; }
body.pb-detail.is-de .pb-en { display: none !important; }
body.pb-detail.is-de h1.pb-de, body.pb-detail.is-de h2.pb-de,
body.pb-detail.is-de h3.pb-de, body.pb-detail.is-de h4.pb-de,
body.pb-detail.is-de p.pb-de,  body.pb-detail.is-de div.pb-de,
body.pb-detail.is-de ul.pb-de, body.pb-detail.is-de ol.pb-de,
body.pb-detail.is-de section.pb-de { display: block !important; }
body.pb-detail.is-de span.pb-de  { display: inline !important; }
body.pb-detail.is-de label.pb-de { display: flex !important; }
body.pb-detail.is-de .pb-phase-pills.pb-de { display: flex !important; }

/* ── Bilingual static pages (privacy notice) ──────────────────
   The playbooks switch language inside a shared document, which needs
   the long list of per-element overrides above. A static page can do
   it with two top-level blocks, so exactly two elements carry a
   language class and both are plain <div>s. */
body.is-bilingual .lang-de,
body.is-bilingual.is-de .lang-en { display: none !important; }
body.is-bilingual.is-de .lang-de { display: block !important; }

/* Placeholders that must be filled in before the page goes live.
   Deliberately loud — an unnoticed [PLATZHALTER] in a privacy notice
   is worse than no privacy notice at all. */
.ts-todo {
	font-family: var(--mono);
	font-size: .8125em;
	font-weight: 600;
	color: var(--sev-crit);
	background: var(--sev-crit-bg);
	border: 1px dashed var(--sev-crit);
	border-radius: var(--radius-sm);
	padding: 0 .3rem;
	white-space: nowrap;
}

/* Definition rows in the privacy notice */
.ts-defs { margin: 0 0 1rem; max-width: 90ch; }
.ts-defs dt {
	font-size: .8125rem;
	font-weight: 600;
	color: var(--text-strong);
	margin-top: .9rem;
}
.ts-defs dt:first-child { margin-top: 0; }
.ts-defs dd {
	margin: .15rem 0 0;
	font-size: .8125rem;
	color: var(--text-muted);
	line-height: 1.6;
}
.ts-defs code {
	color: var(--text);
	background: var(--surface-2);
	border: 1px solid var(--border-soft);
	border-radius: 3px;
	padding: 0 .25rem;
}

/* Hero */
.pb-hero { margin-bottom: 1.75rem; }
.pb-hero-tags {
	display: flex;
	align-items: center;
	gap: .5rem;
	flex-wrap: wrap;
	margin-bottom: .7rem;
}
.pb-badge {
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .04em;
	padding: .12rem .55rem;
	border: 1px solid;
	border-radius: 99px;
}
.pb-badge-critical { color: var(--sev-crit); border-color: rgba(240,80,110,.4); background: var(--sev-crit-bg); }
.pb-badge-high     { color: var(--sev-high); border-color: rgba(255,138,61,.4); background: var(--sev-high-bg); }
.pb-badge-type     { color: var(--text-faint); border-color: var(--border); background: var(--surface); }

.pb-hero h1 {
	font-size: clamp(1.5rem, 3.2vw, 2rem);
	letter-spacing: -.02em;
	margin: 0 0 .5rem;
	line-height: 1.15;
}
.pb-hero-summary {
	font-size: .9375rem;
	line-height: 1.65;
	color: var(--text-muted);
	max-width: 78ch;
	margin: 0 0 1rem;
}
.pb-phase-pills { display: flex; flex-wrap: wrap; gap: .3rem; }
.pb-pill {
	font-size: .6875rem;
	font-weight: 500;
	color: var(--text-faint);
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: 99px;
	padding: .12rem .55rem;
}

/* Section heading bar (retains the legacy class name used in the
   playbook markup, restyled as a plain heading / accordion trigger) */
.ts-section-bar {
	position: relative;
	display: flex;
	align-items: center;
	gap: .6rem;
	margin: 2rem 0 .85rem;
	padding: 0 0 .5rem;
	border-bottom: 1px solid var(--border-soft);
}
.ts-section-bar h2 {
	font-size: 1.0625rem;
	letter-spacing: -.01em;
	margin: 0;
}
section:first-of-type .ts-section-bar { margin-top: 0; }

/* Accordion */
.ti-acc-trigger {
	cursor: pointer;
	user-select: none;
	transition: border-color .14s;
}
.ti-acc-trigger:hover { border-bottom-color: var(--border-hi); }
.ti-acc-trigger:hover h2 { color: var(--accent-hi); }
.ti-acc-trigger .ti-arr {
	margin-left: auto;
	flex-shrink: 0;
	font-size: .625rem;
	line-height: 1;
	color: var(--text-faint);
	transition: transform .2s ease, color .14s;
	display: inline-block;
}
.ti-acc-trigger:hover .ti-arr { color: var(--accent); }
.ti-acc-trigger.is-open .ti-arr { transform: rotate(90deg); color: var(--accent); }
.ti-acc-body { display: none; }
.ti-acc-body.is-open { display: block; }

.pb-acc-body { padding: .25rem 0 .5rem; }

section[id] { scroll-margin-top: 16px; }   /* playbook pages have no sticky sub-nav */

/* Content typography */
.pb-content { font-size: .90625rem; line-height: 1.7; color: var(--text-muted); }
.pb-content p { margin: 0 0 .8rem; }
.pb-content ul, .pb-content ol { margin: 0 0 .8rem; padding-left: 1.25rem; }
.pb-content li { margin-bottom: .35rem; }
.pb-content li::marker { color: var(--text-faint); }
.pb-content strong { color: var(--text); font-weight: 600; }
.pb-content em { color: var(--text); font-style: italic; }
.pb-content a { color: var(--accent); }
.pb-content code {
	background: var(--surface-hi);
	border: 1px solid var(--border);
	border-radius: 3px;
	padding: .05em .35em;
	color: var(--text);
}
.pb-content > *:last-child { margin-bottom: 0; }

.pb-scope-body { padding: 0; }

/* Callouts */
.pb-highlight {
	background: var(--sev-crit-bg);
	border: 1px solid rgba(240,80,110,.25);
	border-left: 3px solid var(--sev-crit);
	border-radius: var(--radius);
	padding: .9rem 1.05rem;
	margin: 0 0 1rem;
}
.pb-highlight h3 {
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--sev-crit);
	margin: 0 0 .6rem;
}
.pb-donot {
	background: var(--sev-crit-bg);
	border: 1px solid rgba(240,80,110,.2);
	border-left: 3px solid var(--sev-crit);
	border-radius: var(--radius);
	padding: .7rem .9rem;
	margin: .85rem 0;
}
.pb-donot h4 {
	font-size: .71875rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--sev-crit);
	margin: 0 0 .4rem;
}
.pb-exit {
	background: var(--sev-med-bg);
	border: 1px solid rgba(242,193,78,.2);
	border-left: 3px solid var(--sev-med);
	border-radius: var(--radius);
	padding: .7rem .9rem;
	margin: .85rem 0;
}
.pb-exit h4 {
	font-size: .71875rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--sev-med);
	margin: 0 0 .4rem;
}
.pb-donot .pb-content, .pb-exit .pb-content, .pb-highlight .pb-content { font-size: .875rem; }

/* Objective pills */
.pb-objective-list { display: flex; flex-wrap: wrap; gap: .3rem; margin-bottom: 1rem; }
.pb-objective-pill {
	font-size: .6875rem;
	color: var(--text-faint);
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: 99px;
	padding: .12rem .55rem;
}

/* Decision + two-column grids */
.pb-decision-grid, .pb-two-col {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: .7rem;
	margin: .5rem 0 1rem;
}
.pb-decision-card, .pb-col-box {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: .85rem .95rem;
}
.pb-decision-card h4, .pb-col-box h4 {
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .07em;
	margin: 0 0 .5rem;
	color: var(--text);
}
.pb-decision-card { border-top: 2px solid var(--border-hi); }
/* Decision-card variants across all four playbooks */
.pb-dc-isolate,  .pb-dc-shutdown, .pb-dc-engage,
.pb-dc-lock,     .pb-dc-stop     { border-top-color: var(--sev-crit); }
.pb-dc-monitor,  .pb-dc-breach,
.pb-dc-yes                       { border-top-color: var(--sev-high); }
.pb-dc-keep,     .pb-dc-gate,
.pb-dc-no,       .pb-dc-ok       { border-top-color: var(--accent); }

.pb-dc-isolate  h4, .pb-dc-shutdown h4, .pb-dc-engage h4,
.pb-dc-lock     h4, .pb-dc-stop     h4 { color: var(--sev-crit); }
.pb-dc-monitor  h4                     { color: var(--sev-med); }
.pb-dc-breach   h4, .pb-dc-yes      h4 { color: var(--sev-high); }
.pb-dc-keep     h4, .pb-dc-gate     h4,
.pb-dc-no       h4, .pb-dc-ok       h4 { color: var(--accent); }

.pb-col-box h4 { color: var(--accent); }

/* Info / regulatory callouts (data-breach, phishing-bec) */
.pb-infobox {
	background: var(--accent-dim);
	border: 1px solid var(--accent-line);
	border-left: 3px solid var(--accent);
	border-radius: var(--radius);
	padding: .8rem .95rem;
	margin: .5rem 0 1rem;
}
.pb-infobox h3, .pb-infobox h4 {
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--accent-hi);
	margin: 0 0 .5rem;
}
.pb-gdpr-box {
	background: var(--sev-med-bg);
	border: 1px solid rgba(242,193,78,.25);
	border-left: 3px solid var(--sev-med);
	border-radius: var(--radius);
	padding: .9rem 1.05rem;
	margin: .5rem 0 1rem;
}
.pb-gdpr-box h3, .pb-gdpr-box h4 {
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--sev-med);
	margin: 0 0 .5rem;
}
.pb-infobox .pb-content, .pb-gdpr-box .pb-content { font-size: .875rem; }

/* Numbered priority list */
.pb-priority-item {
	display: flex;
	align-items: flex-start;
	gap: .65rem;
	margin-bottom: .45rem;
	font-size: .90625rem;
	line-height: 1.6;
	color: var(--text-muted);
}
.pb-priority-num {
	flex-shrink: 0;
	min-width: 1.4rem;
	height: 1.4rem;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: .6875rem;
	font-weight: 700;
	color: var(--accent);
	background: var(--accent-dim);
	border: 1px solid var(--accent-line);
	border-radius: var(--radius-sm);
	margin-top: .1rem;
}

/* Checklist */
.pb-cl-group { margin-bottom: 1.35rem; }
.pb-cl-group h4 {
	font-size: .75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .08em;
	color: var(--accent);
	margin: 0 0 .55rem;
	padding-bottom: .35rem;
	border-bottom: 1px solid var(--border-soft);
}
label.pb-cl-item {
	display: flex;
	align-items: flex-start;
	gap: .55rem;
	font-size: .875rem;
	line-height: 1.55;
	color: var(--text-muted);
	margin-bottom: .35rem;
	cursor: pointer;
	padding: .1rem .3rem .1rem 0;
	border-radius: var(--radius-sm);
	transition: color .13s;
}
label.pb-cl-item:hover { color: var(--text); }
label.pb-cl-item input[type="checkbox"] {
	accent-color: var(--accent);
	width: 15px; height: 15px;
	margin-top: .2rem;
	flex-shrink: 0;
	cursor: pointer;
}
label.pb-cl-item.checked { color: var(--text-faint); text-decoration: line-through; }
.pb-cl-reset { margin-top: .5rem; }

/* Source footer inside playbooks */
.pb-source {
	margin-top: 2.5rem;
	padding-top: 1rem;
	border-top: 1px solid var(--border-soft);
	display: flex;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: .5rem;
}
.pb-source p, .pb-source a {
	font-size: .75rem;
	color: var(--text-faint);
	margin: 0;
}
.pb-source a:hover { color: var(--accent); }

/* Reading progress bar — pinned under the command bar, spanning the
   work area only, because that is what actually scrolls. */
.ts-progress {
	position: fixed;
	top: calc(var(--bar-h) - 2px);
	left: var(--rail-w);
	height: 2px;
	width: 0;
	background: var(--accent);
	z-index: 120;
	transition: width .1s linear, left .16s ease;
}
.is-collapsed .ts-progress { left: var(--rail-w-min); }

/* ── Playbook side rail (phases + progress, right-hand column) ──
   The console keeps the reading column narrow, so the phase list
   that used to be a chip bar moves into a rail of its own. */
.pb-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 250px;
	gap: 1.75rem;
	align-items: start;
}
/* Grid items default to min-width:auto, which lets a wide table or a
   long unbroken string push the reading column past its track. */
.pb-main { min-width: 0; }

.pb-aside {
	position: sticky;
	top: 1rem;
	display: flex;
	flex-direction: column;
	gap: .8rem;
	max-height: calc(100dvh - var(--bar-h) - var(--status-h) - 2.5rem);
	overflow-y: auto;
	padding-right: .2rem;
}
.pb-aside-block {
	background: var(--surface);
	border: 1px solid var(--border-soft);
	border-radius: var(--radius);
	padding: .7rem .75rem;
}
.pb-aside-title {
	font-size: .625rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .13em;
	color: var(--text-faint);
	margin-bottom: .5rem;
}
/* Phase list: reuses .ts-chip so the JS scroll-spy keeps working,
   but laid out as a vertical list rather than a horizontal bar. */
.pb-aside-nav { display: flex; flex-direction: column; gap: 1px; }
.pb-aside-nav .ts-chip {
	border-radius: var(--radius-sm);
	text-align: left;
	padding: .34rem .5rem;
	font-size: .75rem;
	white-space: normal;
	line-height: 1.35;
}
.pb-aside-actions { display: flex; flex-direction: column; gap: .45rem; }
.pb-aside-actions .pb-lang-toggle { width: 100%; }
.pb-aside-actions .pb-lang-btn { flex: 1; }
.pb-aside-actions .ts-subnav-link,
.pb-aside-actions .pb-cl-reset { font-size: .75rem; }

@media (max-width: 1100px) {
	.pb-layout { grid-template-columns: minmax(0, 1fr); }
	.pb-aside {
		position: static;
		max-height: none;
		flex-direction: row;
		flex-wrap: wrap;
		order: -1;
	}
	.pb-aside-block { flex: 1 1 260px; }
	.pb-aside-nav { flex-direction: row; flex-wrap: wrap; }
}

/* ──────────────────────────────────────────────────────────────
   16. FOOTER
────────────────────────────────────────────────────────────── */
.ts-footer {
	max-width: var(--page-max);
	margin: 0 auto;
	padding: 1.25rem var(--page-pad) 2.5rem;
	border-top: 1px solid var(--border-soft);
	color: var(--text-faint);
	font-size: .75rem;
	line-height: 1.7;
}
.ts-footer a { color: var(--text-muted); }
.ts-footer a:hover { color: var(--accent); }

/* ──────────────────────────────────────────────────────────────
   17. UTILITIES
────────────────────────────────────────────────────────────── */
.ts-hidden { display: none !important; }
.ts-nowrap { white-space: nowrap; }
.ts-sr-only {
	position: absolute; width: 1px; height: 1px;
	padding: 0; margin: -1px; overflow: hidden;
	clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ──────────────────────────────────────────────────────────────
   18. RESPONSIVE
────────────────────────────────────────────────────────────── */
/* Narrow desktop / tablet: the rail collapses to icons on its own so
   the work area keeps a usable width, but the shell stays intact. */
@media (max-width: 1180px) {
	.ts-shell { grid-template-columns: var(--rail-w-min) minmax(0, 1fr); }
	.ts-shell .ts-brand-text,
	.ts-shell .ts-nav-link span,
	.ts-shell .ts-nav-group { display: none; }
	.ts-shell .ts-brand      { justify-content: center; padding: 0; gap: 0; }
	.ts-shell .ts-brand-mark { margin-left: 0; }
	.ts-shell .ts-nav-link   { justify-content: center; padding: .5rem 0; }
	.ts-shell .ts-nav-link svg { margin-left: 0; }
	.ts-shell .ts-nav-links  { padding: .55rem .35rem 1rem; }
	.ts-shell .ts-rail-foot  { flex-direction: column; padding: .5rem .35rem; }
	.ts-progress { left: var(--rail-w-min); }

	/* The collapse button has nothing left to collapse */
	#railToggle { display: none; }
}

@media (max-width: 900px) {
	:root { --page-pad: 16px; }
	.ts-page-head h1 { font-size: 1.375rem; }
	.ti-search, .ts-input { max-width: none; }
	.ti-qf-select, .ts-select { max-width: 100%; }

	/* Sticky header off → horizontal scrolling can be enabled safely */
	.ti-table thead th { position: static; }
	.ts-table-scroll {
		overflow-x: auto;
		border-radius: var(--radius);
		-webkit-overflow-scrolling: touch;
	}
	.ti-table { min-width: 720px; }

	.ts-subnav-tools .ts-subnav-link { display: none; }
	.pb-source { flex-direction: column; }
	.ts-bar-search { flex-basis: 200px; }
	.ts-live { display: none; }
}

/* ── Phone: the shell unwinds into a normal page ────────────────
   A fixed-height flexbox with an inner scroller fights mobile
   browsers (dynamic address bar, virtual keyboard). Below 780px the
   document scrolls again, the command bar sticks, and the rail turns
   into an overlay opened by the hamburger. */
@media (max-width: 780px) {
	html, body { height: auto; overflow: visible; }

	.ts-shell {
		display: block;
		height: auto;
		padding-bottom: var(--status-h);
	}

	.ts-rail {
		position: fixed;
		z-index: 90;
		top: 0; bottom: 0; left: 0;
		width: var(--rail-w);
		transform: translateX(-100%);
		transition: transform .18s ease;
	}
	.ts-shell.is-open .ts-rail { transform: none; }
	.ts-shell.is-open .ts-scrim { display: block; }

	/* Overlay rail is always the full labelled version */
	.ts-shell .ts-brand-text,
	.ts-shell .ts-nav-link span,
	.ts-shell .ts-nav-group { display: block; }
	.ts-shell .ts-brand      { justify-content: flex-start; padding: 0 .85rem; gap: .6rem; }
	.ts-shell .ts-brand-mark { margin-left: 5px; }
	.ts-shell .ts-nav-link   { justify-content: flex-start; padding: .5rem .55rem; }
	.ts-shell .ts-nav-links  { padding: .55rem .5rem 1rem; }
	.ts-shell .ts-rail-foot  { flex-direction: row; padding: .5rem .6rem; }

	.ts-bar {
		position: sticky;
		top: 0;
		z-index: 88;
		height: var(--bar-h);
		padding: 0 var(--page-pad);
	}
	.ts-nav-toggle { display: block; order: -1; }
	.ts-crumb { display: none; }
	.ts-bar-search { flex: 1 1 auto; }

	.ts-work {
		overflow: visible;
		scroll-padding-top: calc(var(--bar-h) + var(--subnav-h) + 12px);
	}
	.ts-work.no-subnav { scroll-padding-top: calc(var(--bar-h) + 16px); }
	.ts-subnav { top: var(--bar-h); }

	.ts-status {
		position: fixed;
		z-index: 87;
		bottom: 0; left: 0; right: 0;
		height: var(--status-h);
	}
	.ts-status-right { display: none; }

	.ts-progress { position: fixed; top: 0; left: 0; }
	.pb-aside { max-height: none; }
}

@media (max-width: 560px) {
	.ts-hero h1 { font-size: 1.5rem; }
	.ts-stats { grid-template-columns: repeat(2, 1fr); }
	.ts-toolbar { padding: .6rem; }
	.ts-kbd { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
	}
}

/* ──────────────────────────────────────────────────────────────
   19. PRINT  (playbooks are printed / PDF-exported in practice)
────────────────────────────────────────────────────────────── */
@media print {
	:root {
		--bg: #fff; --surface: #fff; --surface-2: #fff; --surface-hi: #fff;
		--text: #111; --text-strong: #000; --text-muted: #333; --text-faint: #666;
		--border: #bbb; --border-soft: #ddd; --border-hi: #999;
	}
	html, body { height: auto; overflow: visible; }
	body { background: #fff; color: #111; font-size: 10.5pt; }
	.ts-rail, .ts-bar, .ts-status, .ts-scrim, .ts-subnav,
	.ts-progress, .ts-nav-toggle, .pb-aside,
	.pb-cl-reset, .ti-load-more, .ts-toolbar, .ts-skip { display: none !important; }
	.ts-shell { display: block; height: auto; }
	.ts-work  { overflow: visible; }
	.pb-layout { display: block; }
	.ts-page { padding: 0; max-width: none; }
	.ti-acc-body { display: block !important; }
	.ti-arr { display: none !important; }
	a { color: #111; text-decoration: underline; }
	.pb-highlight, .pb-donot, .pb-exit,
	.pb-decision-card, .pb-col-box { border: 1px solid #999; }
	section { break-inside: avoid-page; }
	.ts-section-bar { break-after: avoid-page; }
}
