/* ==========================================================================
   Ecran Product Consolidation - design system
   Warm-neutral, Anthropic-inspired. Same house style as the Integrity
   Intelligence app: tokens, shell and components carried over verbatim, fraud
   specific blocks dropped.
   Variable driven, single file, no build step.
   ========================================================================== */

:root {
    /* Surface Colors */
    --bg-primary: #faf9f7;
    --bg-secondary: #f3f1ed;
    --bg-card: #ffffff;
    --bg-glass: rgba(250, 249, 247, 0.92);
    --bg-sidebar: #e4e1da;

    /* Text Colors */
    --text-primary: #191918;
    --text-secondary: #4a4a48;
    --text-muted: #8b8b89;
    --text-light: #b0b0ae;

    /* Accent Colors */
    --accent-primary: #c4704b;
    --accent-primary-light: #d4896a;
    --accent-primary-hover: #b35f3c;
    --accent-blue: #5b7a9e;
    --accent-blue-light: #7a98b8;
    --accent-green: #5a8a72;
    --accent-green-light: #7aaa92;
    --accent-yellow: #b8943d;
    --accent-yellow-light: #d4b15a;
    --accent-red: #c25e5e;
    --accent-red-light: #d47a7a;
    --accent-purple: #8b7aab;
    --accent-purple-light: #a598c0;

    /* Borders */
    --border-light: #e8e5e1;
    --border-medium: #d5d1cb;

    /* Shadows */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.03);
    --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.05);
    --shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.06);
    --shadow-xl: 0 8px 24px rgba(0, 0, 0, 0.08);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.04);

    /* Gradients */
    --gradient-primary: linear-gradient(135deg, #191918 0%, #2a2a28 100%);
    --gradient-accent: linear-gradient(135deg, #c4704b 0%, #d4896a 100%);
    --gradient-success: linear-gradient(135deg, #5a8a72 0%, #4a7a62 100%);
    --gradient-warning: linear-gradient(135deg, #b8943d 0%, #a8842d 100%);
    --gradient-danger: linear-gradient(135deg, #c25e5e 0%, #b24e4e 100%);

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-base: 200ms ease;
    --transition-slow: 300ms ease;

    /* Border Radius */
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 16px;
    --radius-full: 9999px;

    /* Sidebar */
    --sidebar-width: 260px;
    --sidebar-collapsed-width: 72px;

    /* Typography */
    --font-serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
}

/* ===== Reset & base ===== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
    font-family: var(--font-sans);
    color: var(--text-primary);
    background: var(--bg-primary);
    line-height: 1.65;
    font-size: 14px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, .page-title, .card-title, .section-title, .stat-value {
    font-family: var(--font-serif);
    letter-spacing: -0.01em;
}
a { color: var(--accent-primary); text-decoration: none; }
a:hover { color: var(--accent-primary-hover); }
code, pre, .mono { font-family: var(--font-mono); }

/* ===== Layout shell ===== */
.app-container { display: flex; min-height: 100vh; }
.main-content {
    margin-left: var(--sidebar-width);
    flex: 1;
    background: var(--bg-primary);
    min-height: 100vh;
    transition: margin-left var(--transition-slow);
}
.content-header {
    background: var(--bg-glass);
    padding: 20px 32px;
    border-bottom: 1px solid var(--border-light);
    display: flex; justify-content: space-between; align-items: center;
    position: sticky; top: 0; z-index: 100;
    backdrop-filter: blur(12px);
}
.page-title { font-size: clamp(22px, 2.5vw, 28px); font-weight: 600; }
/* The descriptive phrase, under the title rather than competing with it. The
   title is always the sidebar label a reader just clicked, so the two never
   name the same page differently; this says what the page is for. */
.page-subtitle { font-size: 13px; color: var(--text-muted); margin-top: 1px; }
.header-actions { display: flex; gap: 10px; align-items: center; }
.content-body { padding: 28px 32px; animation: fadeInUp 0.4s ease-out; }
/* The primary user is on an ultrawide monitor. Reading-width prose is capped so
   a paragraph never spans the whole screen; data tables and grids are not. */
.prose, .card-intro, .empty-state p { max-width: 70ch; }

/* ===== Sidebar ===== */
.sidebar {
    width: var(--sidebar-width);
    background: var(--bg-sidebar);
    position: fixed; top: 0; left: 0; bottom: 0;
    display: flex; flex-direction: column;
    border-right: 1px solid var(--border-medium);
    transition: width var(--transition-slow), transform var(--transition-slow);
    z-index: 200;
}
.sidebar-brand { border-bottom: 1px solid var(--border-medium); }
.sidebar-logo-card {
    margin: 16px 16px 0;
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    padding: 18px 20px;
    display: flex; align-items: center; justify-content: center;
}
.sidebar-logo-card img { max-width: 100%; height: auto; }
.sidebar-header {
    padding: 14px 20px 16px;
    display: flex; align-items: center; gap: 12px;
}
.logo { display: flex; align-items: center; gap: 12px; }
.logo-mark {
    width: 36px; height: 36px; border-radius: var(--radius-md);
    background: var(--gradient-accent);
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 700; font-family: var(--font-serif);
    flex-shrink: 0; box-shadow: var(--shadow-sm);
}
.logo-text { font-family: var(--font-serif); font-weight: 600; font-size: 16px; line-height: 1.2; }
.logo-text small { display: block; font-size: 10px; color: var(--text-muted); font-family: var(--font-sans); text-transform: uppercase; letter-spacing: 0.08em; }

.sidebar-nav { padding: 8px 12px; flex: 1; overflow-y: auto; }
.nav-section-label {
    font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--text-muted); font-weight: 600;
    padding: 14px 12px 6px;
}
.nav-item {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 12px; margin: 2px 0;
    border-radius: var(--radius-md);
    color: var(--text-secondary); font-weight: 500;
    position: relative;
    transition: all var(--transition-fast);
}
.nav-item:hover { background: rgba(255,255,255,0.5); color: var(--text-primary); }
.nav-item.active { background: var(--bg-card); color: var(--accent-primary); box-shadow: var(--shadow-sm); }
.nav-item.active::before {
    content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
    width: 3px; height: 22px; border-radius: var(--radius-full);
    background: var(--accent-primary);
}
.nav-icon { display: inline-flex; width: 20px; height: 20px; flex-shrink: 0; }
.nav-icon svg { width: 20px; height: 20px; }
.nav-text { white-space: nowrap; }

.sidebar-footer { padding: 14px 16px; border-top: 1px solid var(--border-medium); }

/* ===== Collapsed (slim icon rail) ===== */
.sidebar-collapse-btn { display: inline-flex; }
.sidebar-collapse-btn svg { width: 18px; height: 18px; }

.sidebar-collapsed .sidebar { width: var(--sidebar-collapsed-width); }
.sidebar-collapsed .main-content { margin-left: var(--sidebar-collapsed-width); }

/* Hide text-bearing chrome; keep icons centered on the rail. */
.sidebar-collapsed .nav-text,
.sidebar-collapsed .logo-text,
.sidebar-collapsed .nav-section-label,
.sidebar-collapsed .sidebar-logo-card,
.sidebar-collapsed .sidebar-footer-text,
.sidebar-collapsed .sidebar-footer .nav-text { display: none; }

.sidebar-collapsed .sidebar-header { justify-content: center; padding: 16px 0; }
.sidebar-collapsed .logo { justify-content: center; }
.sidebar-collapsed .nav-item { justify-content: center; padding: 10px 0; }
.sidebar-collapsed .nav-item.active::before { left: 0; }
.sidebar-collapsed .sidebar-footer { padding: 12px 8px; }
.sidebar-collapsed .sidebar-footer > div { flex-direction: column; justify-content: center; gap: 8px; }

/* Tooltip on hover so nav stays discoverable when labels are hidden. */
.sidebar-collapsed .nav-item::after {
    content: attr(data-label);
    position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
    background: var(--text-primary); color: #fff;
    padding: 5px 10px; border-radius: var(--radius-sm);
    font-size: 12px; font-weight: 500; white-space: nowrap;
    opacity: 0; pointer-events: none; box-shadow: var(--shadow-md);
    transition: opacity var(--transition-fast); z-index: 300;
}
.sidebar-collapsed .nav-item:hover::after { opacity: 1; }
.avatar {
    width: 34px; height: 34px; border-radius: var(--radius-full);
    background: var(--gradient-primary); color: #fff;
    display: flex; align-items: center; justify-content: center;
    font-weight: 600; flex-shrink: 0;
}
.sidebar-footer-text { margin-top: 8px; }

/* ===== Buttons ===== */
.btn {
    padding: 10px 20px;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    font-size: 14px; font-weight: 500;
    cursor: pointer;
    transition: all var(--transition-base);
    text-decoration: none;
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    position: relative; overflow: hidden;
    font-family: var(--font-sans);
}
.btn-primary { background: var(--accent-primary); color: #fff; border-color: var(--accent-primary); }
.btn-primary:hover { background: var(--accent-primary-hover); border-color: var(--accent-primary-hover); transform: translateY(-1px); box-shadow: var(--shadow-md); color: #fff; }
/* Soft tinted action buttons - same colour language as the badges and alerts. */
.btn-success { background: rgba(90, 138, 114, 0.08); color: var(--accent-green); border-color: rgba(90, 138, 114, 0.30); }
.btn-success:hover { background: rgba(90, 138, 114, 0.16); border-color: var(--accent-green); transform: translateY(-1px); box-shadow: var(--shadow-sm); color: var(--accent-green); }
.btn-warning { background: rgba(184, 148, 61, 0.08); color: var(--accent-yellow); border-color: rgba(184, 148, 61, 0.30); }
.btn-warning:hover { background: rgba(184, 148, 61, 0.16); border-color: var(--accent-yellow); transform: translateY(-1px); box-shadow: var(--shadow-sm); color: var(--accent-yellow); }
.btn-danger { background: rgba(194, 94, 94, 0.08); color: var(--accent-red); border-color: rgba(194, 94, 94, 0.30); }
.btn-danger:hover { background: rgba(194, 94, 94, 0.16); border-color: var(--accent-red); transform: translateY(-1px); box-shadow: var(--shadow-sm); color: var(--accent-red); }
.btn-secondary { background: transparent; color: var(--text-secondary); border: 1px solid var(--border-medium); }
.btn-secondary:hover { background: var(--bg-secondary); border-color: var(--text-muted); color: var(--text-primary); }
.btn-sm { padding: 8px 16px; font-size: 13px; }
.btn-lg { padding: 14px 28px; font-size: 16px; }
.btn:disabled, .btn.disabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }
.btn:focus { outline: none; box-shadow: 0 0 0 2px var(--bg-primary), 0 0 0 4px var(--accent-primary); }
.btn-icon {
    width: 34px; height: 34px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--radius-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border-light);
    color: var(--text-muted); cursor: pointer;
    transition: all var(--transition-fast);
}
.btn-icon:hover { background: var(--accent-primary); color: #fff; border-color: var(--accent-primary); }

/* ===== Cards ===== */
.card {
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    padding: 24px;
    box-shadow: var(--shadow-card);
    border: 1px solid var(--border-light);
    transition: all var(--transition-base);
    position: relative; overflow: hidden;
}
.card:hover { box-shadow: var(--shadow-md); border-color: var(--border-medium); }
.card-title {
    font-size: 17px; font-weight: 600; margin-bottom: 16px;
    color: var(--text-primary); font-family: var(--font-serif);
    display: flex; align-items: center; gap: 10px;
}
/* Card title with a right-aligned count, meta or link. */
.card-title.split { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.card-title.split .meta { font-size: 13px; font-weight: 400; color: var(--text-muted); }
.card-subtitle { font-size: 13px; color: var(--text-muted); margin-top: -10px; margin-bottom: 16px; }
/* Muted lead line under a card title. */
.card-intro { font-size: 12.5px; color: var(--text-muted); margin: -2px 0 14px; }
.section-title { font-size: 15px; font-weight: 600; margin: 4px 0 14px; }

/* ===== Stat cards ===== */
.stat-card {
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    padding: 24px;
    box-shadow: var(--shadow-card);
    border: 1px solid var(--border-light);
    transition: all var(--transition-base);
}
.stat-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
/* KPI cards that drill through into a filtered view. */
a.stat-card { display: block; text-decoration: none; color: inherit; cursor: pointer; }
a.stat-card:focus-visible { outline: 2px solid var(--accent-primary); outline-offset: 2px; }
.stat-label { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 500; margin-bottom: 8px; }
.stat-value { font-size: 32px; font-weight: 700; color: var(--text-primary); line-height: 1.1; }
.stat-value.success { color: var(--accent-green); }
.stat-value.warning { color: var(--accent-yellow); }
.stat-value.danger  { color: var(--accent-red); }
.stat-meta { font-size: 12px; color: var(--text-muted); margin-top: 8px; }

/* ===== Grids ===== */
.grid { display: grid; gap: 24px; }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 20px;
    margin-bottom: 28px;
}

/* ===== Badges / pills ===== */
.badge {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 12px; border-radius: var(--radius-full);
    font-size: 12px; font-weight: 600;
}
.badge-primary { background: rgba(196, 112, 75, 0.08); color: var(--accent-primary); }
.badge-success { background: rgba(90, 138, 114, 0.08); color: var(--accent-green); }
.badge-warning { background: rgba(184, 148, 61, 0.08); color: var(--accent-yellow); }
.badge-danger  { background: rgba(194, 94, 94, 0.08);  color: var(--accent-red); }
.badge-blue    { background: rgba(91, 122, 158, 0.08); color: var(--accent-blue); }
.badge-purple  { background: rgba(139, 122, 171, 0.10); color: var(--accent-purple); }
.badge-muted   { background: var(--bg-secondary); color: var(--text-muted); }

/* Wrapping row of small chips, for dense tables. */
.chip-row { display: flex; flex-wrap: wrap; gap: 5px; }
.chip-row .badge { padding: 2px 9px; font-size: 11.5px; font-weight: 500; }

/* Uppercase status pills. */
.project-status {
    padding: 6px 14px; border-radius: var(--radius-full);
    font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.5px;
    display: inline-flex; align-items: center; gap: 6px;
}
.project-status.active   { background: rgba(90, 138, 114, 0.08); color: var(--accent-green);  border: 1px solid rgba(90, 138, 114, 0.15); }
.project-status.pending  { background: rgba(184, 148, 61, 0.08); color: var(--accent-yellow); border: 1px solid rgba(184, 148, 61, 0.15); }
.project-status.danger   { background: rgba(194, 94, 94, 0.08);  color: var(--accent-red);    border: 1px solid rgba(194, 94, 94, 0.15); }
.project-status.info     { background: rgba(91, 122, 158, 0.08); color: var(--accent-blue);   border: 1px solid rgba(91, 122, 158, 0.15); }
.project-status.muted    { background: var(--bg-secondary);      color: var(--text-muted);    border: 1px solid var(--border-light); }

/* ===== Attribution list =====
   One labelled bar per contributing signal, showing its share of a total. Used
   anywhere the question is "why is this number what it is": match evidence
   behind a score, and survivorship behind a merged value. One component,
   rendered identically everywhere, so it is learned once. */
.attr-list { display: flex; flex-direction: column; gap: 12px; }
.attr-row { display: flex; flex-direction: column; gap: 5px; }
.attr-head { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.attr-label { font-weight: 600; }
.attr-group { font-size: 10.5px; padding: 1px 7px; flex-shrink: 0; }
.attr-value { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--text-muted); flex-shrink: 0; }
.attr-track { background: var(--bg-secondary); height: 8px; border-radius: var(--radius-full); overflow: hidden; }
.attr-fill { height: 100%; border-radius: var(--radius-full); background: var(--accent-primary); }
.attr-note { font-size: 11px; margin: 10px 0 0; }

/* ===== Status strip =====
   A row of pill links, each with a coloured dot, jumping to the matching
   section further down the page. */
.lane-strip { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 20px; }
.lane-strip a { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px;
    border: 1px solid var(--border-light); border-radius: var(--radius-full);
    font-size: 12.5px; font-weight: 500; color: var(--text-secondary);
    background: var(--bg-card); text-decoration: none; transition: all var(--transition-fast); }
.lane-strip a:hover { border-color: var(--text-muted); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.lane-strip a .ls-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text-light); }
.lane-strip a.st-issues .ls-dot { background: var(--accent-red); }
.lane-strip a.st-review .ls-dot { background: var(--accent-yellow); }
.lane-strip a.st-clear  .ls-dot { background: var(--accent-green); }
.lane-strip a.st-none   .ls-dot { background: var(--text-light); }
/* A gate is not another stage. Squared off and in the accent colour so the
   strip reads as four stages with two gates between them rather than as six
   things of the same kind. */
.lane-strip a.st-gate { border-color: var(--accent-primary); color: var(--accent-primary);
    border-radius: var(--radius-sm); font-weight: 600; }
.lane-strip a.st-gate .ls-dot { background: var(--accent-primary); border-radius: 2px; }
[id^="lane-"] { scroll-margin-top: 90px; }

/* ===== Verdict =====
   One stage's conclusion, above the numbers that support it. Set in the serif
   the headings use, because it is a statement rather than a label, and hung off
   a rule in the tone colour so the state is legible before the sentence is
   read. Grey is "not run" and never means good. */
.verdict { margin: 0 0 22px; padding: 2px 0 2px 16px;
           border-left: 3px solid var(--text-light); max-width: 92ch; }
.verdict-text { font-family: var(--font-serif); font-size: 16.5px; line-height: 1.5;
                color: var(--text-primary); }
.verdict-next { font-size: 12.5px; color: var(--text-muted); margin-top: 6px; }
.verdict.is-good { border-left-color: var(--accent-green); }
.verdict.is-attention { border-left-color: var(--accent-yellow); }
.verdict.is-neutral { border-left-color: var(--border-medium); }

/* ===== Rule set marker =====
   Which rule set a page's results were produced under. One line, because the
   full-width version of this appeared on six pages identically and stopped
   being read. The banner survives only where somebody signs. */
.rs-marker { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
             font-size: 12px; color: var(--text-muted); margin: 0 0 18px; }
.rs-marker a { color: var(--text-secondary); }
.rs-why { color: var(--text-light); }

/* ===== The story =====
   The newest run's seven conclusions, on the dashboard. One row per stage, each
   quoting that stage's own verdict, so the front page cannot describe a stage
   differently from the stage. Read down and you have the run. */
.story { display: flex; flex-direction: column; }
.story-row { display: flex; gap: 12px; align-items: baseline; padding: 11px 0;
             border-bottom: 1px solid var(--border-light); text-decoration: none;
             color: inherit; }
.story-row:last-child { border-bottom: none; }
.story-row:hover { background: var(--bg-secondary); }
.story-mark { flex: none; width: 9px; height: 9px; border-radius: 50%;
              background: var(--text-light); align-self: center; }
.story-row.is-good .story-mark { background: var(--accent-green); }
.story-row.is-attention .story-mark { background: var(--accent-yellow); }
.story-body { display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
              flex: 1 1 auto; min-width: 0; }
.story-label { flex: 0 0 108px; font-size: 12.5px; font-weight: 600;
               color: var(--text-primary); }
.story-text { flex: 1 1 320px; font-size: 13px; color: var(--text-secondary);
              line-height: 1.5; }

/* ===== Setup, folded away =====
   A first-day concern. It used to open the dashboard, so a reader on day thirty
   met ten provisioning steps before anything about their run. */
.setup > summary { cursor: pointer; font-size: 13px; color: var(--text-muted);
                   padding: 10px 0; list-style: none; }
.setup > summary::-webkit-details-marker { display: none; }
.setup > summary::before { content: "B8"; display: inline-block; width: 14px;
                           color: var(--text-light); transition: transform var(--transition-fast); }
.setup[open] > summary::before { transform: rotate(90deg); }
.setup > summary:hover { color: var(--text-secondary); }

/* ===== Outcome icons and dots ===== */
.ic { width: 14px; height: 14px; vertical-align: -2px; flex: none; }
.ic-pass { color: var(--accent-green); }
.ic-fail { color: var(--accent-red); }
.ic-review { color: var(--accent-yellow); }
.sort-ic { width: 11px; height: 11px; margin-left: 3px; vertical-align: 0; opacity: 0.7; }

/* Grey means not applicable or no data. It never means good. */
.risk-dot { display: inline-block; width: 9px; height: 9px; border-radius: var(--radius-full); margin-right: 8px; vertical-align: middle; }
.risk-high   { background: var(--accent-red); }
.risk-medium { background: var(--accent-yellow); }
.risk-low    { background: var(--accent-green); }
.risk-none   { background: var(--text-light); }
.text-high   { color: var(--accent-red); font-weight: 600; }
.text-medium { color: var(--accent-yellow); font-weight: 600; }
.text-low    { color: var(--accent-green); font-weight: 600; }
.text-none   { color: var(--text-light); }

/* ===== Tables ===== */
table {
    width: 100%;
    border-collapse: separate; border-spacing: 0;
    background: var(--bg-card);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-card);
}
th {
    background: var(--bg-secondary);
    padding: 14px 18px;
    text-align: left; font-weight: 600;
    color: var(--text-primary);
    font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px;
    border-bottom: 1px solid var(--border-light);
    white-space: nowrap;
}
th a { color: inherit; display: inline-flex; align-items: center; gap: 4px; }
th a:hover { color: var(--accent-primary); }
/* Sortable headers: every sortable column signals it, not just the active one.
   Inactive columns show a faint marker that strengthens on hover; the active
   column shows its explicit direction via .sort-arrow. */
.sort-link { cursor: pointer; }
.sort-link::after {
    content: '⇅';
    font-size: 10px; opacity: 0;
    transition: opacity var(--transition-fast);
}
.sort-link:hover::after { opacity: 0.55; }
.sort-link.is-sorted::after { content: none; }
.sort-arrow { color: var(--accent-primary); font-size: 10px; }
td {
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-light);
    color: var(--text-secondary);
    font-size: 14px;
}
tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--transition-fast); }
tbody tr:hover td { background: var(--bg-secondary); }
/* A long section scrolls inside itself rather than pushing everything under it
   off the screen. Without this a page with one 400-row table is a page whose
   other sections nobody ever sees, and the reader loses the run's shape.
   --section-max-h is one number so every scrolling section on every page stops
   at the same height; a page may raise it for a section that is the page. */
:root { --section-max-h: 62vh; }
.table-wrap { overflow: auto; max-height: var(--section-max-h);
    border-radius: var(--radius-lg); }
/* The table's own clipping has to go, or it becomes the scroll container and the
   sticky heading below sticks to nothing. The wrap clips the corners instead. */
.table-wrap > table { overflow: visible; }
/* The column headings stay put while the rows move. A scrolled table whose
   headings have gone is a grid of unlabelled numbers. */
.table-wrap thead th { position: sticky; top: 0; z-index: 2; }
/* Everything that is a long list of rows rather than a table. Same cap, so a
   card of 300 differences and a table of 300 rows behave alike.
   No overscroll-behavior: it was "contain", which stops the scroll dead at the
   end of the list instead of handing it on to the page. A reader who scrolled
   to the bottom of a section had to move the mouse off it to carry on down the
   tab. Default chaining, which is what .table-wrap already did. */
.scroll-y { max-height: var(--section-max-h); overflow-y: auto; }
.row-link { cursor: pointer; }
/* Numbers line up in columns; codes and keys read as codes. */
.num { font-variant-numeric: tabular-nums; font-family: var(--font-mono); font-size: 13px; }

/* ===== Forms ===== */
.form-group { margin-bottom: 24px; }
.form-label { display: block; margin-bottom: 8px; font-weight: 600; color: var(--text-primary); font-size: 14px; }
.form-input, select, textarea {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid var(--border-light);
    border-radius: var(--radius-md);
    font-size: 14px;
    transition: all var(--transition-base);
    background: var(--bg-card);
    color: var(--text-primary);
    font-family: var(--font-sans);
}
.form-input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--accent-primary);
    box-shadow: 0 0 0 3px rgba(196, 112, 75, 0.08);
}
.form-input:hover, select:hover { border-color: var(--border-medium); }
textarea { resize: vertical; min-height: 90px; }
select {
    cursor: pointer; appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%234a4a48' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 16px center; padding-right: 44px;
}
.form-hint { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.filter-bar { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 20px; }
.filter-bar .form-group { margin-bottom: 0; min-width: 160px; flex: 1; }
.filter-bar .form-group.grow { flex: 2; }
/* A filter that is not at its default, so applied filters are visible at a glance. */
.filter-active { border-color: var(--accent-primary); background-color: rgba(196, 112, 75, 0.06); }
select.filter-active:hover, .form-input.filter-active:hover { border-color: var(--accent-primary); }

/* ===== Alerts ===== */
.alert {
    padding: 14px 18px; border-radius: var(--radius-md);
    margin-bottom: 20px; display: flex; align-items: center; gap: 12px;
    font-size: 13px;
}
.alert-success { background: rgba(90, 138, 114, 0.06); border: 1px solid rgba(90, 138, 114, 0.15); color: var(--accent-green); }
.alert-warning { background: rgba(184, 148, 61, 0.06); border: 1px solid rgba(184, 148, 61, 0.15); color: var(--accent-yellow); }
.alert-error   { background: rgba(194, 94, 94, 0.06);  border: 1px solid rgba(194, 94, 94, 0.15);  color: var(--accent-red); }
.alert-info    { background: rgba(91, 122, 158, 0.06); border: 1px solid rgba(91, 122, 158, 0.15); color: var(--accent-blue); }

/* ===== Empty / placeholder states ===== */
/* Every list has one. An empty table with no explanation reads as broken. */
.empty-state, .no-data {
    border: 1.5px dashed var(--border-medium);
    border-radius: var(--radius-lg);
    padding: 40px 24px; text-align: center; color: var(--text-muted);
    background: var(--bg-secondary);
}
.empty-state .icon { font-size: 28px; margin-bottom: 8px; opacity: 0.6; }
.empty-state p { margin: 0 auto; }
/* A larger "not built yet" panel, used by the pillar stubs. */
.placeholder-canvas {
    border: 1.5px dashed var(--border-medium);
    border-radius: var(--radius-lg);
    background:
        repeating-linear-gradient(45deg, transparent, transparent 14px, rgba(196,112,75,0.03) 14px, rgba(196,112,75,0.03) 28px),
        var(--bg-secondary);
    min-height: 240px;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 10px; color: var(--text-muted); text-align: center; padding: 32px;
}
.placeholder-canvas .ph-title { font-family: var(--font-serif); font-size: 18px; color: var(--text-secondary); }
.placeholder-badge {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--accent-purple); background: rgba(139,122,171,0.10);
    padding: 4px 10px; border-radius: var(--radius-full); font-weight: 600;
}

/* ===== Breadcrumb ===== */
.breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-muted); }
.breadcrumb a { color: var(--text-muted); }
.breadcrumb a:hover { color: var(--accent-primary); }
.breadcrumb-item.active { color: var(--text-secondary); }
.breadcrumb-separator { color: var(--text-light); }

/* ===== Toasts ===== */
.toast-container { position: fixed; top: 20px; right: 20px; z-index: 11000; display: flex; flex-direction: column; gap: 10px; }
.toast {
    display: flex; align-items: center; gap: 10px;
    background: var(--bg-card); border: 1px solid var(--border-light);
    border-left: 3px solid var(--text-muted);
    border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
    padding: 12px 16px; min-width: 260px; max-width: 380px;
    animation: slideInRight 0.35s ease-out;
}
.toast.success { border-left-color: var(--accent-green); }
.toast.error   { border-left-color: var(--accent-red); }
.toast.warning { border-left-color: var(--accent-yellow); }
.toast.info    { border-left-color: var(--accent-blue); }
.toast-icon { font-weight: 700; }
.toast.success .toast-icon { color: var(--accent-green); }
.toast.error .toast-icon   { color: var(--accent-red); }
.toast.warning .toast-icon { color: var(--accent-yellow); }
.toast-message { flex: 1; font-size: 13px; color: var(--text-secondary); }
.toast-close { background: none; border: none; cursor: pointer; color: var(--text-light); font-size: 16px; }

/* ===== Definition list (detail view) ===== */
.dl { display: grid; grid-template-columns: 1fr; gap: 0; }
.dl-row { display: flex; justify-content: space-between; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--border-light); }
.dl-row:last-child { border-bottom: none; }
.dl-key { color: var(--text-muted); font-size: 13px; }
.dl-val { color: var(--text-primary); font-weight: 500; text-align: right; }

/* ===== Meter =====
   An 8px pill track for any 0 to 1 score: match confidence, fill rate,
   reconciliation variance. */
.meter { background: var(--bg-secondary); border-radius: var(--radius-full); height: 8px; overflow: hidden; margin-top: 6px; }
.meter-fill { height: 100%; border-radius: var(--radius-full); transition: width var(--transition-slow); }
.meter-fill.high { background: var(--accent-green); }
.meter-fill.medium { background: var(--accent-yellow); }
.meter-fill.low { background: var(--accent-red); }
.meter-fill.none { background: var(--text-light); }

/* ===== Timeline (audit trail) ===== */
.timeline { list-style: none; position: relative; padding-left: 22px; }
.timeline::before { content: ""; position: absolute; left: 6px; top: 4px; bottom: 4px; width: 2px; background: var(--border-light); }
.timeline-item { position: relative; padding: 0 0 18px 0; }
.timeline-item::before {
    content: ""; position: absolute; left: -22px; top: 4px;
    width: 12px; height: 12px; border-radius: var(--radius-full);
    background: var(--accent-primary); border: 2px solid var(--bg-card);
}
/* Decision outcomes. */
.timeline-item.approved::before { background: var(--accent-green); }
.timeline-item.rejected::before { background: var(--accent-red); }
.timeline-item.amended::before  { background: var(--accent-yellow); }
.timeline-item.overridden::before { background: var(--accent-purple); }
/* Pipeline stages. Blue and purple categorise, they never mean severity. */
.timeline-item.tl-extract::before,  .g-dot.k-extract  { background: var(--accent-blue); }
.timeline-item.tl-compare::before,  .g-dot.k-compare  { background: var(--accent-purple); }
.timeline-item.tl-merge::before,    .g-dot.k-merge    { background: var(--accent-primary); }
.timeline-item.tl-handover::before, .g-dot.k-handover { background: var(--text-light); }
.g-dot { display: inline-block; width: 9px; height: 9px; border-radius: var(--radius-full); }
.timeline-action { font-weight: 600; color: var(--text-primary); }
.timeline-meta { font-size: 12px; color: var(--text-muted); }
.timeline-notes { font-size: 13px; color: var(--text-secondary); margin-top: 4px; }

/* ===== Tabs ===== */
.tab-strip {
    display: flex; gap: 4px; flex-wrap: wrap;
    border-bottom: 1px solid var(--border-light);
    margin-bottom: 24px;
}
.tab-btn {
    appearance: none; background: none; border: none; cursor: pointer;
    font-family: inherit; font-size: 14px; font-weight: 500;
    color: var(--text-muted); padding: 10px 16px;
    border-bottom: 2px solid transparent; margin-bottom: -1px;
    display: inline-flex; align-items: center; gap: 7px;
    transition: color var(--transition-fast), border-color var(--transition-fast);
    text-decoration: none;
}
.tab-btn:hover { color: var(--text-primary); }
.tab-btn.active {
    color: var(--accent-primary); font-weight: 600;
    border-bottom-color: var(--accent-primary);
}
.tab-count {
    font-size: 11px; font-weight: 600; line-height: 1;
    padding: 3px 7px; border-radius: var(--radius-full);
    background: rgba(194, 94, 94, 0.1); color: var(--accent-red);
}
/* Neutral means "just a count". Only the warm default means needs attention. */
.tab-count.neutral { background: var(--bg-secondary); color: var(--text-muted); }
.tab-strip-sticky { position: sticky; top: 0; z-index: 50; background: var(--bg-primary); }
.tab-pane { display: none; }
.tab-pane.active { display: block; }

/* ===== Utilities ===== */
.muted { color: var(--text-muted); }
.flex { display: flex; }
.flex-between { display: flex; justify-content: space-between; align-items: center; }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; } .gap-16 { gap: 16px; }
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mt-24 { margin-top: 24px; }
.mb-16 { margin-bottom: 16px; } .mb-24 { margin-bottom: 24px; }
.text-right { text-align: right; }
.w-full { width: 100%; }
.mobile-menu-btn, .sidebar-overlay { display: none; }

/* ===== Animations ===== */
@keyframes fadeInUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
@keyframes fadeOutToast { to { opacity: 0; transform: translateX(20px); } }
.stat-card, .card { animation: fadeInUp 0.4s ease-out; }

/* ===== Responsive ===== */
@media (max-width: 1200px) {
    .grid-4 { grid-template-columns: repeat(2, 1fr); }
    .grid-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 992px) {
    :root { --sidebar-width: 240px; }
    .stats-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
    .sidebar { transform: translateX(-100%); }
    .sidebar.open { transform: translateX(0); }
    .main-content { margin-left: 0; }
    /* On mobile the drawer handles the sidebar, so the desktop collapse toggle
       and its margin are not relevant. */
    .sidebar-collapsed .main-content { margin-left: 0; }
    .sidebar-collapse-btn { display: none; }
    .grid-2, .grid-3, .grid-4, .stats-grid { grid-template-columns: 1fr; }
    .mobile-menu-btn { display: inline-flex; }
    .sidebar-overlay.show { display: block; position: fixed; inset: 0; background: rgba(0,0,0,0.35); z-index: 150; }
    .content-body { padding: 20px 16px; }
    .content-header { padding: 16px; }
}
@media (max-width: 480px) {
    .stat-value { font-size: 26px; }
    .btn { padding: 9px 16px; }
}
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ===== Scenario explorer (UR-12) =====
   The slice of the scenario space on the Proof page: the picker, the grid and
   the legend. One coloured square is one scenario, never a bucket of them, so
   the palette can mean exactly one thing per square.

   Five states, and "nobody answers" is deliberately not drawn as agreement even
   though the two rule sets do agree there. The whole point of the picture is
   that a proved run is not the same thing as an answered one. */
.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; }

.sc-picks { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-end; }
.sc-pick { display: flex; flex-direction: column; gap: 4px; }
.sc-pick-label { font-size: 11.5px; color: var(--text-muted); text-transform: lowercase; }
.sc-pick .form-input { min-width: 150px; font-size: 12.5px; padding: 5px 8px; }
.sc-scope { font-size: 12.5px; color: var(--text-secondary); max-width: 88ch;
    font-variant-numeric: tabular-nums; }

.sc-legend { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 4px 22px; }
.sc-key { display: flex; gap: 9px; align-items: flex-start; padding: 8px 0;
    border-top: 1px solid var(--border-light); }
/* A state this slice has none of is dimmed rather than removed: the reader needs
   to know the colour exists and that the count is zero, which is a result. */
.sc-key.is-zero { opacity: 0.5; }
.sc-sw { flex: none; width: 13px; height: 13px; border-radius: 3px; margin-top: 3px;
    border: 1px solid rgba(0, 0, 0, 0.12); }
.sc-key-head { font-size: 12.5px; font-weight: 600; display: flex; gap: 8px;
    align-items: baseline; }
.sc-key-n { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-muted);
    font-variant-numeric: tabular-nums; }
.sc-key-note { font-size: 11.5px; color: var(--text-muted); line-height: 1.45;
    margin-top: 3px; }

/* The five fills. Agreement is quiet on purpose: it is nearly every square on a
   proved run, and a wall of saturated colour hides the handful that are not. */
.sc-agrees     { background: rgba(90, 138, 114, 0.30); }
.sc-unanswered { background: var(--bg-secondary); }
.sc-gained     { background: rgba(184, 148, 61, 0.55); }
.sc-lost       { background: rgba(184, 148, 61, 0.85); }
.sc-differs    { background: var(--accent-red); }
i.sc-unanswered { background: var(--bg-secondary); border-color: var(--border-medium); }

/* WIDTH AUTO, and this is the whole bug that was reported. The base stylesheet
   sets `table { width: 100% }`, which is correct for a table of text and wrong
   for a grid of fixed squares: the table stretched to its container and the
   browser gave every spare pixel to the first column, so the row headings became
   a wide empty band and the squares sat jammed against the right edge. Sizing to
   content puts them under their headings, and .table-wrap already scrolls a grid
   too wide to fit. */
.sc-grid { width: auto; border-collapse: separate; border-spacing: 2px;
    background: none; box-shadow: none; border-radius: 0;
    /* Centred in its card. The grid is narrower than the page on every
       slice with few values, and a small square block pinned left reads
       as a rendering fault rather than a chart. */
    margin-inline: auto; }
/* The heatmap's headings are the axis, not a table heading bar: they have
   no background to hide the rows behind them, so they do not stick. */
.sc-grid thead th { position: static; }
/* A div above the grid, not a <caption>, so its width never sets the table's. */
.sc-cap { text-align: left; font-size: 12px;
    color: var(--text-muted); padding: 0 0 10px; max-width: 88ch; }
/* Empty, and as narrow as its row headings need. The axes are named in the
   caption, which is one place rather than two, and two labels wedged into a
   corner cell were what made the first column look like a column of content. */
.sc-corner { width: 1px; padding: 0; background: none; }
.sc-xh { font-size: 10.5px; font-weight: 500; color: var(--text-muted);
    padding: 0 0 6px; vertical-align: bottom; text-align: center;
    white-space: nowrap; }
/* Turned only when the longest value would otherwise collide with its
   neighbour: a 22px column cannot hold "anything else" horizontally, and turning
   ACT to save room it does not need makes it harder to read, not easier. */
.sc-grid.is-turned .sc-xh span { display: block; writing-mode: vertical-rl;
    transform: rotate(180deg); white-space: nowrap; margin: 0 auto; }
.sc-yh { font-size: 11px; font-weight: 500; color: var(--text-secondary);
    text-align: right; padding: 0 9px 0 0; white-space: nowrap;
    background: none; }
.sc-cell { width: 22px; height: 22px; min-width: 22px; padding: 0;
    border-radius: 3px; cursor: help; }
.sc-cell:hover { outline: 2px solid var(--text-primary); outline-offset: 1px; }

/* The base table styling, undone inside the grid. Every one of these was
   visible in the reported screenshot: `th` paints itself grey and uppercases
   its text, `th`/`td` carry an 18px padding and a bottom rule, and
   `tbody tr:hover td` repaints a whole row -- which on a heatmap means hovering
   one square greys out the twelve beside it and hides the state they encode.
   A grid of coloured squares wants none of it. */
.sc-grid th, .sc-grid td { border-bottom: none; text-transform: none;
    letter-spacing: normal; }
.sc-grid tbody tr:hover td { background: inherit; }
.sc-grid tbody tr:hover .sc-agrees     { background: rgba(90, 138, 114, 0.30); }
.sc-grid tbody tr:hover .sc-unanswered { background: var(--bg-secondary); }
.sc-grid tbody tr:hover .sc-gained     { background: rgba(184, 148, 61, 0.55); }
.sc-grid tbody tr:hover .sc-lost       { background: rgba(184, 148, 61, 0.85); }
.sc-grid tbody tr:hover .sc-differs    { background: var(--accent-red); }
/* The row a reader is on, marked on its heading rather than by repainting the
   data: a wide grid needs the label kept findable, and the squares are the one
   thing that must not change colour for any reason but their state. */
.sc-grid tbody tr:hover .sc-yh { color: var(--text-primary); font-weight: 700; }

.sc-badge { color: var(--text-primary); border: 1px solid var(--border-medium); }
.sc-badge.sc-differs { color: #fff; border-color: transparent; }
.sc-scen { font-size: 12px; }
.sc-bit { display: inline-block; margin: 0 10px 2px 0; white-space: nowrap; }
.sc-bit em { color: var(--text-muted); font-style: normal; font-size: 11px; }
.sc-rules { font-size: 11.5px; }
.sc-arrow { color: var(--text-muted); padding: 0 4px; }

