:root { --hospital-violet: #7667dc; --success-soft: color-mix(in srgb, #18a36f 13%, var(--panel)); --warning-soft: color-mix(in srgb, #e89a23 14%, var(--panel)); --danger-soft: color-mix(in srgb, #df515d 14%, var(--panel)); --info-soft: color-mix(in srgb, #4c8fe7 13%, var(--panel)); --overlay: color-mix(in srgb, #000 48%, transparent); --focus-ring: color-mix(in srgb, var(--accent) 66%, transparent); }
* { box-sizing: border-box; }
body { min-width: 320px; background: var(--bg); color: var(--text); }
button, input, select { font: inherit; } button:focus-visible, input:focus-visible, select:focus-visible, tr:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
.hospital-shell { min-height: 100vh; display: grid; grid-template-columns: 252px minmax(0, 1fr); transition:grid-template-columns .18s ease; }.hospital-shell.sidebar-collapsed { grid-template-columns:76px minmax(0,1fr); }
.hospital-sidebar { position: sticky; top: 0; height: 100vh; overflow-y: auto; padding: 16px 12px; border-right: 1px solid var(--border); background: var(--panel); display: flex; flex-direction: column; gap: 16px; }.sidebar-brand-row { display:flex; align-items:flex-start; gap:6px; padding-bottom:16px; border-bottom:1px solid var(--border); }
.hospital-brand { min-width:0; flex:1; display: flex; align-items: center; gap: 10px; padding: 6px 8px; color: var(--text); text-decoration: none; }
.hospital-brand img { width: 34px; height: 34px; object-fit: contain; }.hospital-brand strong, .hospital-brand small { display:block; }.hospital-brand strong { letter-spacing: .08em; font-size: .84rem; }.hospital-brand small { color: var(--muted); font-size: .7rem; margin-top: 2px; }
.sidebar-toggle { width:32px; height:32px; flex:0 0 32px; display:grid; place-items:center; margin-top:5px; padding:0; border:1px solid var(--border); border-radius:6px; color:var(--muted); background:var(--panel-2); cursor:pointer; font-size:1.2rem; }.sidebar-toggle:hover { color:var(--accent); border-color:var(--accent); }.hospital-nav-label { margin: 4px 8px -6px; color: var(--muted); font-size: .66rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }.hospital-nav { display: flex; gap: 10px; align-items: center; min-height: 42px; padding: 0 10px; color: var(--muted); text-decoration: none; font-size: .86rem; border-radius: 6px; }.hospital-nav:hover { background: var(--panel-2); color: var(--text); }.hospital-nav.active { color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, var(--panel-2)); font-weight: 700; }.hospital-nav .h-icon { width: 20px; text-align:center; font-size: 1.08rem; }.sidebar-bottom { margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); display:grid; gap:6px; }.sidebar-bottom button { min-height: 40px; display:flex; gap:10px; align-items:center; justify-content:flex-start; color: var(--muted); background: transparent; border: 0; border-radius: 6px; text-align: left; padding: 0 9px; }.sidebar-bottom button:hover { color:var(--text); background:var(--panel-2); }
.hospital-main { min-width: 0; }.hospital-topbar { min-height: 76px; position: sticky; top: 0; z-index: 10; display:flex; align-items:center; gap:14px; padding: 10px clamp(16px, 3vw, 34px); border-bottom:1px solid var(--border); background:var(--bg); /* Fond opaque, sans `backdrop-filter` : un flou d'arrière-plan compose la barre dans sa propre couche et le texte y perd le lissage sous-pixels (OPS-CONSOLE-FONT-SMOOTHING-001). */ }.mobile-menu { display:none; }.top-title { min-width:0; }.top-title strong, .top-title small { display:block; }.top-title strong { font-size:.95rem; }.top-title small { color:var(--muted); font-size:.76rem; margin-top:3px; }.top-spacer { flex:1; }.top-profile { min-width:0; max-width:300px; padding: 7px 10px; text-align:left; color:var(--text); background:var(--panel); border:1px solid var(--border); border-radius:7px; cursor:pointer; }.top-profile strong, .top-profile span { display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }.top-profile strong { font-size:.79rem; }.top-profile span { color:var(--muted); font-size:.69rem; margin-top:2px; }.icon-button { width:40px; height:40px; display:inline-grid; place-items:center; padding:0; color:var(--text); background:var(--panel); border:1px solid var(--border); border-radius:7px; cursor:pointer; font-size:1.25rem; }.icon-button:hover { border-color:var(--accent); color:var(--accent); }
.hospital-shell.sidebar-collapsed .hospital-brand span,.hospital-shell.sidebar-collapsed .hospital-nav > span:last-child,.hospital-shell.sidebar-collapsed .hospital-nav-label,.hospital-shell.sidebar-collapsed .sidebar-bottom button > span:last-child { display:none; }.hospital-shell.sidebar-collapsed .sidebar-brand-row { justify-content:center; }.hospital-shell.sidebar-collapsed .hospital-brand { flex:0 0 auto; padding:6px 0; }.hospital-shell.sidebar-collapsed .hospital-nav,.hospital-shell.sidebar-collapsed .sidebar-bottom button { justify-content:center; padding:0; }.hospital-shell.sidebar-collapsed .sidebar-toggle { transform:rotate(180deg); }.hospital-content { max-width:none; margin:0; padding: clamp(14px, 1.6vw, 26px) clamp(16px, 2vw, 32px); }.environment-bar { display:flex; gap:10px; align-items:center; min-height:38px; margin:-4px 0 20px; padding:8px 12px; border:1px solid color-mix(in srgb, var(--warn) 42%, var(--border)); background:var(--warning-soft); color:var(--text); font-size:.78rem; }.environment-bar strong { color:var(--warn); }.context-bar { display:grid; gap:8px; align-items:end; margin-bottom:24px; padding:10px; border:1px solid var(--border); background:var(--panel); }.context-bar.basic-context { grid-template-columns:minmax(150px,.7fr) minmax(320px,1fr) 1fr; }.context-bar.provider-context { grid-template-columns:minmax(150px,.65fr) repeat(3,minmax(180px,1fr)); }.context-heading { display:grid; gap:4px; min-height:38px; align-content:center; }.context-heading span { color:var(--muted); font-size:.68rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }.context-heading strong { font-size:.84rem; }.context-field { min-width:0; display:grid; gap:4px; }.context-field label { color:var(--muted); font-size:.68rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }.context-field select { width:100%; min-height:38px; border:1px solid var(--border); border-radius:6px; padding:0 8px; color:var(--text); background:var(--panel-2); }
.module-header { display:flex; justify-content:space-between; gap:20px; align-items:flex-start; margin-bottom:24px; }.module-header h1 { margin:0; font-size:clamp(1.55rem, 2.5vw, 2.2rem); letter-spacing:0; }.module-header p:not(.eyebrow) { max-width:72ch; margin:8px 0 0; color:var(--muted); line-height:1.55; }.eyebrow { margin:0 0 6px; color:var(--accent); font-size:.68rem; font-weight: 700; letter-spacing:.1em; text-transform:uppercase; }.read-only { flex:0 0 auto; display:inline-flex; align-items:center; min-height:30px; padding:0 9px; color:var(--warn); border:1px solid color-mix(in srgb, var(--warn) 60%, var(--border)); background:var(--warning-soft); border-radius:6px; font-size:.73rem; font-weight: 700; }.kpi-grid { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:10px; margin-bottom:22px; }.kpi { min-height:122px; padding:16px; border:1px solid var(--border); border-left-width:3px; background:var(--panel); }.kpi span, .kpi small { display:block; color:var(--muted); font-size:.73rem; }.kpi strong { display:block; margin:10px 0 7px; font-size:2rem; line-height:1; }.kpi.good { border-left-color:#18a36f; }.kpi.warn { border-left-color:#e89a23; }.kpi.bad { border-left-color:#df515d; }.kpi.info { border-left-color:#4c8fe7; }
.panel { margin-bottom:18px; border:1px solid var(--border); background:var(--panel); }.panel > header { display:flex; justify-content:space-between; gap:12px; align-items:start; min-height:66px; padding:15px 17px; border-bottom:1px solid var(--border); }.panel h2 { margin:0; font-size:1rem; }.panel header p { margin:5px 0 0; color:var(--muted); font-size:.77rem; }.two-columns { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }.health-list { display:grid; }.health-row { min-height:62px; display:flex; justify-content:space-between; gap:12px; align-items:center; padding:10px 16px; border-bottom:1px solid var(--border); }.health-row:last-child { border-bottom:0; }.health-row strong, .health-row span, .health-row small { display:block; }.health-row strong { font-size:.84rem; }.health-row span, .health-row small { color:var(--muted); font-size:.73rem; margin-top:3px; }.health-row > div:last-child { text-align:right; }.h-status { display:inline-flex; align-items:center; min-height:23px; padding:0 7px; border:1px solid var(--border); border-radius:999px; font-size:.68rem; font-weight: 700; white-space:nowrap; }.h-status.good { color:var(--accent-2); border-color:#159364; background:var(--success-soft); }.h-status.warn { color:var(--warn); border-color:var(--warn); background:var(--warning-soft); }.h-status.bad { color:var(--danger); border-color:var(--danger); background:var(--danger-soft); }.h-status.info { color:var(--accent); border-color:var(--accent); background:var(--info-soft); }
.hospital-toolbar { display:flex; justify-content:space-between; gap:12px; align-items:center; margin-bottom:14px; }.hospital-toolbar > span { color:var(--muted); font-size:.76rem; }.search-input { display:flex; gap:8px; align-items:center; min-width:min(100%,360px); height:40px; padding:0 10px; border:1px solid var(--border); border-radius:7px; background:var(--panel); color:var(--muted); }.search-input input { width:100%; min-width:0; border:0; outline:0; color:var(--text); background:transparent; }.grid-panel { overflow:hidden; }.grid-wrap { max-width:100%; overflow:auto; }.data-grid { width:100%; border-collapse:collapse; min-width:760px; }.data-grid th { height:42px; padding:0 16px; color:var(--muted); background:var(--panel-2); border-bottom:1px solid var(--border); text-align:left; font-size:.67rem; letter-spacing:.08em; text-transform:uppercase; }.data-grid td { padding:12px 16px; border-bottom:1px solid var(--border); font-size:.81rem; vertical-align:middle; }.data-grid tbody tr { cursor:pointer; }.data-grid tbody tr:hover td, .data-grid tbody tr:focus td { background:color-mix(in srgb, var(--accent) 7%, var(--panel)); }.data-grid tr:last-child td { border-bottom:0; }.data-grid strong,.data-grid small { display:block; }.data-grid small { margin-top:3px; color:var(--muted); font-size:.72rem; }.context-notice { display:flex; flex-wrap:wrap; gap:9px 18px; align-items:center; margin-bottom:14px; padding:11px 13px; border:1px solid color-mix(in srgb, var(--accent) 40%, var(--border)); background:var(--info-soft); font-size:.78rem; }.context-notice span { color:var(--muted); }.capability { display:flex; gap:12px; align-items:flex-start; margin:16px; padding:13px; border:1px solid var(--border); background:var(--panel-2); }.capability .h-icon { color:var(--hospital-violet); font-size:1.15rem; }.capability strong { font-size:.83rem; }.capability p { margin:4px 0 0; color:var(--muted); font-size:.77rem; line-height:1.45; }.empty-state { display:grid; justify-items:center; max-width:640px; margin:50px auto; padding:20px; text-align:center; }.empty-state .h-icon { color:var(--accent); font-size:1.8rem; }.empty-state h2 { margin:12px 0 5px; font-size:1rem; }.empty-state p { margin:0; color:var(--muted); font-size:.83rem; line-height:1.5; }
.sidebar-backdrop { position:fixed; inset:0; z-index:24; border:0; background:var(--overlay); }.drawer-body { padding:2px 0 22px; }.detail-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); margin:16px; border:1px solid var(--border); }.detail-grid div { min-height:70px; padding:12px; border-right:1px solid var(--border); border-bottom:1px solid var(--border); }.detail-grid div:nth-child(2n) { border-right:0; }.detail-grid div:nth-last-child(-n+2) { border-bottom:0; }.detail-grid span,.detail-grid strong { display:block; }.detail-grid span { margin-bottom:6px; color:var(--muted); font-size:.69rem; text-transform:uppercase; letter-spacing:.05em; }.detail-grid strong { font-size:.8rem; }.drawer-section { margin:16px; padding:14px; border:1px solid var(--border); }.drawer-section h3 { margin:0; font-size:.86rem; }.drawer-section p { margin:8px 0 0; color:var(--muted); font-size:.8rem; line-height:1.45; }.toast { position:fixed; right:20px; bottom:20px; z-index:50; max-width:380px; padding:12px 14px; color:var(--text); border:1px solid var(--danger); background:var(--danger-soft); box-shadow:var(--shadow, 0 8px 30px rgba(0,0,0,.2)); font-size:.82rem; }
@media (max-width:1050px) { .hospital-shell,.hospital-shell.sidebar-collapsed { grid-template-columns:76px minmax(0,1fr); }.hospital-brand span,.hospital-nav > span:last-child,.hospital-nav-label,.sidebar-bottom button > span:last-child { display:none; }.sidebar-brand-row { justify-content:center; }.hospital-brand { flex:0 0 auto; padding:6px 0; }.hospital-brand img { width:32px; }.sidebar-toggle { display:none; }.hospital-nav,.sidebar-bottom button { justify-content:center; padding:0; }.hospital-nav .h-icon { font-size:1.2rem; }.context-bar.provider-context { grid-template-columns:repeat(2,minmax(0,1fr)); }.context-heading { grid-column:span 2; }.kpi-grid { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width:720px) { .hospital-shell,.hospital-shell.sidebar-collapsed { display:block; }.hospital-sidebar { position:fixed; z-index:25; left:0; top:0; width:260px; transform:translateX(-105%); transition:transform .18s ease; box-shadow:8px 0 30px rgba(0,0,0,.2); }.hospital-sidebar.open { transform:translateX(0); }.hospital-sidebar .hospital-brand span,.hospital-sidebar .hospital-nav > span:last-child,.hospital-sidebar .hospital-nav-label,.hospital-sidebar .sidebar-bottom button > span:last-child { display:initial; }.hospital-sidebar .sidebar-brand-row { justify-content:space-between; }.hospital-sidebar .hospital-brand { flex:1; padding:6px 8px; }.hospital-sidebar .hospital-nav,.hospital-sidebar .sidebar-bottom button { justify-content:flex-start; padding:0 10px; }.mobile-menu { display:inline-grid; }.hospital-topbar { min-height:64px; padding:8px 12px; }.top-title small,.top-profile span { display:none; }.top-profile { max-width:150px; }.hospital-content { padding:16px; }.environment-bar { margin-bottom:14px; }.context-bar.basic-context,.context-bar.provider-context { grid-template-columns:1fr; max-width:none; margin-bottom:18px; }.context-heading { grid-column:auto; }.module-header { align-items:flex-start; }.module-header h1 { font-size:1.5rem; }.read-only { font-size:.67rem; }.two-columns,.kpi-grid { grid-template-columns:1fr; }.hospital-toolbar { align-items:stretch; flex-direction:column; }.search-input { min-width:0; }.data-grid { min-width:660px; }.detail-grid { grid-template-columns:1fr; }.detail-grid div { border-right:0; border-bottom:1px solid var(--border); }.detail-grid div:last-child { border-bottom:0; } }
@media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto!important; transition:none!important; } }

/* ── Provider filter panel (CDP-PROVIDER-FILTER-001) ───────────────────────── */
.filter-panel .filter-rules { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); padding: 0 16px 4px; }
.filter-rule { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; background: var(--panel); display: grid; gap: 8px; align-content: start; }
.filter-rule header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.filter-rule header small { display: block; color: var(--muted); font-size: .78rem; }
.filter-origin { font-size: .72rem; color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
.filter-description { margin: 0; color: var(--muted); font-size: .84rem; line-height: 1.45; }
.filter-hint { margin: 0; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.filter-options { display: grid; gap: 4px; }
.filter-option { display: flex; align-items: center; gap: 8px; font-size: .86rem; }
.filter-pair { display: flex; flex-wrap: wrap; gap: 10px; }
.filter-pair label { display: grid; gap: 4px; font-size: .78rem; color: var(--muted); }
.filter-pair input, .filter-pair select, .filter-rule > input[type="text"] { padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); min-width: 0; }
.filter-actions { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 12px 16px 0; }
.filter-limit { display: grid; gap: 4px; font-size: .78rem; color: var(--muted); }
.filter-limit input { width: 110px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); }
.filter-panel > .filter-hint { padding: 0 16px 12px; }
.filter-notice { margin: 0; padding: 10px 16px; color: var(--text); background: var(--info-soft); border-radius: 10px; }

.contour-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); padding: 4px 16px 16px; }
.contour-card { border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; display: grid; gap: 8px; align-content: start; }
.contour-card header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.contour-headline { margin: 0; font-size: 1.4rem; line-height: 1.2; }
.contour-headline span { font-size: .82rem; color: var(--muted); }
.contour-drops, .contour-samples { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: .82rem; }
.contour-drops li { display: flex; justify-content: space-between; gap: 10px; border-bottom: 1px dashed var(--border); padding-bottom: 3px; }
.link-button { background: none; border: 0; color: var(--muted); cursor: pointer; text-decoration: underline; font-size: .78rem; }

.run-panel .run-progress { height: 6px; border-radius: 999px; background: var(--border); margin: 0 16px; overflow: hidden; }
.run-panel .run-progress span { display: block; height: 100%; background: var(--accent); transition: width .3s ease; }
.run-steps { list-style: none; margin: 0; padding: 12px 16px 16px; display: grid; gap: 10px; }
.run-step { border: 1px solid var(--border); border-left-width: 3px; border-radius: 10px; padding: 10px 12px; display: grid; gap: 6px; }
.run-step > div { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.run-step p { margin: 0; color: var(--muted); font-size: .82rem; line-height: 1.45; }
.run-step.done { border-left-color: #18a36f; } .run-step.running { border-left-color: #4c8fe7; }
.run-step.skipped { border-left-color: #e89a23; } .run-step.failed { border-left-color: #df515d; }
.run-count { font-variant-numeric: tabular-nums; font-weight: 600; }
.run-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.run-message { margin: 0; padding: 0 16px 16px; color: var(--muted); font-size: .86rem; }

.filter-picker { display: flex; flex-wrap: wrap; gap: 10px; padding: 0 16px 12px; }
.filter-pick { display: grid; gap: 2px; text-align: left; padding: 10px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); cursor: pointer; }
.filter-pick:hover { border-color: var(--accent); }
.filter-pick small { color: var(--muted); font-size: .78rem; }

/* ── Dashboard by domain ────────────────────────────────────────────────────── */
.domain-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); padding: 0 16px 16px; }
.domain-card { border: 1px solid var(--border); border-left-width: 3px; border-radius: 12px; background: var(--panel); padding: 14px 16px; display: grid; gap: 10px; align-content: start; }
.domain-card.ok { border-left-color: #18a36f; } .domain-card.warn { border-left-color: #e89a23; }
.domain-card.bad { border-left-color: #df515d; } .domain-card.unavailable { border-left-color: var(--border); }
.domain-card header { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.domain-card header small { display: block; color: var(--muted); font-size: .8rem; line-height: 1.4; margin-top: 2px; }
.domain-caption { margin: 0; color: var(--text); font-size: .86rem; }
.domain-reason { margin: 0; color: var(--muted); font-size: .84rem; line-height: 1.5; }
.domain-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.domain-rows li { display: flex; align-items: center; justify-content: space-between; gap: 10px; border-bottom: 1px dashed var(--border); padding-bottom: 5px; }
.domain-rows li:last-child { border-bottom: 0; padding-bottom: 0; }
.domain-rows small { display: block; color: var(--muted); font-size: .76rem; }
.domain-more { margin: 0; color: var(--muted); font-size: .78rem; }
.domain-open { justify-self: start; color: var(--accent); text-decoration: none; font-size: .84rem; font-weight: 600; }
.domain-open:hover { text-decoration: underline; }

/* ── Consultation ───────────────────────────────────────────────────────────── */
.record-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; padding: 0 16px 12px; }
.record-filter { display: grid; gap: 4px; font-size: .78rem; color: var(--muted); }
.record-filter input, .record-filter select { padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); color: var(--text); min-width: 130px; }
.records-grid td { vertical-align: middle; }
.records-grid tbody tr { cursor: pointer; }
.mono { font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.col-sort { background: none; border: 0; color: inherit; font: inherit; font-weight: 600; cursor: pointer; padding: 0; }
.col-sort:hover { color: var(--accent); }
.col-sort.is-active { color: var(--accent); }
.record-pager { display: flex; align-items: center; gap: 8px; padding: 0 16px 16px; flex-wrap: wrap; }
.record-pager button { padding: 6px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); cursor: pointer; }
.record-pager button:disabled { opacity: .45; cursor: default; }
.record-pager span { color: var(--muted); font-size: .86rem; }
.record-detail .record-fields { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); padding: 0 16px 16px; margin: 0; }
.record-fields dt { color: var(--muted); font-size: .78rem; }
.record-fields dd { margin: 2px 0 0; font-weight: 600; }

/* ── Consultation d'une famille (records) ──────────────────────────────────
 *
 * OPS-RADAR-CONSOLE-001. Le module `records` a été livré avec son markup mais
 * SANS feuille de style : `records-panel`, `records-grid`, `record-detail`,
 * `record-fields`, `record-toolbar`, `record-filter`, `record-pager` et
 * `col-sort` n'avaient aucune règle. D'où le tableau plus large que la page
 * avec un défilement hors d'atteinte, les filtres en vrac, et la fiche de
 * droite invisible alors qu'elle était déjà construite au clic sur une ligne.
 */

/* Le tableau et la fiche côte à côte, sur toute la largeur disponible. La
 * fiche ne s'insère que lorsqu'une ligne est choisie : sans elle, le tableau
 * prend tout — c'est le vide à droite et à gauche qui était signalé. */
.records-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-items: start; }
/* 380–560 px : le volet portait aussi le formulaire de correction, coincé à 400 px sur un
   écran de 2560 — le retour terrain exact « la place n'est pas exploitée ». */
.records-layout.has-detail { grid-template-columns: minmax(0, 1fr) minmax(340px, 480px); }
@media (max-width: 1180px) { .records-layout.has-detail { grid-template-columns: minmax(0, 1fr); } }

.records-panel { min-width: 0; }

/* Tableau de bord des filtres : ordonné, aligné, avant les données.
 * `auto-fill` plutôt qu'un nombre fixe de colonnes — le nombre de filtres est
 * déclaré par le propriétaire de la famille, il n'est pas connu ici. */
.record-toolbar {
  display: grid; gap: 10px 12px; align-items: end;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  padding: 14px 16px; border-bottom: 1px solid var(--border); background: var(--panel-2);
}
.record-toolbar .search-input { grid-column: 1 / -1; min-width: 0; }
.record-filter { display: grid; gap: 5px; min-width: 0; }
.record-filter > span { color: var(--muted); font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.record-filter input, .record-filter select {
  width: 100%; min-width: 0; min-height: 36px; padding: 0 8px;
  color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 6px;
}
.record-filter input:focus, .record-filter select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.record-toolbar .link-button { justify-self: start; align-self: end; }

/* Le défilement horizontal appartient au tableau, pas à la page : sinon la
 * barre se retrouve tout en bas du document, hors de vue. */
.records-panel .grid-wrap { max-width: 100%; overflow-x: auto; overscroll-behavior-x: contain; }
.records-grid th { position: sticky; top: 0; z-index: 1; white-space: nowrap; }
.records-grid tbody tr[aria-selected="true"] td { background: color-mix(in srgb, var(--accent) 14%, var(--panel)); }

.col-sort {
  display: inline-flex; align-items: center; gap: 4px; padding: 0; cursor: pointer;
  color: inherit; background: none; border: 0; font: inherit; letter-spacing: inherit; text-transform: inherit;
}
.col-sort:hover { color: var(--accent); }
.col-sort.is-active { color: var(--accent); }

.record-pager { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 12px 16px; border-top: 1px solid var(--border); }
.record-pager button { min-height: 32px; padding: 0 10px; color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 6px; cursor: pointer; }
.record-pager button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.record-pager button:disabled { opacity: .45; cursor: default; }
.record-pager span { color: var(--muted); font-size: .78rem; }

/* Fiche complète, collée en haut : on fait défiler le tableau sans la perdre. */
.record-detail { position: sticky; top: 92px; max-height: calc(100vh - 112px); overflow-y: auto; }
.record-fields { display: grid; gap: 1px; margin: 0; padding: 0; background: var(--border); }
.record-fields > div { padding: 10px 14px; background: var(--panel); }
.record-fields dt { color: var(--muted); font-size: .67rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.record-fields dd { margin: 4px 0 0; font-size: .82rem; overflow-wrap: anywhere; }
.record-fields .filter-hint { margin: 6px 0 0; color: var(--muted); font-size: .72rem; line-height: 1.4; }

/* Le menu ☰ ouvrait `state.sidebarOpen` sans qu'aucune règle ne réagisse à la
 * classe `open` : le clic ne faisait rien. En étroit, la barre latérale se
 * pose désormais au-dessus du contenu. */
@media (max-width: 1050px) {
  .hospital-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 25; width: 264px; transform: translateX(-100%); transition: transform .18s ease; }
  .hospital-sidebar.open { transform: translateX(0); }
  .hospital-sidebar.open .hospital-brand span,
  .hospital-sidebar.open .hospital-nav > span:last-child,
  .hospital-sidebar.open .hospital-nav-label,
  .hospital-sidebar.open .sidebar-bottom button > span:last-child { display: inline; }
  .hospital-sidebar.open .hospital-nav, .hospital-sidebar.open .sidebar-bottom button { justify-content: flex-start; padding: 0 10px; }
}

/* ── Retouche d'un enregistrement (HOSP-000 phase 3) ──────────────────────────
   Rendu SOUS la fiche, jamais à sa place : l'opérateur corrige en gardant sous
   les yeux la valeur qu'il corrige. */
.record-correction { margin-top: 12px; }
.record-correction h3 { margin: 0; font-size: 15px; }
.record-correction header p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }

.correction-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin: 14px 0;
}
.correction-fields label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; }
.correction-fields select,
.correction-fields input {
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
}
.correction-fields select:disabled,
.correction-fields input:disabled { opacity: .55; cursor: not-allowed; }

.correction-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* Le verdict du propriétaire, relayé tel quel — vert pour ce qui a été accepté,
   rouge pour ce qui a été refusé. Une seule couleur pour les deux obligerait à
   lire le texte pour savoir si l'action a eu lieu. */
.correction-done,
.correction-error {
  margin: 0 0 12px;
  padding: 9px 11px;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.45;
}
.correction-done { background: rgba(34, 160, 92, .12); border: 1px solid rgba(34, 160, 92, .38); }
.correction-error { background: rgba(200, 60, 60, .12); border: 1px solid rgba(200, 60, 60, .38); }

/* ── Éditeur de définition de provider (OPS-PROVIDER-DEFINITION-EDIT-001) ─────
   Deux niveaux : les réglages courants à plat, le reste replié. Un formulaire à
   quinze champs pour un objet que personne n'édite en entier serait pire que le
   fichier qu'il remplace. */
.definition-editor .correction-fields { margin: 12px 0; }
.definition-json { margin: 10px 0 14px; }
.definition-json > summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 0;
}
.definition-json textarea {
  width: 100%;
  margin-top: 8px;
  padding: 9px 11px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.5;
  resize: vertical;
}
.definition-reason { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; font-size: 13px; }
.definition-reason input {
  padding: 7px 9px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
}

/* ── La vraie cause du « format A4 » ────────────────────────────────────────
   `shared/console.css` porte, ligne 75, un sélecteur d'ÉLÉMENT :

       main { max-width: 1180px; margin: 0 auto; padding: 1.4rem; }

   `<main class="hospital-main">` EST un `<main>`. Toutes les tentatives
   précédentes visaient des classes (`.hospital-content`, `.context-bar`…) et
   passaient donc à côté : le cadre venait d'un cran plus haut, sur l'élément
   lui-même, et il a survécu à chaque correctif « largeur » de cette console.

   On surcharge ICI plutôt que d'amender la feuille partagée : elle habille
   d'autres consoles que je ne peux pas voir, et un sélecteur nu qu'on retire
   change leur mise en page sans que personne ne l'ait demandé. `main.hospital-main`
   suffit — un élément + une classe l'emportent sur l'élément seul. */
main.hospital-main { max-width: none; margin: 0; padding: 0; }

/* ── L'icône ☰ ne s'affiche que quand elle sert ─────────────────────────────
   `.mobile-menu { display:none }` était déclaré AVANT `.icon-button
   { display:inline-grid }`. Même spécificité, donc c'est l'ordre du fichier qui
   tranchait : le bouton s'affichait sur TOUTES les largeurs. Sur un grand écran
   il ouvre un panneau déjà ouvert — une commande visible qui ne fait rien.
   `.icon-button.mobile-menu` remet la règle du bon côté. */
.icon-button.mobile-menu { display: none; }
@media (max-width: 720px) { .icon-button.mobile-menu { display: inline-grid; } }

/* ── Plan de travail : l'écran sert, il ne cadre pas ────────────────────────
   `.hospital-content` était borné à 1680 px et centré. Sur un écran large, deux
   bandes vides encadraient le contenu et les tableaux devaient défiler
   horizontalement alors que la place existait — « comme un livre au milieu ».
   Le cadre est retiré ; ce qui reste est la marge de lecture. */

/* ── Le rail des étapes ─────────────────────────────────────────────────────
   Quatre panneaux de même poids, dont le plus grand tableau passait en premier :
   les étapes 2 à 4 vivaient sous la ligne de flottaison, et rien ne disait qu'il
   y avait un ordre. Le rail met le chemin en tête et dit où l'on en est.

   `flex` et pas `grid` : sur un écran étroit les étapes se replient au lieu de
   se serrer en colonnes illisibles. */
.step-rail {
  display:flex; flex-wrap:wrap; gap:8px; margin:0 0 20px;
  padding:8px; border:1px solid var(--border); background:var(--panel);
}
.step-rail-item {
  flex:1 1 200px; display:flex; gap:11px; align-items:center; min-width:0;
  padding:10px 12px; border:1px solid transparent; border-radius:8px;
  color:var(--muted); text-decoration:none;
}
.step-rail-item:hover { border-color:var(--border); background:var(--panel-2); }
.step-rail-num {
  flex:0 0 28px; width:28px; height:28px; display:grid; place-items:center;
  border:1px solid currentColor; border-radius:999px;
  font-size:.8rem; font-weight: 700;
}
.step-rail-text { min-width:0; display:grid; gap:2px; }
.step-rail-text strong { font-size:.83rem; }
.step-rail-text small { color:var(--muted); font-size:.71rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* L'étape FAITE se lit d'un coup d'œil ; l'étape COURANTE est la seule accentuée.
   Accentuer les quatre reviendrait à n'en accentuer aucune. */
.step-rail-item.done { color:var(--accent-2); }
.step-rail-item.done .step-rail-text strong { color:var(--text); }
.step-rail-item.current { color:var(--accent); background:color-mix(in srgb, var(--accent) 12%, var(--panel-2)); border-color:color-mix(in srgb, var(--accent) 45%, var(--border)); }
.step-rail-item.current .step-rail-text strong { color:var(--text); }
.step-rail-item.todo { opacity:.72; }
/* PASSÉE n'est ni faite ni à faire : la contre-visite peut être sautée avec un
   motif, et confondre les trois cacherait précisément la décision qu'on veut
   pouvoir relire. */
.step-rail-item.skipped { color:var(--warn); }
.step-rail-item.skipped .step-rail-text strong { color:var(--text); }
/* Six étapes au lieu de quatre : le rail se replie plutôt que de comprimer
   chaque libellé jusqu'à l'illisible. */
.step-rail { flex-wrap: wrap; }
/* ── Provenance d'une valeur ────────────────────────────────────────────────
   Une pastille COURTE dans le tableau (la place y est comptée), la mention en
   toutes lettres dans la fiche (on y vient pour comprendre). La valeur de source
   ne porte aucun signe : baliser les quatre origines reviendrait à ne rien
   distinguer — ce qui mérite un signe, c'est ce qui a été TOUCHÉ. */
.provenance {
  display:inline-block; margin-left:7px; padding:1px 6px; vertical-align:middle;
  border:1px solid currentColor; border-radius:999px;
  font-size:.63rem; font-weight: 700; letter-spacing:.04em; text-transform:uppercase;
}
.provenance.info { color:var(--accent); }
.provenance.warn { color:var(--warn); }
.provenance-line { display:flex; gap:8px; align-items:center; margin:6px 0 0; }
.provenance-line span { color:var(--muted); font-size:.73rem; }
.provenance-line .provenance { margin-left:0; }

/* Étapes numérotées : consultation → simulation → validation → publication.
   Un opérateur qui découvre l'écran doit voir l'ORDRE, pas une pile de
   panneaux de même poids. */
.step-panel > header { position:relative; padding-left:58px; }
.step-panel > header::before {
  content: attr(data-step-num);
  position:absolute; left:16px; top:14px;
  width:30px; height:30px; display:grid; place-items:center;
  border:1px solid var(--accent); border-radius:999px;
  color:var(--accent); background:var(--info-soft);
  font-size:.82rem; font-weight: 700;
}
.step-panel.done > header::before { color:var(--accent-2); border-color:#159364; background:var(--success-soft); }

/* Agrandir un tableau sur tout l'écran. Le besoin est réel : certaines familles
   déclarent une dizaine de colonnes, et les lire en défilant horizontalement
   fait perdre la ligne qu'on suivait. */
.panel.expanded {
  position:fixed; inset:0; z-index:40; margin:0;
  display:flex; flex-direction:column;
  background:var(--bg); border:0;
}
.panel.expanded > header { flex:0 0 auto; }
.panel.expanded .grid-wrap { flex:1 1 auto; max-height:none; }
.panel.expanded .data-grid { min-width:0; }
.expand-toggle {
  flex:0 0 auto; height:32px; padding:0 11px;
  color:var(--muted); background:var(--panel-2);
  border:1px solid var(--border); border-radius:6px; cursor:pointer; font-size:.75rem;
}
.expand-toggle:hover { color:var(--accent); border-color:var(--accent); }

/* La progression d'une course doit se voir sans chercher. */
.run-progress { height:8px; margin:0 17px 14px; border:1px solid var(--border); background:var(--panel-2); border-radius:999px; overflow:hidden; }
.run-progress > span { display:block; height:100%; background:var(--accent); transition:width .25s ease; }

/* ── Champ à jetons : une valeur choisie = un jeton retirable ────────────────
   Le texte à virgules faisait d'une faute de frappe un filtre qui ne matche
   rien, sans erreur. Ici chaque valeur se voit, se retire d'un geste, et les
   suggestions viennent des valeurs réelles de la colonne. */
.token-field { display:grid; gap:8px; }
.token-list { display:flex; flex-wrap:wrap; gap:6px; min-height:26px; }
.token { display:inline-flex; align-items:center; gap:6px; padding:3px 8px;
  border:1px solid var(--accent); border-radius:999px; background:var(--info-soft);
  font-size:.78rem; }
.token-remove { border:0; background:none; color:var(--accent); cursor:pointer;
  font-size:.72rem; padding:0 2px; }
.token-remove:hover { color:var(--danger); }
.filter-options-toolbar { display:flex; justify-content:space-between; align-items:center;
  margin-bottom:8px; }
.filter-pair-input { display:flex; align-items:center; gap:6px; }
.filter-unit { color:var(--muted); font-size:.74rem; white-space:nowrap; }
.page-size { display:flex; align-items:center; gap:6px; color:var(--muted); font-size:.76rem; }
.page-size select { min-height:32px; border:1px solid var(--border); border-radius:6px;
  background:var(--panel-2); color:var(--text); padding:0 6px; }

/* ── Tableau de bord : console d'exploitation ────────────────────────────────
   Compteurs cliquables en haut, ce qu'il faut traiter maintenant, puis LE
   tableau des sources. Le tableau est borné en hauteur avec un en-tête collant :
   sur trente sources, une page qui s'allonge sans fin oblige à remonter pour
   savoir quelle colonne on lit. */
.board-header { align-items: flex-start; }
.board-header .title-icon { display: inline-block; margin-right: 11px; color: var(--accent);
  font-size: .72em; vertical-align: .06em; }
.board-header .title-icon .h-icon { font-size: inherit; }
.board-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }

.ghost-button { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 32px; padding: 0 11px; color: var(--text); background: var(--panel);
  border: 1px solid var(--border); border-radius: 6px; font-size: .78rem; font-weight: 600;
  text-decoration: none; cursor: pointer; white-space: nowrap; }
.ghost-button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.ghost-button:disabled { opacity: .45; cursor: default; }
.ghost-button.active { border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel)); }

/* Cinq compteurs qui partagent un total. `auto-fit` plutôt qu'un nombre figé :
   la rangée a longtemps été calée sur quatre colonnes pour trois cartes, et la
   quatrième case vide se lisait comme une donnée manquante. */
.kpi-grid { grid-template-columns: repeat(auto-fit, minmax(min(100%, 178px), 1fr)); }
.kpi { min-height: 108px; text-align: left; cursor: pointer; font: inherit; }
.kpi:hover { border-color: var(--accent); }
.kpi.active { background: color-mix(in srgb, var(--accent) 9%, var(--panel));
  box-shadow: inset 0 0 0 1px var(--accent); }
.kpi.neutral { border-left-color: var(--muted); }
.kpi strong { display: flex; align-items: baseline; gap: 5px; }
.kpi strong small { font-size: .95rem; color: var(--muted); }

.board-split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px;
  align-items: stretch; margin-bottom: 18px; }
.board-split > .panel { height: 100%; margin-bottom: 0; }
.board-panel > header { min-height: 54px; align-items: center; }
.board-panel .link-button { flex: 0 0 auto; }
.board-none { margin: 0; padding: 16px; color: var(--muted); font-size: .82rem; line-height: 1.5; }

.triage-list, .run-list { list-style: none; margin: 0; padding: 0; }
.triage-list li, .run-list li { display: flex; align-items: center; gap: 11px; min-height: 58px;
  padding: 9px 16px; border-bottom: 1px solid var(--border); }
.triage-list li:last-child, .run-list li:last-child { border-bottom: 0; }
.triage-list li > div, .run-list li > div { flex: 1; min-width: 0; }
.triage-list strong, .run-list strong { display: block; font-size: .84rem; }
.triage-list small, .run-list small { display: block; margin-top: 3px; color: var(--muted);
  font-size: .74rem; line-height: 1.4; }
.dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 999px; background: var(--muted); }
.dot.good { background: #18a36f; } .dot.warn { background: #e89a23; }
.dot.bad { background: #df515d; } .dot.info { background: #4c8fe7; }
.run-time { flex: 0 0 auto; color: var(--muted); font-size: .76rem;
  font-variant-numeric: tabular-nums; }
.run-ago { flex: 0 0 auto; color: var(--muted); font-size: .74rem; }

.board-filters { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--border); }
.board-field { display: grid; gap: 5px; min-width: 0; }
.board-field.grow { flex: 1 1 220px; }
.board-field > span { color: var(--muted); font-size: .67rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; }
.board-field select, .board-field input { min-height: 34px; min-width: 150px; padding: 0 8px;
  color: var(--text); background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 6px; }
.board-filters .ghost-button { min-height: 34px; }
.board-chips { display: flex; flex-wrap: wrap; gap: 7px; padding: 11px 16px;
  border-bottom: 1px solid var(--border); }
.chip { display: inline-flex; align-items: center; gap: 6px; min-height: 26px; padding: 0 9px;
  color: var(--accent); background: var(--info-soft); border: 1px solid var(--accent);
  border-radius: 999px; font-size: .74rem; font-weight: 620; cursor: pointer; }
.chip:hover { color: var(--danger); border-color: var(--danger); background: var(--danger-soft); }

/* Hauteur bornée : le tableau tient dans l'écran, et l'en-tête reste lisible pendant
   qu'on descend. Sans `max-height`, trente lignes poussaient la pagination hors de vue. */
.board-scroll { max-height: clamp(320px, calc(100vh - 300px), 780px); overflow: auto;
  overscroll-behavior: contain; }
.board-grid { min-width: 1080px; }
.board-grid th { position: sticky; top: 0; z-index: 1; white-space: nowrap; }
.board-grid td { height: 36px; }
.board-grid .reason-cell { display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; max-width: none; overflow: hidden;
  overflow-wrap: anywhere; margin-top: 3px; color: var(--muted);
  font-size: .72rem; line-height: 1.35; }
.board-grid .actions-col { text-align: right; white-space: nowrap; }
.board-grid td.board-none { text-align: center; }

.board-pager { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; padding: 12px 16px;
  border-top: 1px solid var(--border); }
.board-pager .board-field select { min-width: 120px; }
.pager-info { margin-left: auto; color: var(--muted); font-size: .78rem; align-self: center; }
.pager-buttons { display: flex; flex-wrap: wrap; gap: 6px; align-self: center; }

/* Les services ne sont PAS des sources : ni cadence, ni volume, ni dernier succès. Les mettre
   dans le tableau aurait demandé quatre colonnes vides sur chaque ligne. */
.service-strip ul { list-style: none; margin: 0; padding: 0; }
.service-strip li { display: flex; align-items: center; gap: 12px; min-height: 56px;
  padding: 9px 16px; border-bottom: 1px solid var(--border); }
.service-strip li:last-child { border-bottom: 0; }
.service-strip li > div { flex: 1; min-width: 0; }
.service-strip strong { display: block; font-size: .84rem; }
.service-strip small { display: block; margin-top: 3px; color: var(--muted); font-size: .74rem;
  line-height: 1.45; }

@media (max-width: 1100px) {
  .board-split { grid-template-columns: 1fr; }
  .board-scroll { max-height: none; }
}

/* ── Largeur des colonnes : la donnée décide ───────────────────────────────
   `.data-grid` n'avait AUCUNE largeur déclarée : en `table-layout: auto`, chaque
   colonne prend la taille de son plus long contenu. C'est ainsi qu'« Source
   d'origine » occupait 514 px pour répéter la même phrase de 65 caractères sur
   chaque ligne, pendant que « Cap » en prenait 121 pour trois chiffres.

   Dix classes, dix largeurs. Une seule colonne par tableau reste LIBRE et absorbe
   le reste : l'identité de la ligne (`c-id`), ou le curseur (`c-range`) là où la
   largeur est de la précision.

   `display` n'est JAMAIS posé sur un <td> : un td sorti du flux de tableau fait
   fabriquer des cellules anonymes au navigateur, et deux td voisins fusionnent.
   La COUPE se pose sur la cellule, la mise en BLOC sur ses enfants. Ne pas
   « simplifier » en factorisant ce display. */
.data-grid { table-layout: fixed; }
.data-grid th { height: 34px; padding: 0 10px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-grid td { height: 36px; padding: 8px 10px; font-size: .8125rem;
  line-height: 1.4; vertical-align: top; }
.data-grid small { margin-top: 2px; font-size: .72rem; line-height: 1.35; }

.data-grid th.c-label   { width: 130px; }  /* libellé court : domaine, famille */
.data-grid th.c-code    { width: 58px; }   /* code pays, oui/non */
.data-grid th.c-state   { width: 190px; }  /* pastille + motif sur deux lignes */
.data-grid th.c-date    { width: 120px; }  /* « Il y a 4 h » */
.data-grid th.c-num     { width: 120px; }  /* un nombre + sa pastille de provenance */
.data-grid th.c-geo     { width: 140px; }
.data-grid th.c-actions { width: 96px; }
.data-grid th.c-text    { width: 300px; }  /* prose : deux lignes puis coupé */
/* L'identité porte le nom ET la clé technique : elle a besoin de place, mais
   pas de TOUTE la place. Première version : `c-id` était la seule colonne sans
   largeur, donc en `table-layout: fixed` elle absorbait tout l'excédent — 600 px
   pour « Bezons », ce qui remplaçait un défaut de largeur par son inverse.
   Toutes les colonnes sont déclarées désormais : l'excédent se répartit. */
.data-grid th.c-id    { width: 210px; min-width: 150px; }
.data-grid th.c-range { min-width: 160px; }

.data-grid .c-num, .data-grid .c-geo { text-align: right; font-variant-numeric: tabular-nums; }
.data-grid .c-code    { text-align: center; }
.data-grid .c-actions { text-align: right; }

/* UNE ligne, coupée à l'ellipse : tout ce qui se COMPARE d'une ligne à l'autre. */
.data-grid td.c-label, .data-grid td.c-code, .data-grid td.c-date,
.data-grid td.c-num, .data-grid td.c-geo,
.data-grid .c-id > strong, .data-grid .c-id > small, .data-grid .cell-id {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* `cell-id` : la consultation rend du texte NU dans sa colonne d'identité — ni
   <strong> ni <small>. Sans cette enveloppe, c'est la seule cellule de la console
   sans garde-fou : elle ne tronque pas, elle s'allonge sur N lignes. */
.data-grid .cell-id { display: block; }

/* DEUX lignes, puis coupé : tout ce qui se LIT.
   Le clamp porte sur un élément DANS la cellule, jamais sur le <td> lui-même —
   c'est la règle que la garde §9 fait respecter, et le plan de refonte la
   violait sur sa propre ligne `td.c-text`. Sélecteurs QUALIFIÉS par ailleurs :
   `.data-grid small { display:block }` l'emporterait sur une classe nue et
   annulerait le clamp en silence, sans qu'aucun test ne bouge. */
.data-grid .cell-text, .data-grid .c-state small, .data-grid small.reason-cell {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  line-clamp: 2; max-width: none; overflow: hidden; overflow-wrap: anywhere;
}

/* Un en-tête triable vit désormais dans une colonne bornée : `inline-flex` ne
   coupe pas à l'ellipse, `inline-block` si. */
.col-sort { display: inline-block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* ── Icônes : des SVG en ligne, plus des caractères ────────────────────────
   TAILLE : 1em. L'icône suit le texte qu'elle accompagne, donc les réglages de
   police déjà en place valent sans être réécrits. Le plancher de 14 px empêche
   la seule chose qu'un système en em ne sait pas empêcher : l'icône qui
   rétrécit avec un libellé de 10 px jusqu'à n'être qu'une tache. */
.h-icon { width: 1em; height: 1em; min-width: 14px; min-height: 14px; flex: 0 0 auto;
  display: inline-block; vertical-align: -.125em; stroke-width: 1.5; }
.icon-button .h-icon, .search-input .h-icon, .sidebar-toggle .h-icon,
.pager-buttons .h-icon { stroke-width: 1.85; }
.empty-state .h-icon, .title-icon .h-icon, .capability .h-icon { stroke-width: 1.3; }
.hospital-nav .h-icon, .sidebar-bottom .h-icon, .icon-button .h-icon,
.search-input .h-icon, .sidebar-toggle .h-icon { vertical-align: 0; }
/* La règle d'origine fixait width:20px avec une hauteur héritée en em : un
   caractère s'en moquait, un SVG sortait à 20×17,3. */
.hospital-nav .h-icon { width: 20px; height: 20px; }
.icon-button .h-icon { width: 1.05rem; height: 1.05rem; }
.sidebar-toggle .h-icon { width: .95rem; height: .95rem; }
/* Dé-scopée : `.board-header .title-icon` ne couvrait que le tableau de bord,
   le seul écran qui portait cette classe. Les autres en-têtes rendaient une
   icône démesurée, sans écart ni couleur. */
.title-icon { display: inline-block; margin-right: 11px; color: var(--accent);
  font-size: .72em; vertical-align: .06em; }
.title-icon .h-icon { font-size: inherit; }
.empty-state .h-icon { width: 1.8rem; height: 1.8rem; color: var(--accent); }
.capability .h-icon { width: 1.15rem; height: 1.15rem; }
@media (forced-colors: active) { .h-icon { stroke: CanvasText; } }

/* ── Un contour en attente de décision ─────────────────────────────────────
   Il existait en base sans que l'écran puisse le montrer : les boutons
   « Publier » et « Refuser » portaient sur un objet invisible. Publier à
   l'aveugle n'est pas une décision. */
.candidate-banner { display: flex; align-items: flex-start; gap: 12px; margin: 0 16px 14px;
  padding: 12px 14px; border: 1px solid color-mix(in srgb, var(--warn) 48%, var(--border));
  background: var(--warning-soft); }
/* Un verdict de contre-visite en échec : la publication reste possible (RETENUE, pas
   interdiction — HOSP-PUBLICATION-DECISION-001 point 7), mais le dire discrètement
   reviendrait à cacher qu'on outrepasse un contrôle. */
.run-warning { flex: 1 1 100%; margin: 0; padding: 8px 10px; color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 55%, var(--border));
  background: var(--warning-soft); font-size: .78rem; line-height: 1.45; }
.candidate-banner strong { display: block; font-size: .86rem; }
.candidate-banner small { display: block; margin-top: 4px; color: var(--muted);
  font-size: .78rem; line-height: 1.5; }
/* La ligne « avant → après » d'une règle : elle vit dans la carte de règle, au-dessus
   du contrôle, pour qu'on lise ce qui change avant de toucher au réglage. */
.rule-candidate { display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: .8rem; }
.rule-candidate strong { font-variant-numeric: tabular-nums; }

/* Ne SAIT PAS n'est pas un environnement. Le bandeau annonçait « PRODUCTION » sur
   l'hôte `dev` (2026-09-07) : quand le serveur ne dit rien, on l'affiche comme un
   trou, pas comme un nom. */
.environment-bar.environment-unknown { border-color:var(--danger, #c0392b); }
.environment-bar.environment-unknown strong { color:var(--danger, #c0392b); }

/* ── Ce qui charge se voit, et ce qui est périmé ne se manipule pas ──────────
   La console n'avait AUCUN indicateur de chargement : zéro animation, zéro
   squelette, zéro grisé. Recharger une page d'enregistrements re-rendait la
   table PÉRIMÉE sans rien signaler.
   `prefers-reduced-motion` coupe l'animation sans retirer l'information : la
   barre reste, elle cesse de courir. */
.loading-bar { display:flex; align-items:center; gap:10px; margin:0 17px 12px; }
.loading-bar-track { flex:1; height:6px; border-radius:999px; background:var(--panel-2); border:1px solid var(--border); overflow:hidden; }
.loading-bar-fill { display:block; width:34%; height:100%; border-radius:999px; background:var(--accent); animation:loading-slide 1.1s ease-in-out infinite; }
.loading-bar-label { color:var(--muted); font-size:12px; }

@keyframes loading-slide {
  0%   { transform:translateX(-100%); }
  100% { transform:translateX(320%); }
}

/* Grisé ET inerte. L'attribut `inert` fait le retrait clavier/souris ; cette
   règle ne fait que le rendre visible. Un bouton grisé qui répond quand même
   est pire qu'un bouton net. */
.is-busy { opacity:.55; filter:saturate(.7); transition:opacity .15s ease; }

@media (prefers-reduced-motion: reduce) {
  .loading-bar-fill { animation:none; width:100%; opacity:.6; }
  .is-busy { transition:none; }
}

/* Un succès et un échec ne partagent plus un élément. `.filter-notice` disait
   « Simulation terminée » et « Action impossible » dans le même bleu. */
.filter-notice.notice-ok  { background:rgba(34, 160, 92, .12); border:1px solid rgba(34, 160, 92, .38); }
.filter-notice.notice-bad { background:rgba(200, 60, 60, .12); border:1px solid rgba(200, 60, 60, .38); }

/* La portée de la consultation : ce provider, ou toute sa catégorie. Le bandeau
   n'apparaît qu'en vue élargie — dire « vous voyez ce provider » sur le mode par
   défaut serait du bruit sur chaque page. */
.scope-picker { display:flex; align-items:center; gap:6px; color:var(--muted); font-size:12px; }
.scope-picker select { font-size:12px; }
.scope-notice { margin:0 17px 12px; padding:8px 12px; border-radius:10px; color:var(--text);
  background:var(--info-soft); border:1px solid var(--border); font-size:12px; }
/* Les sources, regroupées par domaine. Trente-trois lignes à plat ne disaient
   pas de quoi elles parlaient ; la catégorie est déjà ce qui structure le CDP.
   `position: sticky` sur la ligne de groupe la garde lisible pendant qu'on
   parcourt un domaine long. */
.board-grid tr.board-group td { position:sticky; top:0; z-index:1;
  padding:8px 12px; background:var(--panel-2); border-top:1px solid var(--border);
  border-bottom:1px solid var(--border); }
.board-grid tr.board-group strong { font-size:13px; }
.board-group-count { margin:0 10px; color:var(--muted); font-size:12px; }

/* La simulation rend le MÊME tableau que la consultation, retenues et écartées
   ensemble. On y lisait « 900 retenus sur 1571 » sans jamais voir CE QUI SORT —
   or c'est là-dessus qu'un contour se juge. Les écartées sont teintées, pas
   barrées : elles restent lisibles, c'est ce qu'on vient examiner. */
.contour-samples-grid tr.contour-dropped td { background: color-mix(in srgb, var(--danger, #c0392b) 8%, transparent); }
.contour-samples-grid tr.contour-kept td { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.contour-score-link { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:0 17px 10px; color:var(--muted); font-size:12px; }

/* ── Le popup de retouche ──────────────────────────────────────────────────────
   Trois exigences du fondateur, et une contrainte de lecture :
   · les actions « modifier / supprimer » TOUJOURS visibles — d'où le `footer` collant
     plutôt qu'en bas de page : sur une fiche de vingt champs, valider ce qu'on ne voit
     plus oblige à faire défiler en aveugle ;
   · un champ non corrigible reste LISIBLE, simplement sans saisie ;
   · le motif est au même niveau que les boutons, pas relégué : il est obligatoire. */
.retouche-fond {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(6, 10, 18, .55);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
dialog.retouche {
  position: static; margin: 0; padding: 0; border: 1px solid var(--border);
  border-radius: 14px; background: var(--panel); color: inherit;
  width: min(760px, 100%); max-height: min(86vh, 900px);
  display: flex; flex-direction: column; overflow: hidden;
}
dialog.retouche > header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 18px 22px 12px; border-bottom: 1px solid var(--border);
}
dialog.retouche > header h2 { margin: 0 0 4px; font-size: 16px; }
dialog.retouche > header p { margin: 0; color: var(--muted); font-size: 12px; max-width: 62ch; }

/* Seul ce bloc défile. Les actions et le motif restent sous les yeux. */
.retouche-corps { overflow-y: auto; padding: 16px 22px; display: grid; gap: 14px; }
.retouche-champ label { display: grid; gap: 5px; font-size: 12px; color: var(--muted); }
.retouche-champ input, .retouche-champ select {
  width: 100%; padding: 7px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg); color: inherit; font-size: 13px;
}
.retouche-fige { opacity: .72; }
.retouche-etiquette { display: block; font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.retouche-valeur { margin: 0; font-size: 13px; }

.retouche-actions {
  border-top: 1px solid var(--border); padding: 14px 22px 18px;
  display: grid; gap: 10px; background: var(--panel);
}
.retouche-motif { display: grid; gap: 5px; font-size: 12px; color: var(--muted); }
.retouche-motif input {
  padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg); color: inherit; font-size: 13px;
}
.retouche-boutons { display: flex; gap: 10px; flex-wrap: wrap; }
.record-detail-actions { margin-top: 14px; }

/* ── Planification (étape 5) ───────────────────────────────────────────────────
   Le choix « maintenant ou à une date » se lit d'un coup : le champ d'heure et le
   bouton sur la même ligne, la mise en garde dessous. Une heure saisie loin de son
   bouton se remplit puis s'oublie. */
.planification-actions {
  display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap;
  margin-top: 12px;
}
.planification-quand { display: grid; gap: 5px; font-size: 12px; color: var(--muted); }
.planification-quand input {
  padding: 7px 10px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg); color: inherit; font-size: 13px;
}
.planification-actions .filter-hint { flex-basis: 100%; margin: 0; }

/* L'explication d'une colonne, à côté de son nom.
   Elle vient du SCHÉMA (`column.hint`) et n'était rendue que dans la fiche — donc jamais là
   où l'on regarde. Discrète, mais présente : « vide = enseigne non résolue par la source »
   est la différence entre un défaut de donnée compris et un bogue d'affichage supposé. */
.col-hint {
  margin-left: 4px; font-size: 11px; color: var(--muted);
  border: 0; text-decoration: none; cursor: help;
}

/* Le bandeau « la communauté attend ».
   Il INFORME, il n'agit pas : aucun bouton, et c'est délibéré — trancher une question
   communautaire depuis l'Hôpital demanderait d'abord de décider qui, de l'Hôpital ou de
   la modération, en a la charge. Court-circuiter un quorum par un bouton serait la pire
   façon de répondre à cette question-là. */
.attente-cds .attente-liste {
  margin: 8px 0 6px; padding-left: 18px; font-size: 12px; color: var(--muted);
}
.attente-cds .attente-liste li + li { margin-top: 3px; }
.attente-cds .attente-liste code {
  font-size: 11px; padding: 1px 5px; border-radius: 5px;
  background: var(--bg); border: 1px solid var(--border);
}

/* ── Le champ que la famille EXIGE et qui manque ────────────────────────────
   Surligné sur le champ lui-même, jamais seulement dans un bandeau : sur une saisie de six
   champs, « il manque le titre » écrit en haut oblige à relire les six pour trouver lequel.
   C'est la moitié visible de la distinction que le serveur prend soin de faire entre
   « il en manque un » et « celui-là ne se saisit pas ». */
.retouche-manque input {
  border-color: var(--danger, #c0392b);
  background: color-mix(in srgb, var(--danger, #c0392b) 6%, transparent);
}
.filter-hint.danger { color: var(--danger, #c0392b); }
