/* =========================================================================
   vebb3 — internal operator dashboard for kmakoll.se
   Visual system layered on top of Pico CSS 2.0.6.

   Strategy:
   - Define a small set of semantic tokens (--surface-*, --text-*, --accent-*).
   - Map Pico's own CSS variables onto those tokens so classless Pico markup
     (nav, table, article, form) inherits the system for free.
   - Add bespoke classes ONLY for things Pico can't express: status chips,
     the tool ribbon, the regulation-detail sidebar, the dark ASCII-V hero.

   One mode only (light / paper). No dark-mode toggle by design.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. TOKENS
   ------------------------------------------------------------------------- */
:root {
  /* Surfaces — calm cool field, bright white documents. Wide value gap so
     the table reads as paper floating on a desk, not grey-on-grey. */
  --surface-paper:    #eef1f6;   /* app background (the workbench)       */
  --surface-raised:   #ffffff;   /* cards, table, inputs (the document)  */
  --surface-sunken:   #f4f6f9;   /* table head, ribbon wells (near-white)*/
  --surface-inset:    #eef1f5;   /* wells on white (audit/preview/bars)  */

  /* Ink — cool near-black, real contrast. */
  --text-primary:     #15171c;
  --text-secondary:   #4d535c;
  --text-muted:       #7b828d;
  --text-faint:       #a7adb6;

  /* Hairlines — crisp, so structure reads as lines not value shifts. */
  --border:           #dde1e8;
  --border-strong:    #c3c9d2;

  /* Accent — "live / official". Brand teal-green. */
  --accent-live:        #009b72;
  --accent-live-hover:  #007a5a;
  --accent-live-bright: #45c7a3;  /* on dark chrome */
  --accent-live-soft:   #dcf1ea;
  --accent-live-border: #b3ddcf;

  /* Dark contrast — deep green-black for chrome (topbar, hero, CTAs on dark). */
  --contrast-dark:        #253022;
  --contrast-dark-deep:   #1a241a;
  --contrast-dark-soft:   #34412f;

  /* "Superseded / revoked / draft". Warm clay — pops against the cool field. */
  --accent-revoked:        #a85a30;
  --accent-revoked-soft:   #f6e8dd;
  --accent-revoked-border: #eccdb8;

  /* Quiet slate for "change / informational" relations. */
  --accent-info:        #3f5670;
  --accent-info-soft:   #e4e9ef;
  --accent-info-border: #c7d1dd;

  /* Per-authority source tints — low chroma, editorial not rainbow. Each
     authority gets a stable hue so cross-source scanning is instant. */
  --src-afs:    #009b72;  --src-afs-bg:    #dcf1ea;  --src-afs-bd:    #b3ddcf;  /* arbetsmiljö  */
  --src-sfs:    #3f5670;  --src-sfs-bg:    #e4e9f0;  --src-sfs-bd:    #c8d2e0;  /* riksdag/lag  */
  --src-nfs:    #1f6a6a;  --src-nfs-bg:    #e0eded;  --src-nfs-bd:    #c2dada;  /* miljö        */
  --src-livsfs: #9a5a1f;  --src-livsfs-bg: #f4e9da;  --src-livsfs-bd: #e6cfb2;  /* livsmedel    */
  --src-tsfs:   #5a4a86;  --src-tsfs-bg:   #ebe7f3;  --src-tsfs-bd:   #d6cee9;  /* transport    */
  --src-bfs:    #6d6257;  --src-bfs-bg:    #eeeae5;  --src-bfs-bd:    #dcd4ca;  /* bygg         */
  --src-kifs:   #6c7326;  --src-kifs-bg:   #eff1de;  --src-kifs-bd:   #dde1bd;  /* kemikalier   */
  --src-msbfs:  #a8443a;  --src-msbfs-bg:  #f6e6e3;  --src-msbfs-bd:  #ecccc6;  /* brand/farligt*/
  --src-elsakfs:#8a7100;  --src-elsakfs-bg:#f5efd4;  --src-elsakfs-bd:#e7dcaa;  /* el           */
  --src-ssmfs:  #8d3a6e;  --src-ssmfs-bg:  #f3e4ee;  --src-ssmfs-bd:  #e5c8dc;  /* strålning    */
  --src-eu:     #1c4f9c;  --src-eu-bg:     #e2e9f6;  --src-eu-bd:     #c3d2ec;  /* EU           */

  /* Type. */
  --font-ui:   "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --radius:    5px;
  --radius-sm: 3px;
  --shadow-card: 0 1px 2px rgba(36, 35, 30, 0.05),
                 0 1px 1px rgba(36, 35, 30, 0.04);
  --shadow-pop:  0 6px 24px rgba(36, 35, 30, 0.12),
                 0 2px 6px rgba(36, 35, 30, 0.08);
}

/* -------------------------------------------------------------------------
   2. PICO VARIABLE MAPPING  (drive Pico from our tokens)
   ------------------------------------------------------------------------- */
:root:not([data-theme="dark"]),
[data-theme="light"] {
  --pico-font-family: var(--font-ui);
  --pico-font-family-sans-serif: var(--font-ui);
  --pico-font-family-monospace: var(--font-mono);
  --pico-font-size: 100%;
  --pico-line-height: 1.5;
  --pico-font-weight: 400;

  --pico-background-color: var(--surface-paper);
  --pico-color: var(--text-primary);
  --pico-h1-color: var(--text-primary);
  --pico-h2-color: var(--text-primary);
  --pico-h3-color: var(--text-primary);
  --pico-h4-color: var(--text-primary);
  --pico-h5-color: var(--text-primary);
  --pico-h6-color: var(--text-primary);

  --pico-muted-color: var(--text-muted);
  --pico-muted-border-color: var(--border);
  --pico-secondary: var(--text-secondary);
  --pico-secondary-hover: var(--text-primary);

  /* Primary === live accent. */
  --pico-primary: var(--accent-live);
  --pico-primary-hover: var(--accent-live-hover);
  --pico-primary-focus: var(--accent-live-soft);
  --pico-primary-background: var(--accent-live);
  --pico-primary-hover-background: var(--accent-live-hover);
  --pico-primary-border: var(--accent-live);
  --pico-primary-hover-border: var(--accent-live-hover);
  --pico-primary-underline: var(--accent-live-border);
  --pico-primary-inverse: #ffffff;

  --pico-contrast: var(--text-primary);
  --pico-contrast-hover: #000;
  --pico-contrast-background: var(--text-primary);
  --pico-contrast-inverse: var(--surface-raised);

  --pico-border-radius: var(--radius);
  --pico-border-color: var(--border);

  --pico-card-background-color: var(--surface-raised);
  --pico-card-border-color: var(--border);
  --pico-card-box-shadow: var(--shadow-card);
  --pico-card-sectioning-background-color: var(--surface-sunken);

  --pico-form-element-background-color: var(--surface-raised);
  --pico-form-element-border-color: var(--border-strong);
  --pico-form-element-color: var(--text-primary);
  --pico-form-element-placeholder-color: var(--text-faint);
  --pico-form-element-active-background-color: var(--surface-raised);
  --pico-form-element-active-border-color: var(--accent-live);
  --pico-form-element-focus-color: var(--accent-live);

  --pico-table-border-color: var(--border);
  --pico-table-row-stripped-background-color: rgba(36, 35, 30, 0.018);

  --pico-mark-background-color: #fff2c4;
  --pico-mark-color: var(--text-primary);

  --pico-spacing: 1rem;
  --pico-block-spacing-vertical: 1rem;
  --pico-form-element-spacing-vertical: 0.45rem;
  --pico-form-element-spacing-horizontal: 0.6rem;

  --pico-link-color: var(--accent-live);
  --pico-link-hover-color: var(--accent-live-hover);

  color-scheme: light;
}

/* -------------------------------------------------------------------------
   3. BASE / TYPOGRAPHY
   ------------------------------------------------------------------------- */
html, body { min-height: 100vh; margin: 0; padding: 0; }
body {
  background: var(--surface-paper);
  color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

* { transition: none; }
a, button, input, select, summary, .chip, .ribbon-btn, tr {
  transition: color .15s ease, background-color .15s ease,
              border-color .15s ease, box-shadow .15s ease;
}

h1, h2, h3, h4, h5, h6 { letter-spacing: -0.012em; font-weight: 650; }
h1 { font-size: 1.75rem; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.05rem; }

/* Mono treatment for IDs / SN — first-class navigation handles. */
.mono, code, kbd, .reg-id, .sn {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.reg-id {
  font-size: 0.82em;
  color: var(--accent-live);
  letter-spacing: -0.01em;
}
.sn { font-size: 0.9em; color: var(--text-secondary); }

.app-wide { max-width: 1440px; margin-inline: auto; padding-inline: 1.5rem; }

.muted   { color: var(--text-muted); }
.tiny    { font-size: 0.78rem; }
.caps    { text-transform: uppercase; letter-spacing: 0.07em;
           font-size: 0.7rem; font-weight: 600; color: var(--text-muted); }

/* -------------------------------------------------------------------------
   4. APP BAR — one paper-white horizontal bar with an inline hamburger
   -------------------------------------------------------------------------
   The hamburger button is a regular icon-sized control that lives inside
   the white surface (left padding), not a separate dark tile. Clicking
   it discloses a small nav panel anchored under it. */
.app-bar {
  background: var(--surface-raised);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center;
  gap: 0.5rem;
  height: 48px;
  padding: 0 1rem;
}

/* The hamburger button + its drop-down menu. <details>/<summary> for a
   keyboard-accessible disclosure without JS. */
.app-bar .brand-menu { position: relative; margin: 0; flex: none; }
.app-bar .brand-tile {
  list-style: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  background: transparent;
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.app-bar .brand-tile::-webkit-details-marker,
.app-bar .brand-tile::marker { display: none; content: ""; }
.app-bar .brand-tile::after { content: none !important; display: none !important; }
.app-bar .brand-tile:hover,
.app-bar .brand-menu[open] > .brand-tile {
  background: var(--surface-inset);
}
.app-bar .brand-tile .glyph {
  font-family: var(--font-mono); font-weight: 700; font-size: 1.1rem;
  color: var(--accent-live);
  line-height: 1;
}

.app-bar .brand-menu-panel {
  position: absolute; top: calc(100% + 6px); left: 0;
  min-width: 220px;
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
  padding: 0.4rem;
  display: flex; flex-direction: column; gap: 0.05rem;
  z-index: 60;
}
.app-bar .brand-menu-head {
  font-family: var(--font-mono); font-weight: 600; font-size: 0.85rem;
  color: var(--text-muted); letter-spacing: -0.02em;
  padding: 0.35rem 0.7rem 0.5rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.35rem;
  display: flex; align-items: center; gap: 0.4rem;
}
.app-bar .brand-menu-head .glyph { color: var(--accent-live); font-weight: 700; }
.app-bar .brand-menu-panel a {
  display: flex; align-items: center;
  padding: 0.45rem 0.7rem;
  font-size: 0.88rem; color: var(--text-primary);
  text-decoration: none; border-radius: var(--radius-sm);
}
.app-bar .brand-menu-panel a:hover { background: var(--surface-inset); color: var(--text-primary); }
.app-bar .brand-menu-panel a.active {
  color: var(--accent-live); background: var(--accent-live-soft);
  box-shadow: inset 2px 0 0 var(--accent-live);
}
.app-bar .brand-menu-panel hr {
  margin: 0.35rem 0; border: 0; border-top: 1px solid var(--border);
}
.app-bar .brand-menu-panel form { margin: 0; }
.app-bar .brand-menu-logout {
  display: flex; align-items: center; gap: 0.5rem;
  width: 100%; text-align: left;
  padding: 0.45rem 0.7rem; font-size: 0.88rem;
  color: var(--text-secondary); background: transparent;
  border: 0; border-radius: var(--radius-sm); cursor: pointer;
  margin: 0;
}
.app-bar .brand-menu-logout:hover { background: var(--surface-inset); color: var(--accent-revoked); }

/* Paper-white centre area — flex:1 so the search input on the
   dashboard fills the remaining width. */
.app-bar-center {
  flex: 1; display: flex; align-items: center; gap: 0.5rem;
  min-width: 0;
}
/* Dashboard Status (kmakoll-category) chips, hosted in the app-bar. */
/* One scrollable line, never wrapped. The chips live inside the 48px-tall
   .app-bar, so a wrapped second row has nowhere to go and gets clipped — and
   because each chip is nowrap, narrow viewports pushed the last one ("Saknas")
   off the right edge with no way to reach it. `min-width: 0` is what actually
   lets the strip shrink below its content width inside the flex parent;
   without it `overflow-x` never engages. */
.app-bar-status-filters {
  display: flex; align-items: center; gap: 0.35rem;
  flex-wrap: nowrap;
  min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
/* Padding rather than margin so the last chip clears the scrollbar gutter
   instead of sitting flush against the fade of the overflow edge. */
.app-bar-status-filters { padding-bottom: 1px; }
.app-bar-status-filters .toggle-chip { white-space: nowrap; flex: none; }

/* -------------------------------------------------------------------------
   5. BUTTONS
   ------------------------------------------------------------------------- */
button, [role="button"], input[type="submit"] {
  --pico-font-weight: 550;
  letter-spacing: -0.005em;
  font-size: 0.875rem;
  white-space: nowrap;
}
.btn-sm { padding: 0.3rem 0.7rem !important; font-size: 0.8rem !important; }

/* Generic ghost / outline button used across ribbon + nav. */
.ribbon-btn, .ghost-btn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--font-ui); font-size: 0.82rem; font-weight: 550;
  color: var(--text-secondary);
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.65rem; margin: 0; cursor: pointer;
  line-height: 1.2; white-space: nowrap; width: auto;
}
.ribbon-btn:hover, .ghost-btn:hover {
  color: var(--text-primary); border-color: var(--text-muted);
  background: var(--surface-inset);
}
.ribbon-btn.is-active { color: var(--accent-live); border-color: var(--accent-live-border); background: var(--accent-live-soft); }
.ribbon-btn svg, .ghost-btn svg { width: 14px; height: 14px; flex: none; }

/* Pico styles `details.dropdown summary` with its own background, caret
   pseudo-element, and padding — these all out-specify `.ribbon-btn`,
   so a `<summary class="ribbon-btn">` ends up looking washed-out next
   to its sibling buttons. Reassert the ribbon-btn surface and tame
   Pico's caret so the column-picker reads as just another ribbon
   button. */
details.dropdown > summary.ribbon-btn {
    background: var(--surface-sunken);
    color: var(--text-secondary);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    padding: 0.35rem 0.65rem;
    font-size: 0.82rem;
    font-weight: 550;
    line-height: 1.2;
}
details.dropdown > summary.ribbon-btn::after {
    /* Pico's caret — keep it, but shrink + recolour to match ribbon tone. */
    width: 0.45em; height: 0.45em;
    margin-left: 0.4rem;
    background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
                      linear-gradient(-45deg, var(--text-muted) 50%, transparent 50%);
    border: 0;
    transform: rotate(0deg);
}
details[open].dropdown > summary.ribbon-btn,
details.dropdown > summary.ribbon-btn:hover {
    background: var(--surface-inset);
    color: var(--text-primary);
    border-color: var(--text-muted);
}
/* The dropdown body floats on top of the table — use the card surface
   so it doesn't blend into the page. */
details.dropdown > ul {
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: var(--shadow-pop);
    padding: 0.4rem 0.55rem;
}

/* -------------------------------------------------------------------------
   6. STATUS CHIPS + KMA FLAG SQUARES
   ------------------------------------------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.72rem; font-weight: 600; line-height: 1;
  padding: 0.22rem 0.45rem; border-radius: 99px;
  border: 1px solid transparent; white-space: nowrap;
  letter-spacing: 0.01em;
}
.chip .dot { width: 6px; height: 6px; border-radius: 99px; background: currentColor; }
.chip-live    { color: var(--accent-live);    background: var(--accent-live-soft);    border-color: var(--accent-live-border); }
.chip-live .dot { background: var(--accent-live); box-shadow: 0 0 0 2px var(--accent-live-soft), 0 0 5px var(--accent-live); }
.chip-revoked { color: var(--accent-revoked); background: var(--accent-revoked-soft); border-color: var(--accent-revoked-border); }
.chip-revocation {
  color: var(--accent-revoked); background: transparent; border-color: var(--accent-revoked-border);
  border-style: dashed;
}
.chip-change  { color: var(--accent-info);    background: var(--accent-info-soft);    border-color: var(--accent-info-border); }
.chip-neutral { color: var(--text-secondary); background: var(--surface-sunken);      border-color: var(--border); }
.chip-warn    { color: #9a6a1f; background: #faf0dc; border-color: #ecd9b5; }
.chip-test    { color: var(--text-secondary); background: transparent; border-color: var(--border-strong); border-style: dashed; }
/* A chip that's also a link (e.g. the change that drove "Senast ändrad"). */
.chip-link { text-decoration: none; cursor: pointer; transition: filter 0.12s ease; }
.chip-link:hover { filter: brightness(1.08); text-decoration: none; }

/* Source tag — authority label, subtly tinted per series (AFS/SFS/NFS/…). */
.src-tag {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.05em; color: var(--text-secondary);
  background: var(--surface-sunken); border: 1px solid var(--border);
  border-radius: 3px; padding: 0.14rem 0.4rem; white-space: nowrap;
}
.src-tag.s-afs    { color: var(--src-afs);    background: var(--src-afs-bg);    border-color: var(--src-afs-bd); }
.src-tag.s-sfs    { color: var(--src-sfs);    background: var(--src-sfs-bg);    border-color: var(--src-sfs-bd); }
.src-tag.s-nfs    { color: var(--src-nfs);    background: var(--src-nfs-bg);    border-color: var(--src-nfs-bd); }
.src-tag.s-livsfs { color: var(--src-livsfs); background: var(--src-livsfs-bg); border-color: var(--src-livsfs-bd); }
.src-tag.s-tsfs   { color: var(--src-tsfs);   background: var(--src-tsfs-bg);   border-color: var(--src-tsfs-bd); }
.src-tag.s-bfs    { color: var(--src-bfs);    background: var(--src-bfs-bg);    border-color: var(--src-bfs-bd); }
.src-tag.s-kifs   { color: var(--src-kifs);   background: var(--src-kifs-bg);   border-color: var(--src-kifs-bd); }
.src-tag.s-msbfs  { color: var(--src-msbfs);  background: var(--src-msbfs-bg);  border-color: var(--src-msbfs-bd); }
.src-tag.s-elsakfs{ color: var(--src-elsakfs);background: var(--src-elsakfs-bg);border-color: var(--src-elsakfs-bd); }
.src-tag.s-ssmfs  { color: var(--src-ssmfs);  background: var(--src-ssmfs-bg);  border-color: var(--src-ssmfs-bd); }
.src-tag.s-eu     { color: var(--src-eu);     background: var(--src-eu-bg);     border-color: var(--src-eu-bd); }

/* File presence glyph. */
.file-tick { color: var(--accent-live); display: inline-flex; vertical-align: -2px; }
.file-tick.absent { color: var(--text-faint); }

/* KMA flag squares — kvalitet / miljö / arbetsmiljö. */
.kma { display: inline-flex; gap: 2px; }
.kma span {
  font-family: var(--font-mono); font-size: 0.66rem; font-weight: 600;
  width: 16px; height: 16px; border-radius: 2px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-faint); background: var(--surface-sunken);
  border: 1px solid var(--border);
}
.kma span.on { color: #fff; background: var(--accent-live); border-color: var(--accent-live); }

/* -------------------------------------------------------------------------
   7. TOOL RIBBON + FILTER PANEL
   ------------------------------------------------------------------------- */
.ribbon {
  display: flex; align-items: center; gap: 0.5rem;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.5rem 0.6rem;
  box-shadow: var(--shadow-card);
  flex-wrap: wrap;
}
.ribbon .divider { width: 1px; align-self: stretch; background: var(--border-strong); margin: 0 0.15rem; }
.ribbon .spacer { flex: 1; }
.ribbon-group { display: flex; align-items: center; gap: 0.4rem; }
.ribbon .caps { white-space: nowrap; }

/* Module multiselect rendered as toggle chips. */
.module-chips { display: flex; gap: 0.3rem; }
.module-chips label {
  font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.02em; cursor: pointer;
  padding: 0.28rem 0.5rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface-sunken);
  color: var(--text-muted); user-select: none;
}
.module-chips input { position: absolute; opacity: 0; pointer-events: none; }
.module-chips label:has(input:checked) {
  color: var(--accent-live); background: var(--accent-live-soft); border-color: var(--accent-live-border);
}

/* Inline progress (htmx target friendly). */
.run-status { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.run-status .bar {
  width: 120px; height: 6px; border-radius: 99px;
  background: var(--surface-inset); overflow: hidden;
}
.run-status .bar > i {
  display: block; height: 100%; width: 0%;
  background: var(--accent-live); border-radius: 99px;
}
.run-status small { color: var(--text-secondary); font-size: 0.76rem; white-space: nowrap; }
/* Faint settled tone for "Klar · 100%" / "Status: idle" — the run is done,
   the message shouldn't compete with the rest of the ribbon. */
.run-status small.is-settled { color: var(--text-muted); }

/* Caps label that opens the module group — small left margin so it
   doesn't kiss the ribbon edge, no inline style needed. */
.ribbon-group > .caps:first-child { margin-left: 0.2rem; }

/* Tighter typography inside dropdown bodies. */
details.dropdown > ul,
details.dropdown > ul li { font-size: 0.82rem; }

/* Ribbon-embedded dropdown: kill Pico's default outer margin so it
   sits flush with sibling buttons in the ribbon row. */
details.ribbon-dropdown { margin: 0; }

/* ── Dashboard search input (sits in the paper-white app-bar) ────────
   Calm input chrome that matches the page filter inputs but slightly
   tighter so it fits the 52px bar height. */
.app-bar input[type="search"],
.app-bar select {
    background: var(--surface-raised);
    border: 1px solid var(--border-strong);
    color: var(--text-primary);
    height: 36px;
    margin: 0;
    padding: 0 0.75rem;
    font-size: 0.9rem;
    border-radius: var(--radius-sm);
    box-shadow: none;
}
.app-bar input[type="search"]::placeholder { color: var(--text-faint); }
.app-bar input[type="search"]:focus,
.app-bar select:focus {
    border-color: var(--accent-live);
    outline: none;
    box-shadow: 0 0 0 1px var(--accent-live);
}
.app-bar select { padding-right: 1.7rem; max-width: 140px; flex: none; }

/* ── Dashboard full-height layout ────────────────────────────────────
   When the dashboard page sets `body.dashboard-layout`, the document
   becomes a vertical flex container that pins to the viewport.
   `main.page` flexes to fill what's left under the app-bar, the
   `#dash-results` block inside it flexes again, and `.table-wrap`
   takes whatever vertical space remains — so the table scrolls
   inside its own region rather than scrolling the page. */
body.dashboard-layout {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}
body.dashboard-layout > div[hx-history-elt] {
    flex: 1; display: flex; flex-direction: column; min-height: 0;
}
body.dashboard-layout main.page {
    flex: 1; display: flex; flex-direction: column; min-height: 0;
    width: 100%;
    padding: 0.7rem 1.4rem;
}
/* The Dashboard worklist is a narrow, centred column (same as /diagnostics) —
   it has few columns and doesn't need the ultra-wide viewport. */
body.dashboard-layout.is-dash main.page {
    max-width: 1280px;
    margin-inline: auto;
}
/* The /search surface is data-dense (more columns + free-text) — full-bleed. */
body.dashboard-layout.is-search main.page {
    max-width: 100%;
    margin-inline: 0;
}
body.dashboard-layout #dash-results {
    flex: 1; display: flex; flex-direction: column; min-height: 0;
}
body.dashboard-layout #dash-results .table-wrap {
    flex: 1; max-height: none;
}
body.dashboard-layout #dash-results .pager { flex: none; }

/* Filter row sits between the app-bar and the table. Always visible —
   no toggle, no collapse. Two-row layout: boolean chips left, view
   actions (Kolumner / Tät / .csv) right. */
.dash-filters {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.6rem;
}
.dash-filters .filter-actions {
    margin-left: auto;
    display: inline-flex; align-items: center; gap: 0.4rem;
}
/* Pin every control in the dash-filters row (Källa, the date inputs, Kolumner,
   .csv) to one height so they sit flush on a single line. The date <input> is a
   replaced element — it gets height only (NOT inline-flex, which Chrome
   misrenders), and its label wrapper is pinned so it can't stretch the row. */
.dash-filters .ribbon-btn,
.dash-filters details.dropdown > summary.ribbon-btn {
    height: 30px; box-sizing: border-box;
    padding-block: 0 !important;
    display: inline-flex; align-items: center;
}
/* Override Pico's full-width + bottom-margin defaults for the inline inputs. */
.dash-filters .date-input {
    height: 30px; box-sizing: border-box;
    width: auto; flex: none; margin: 0;
}
.date-affix { font-size: 0.65rem; color: var(--text-muted); letter-spacing: 0.06em; }

/* ── Uniform vertical metrics across ribbon controls ─────────────────
   Without this, three different padding/font combinations (the 0.72rem
   mono module chips, the 0.82rem ui ribbon-btn, the 0.8rem btn-sm
   primary) end up at three different heights — chips ~24px, ribbon-btn
   ~30px, btn-sm ~28px — and the line of controls reads as ragged.
   Pin everyone to one height + horizontal-only padding so the ribbon
   sits on a single baseline. Scoped to `.ribbon` so .btn-sm in the
   filter panel keeps its own metrics. */
.ribbon .ribbon-btn,
.ribbon .ghost-btn,
.ribbon .module-chips label,
.ribbon .btn-sm,
.ribbon details.ribbon-dropdown > summary.ribbon-btn {
    height: 28px;
    padding-block: 0 !important;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    line-height: 1;
}
/* Status text and the progress bar live in the middle group — flex
   centering on the parent already vertical-centers them; this just
   pins the bar's height so it doesn't drive the row taller than 28px. */
.ribbon .run-status .bar { height: 6px; }

/* Pico applies `margin-bottom: calc(spacing * .375)` to <label> and
   `margin-bottom: spacing` to <button>. In a flex container with
   `align-items: center`, the alignment is based on the *margin box*,
   so the label-vs-button margin asymmetry shifts the chips up by
   ~3px relative to the buttons. Zero margins on every flex item in
   the ribbon to put them on the same baseline. Scoped to .ribbon so
   form-stack defaults elsewhere (filter panel labels, login form)
   keep their breathing room. */
.ribbon label,
.ribbon button,
.ribbon input,
.ribbon select,
.ribbon a,
.ribbon details,
.ribbon summary,
.ribbon .module-chips label {
    margin: 0;
}

/* Filter panel — inline, collapsible. No 2014 slide-in drawer. */
.filter-panel {
  margin-top: 0.55rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); padding: 0.85rem 0.95rem;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)) auto;
  gap: 0.85rem 1.4rem; align-items: end;
}
.filter-panel.hidden { display: none; }
.filter-field { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.filter-field > .caps { margin: 0; }
.filter-field input, .filter-field select { margin: 0; font-size: 0.85rem; }
.filter-toggles { display: flex; flex-wrap: wrap; gap: 0.4rem; grid-column: 1 / -1; }
.toggle-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; font-weight: 500; cursor: pointer; user-select: none;
  padding: 0.3rem 0.6rem; border-radius: 99px;
  border: 1px solid var(--border-strong); background: var(--surface-sunken);
  color: var(--text-secondary);
}
.toggle-chip input { position: absolute; opacity: 0; pointer-events: none; }
.toggle-chip:has(input:checked),
.toggle-chip.is-active {
  color: var(--accent-live); background: var(--accent-live-soft); border-color: var(--accent-live-border);
}

/* Source chips live in the same row as the boolean chips but each
   carries a count next to the body tag. Button defaults (browser font,
   padding) get reset to match the <label> variant. */
button.toggle-chip {
  font: inherit; font-size: 0.78rem; font-weight: 500;
  margin: 0;
}
/* Source filter — multi-select dropdown (same <details> popover as the
   column picker), leading the .dash-filters row. Mono font on the
   options so the body codes (AFS, SFS, …) read as codes; the summary
   takes the accent-live tint while any source is filtered so the active
   state stays visible with the popover closed. */
.source-option { font-family: var(--font-mono); letter-spacing: -0.01em; }
details.dropdown > summary.source-summary.is-active {
  color: var(--accent-live);
  background: var(--accent-live-soft);
  border-color: var(--accent-live-border);
}
.source-count { font-variant-numeric: tabular-nums; }

/* Secondary filter row — sits under the boolean chips, hosts the
   date_published range selector. Tighter top margin so it reads as a
   continuation. */
.dash-filters-secondary {
  margin-top: -0.25rem;
  margin-bottom: 0.6rem;
}
.dash-filters-secondary .filter-label {
  font-size: 0.65rem; color: var(--text-muted); letter-spacing: 0.08em; margin-right: 0.2rem;
}
/* Date-range filter — two native date inputs (Från / Till), either side
   optional. Styled to match the ribbon buttons (Källa / Kolumner) that share
   the row: same square radius, border, fill, height and hover. */
.date-range-field {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.65rem; color: var(--text-muted); letter-spacing: 0.06em;
}
.date-input {
  font-family: var(--font-mono); font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  padding: 0 0.55rem; height: 30px; box-sizing: border-box;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface-sunken);
  color: var(--text-secondary);
}
.date-input:hover { border-color: var(--text-muted); color: var(--text-primary); }
.date-input:focus {
  outline: none;
  border-color: var(--accent-live-border); color: var(--accent-live);
}
.date-input::-webkit-calendar-picker-indicator { opacity: 0.5; cursor: pointer; }
.filter-actions { display: flex; gap: 0.5rem; justify-self: end; }

.result-count {
    color: var(--text-muted); font-size: 0.82rem;
    margin: 0.5rem 0.15rem 0.4rem;
    font-family: var(--font-mono); letter-spacing: -0.01em;
    display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
}
.result-count b { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }
.result-count .applied-facets {
    display: inline-flex; align-items: center; gap: 0.3rem;
    margin-left: 0.4rem;
}
.facet-chip {
    display: inline-flex; align-items: center; gap: 0.3rem;
    height: 22px; padding: 0 0.45rem;
    font-size: 0.72rem; font-weight: 500;
    border: 1px solid var(--border); border-radius: 99px;
    background: var(--surface-raised);
    color: var(--text-secondary);
    cursor: pointer; margin: 0;
    line-height: 1; box-sizing: border-box;
}
.facet-chip:hover { border-color: var(--border-strong); color: var(--text-primary); }
.facet-chip.is-active {
    background: var(--accent-live-soft);
    border-color: var(--accent-live-border);
    color: var(--accent-live);
}
.facet-chip .src-tag { padding: 0 0.25rem; height: 16px; font-size: 0.66rem; }
.facet-chip .mono { font-size: 0.7rem; }

/* Inline expanded parser-run log buffer on /queues. Scrolls vertically
   so a long run doesn't push the page miles down; mono so column-
   aligned log lines stay readable. */
.run-log-pre {
    margin: 0.4rem 0 0;
    padding: 0.6rem 0.75rem;
    background: var(--contrast-dark, #1e2622);
    color: #d6e0d8;
    font-family: var(--font-mono);
    font-size: 0.74rem;
    line-height: 1.45;
    border-radius: var(--radius-sm);
    max-height: 360px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

/* -------------------------------------------------------------------------
   8. DATA TABLE (dense, sticky head, density toggle)
   ------------------------------------------------------------------------- */
.table-wrap {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); overflow: auto;
  max-height: calc(100vh - 230px);
}
table.data { margin: 0; font-size: 0.76rem; border-collapse: separate; border-spacing: 0; width: 100%; }
table.data thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface-raised);
  color: var(--text-secondary);
  font-weight: 600; font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  text-align: left; white-space: nowrap;
  padding: 0.35rem 0.6rem;
  border-bottom: 2px solid var(--text-primary);
  --pico-border-width: 0;
}
table.data thead th.sortable { cursor: pointer; user-select: none; }
table.data thead th.sortable:hover { color: var(--text-primary); }
table.data thead th .arrow { color: var(--accent-live); font-size: 0.85em; margin-left: 0.2rem; }
table.data tbody td {
  padding: 0.2rem 0.6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle; color: var(--text-primary);
}
table.data tbody tr:last-child td { border-bottom: 0; }
table.data tbody tr:nth-child(even) td { background: var(--surface-sunken); }
table.data tbody tr:hover td { background: var(--accent-live-soft); }
/* Row hierarchy: the live corpus reads first; superseded/non-live recede. */
table.data tbody tr.is-muted td { color: var(--text-secondary); }
table.data tbody tr.is-muted .reg-id { color: var(--text-secondary); }
table.data tbody tr.is-muted .t { font-weight: 400; }
/* Muted metadata inside tables (dates, counts, em-dashes) reads one step
   darker than the global muted token so the dense grid stays legible. */
table.data .muted { color: var(--text-secondary); }
/* The title column is the elastic one — `width: 100%` tells the table
   to give it all the slack the other content-sized cells don't claim.
   The fixed `max-width` is kept so a single ultra-long title never
   pushes the right-hand columns off the screen. */
table.data td.col-title { width: 100%; max-width: 0; }
table.data td.col-title .t {
  display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500;
}
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data td .row-id { text-decoration: none; font-weight: 500; }
table.data td .row-id:hover { text-decoration: underline; }
table.data td.col-status { white-space: nowrap; }
table.data .status-cluster { display: inline-flex; gap: 0.3rem; align-items: center; }

/* Chips inside the data table are sized for the dense baseline. */
table.data .chip { padding: 0.12rem 0.38rem; font-size: 0.66rem; }

/* -------------------------------------------------------------------------
   9. PAGINATION (rebuilt — quiet, mono page numbers)
   ------------------------------------------------------------------------- */
.pager { display: flex; align-items: center; justify-content: space-between; margin: 0.9rem 0.15rem; }
.pager .pages { display: flex; gap: 0.3rem; align-items: center; }
.pager a, .pager span.cur {
  font-family: var(--font-mono); font-size: 0.8rem;
  min-width: 30px; height: 30px; padding: 0 0.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-raised); color: var(--text-secondary); text-decoration: none;
}
.pager a:hover { border-color: var(--text-muted); color: var(--text-primary); }
.pager span.cur { background: var(--text-primary); color: var(--surface-raised); border-color: var(--text-primary); }
.pager .meta { color: var(--text-muted); font-size: 0.8rem; }

/* -------------------------------------------------------------------------
   10. REGULATION DETAIL (editorial column + sidebar + version timeline)
   ------------------------------------------------------------------------- */
.reg-back {
  display: inline-flex; align-items: center; gap: 0.35rem; white-space: nowrap;
  color: var(--text-muted); text-decoration: none; font-size: 0.82rem; margin: 0.4rem 0 0.9rem;
}
.reg-back:hover { color: var(--text-primary); }

.reg-head { border-bottom: 1px solid var(--border); padding-bottom: 1.2rem; margin-bottom: 1.4rem; }
.reg-head .idline { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.reg-head .idline .reg-id { font-size: 0.9rem; font-weight: 600; }
.reg-head .idline .sn {
  font-family: var(--font-mono); font-weight: 600; font-size: 0.9rem; color: var(--text-primary);
  background: var(--surface-sunken); border: 1px solid var(--border);
  border-radius: 3px; padding: 0.1rem 0.45rem; font-variant-numeric: tabular-nums;
}
.reg-head h1 {
  font-size: 2.1rem; line-height: 1.15; margin: 0 0 0.5rem;
  font-weight: 680; max-width: 46rem; text-wrap: balance; letter-spacing: -0.02em;
}
.reg-head .sub { color: var(--text-secondary); font-size: 0.9rem; }
.reg-head .sub .sep { color: var(--text-faint); margin: 0 0.4rem; }

.reg-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 2.2rem; align-items: start; }

/* Version chain timeline. */
.version-chain {
  display: flex; align-items: stretch; gap: 0; overflow-x: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-raised); padding: 0.85rem 1rem; margin-bottom: 1.6rem;
  box-shadow: var(--shadow-card);
}
.vc-node { display: flex; align-items: center; gap: 0; flex: none; }
.vc-card {
  min-width: 0; display: flex; flex-direction: column; gap: 0.22rem;
  padding: 0.45rem 0.75rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface-paper);
  text-decoration: none;
}
.vc-card:hover { border-color: var(--text-muted); }
.vc-card.is-current {
  border-color: var(--accent-live); background: var(--accent-live-soft);
  box-shadow: 0 0 0 1px var(--accent-live);
}
.vc-card .vc-id { font-family: var(--font-mono); font-size: 0.78rem; font-weight: 600; color: var(--accent-live); }
.vc-card.is-current .vc-id { color: var(--accent-live-hover); }
.vc-card .vc-meta { font-size: 0.67rem; color: var(--text-muted); letter-spacing: 0.01em; }
.vc-arrow { color: var(--border-strong); padding: 0 0.7rem; align-self: center; flex: none; font-size: 1.1rem; }
.vc-label { font-size: 0.66rem; color: var(--text-muted); align-self: center; padding-right: 0.85rem; margin-right: 0.25rem; white-space: nowrap;
  border-right: 1px solid var(--border); text-transform: uppercase; letter-spacing: 0.07em; font-weight: 600; }

/* Reading column. */
.reading h2 { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em;
              color: var(--text-muted); font-weight: 600; margin: 1.8rem 0 0.6rem; }
.reading .summary {
  font-size: 1.08rem; line-height: 1.65; color: var(--text-primary);
  border-left: 2px solid var(--accent-live); padding: 0.2rem 0 0.2rem 1.15rem; margin: 0;
}
.doc-text {
  font-size: 0.92rem; line-height: 1.6; color: var(--text-secondary);
  background: var(--surface-raised); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1rem 1.15rem;
  max-height: 320px; overflow-y: auto; white-space: pre-wrap;
}
.doc-text.audit { background: var(--surface-inset); }

/* Sidebar. */
.reg-side { display: flex; flex-direction: column; gap: 1.3rem; position: sticky; top: 70px; }
.side-block { }
.side-block > .caps { display: block; margin-bottom: 0.55rem; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 0.9rem; font-size: 0.84rem; }
.kv dt { color: var(--text-muted); }
.kv dd { margin: 0; text-align: right; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.kv dd.empty { color: var(--text-faint); }
.side-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }

/* File download CTA — hard to miss. */
.file-cta {
  display: flex; align-items: center; gap: 0.7rem;
  background: var(--accent-live); color: #fff; text-decoration: none;
  border-radius: var(--radius); padding: 0.7rem 0.85rem; font-weight: 600; font-size: 0.9rem;
}
.file-cta:hover { background: var(--accent-live-hover); color: #fff; }
.file-cta .meta { font-weight: 400; font-size: 0.74rem; opacity: 0.85; font-family: var(--font-mono); }
.file-cta svg { flex: none; }
.file-cta.absent {
  background: var(--surface-sunken); color: var(--text-muted);
  border: 1px dashed var(--border-strong); pointer-events: none;
}

/* -------------------------------------------------------------------------
   11. SEARCH (Linear-style rows)
   ------------------------------------------------------------------------- */
.search-head { max-width: 1440px; margin-inline: auto; padding: 0 1.5rem; }
.search-form { display: flex; gap: 0.5rem; margin: 0.6rem 0 0.4rem; }
.search-form input[type="search"] { margin: 0; font-size: 0.95rem; }
.search-form button { width: auto; flex: none; }
.source-chips { display: flex; gap: 0.4rem; margin: 0.7rem 0 0.3rem; flex-wrap: wrap; }

.results { display: flex; flex-direction: column; }
.result-row {
  display: grid; grid-template-columns: 1fr auto; gap: 0.2rem 1.2rem;
  padding: 0.95rem 0.4rem; border-bottom: 1px solid var(--border);
  text-decoration: none;
}
.result-row:hover { background: var(--accent-live-soft); }
.result-row .r-title { font-size: 1rem; font-weight: 600; color: var(--text-primary); }
.result-row .r-snippet {
  grid-column: 1 / 2; font-size: 0.88rem; line-height: 1.55; color: var(--text-secondary);
}
.result-row .r-snippet mark { background: var(--pico-mark-background-color); padding: 0 1px; border-radius: 2px; }
.result-row .r-foot {
  grid-column: 1 / 2; display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  font-size: 0.76rem; color: var(--text-muted); margin-top: 0.15rem;
}
.result-row .r-foot > span { white-space: nowrap; }
.result-row .r-foot .sep { color: var(--border-strong); }
.rank { display: flex; align-items: center; gap: 0.4rem; align-self: start; }
.rank .rank-bar { width: 44px; height: 4px; border-radius: 99px; background: var(--surface-inset); overflow: hidden; }
.rank .rank-bar > i { display: block; height: 100%; background: var(--text-muted); }
.rank .rank-val { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-faint); }

/* -------------------------------------------------------------------------
   12. PROMPTS (two-pane editor)
   ------------------------------------------------------------------------- */
.prompt-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.3rem; align-items: start; }
.pane { border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-raised); overflow: hidden; }
.pane > header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--border); background: var(--surface-sunken);
}
.pane > header h2 { margin: 0; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-secondary); }
.pane textarea {
  width: 100%; border: 0; border-radius: 0; margin: 0; resize: vertical;
  font-family: var(--font-mono); font-size: 0.82rem; line-height: 1.55;
  background: var(--surface-raised); min-height: 460px; padding: 0.9rem;
}
.pane textarea:focus { box-shadow: none; }
.preview-body {
  font-family: var(--font-mono); font-size: 0.8rem; line-height: 1.6;
  white-space: pre-wrap; color: var(--text-secondary);
  padding: 0.9rem; min-height: 460px; max-height: 620px; overflow-y: auto;
  background: var(--surface-inset);
}
.preview-body .token { background: var(--accent-live-soft); color: var(--accent-live);
  border: 1px solid var(--accent-live-border); border-radius: 3px; padding: 0 3px; font-weight: 600; }
.prompt-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  margin-top: 0.9rem; font-size: 0.8rem; color: var(--text-muted);
}
.prompt-foot .saved { flex: 1; }
.prompt-foot .saved b { color: var(--text-secondary); font-weight: 600; }
/* Pico's default `button { width: 100% }` stretches the submit across
   the row otherwise — pin to its content width so it sits as a chip. */
.prompt-foot button { width: auto; }

/* -------------------------------------------------------------------------
   13. LOGIN
   ------------------------------------------------------------------------- */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: 2rem; }
.login-card { width: 100%; max-width: 360px; }
.login-card .brand {
  display: flex; align-items: center; gap: 0.5rem; justify-content: center;
  font-family: var(--font-mono); font-weight: 600; margin-bottom: 1.4rem;
  color: var(--text-primary); letter-spacing: -0.02em; font-size: 1.05rem;
}
.login-card .brand .glyph { color: var(--accent-live); font-weight: 700; }
.login-card article { padding: 1.6rem; }
.login-card h1 { font-size: 1.25rem; margin: 0 0 1.1rem; }
.login-card label { font-size: 0.85rem; }
.login-card button { width: 100%; margin-top: 0.4rem; }
.form-error {
  background: var(--accent-revoked-soft); border: 1px solid var(--accent-revoked-border);
  color: var(--accent-revoked); border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem; font-size: 0.82rem; margin-bottom: 0.9rem;
}

/* -------------------------------------------------------------------------
   14. LANDING — dark ASCII-V hero
   ------------------------------------------------------------------------- */
body.landing {
  background: var(--contrast-dark);
  background: radial-gradient(120% 120% at 50% 35%, var(--contrast-dark-soft) 0%, var(--contrast-dark-deep) 80%);
}
.hero {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1.5rem; padding: 2rem;
}
.hero pre {
  font-family: var(--font-mono); margin: 0; padding: 0; background: transparent;
  overflow: visible; white-space: pre; border: 0;
  color: var(--accent-live-bright);
  font-size: 1.15rem; line-height: 1.15rem; letter-spacing: 0.04em;
  text-shadow: 0 0 28px rgba(0, 155, 114, 0.5);
}
.hero .wordmark {
  font-family: var(--font-mono); color: #eef3f0; font-size: 1.05rem;
  letter-spacing: 0.32em; text-transform: lowercase; font-weight: 500;
  padding-left: 0.32em;
}
.hero .tagline { color: #8fa098; font-size: 0.82rem; letter-spacing: 0.02em; text-align: center; max-width: 24rem; }
.hero .cta {
  display: inline-flex; align-items: center; gap: 0.5rem; margin-top: 0.4rem;
  white-space: nowrap;
  background: var(--accent-live); color: #fff; text-decoration: none;
  font-weight: 600; font-size: 0.9rem; padding: 0.65rem 1.3rem; border-radius: var(--radius);
}
.hero .cta:hover { background: var(--accent-live-hover); }
.hero .build {
  position: fixed; bottom: 1.2rem; left: 0; right: 0; text-align: center;
  font-family: var(--font-mono); font-size: 0.72rem; color: #5d6b5b; letter-spacing: 0.04em;
}

/* -------------------------------------------------------------------------
   15. PAGE SCAFFOLD
   ------------------------------------------------------------------------- */
.page { max-width: 1440px; margin-inline: auto; padding: 1.1rem 1.5rem 3rem; }
.page-head { display: flex; align-items: baseline; gap: 0.8rem; margin-bottom: 0.9rem; }
.page-head h1 { font-size: 1.4rem; margin: 0; white-space: nowrap; }
.page-head .count { color: var(--text-muted); font-size: 0.85rem; white-space: nowrap; }

details.dropdown summary { font-size: 0.82rem; }

/* -------------------------------------------------------------------------
   16. RUN-HEALTH STRIP (Phase 0 of adaptive scraping)
   -------------------------------------------------------------------------
   Latest yield vs. baseline per parser module, with a drift indicator.
   Sits above the tool ribbon so the operator's first scan answers
   "did anything fail in the last run?" before they look at the table.
   Pure visibility — the repair loop's paired-signal threshold lives in
   the runner. */
.run-health {
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 0.55rem 0.85rem 0.7rem;
    margin-bottom: 0.85rem;
}
.run-health > .caps { display: block; margin-bottom: 0.45rem; }
.run-health-grid {
    display: flex; flex-wrap: wrap; gap: 0.4rem 1.15rem;
    align-items: center;
}
.run-health-item {
    display: inline-flex; align-items: center; gap: 0.4rem;
    font-size: 0.78rem; min-width: 0;
}
.run-health-count { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.run-health-base  { color: var(--text-muted);   font-variant-numeric: tabular-nums; }
.run-health-drift { font-size: 0.72rem; font-variant-numeric: tabular-nums; }
.run-health-drift.ok   { color: var(--text-muted); }
.run-health-drift.info { color: var(--text-muted); }
.run-health-drift.warn { color: var(--accent-revoked); }
.run-health-flag { font-size: 0.95rem; line-height: 1; }
.run-health-flag.ok   { color: var(--accent-live); }
.run-health-flag.info { color: var(--text-muted); }
.run-health-flag.warn { color: var(--accent-revoked); }
.run-health-when { white-space: nowrap; }

/* ── Scraping diagnostics page (/diagnostics) ─────────────────────────── */
.diag-wrap { max-width: 1280px; margin: 0 auto; padding: 1.2rem 1.4rem 3rem; }
.diag-head h1 { font-size: 1.5rem; margin: 0 0 0.2rem; }
.diag-sub { color: var(--text-secondary); font-size: 0.86rem; margin: 0 0 1.2rem; max-width: 70ch; }
.diag-sub a { color: var(--accent-info); }

.diag-cards { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-bottom: 1.6rem; }
.diag-card {
  display: flex; flex-direction: column; gap: 0.15rem;
  min-width: 7.5rem; padding: 0.7rem 0.9rem;
  background: var(--surface-raised); border: 1px solid var(--border); border-radius: 10px;
}
.diag-card-n { font-size: 1.5rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }
.diag-card-l { font-size: 0.72rem; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.03em; }
.diag-card-warn { border-color: var(--accent-revoked-border); background: var(--accent-revoked-soft); }
.diag-card-warn .diag-card-n { color: var(--accent-revoked); }

.diag-h2 { font-size: 1.02rem; margin: 1.8rem 0 0.4rem; }
.diag-note { color: var(--text-secondary); font-size: 0.78rem; margin: 0 0 0.6rem; max-width: 80ch; }
.diag-note code { font-size: 0.74rem; background: var(--surface-sunken); padding: 0.05rem 0.3rem; border-radius: 4px; }

.diag-table td, .diag-table th { white-space: nowrap; }
.diag-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.diag-zero, .diag-ok { color: var(--text-faint); }
.diag-ok { color: var(--text-secondary); }
.diag-frac { display: inline-flex; align-items: baseline; gap: 0.35rem; font-variant-numeric: tabular-nums; }
.diag-pct { font-size: 0.68rem; color: var(--text-faint); }
.diag-range { font-size: 0.76rem; color: var(--text-secondary); }
.diag-total-row td { border-top: 2px solid var(--border-strong); font-weight: 600; color: var(--text-secondary); }
.diag-drift-down { color: var(--accent-revoked); font-weight: 600; }
.diag-drift-up { color: var(--accent-live); font-weight: 600; }

/* Diagnostics — date-field legend + derived-column tint. */
.diag-legend {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 0.3rem 1.4rem; margin: 0 0 0.9rem; padding: 0.8rem 1rem;
  background: var(--surface-sunken); border: 1px solid var(--border); border-radius: 8px;
}
.diag-legend div { display: block; }
.diag-legend dt { font-weight: 600; font-size: 0.8rem; margin: 0; }
.diag-legend dt code { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-muted); font-weight: 400; }
.diag-legend dd { margin: 0 0 0.35rem; font-size: 0.76rem; color: var(--text-secondary); }
.diag-legend code { background: var(--surface-raised); padding: 0.02rem 0.28rem; border-radius: 4px; }
/* Derived (computed) columns get a faint tint so they read apart from raw data. */
.diag-derived-col { background: var(--accent-info-soft); }

/* Diagnostics — two-rows-per-source date table grouping. */
.diag-table tr.diag-group-start td { border-top: 1px solid var(--border-strong); }
.diag-table tr.diag-sub-row td { border-top: none; }
.diag-table tr.diag-sub-row { background: rgba(36, 35, 30, 0.015); }
.diag-table tr.diag-sub-row .diag-frac { color: var(--text-secondary); }

/* -------------------------------------------------------------------------
   Dashboard data table — fixed column budget + trailing spacer. Fixed layout
   gives every metadata column a guaranteed width (no cramping); the title is
   capped and ellipsised instead of absorbing all slack; and a zero-content
   spacer column soaks up the leftover so the real columns pack to the LEFT
   rather than leaving a giant gap mid-table on wide screens.
   ------------------------------------------------------------------------- */
table.dashboard-table { table-layout: fixed; }
table.dashboard-table [data-col="id"]      { width: 9.5rem; }
table.dashboard-table [data-col="sn"]      { width: 4.75rem; }
table.dashboard-table th[data-col="title"],
table.dashboard-table td.col-title         { width: 20rem; max-width: 20rem; }
table.dashboard-table [data-col="body"]    { width: 4.5rem; }
table.dashboard-table [data-col="kind"]    { width: 7.5rem; }
table.dashboard-table [data-col="dates"]   { width: 7.5rem; }
table.dashboard-table [data-col="changed"] { width: 11rem; }
table.dashboard-table [data-col="kma"]     { width: 4rem; }
table.dashboard-table [data-col="status"]  { width: 8rem; }
/* Trailing spacer absorbs all leftover width so columns stay packed left. */
table.dashboard-table [data-col="spacer"]  { width: auto; padding: 0; }
/* Keep the ID on one line; ellipsis the rare long ones (hover shows full). */
table.dashboard-table td[data-col="id"] { overflow: hidden; }
table.dashboard-table td[data-col="id"] .reg-id {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Date columns: keep the date and its mark (file tick / change pill) on ONE
   line so rows stay a uniform height regardless of whether a pill/clip shows. */
table.dashboard-table td[data-col="dates"],
table.dashboard-table td[data-col="changed"] { white-space: nowrap; }
table.dashboard-table td[data-col="dates"] .mono,
table.dashboard-table td[data-col="changed"] .mono { display: inline; }
table.dashboard-table td[data-col="dates"] .file-tick { margin-left: 0.25rem; vertical-align: middle; }
table.dashboard-table td[data-col="changed"] .chip-link { margin-left: 0.3rem; vertical-align: middle; }

/* Diagnostics — health alert banner. */
.diag-alerts { display: flex; flex-direction: column; gap: 0.4rem; margin: 0 0 1.4rem; }
.diag-alert {
  display: flex; align-items: center; gap: 0.55rem;
  padding: 0.5rem 0.8rem; border-radius: 8px; font-size: 0.82rem; font-weight: 500;
  border: 1px solid var(--border);
}
.diag-alert-dot { width: 8px; height: 8px; border-radius: 99px; background: currentColor; flex: none; }
.diag-alert-error { color: var(--accent-revoked); background: var(--accent-revoked-soft); border-color: var(--accent-revoked-border); }
.diag-alert-warn  { color: #9a6a1f; background: #faf0dc; border-color: #ecd9b5; }
.diag-alert-info  { color: var(--accent-info); background: var(--accent-info-soft); border-color: var(--accent-info-border); }
.diag-alert-ok    { color: var(--accent-live); background: var(--accent-live-soft); border-color: var(--accent-live-border); }

/* ─── §Chat — assistant page (streaming markdown + reg cards + modal) ─── */
body.chat-layout { height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
body.chat-layout > div[hx-history-elt] { flex: 1; min-height: 0; display: flex; }
.chat-page { flex: 1; min-height: 0; display: flex; flex-direction: column; max-width: 880px; width: 100%; margin-inline: auto; }
.chat-thread { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 1.1rem; padding: 0.5rem 0 1rem; }
.chat-empty { margin: auto; max-width: 30rem; text-align: center; color: var(--text-muted); }

.msg { display: flex; flex-direction: column; max-width: 85%; }
.msg-user { align-self: flex-end; align-items: flex-end; }
.msg-assistant { align-self: flex-start; }
.msg-body {
    padding: 0.6rem 0.85rem; border-radius: 0.9rem; line-height: 1.5;
    border: 1px solid var(--border-strong); background: var(--surface-sunken);
    overflow-wrap: anywhere;
}
.msg-user .msg-body { background: var(--accent-info-soft, #eef2ff); border-color: var(--accent-info-border, #c7d2fe); white-space: pre-wrap; }
.msg-body > :first-child { margin-top: 0; }
.msg-body > :last-child { margin-bottom: 0; }
.msg-body p { margin: 0 0 0.5rem; }
.msg-body ul, .msg-body ol { margin: 0 0 0.5rem; padding-left: 1.25rem; }
.msg-body code { font-family: var(--font-mono); font-size: 0.85em; background: rgba(0,0,0,0.05); padding: 0.05em 0.3em; border-radius: 4px; }
.msg-body pre { background: rgba(0,0,0,0.05); padding: 0.7rem; border-radius: var(--radius-sm); overflow-x: auto; }
.msg-body a { color: var(--accent-info, #4f46e5); }
.msg.streaming .msg-body::after {
    content: '▌'; margin-left: 1px; color: var(--text-muted);
    animation: chat-blink 1s steps(2) infinite;
}
@keyframes chat-blink { 50% { opacity: 0; } }

/* inline regulation reference -> clickable chip */
a.reg-ref {
    text-decoration: none; cursor: pointer; white-space: nowrap;
    font-weight: 600; color: var(--accent-info, #4f46e5);
    border-bottom: 1px dashed currentColor;
}
a.reg-ref:hover { background: var(--accent-info-soft, #eef2ff); }

/* reference card deck under an answer */
.msg-refs { margin-top: 0.7rem; }
.msg-refs-label { font-size: 0.65rem; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.4rem; }
.ref-deck { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ref-card {
    text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 0.1rem;
    padding: 0.5rem 0.7rem; max-width: 22rem;
    background: var(--surface-sunken); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
}
.ref-card:hover { border-color: var(--accent-info-border, #c7d2fe); background: var(--accent-info-soft, #eef2ff); }
.ref-card-name { font-weight: 600; font-family: var(--font-mono); font-size: 0.82rem; }
.ref-card-title { font-size: 0.74rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* input row */
.chat-input { display: flex; gap: 0.5rem; align-items: flex-end; padding: 0.6rem 0 0.2rem; border-top: 1px solid var(--border-strong); }
.chat-input textarea { flex: 1 1 auto; width: auto; resize: none; margin: 0; min-height: 40px; max-height: 160px; }
.chat-input button { flex: 0 0 auto; width: auto; margin: 0; align-self: stretch; }

/* Modals follow the Pico pattern — Pico styles the overlay, card, header,
   footer and the rel="prev" close button. We only widen the card and style
   the modal-specific content. */
dialog.modal-wide > article { max-width: min(920px, 95vw); }
dialog > article > header p { margin: 0; }
dialog > article > header .count { font-weight: 400; }
dialog > article > footer { display: flex; align-items: center; gap: 0.75rem; }
dialog > article > footer .saved { margin-right: auto; color: var(--text-muted); font-size: 0.8rem; }
dialog > article > footer button { width: auto; margin: 0; }

/* regulation-detail modal body */
#reg-modal-body { max-height: 72vh; overflow-y: auto; }
#reg-modal-body .page { max-width: none; }

/* base-prompt editor (Prompt modal) */
textarea.prompt-edit { width: 100%; min-height: 44vh; resize: vertical; margin-bottom: 0.6rem; font-family: var(--font-mono); font-size: 0.78rem; line-height: 1.5; }
.prompt-preview-wrap summary { cursor: pointer; font-size: 0.75rem; color: var(--text-muted); }
.prompt-preview-wrap .preview-body { margin-top: 0.5rem; max-height: 30vh; overflow: auto; }

/* file sync (Filer modal) */
.ai-config { display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 0.9rem; align-items: center; margin-bottom: 1rem; }
.ai-config code { font-family: var(--font-mono); font-size: 0.78rem; }
.ai-stats { display: flex; gap: 0.6rem; margin-bottom: 1rem; }
.ai-stats .stat { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; padding: 0.6rem 0.8rem; background: var(--surface-sunken); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); }
.ai-stats .stat b { font-size: 1.4rem; font-family: var(--font-mono); line-height: 1.1; }
.ai-stats .stat small { color: var(--text-muted); font-size: 0.66rem; }
.ai-sync-row { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.ai-sync-row button { width: auto; margin: 0; }
.chat-navbtns { display: flex; gap: 0.4rem; }

/* ─── §Users — admin user management ─── */
.user-create { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 1.1rem; }
.user-create input[type="text"], .user-create input[type="password"] { width: auto; flex: 1 1 11rem; margin: 0; }
.user-create button { flex: none; width: auto; margin: 0; }
.user-admin-check { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; font-size: 0.85rem; margin: 0; }
.user-table td { vertical-align: middle; }
.user-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.user-actions form { margin: 0; display: inline-flex; }
.user-actions .pw-form { gap: 0.25rem; }
.user-actions .pw-form input { width: 9rem; margin: 0; font-size: 0.78rem; padding: 0.15rem 0.45rem; }
.user-actions .danger { color: var(--accent-revoked, #b91c1c); }
.user-actions .danger:hover { background: #fdecec; border-color: #f3c0c0; }

/* ─── Dashboard per-user "mark as viewed" action ─── */
.dashboard-table th[data-col="action"], .dashboard-table td[data-col="action"] { width: 5.75rem; text-align: right; padding-right: 0.6rem; }
.row-ack-btn {
    font-size: 0.68rem; line-height: 1; white-space: nowrap; cursor: pointer;
    padding: 0.22rem 0.5rem; border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong); background: var(--surface-raised); color: var(--text-secondary);
}
.row-ack-btn:hover { background: var(--surface-sunken); color: var(--text-primary, #111); border-color: var(--accent-live, #9bbf9b); }
.row-ack-btn.undo:hover { color: var(--accent-revoked, #b91c1c); border-color: #e7b8b8; }

/* Dashboard help modal — explains inclusion and sort rules. */
#dash-help .help-h {
  font-size: 0.78rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-muted); margin: 1.1rem 0 0.4rem;
}
#dash-help .help-h:first-of-type { margin-top: 0.2rem; }
#dash-help .help-list { margin: 0; padding-left: 1.1rem; }
#dash-help .help-list li { margin-bottom: 0.45rem; line-height: 1.5; font-size: 0.86rem; }
#dash-help .help-list .chip { margin-right: 0.3rem; }

/* Recent-runs table: bind a run's error message to the run it belongs to.
   The message is its own <tr>, and with the default row border it read as a
   heading for the *next* run rather than as output from the one above. */
.run-table tr.has-error > td { border-bottom: 0; }
.run-table tr.run-error > td {
  background: var(--surface-inset);
  padding: 0.25rem 0.75rem 0.5rem 0.9rem;
  /* Accent rail down the left, continuing the run row it belongs to. */
  box-shadow: inset 3px 0 0 var(--accent-revoked);
}
.run-table tr.run-error .run-error-mark {
  color: var(--accent-revoked); opacity: 0.65;
  margin-right: 0.4rem; font-size: 0.8rem;
}
.run-table tr.run-error small {
  color: var(--accent-revoked); white-space: pre-wrap;
}

/* Provisional figures on a still-running parser run: the number is real but
   will keep climbing, so it reads a shade lighter than a settled total. */
.run-table .run-partial { color: var(--accent-live); }
