/* Obsidian: local assets, a cobalt accent, and deliberately quiet surfaces. */
@font-face{font-family:Figtree;src:url("/panel/font/figtree-latin-v1.woff2") format("woff2");font-weight:300 900;font-style:normal;font-display:optional}
@font-face{font-family:"Plex Mono";src:url("/panel/font/plex-mono-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:optional}
@font-face{font-family:"Plex Mono";src:url("/panel/font/plex-mono-600.woff2") format("woff2");font-weight:600;font-style:normal;font-display:optional}
:root, :root[data-theme="dark"] {
  color-scheme:dark;
  --paper:#08090c; --card:#101216; --sunk:#181b21;
  --side:#0b0c0f; --rule:#272c35; --rule-soft:#22262e; --edge:#727d90;
  --ink:#f3f4f7; --ink-soft:#a3acbd; --ink-faint:#939eaf;
  --accent:#9ab6ff; --accent-bg:#14213f; --action:#3564e7;
  --ok:#63d9ad; --ok-bg:#112c25; --warn:#edbd72; --warn-bg:#312619;
  --bad:#ff9289; --bad-bg:#351e23; --on-accent:#08090c;
  --scrim:rgba(0,0,0,.72); --shadow:none; --shadow-lift:0 20px 60px #0006;
  --h:220deg; --mark-s:30%; --mark-l:22%; --mark-i:82%;
  --t1:11px; --t2:12px; --t3:13px; --t4:14px; --t5:16px; --t6:22px; --t7:28px;
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px; --s8:32px; --s12:48px;
  --r1:5px; --r2:8px; --r3:13px; --r-pill:999px;
  --sans:Figtree,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
:root[data-theme="light"] {
  color-scheme:light;
  --paper:#f4f5f8; --card:#fff; --sunk:#edf0f5; --side:#fff;
  --rule:#dce0e8; --rule-soft:#e4e7ed; --edge:#7b8596;
  --ink:#1c2330; --ink-soft:#536076; --ink-faint:#5c687b;
  --accent:#264fbd; --accent-bg:#e8eefe; --action:#315bd2;
  --ok:#226240; --ok-bg:#e9f4ed; --warn:#805418; --warn-bg:#f8edda;
  --bad:#a1332e; --bad-bg:#fbe9e7; --on-accent:#fff;
  --scrim:rgba(15,23,42,.55); --shadow:none; --shadow-lift:0 20px 60px #10204025;
  --mark-s:38%; --mark-l:92%; --mark-i:28%;
}

*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);
     font:var(--t4)/1.55 var(--sans);-webkit-font-smoothing:antialiased}
/* Tabular figures are the default, not an opt-in: on this panel almost
   every number sits in a column under another number, and a proportional
   `1` made counts of the same magnitude look like different lengths. */
body{font-variant-numeric:tabular-nums}
/* Prose is the exception — a product name is not a column of figures. */
p,.prose,.ptag,.why,h2,h3{font-variant-numeric:normal}
a{color:var(--accent)}
a:hover{text-decoration:underline}
.mono{font-family:var(--mono)}
.num{font-variant-numeric:tabular-nums}
.muted{color:var(--ink-soft)}
.faint{color:var(--ink-faint)}
.ok{color:var(--ok)} .warn{color:var(--warn)} .bad{color:var(--bad)}
.r{text-align:right}
h2{font:600 var(--t6)/1.2 var(--sans);letter-spacing:-.018em;margin:0 0 var(--s1)}
h3{margin:0}

/* One focus ring, on everything, drawn outside the element so it never
   reflows a table row. There was no focus style at all: an operator
   working the queue from the keyboard could not see where they were. */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--r1)}
.skip{position:absolute;left:var(--s2);top:-64px;z-index:80;
      padding:var(--s2) var(--s3);background:var(--card);color:var(--ink);
      border:1px solid var(--edge);border-radius:var(--r2);
      font-size:var(--t4);text-decoration:none}
.skip:focus{top:var(--s2)}

/* Motion is functional only — a hover tint and a focus ring. Nothing
   enters, lifts or shimmers, so there is little to switch off; what there
   is, switches off. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{transition-duration:0s!important;animation-duration:0s!important;
                       animation-iteration-count:1!important;scroll-behavior:auto!important}
}

/* ---------- layout ---------- */
/* The rail collapses. Two different reasons at two different widths, one
   mechanism:

   On a wide display it buys 202px for a table that is scrolling inside
   its own container to fit — the rights and sources screens both do. On a
   phone the rail is not a column at all, it stacks, and it measured 433px
   tall: on an 844px screen more than half of every page load was
   navigation the operator had already read.

   So it is closed by default below 820px and open by default above, and
   whatever the operator chooses is remembered. The counts go with it when
   it closes, which is the real cost — `nav` is where the work is. That is
   why the control says "Menu" rather than showing a hamburger alone, and
   why closing is one click from anywhere rather than a preference buried
   somewhere. */
.shell{display:grid;grid-template-columns:202px minmax(0,1fr);min-height:100vh}
.shell[data-rail="closed"]{grid-template-columns:0 minmax(0,1fr)}
.shell[data-rail="closed"] .rail{display:none}
@media (max-width:820px){.shell,.shell[data-rail="closed"]{grid-template-columns:1fr}}

.rail{background:var(--sunk);border-right:1px solid var(--rule);padding:var(--s4) 0;
      position:sticky;top:0;height:100vh;overflow-y:auto;display:flex;flex-direction:column}
@media (max-width:820px){.rail{position:static;height:auto;
  border-right:0;border-bottom:1px solid var(--rule)}}

/* The lockup. The mark existed only as a 16px favicon; the rail set the
   name as plain text beside nothing at all. */
.rail-brand{display:flex;align-items:center;gap:var(--s2);
            padding:0 var(--s4) var(--s3);
            border-bottom:1px solid var(--rule-soft);margin-bottom:var(--s2)}
.rail-brand .mark{width:20px;height:20px;flex:0 0 auto;color:var(--accent)}
/* Scoped to `.wm`, not to any descendant span. `.rail-brand span` also
   matched the wrapper, so `text-transform:uppercase` inherited into the
   name and the rail read "CATALOG SCRAPER". */
.rail-brand .wm{display:flex;flex-direction:column;min-width:0}
.rail-brand .wm b{font:600 var(--t4)/1.2 var(--sans);letter-spacing:-.015em;
                  color:var(--ink)}
.rail-brand .wm .sub{font:500 var(--t1)/1.6 var(--mono);
                     color:var(--ink-faint);letter-spacing:.13em;text-transform:uppercase}
.rail a{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);
        padding:var(--s2) var(--s4);color:var(--ink-soft);text-decoration:none;
        font-size:var(--t4);border-left:2px solid transparent;
        transition:background .08s linear,color .08s linear}
.rail a:hover{color:var(--ink);background:var(--card);text-decoration:none}
.rail a:focus-visible{outline-offset:-2px;border-radius:0}
.rail a[aria-current=page]{color:var(--ink);background:var(--card);
           border-left-color:var(--accent);font-weight:600}
.rail .n{font:600 var(--t1)/1 var(--mono);padding:var(--s1) 5px;border-radius:var(--r1);
         background:var(--rule-soft);color:var(--ink-soft);font-variant-numeric:tabular-nums}
.rail a[aria-current=page] .n{background:var(--accent-bg);color:var(--accent)}
.rail .n.hot{background:var(--warn-bg);color:var(--warn)}
.rail-sep{height:1px;background:var(--rule-soft);margin:var(--s2) var(--s4)}
.rail form{padding:var(--s3) var(--s4) 0;margin-top:var(--s2);
           border-top:1px solid var(--rule-soft)}
.rail form button{width:100%}
.rail-build{font:500 var(--t1)/1 var(--mono);color:var(--ink-faint);
            padding:var(--s3) var(--s4) var(--s1);letter-spacing:.04em;margin-top:auto}

/* No page-level width cap. A `max-width` on `main` is a blunt instrument:
   it exists to stop prose running to unreadable line lengths, and it was
   doing that by also constraining six tables that have no measure problem
   at all. On a 2200px display it left 684px — nearly a third of the window
   — empty beside a rights table that was scrolling horizontally inside its
   own container to fit. Measure is a property of the content, so the prose
   below caps itself in `ch` and everything tabular takes the width it is
   given. */
main{padding:var(--s6) var(--s6) var(--s12);min-width:0}
@media (max-width:820px){main{padding:var(--s4) var(--s4) var(--s8)}}
.pagesub{color:var(--ink-soft);font-size:var(--t4);margin:0 0 var(--s5);max-width:78ch}

/* The mark's two rules, at heading scale, and a hairline that carries the
   eye across a column that is now up to 2200px wide. Same type, same
   size, same colour as before — the rules are the whole change. */
h3.sec{display:flex;align-items:center;gap:var(--s2);
       margin:var(--s6) 0 var(--s3);font:600 var(--t1)/1 var(--mono);letter-spacing:.1em;
       text-transform:uppercase;color:var(--ink-faint)}
h3.sec::before{content:"";flex:0 0 auto;width:14px;height:4px;opacity:.55;
               border-top:1px solid currentColor;border-bottom:1px solid currentColor}
h3.sec::after{content:"";flex:1 1 auto;height:1px;background:var(--rule-soft)}
h3.sec:first-of-type{margin-top:0}
.hint{color:var(--ink-soft);font-size:var(--t3);margin:calc(var(--s2) * -1) 0 var(--s2)}

/* ---------- the rail toggle ---------- */
/* First thing in `main`, so it is in the same place whether the rail is
   open or shut and the tab order reaches it before the page. */
/* 7px of vertical padding, not 5: at 5 the control measured 23px high and
   WCAG 2.2 SC 2.5.8 asks for 24. It is one pixel and it is the only new
   control on the panel, so it starts on the right side of the line. */
.railtoggle{display:inline-flex;align-items:center;gap:var(--s2);
            margin-bottom:var(--s4);padding:7px var(--s3);
            font:600 var(--t2)/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;
            color:var(--ink-soft);background:var(--card);border:1px solid var(--edge);
            border-radius:var(--r2);cursor:pointer}
.railtoggle:hover{color:var(--ink);border-color:var(--ink-faint)}
.railtoggle .bars{display:inline-flex;flex-direction:column;gap:2px;width:11px}
.railtoggle .bars i{display:block;height:1.5px;background:currentColor;border-radius:1px}
/* The middle rule is short — the mark, at control scale. */
.railtoggle .bars i:nth-child(2){width:64%}
.page-tools{display:flex;align-items:center;justify-content:space-between;gap:var(--s2)}
.theme-toggle{display:inline-flex;align-items:center;gap:var(--s2);margin-bottom:var(--s4);
  min-height:29px;padding:6px var(--s3);border:1px solid var(--edge);border-radius:var(--r-pill);
  background:var(--card);color:var(--ink-soft);cursor:pointer;font:600 var(--t2)/1 var(--sans)}
.theme-toggle:hover{color:var(--ink);border-color:var(--accent)}
.theme-toggle .theme-icon{font-size:14px;line-height:1}

/* ---------- live state: form, not a fifth hue ----------
   A dedicated live colour was measured and rejected. Cyan sits ΔE 0.035
   from the accent in OKLab and ΔE 0.003 under protanopia in dark mode —
   indistinguishable, so a running crawl would read as a hyperlink. Teal
   collides with --ok at ΔE 0.041, which would make "running" look like
   "succeeded". Four hues is this palette's capacity, so live state is a
   dot, a pulse and a word instead. */
.live{display:inline-flex;align-items:center;gap:var(--s1);
      padding:2px var(--s2) 2px 5px;border:1px solid var(--rule);border-radius:var(--r1);
      background:var(--card);font:600 var(--t1)/1.6 var(--mono);letter-spacing:.1em;
      text-transform:uppercase;color:var(--ink-soft);white-space:nowrap}
.live i{width:7px;height:7px;border-radius:50%;background:var(--ink-faint);
        flex:0 0 auto;display:block}
.live.on{color:var(--ink);border-color:var(--ink-soft)}
.live.on i{background:var(--accent);animation:beat 2s ease-in-out infinite}
@keyframes beat{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.72)}}
/* The blanket reduced-motion rule above sets animation-duration to 0s,
   which leaves the dot mid-keyframe at whatever the first frame is. Say
   what it should look like instead of relying on that. */
@media (prefers-reduced-motion: reduce){
  .live.on i{animation:none!important;opacity:1;transform:none}
}

/* ---------- the record glyph ----------
   The mark is a frame around two rules of unequal length: a record, part
   filled. Each of the four gate facts is one rule here — full width when
   the record carries it, a stub when it does not. Length is the signal,
   so it survives greyscale and every dichromacy, and it replaces four
   letters (S I D #) whose meaning lived only in a `title` tooltip — which
   a touch device never shows and `#` for "identifier" never explained.
   The legend below the table is what makes the order readable. */
.rec{display:inline-flex;align-items:center;gap:var(--s2)}
.rec .box{display:inline-flex;flex-direction:column;gap:2px;padding:3px 4px;
          border:1px solid var(--rule);border-radius:var(--r1);background:var(--card)}
.rec .box i{display:block;width:12px;height:2px;border-radius:1px;
            background:var(--ink-soft)}
.rec .box i.n{width:5px;background:var(--rule)}
.rec .lab{font:600 var(--t2)/1 var(--mono);color:var(--ink-soft)}
.rec.part .box{border-color:var(--bad)}
/* Full strength, not a dimmed one. The stub is 5x2px and it is the thing
   that says which fact is missing, so 1.4.11 governs it; `--bad` on
   `--card` is in the tested matrix and an opacity is not. */
.rec.part .box i.n{background:var(--bad)}
.rec.part .lab{color:var(--bad)}
.reclegend{display:flex;gap:var(--s3);flex-wrap:wrap;margin:var(--s2) 0 0;
           font:500 var(--t2)/1.4 var(--mono);color:var(--ink-faint)}
.reclegend b{color:var(--ink-soft);font-weight:600}

/* ---------- the answer bar: a sentence before the numbers ---------- */
/* `[hidden]` has to beat the class, or the element is drawn anyway — the
   review dialog was displayed permanently for exactly this reason. */
.answer[hidden]{display:none}
.answer{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
        padding:var(--s3) var(--s4);border-radius:var(--r3);margin-bottom:var(--s5);
        border:1px solid var(--rule);background:var(--sunk)}
.answer.good{border-left:3px solid var(--ok)}
.answer.warn{border-left:3px solid var(--warn)}
.answer.bad{border-left:3px solid var(--bad)}
.answer .big{font:600 var(--t6)/1.2 var(--sans);letter-spacing:-.018em}
.answer .why{font-size:var(--t4);color:var(--ink-soft);max-width:74ch}
.answer .why b{color:var(--ink);font-weight:600}
.answer .grow{flex:1 1 340px}

/* ---------- metrics ---------- */
.metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:var(--s2)}
.metric{border:1px solid var(--rule);border-radius:var(--r2);padding:var(--s3);
        background:var(--card)}
.metric .k{font:600 var(--t1)/1.3 var(--mono);letter-spacing:.1em;text-transform:uppercase;
           color:var(--ink-faint);margin-bottom:var(--s2)}
.metric .v{font:600 var(--t7)/1 var(--sans);letter-spacing:-.02em}
.metric .d{font-size:var(--t2);color:var(--ink-faint);margin-top:var(--s1)}
.metric.acc .v{color:var(--accent)} .metric.ok .v{color:var(--ok)}
.metric.warn .v{color:var(--warn)} .metric.bad .v{color:var(--bad)}
/* "review a sample →" is the only control on a metric tile and measured
   13px tall. Inline-flex to a 24px box; the type stays at t2. */
.metric a{font-size:var(--t2);display:inline-flex;align-items:center;min-height:24px}

/* ---------- controls ---------- */
.toolbar{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-bottom:var(--s3)}
.toolbar-label{font:600 var(--t1)/1 var(--mono);letter-spacing:.1em;color:var(--ink-faint);
               text-transform:uppercase}
.seg{display:flex;border:1px solid var(--edge);border-radius:var(--r2);overflow:hidden}
.seg a{padding:5px var(--s3);font-size:var(--t3);color:var(--ink-soft);text-decoration:none;
       border-right:1px solid var(--rule);transition:background .08s linear}
.seg a:last-child{border-right:0}
.seg a:hover{background:var(--sunk);color:var(--ink);text-decoration:none}
.seg a:focus-visible{outline-offset:-2px;border-radius:0}
.seg a[aria-current]{background:var(--accent-bg);color:var(--accent);font-weight:600}
.seg a .n{font-family:var(--mono);font-size:var(--t2)}
.chip{display:inline-flex;align-items:center;gap:var(--s1);
      padding:var(--s1) var(--s2);border:1px solid var(--edge);border-radius:var(--r-pill);
      font-size:var(--t3);color:var(--ink-soft);background:var(--card);
      text-decoration:none;white-space:nowrap;transition:background .08s linear}
.chip:hover{background:var(--sunk);color:var(--ink);text-decoration:none}
.chip[aria-current]{border-color:var(--accent);color:var(--accent);
                    background:var(--accent-bg);font-weight:600}

/* Company facts, and the tier each came from.

   The tier is colour-coded because it is the column the eye should land
   on: `site` is ours and free, `registry` is CC0, `licensed` costs a
   licence whose redistribution terms are still open. Colour carries
   meaning here rather than decorating — it is the difference between a
   fact we own and one we rent, which is the whole reason this data moved
   into this service.

   Never colour alone: each chip states its tier in words, so the
   distinction survives a monochrome print and any colour vision. */
.chip.tier-site{border-color:var(--ok);color:var(--ok);background:var(--ok-bg)}
.chip.tier-registry{border-color:var(--accent);color:var(--accent);background:var(--accent-bg)}
.chip.tier-licensed{border-color:var(--warn);color:var(--warn);background:var(--warn-bg)}
.chip.st-approved{border-color:var(--ok);color:var(--ok);background:var(--ok-bg)}
.chip.st-pending{border-color:var(--warn);color:var(--warn);background:var(--warn-bg)}
.chip.st-rejected{border-color:var(--bad);color:var(--bad);background:var(--bad-bg)}

/* The fact list hangs under its company row rather than opening in a
   modal: an operator deciding whether to approve a record is deciding
   about the facts, and a decision that needs a second click to see what
   it is about gets made without looking. */
.empty{padding:var(--s5);border:1px dashed var(--edge);border-radius:var(--r2);
       color:var(--ink-soft);background:var(--sunk)}
/* Seven screens use `.pager` and FIVE carried their own copy of it —
   catalog, logs, runs and rejected identical, and review's drifted onto
   raw rems (.75rem/1rem/.85rem) where the scale at the top of this file
   says a size that is not on the list is a decision nobody made. Adding a
   seventh consumer is what surfaced it, via
   `test_no_class_is_claimed_twice_on_one_page`. One definition, here,
   which is where a class used by more than one screen belongs. Review's
   pager moves onto the token scale as a result — the only visual change. */
.pager{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s4);
       font-size:var(--t3);color:var(--ink-soft);flex-wrap:wrap}
.chip .n{font-family:var(--mono);font-size:var(--t2);color:var(--ink-faint)}
.chip[aria-current] .n{color:var(--accent)}
/* A chip with nothing behind it — a gap filter at zero, the far end of the
   pager. Defined once here; the catalogue, the review queue and the run log
   each had their own copy, and two of them disagreed on the opacity.

   It is not `opacity` any more. At .5 the text composited to 2.16:1 and at
   .45 to 1.98:1, with the count worse than the label — and these carry a
   fact. "images 0" is the answer to "is anything missing an image?", and
   the template's own note says a page boundary is a fact rather than a
   missing control. A fact you cannot read is not one. The token-based
   contrast test cannot see this: it reads hex out of `:root`, and a state
   produced by compositing has no hex to read.

   `--ink-faint` on `--sunk` is in that matrix and passes. Unavailable is
   carried by the dashed edge and the sunk ground instead. */
.chip.is-off{color:var(--ink-faint);background:var(--sunk);
             border-style:dashed;border-color:var(--rule);cursor:default}
.chip.is-off .n{color:var(--ink-faint)}

button,input,select,textarea{font:inherit;font-size:var(--t3);color:var(--ink);
  background:var(--card);border:1px solid var(--edge);border-radius:var(--r2);
  padding:5px var(--s2);transition:border-color .08s linear,background .08s linear}
textarea{font-family:var(--mono);font-size:var(--t3);line-height:1.5;padding:var(--s2)}
button{cursor:pointer;font-weight:600}
button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
button:active:not(:disabled){background:var(--sunk)}
button.primary{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
button.primary:hover:not(:disabled){filter:brightness(1.1);color:var(--on-accent)}
button.ghost{background:none;border-color:transparent;color:var(--ink-soft);font-weight:500}
button.ghost:hover:not(:disabled){color:var(--ink);background:var(--sunk);
                                  border-color:var(--rule)}
/* Disabled has to read as "not now", not as "broken": the htmx subset
   disables a submit for the length of the request, and a control that
   merely faded out looked like the click had failed. */
button:disabled,input:disabled,select:disabled,textarea:disabled{
  cursor:not-allowed;opacity:.55;border-color:var(--rule);
  background:var(--sunk);color:var(--ink-soft)}
button.primary:disabled{background:var(--rule);border-color:var(--rule);color:var(--ink-soft)}
/* In flight, the label stays put and the control says so — a spinner that
   replaced the label made the button change width mid-queue. */
button[aria-busy=true]::after{content:"·";margin-left:var(--s1);font-weight:700}
input:hover:not(:disabled),select:hover:not(:disabled),textarea:hover:not(:disabled){
  border-color:var(--ink-faint)}
input::placeholder,textarea::placeholder{color:var(--ink-faint);opacity:1}
input[type=checkbox]{width:15px;height:15px;padding:0;accent-color:var(--accent);
                     vertical-align:middle;cursor:pointer}
label{font-size:var(--t3);color:var(--ink-soft)}
form.inline{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
         clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- pills ---------- */
.pill{display:inline-flex;align-items:center;gap:var(--s1);padding:2px 6px;
      border-radius:var(--r1);font:600 var(--t1)/1.6 var(--mono);
      border:1px solid var(--rule);color:var(--ink-soft);background:var(--card);
      white-space:nowrap}
.pill.ok{color:var(--ok);border-color:var(--ok);background:var(--ok-bg)}
.pill.warn{color:var(--warn);border-color:var(--warn);background:var(--warn-bg)}
.pill.bad{color:var(--bad);border-color:var(--bad);background:var(--bad-bg)}
.pill.acc{color:var(--accent);border-color:var(--accent);background:var(--accent-bg)}

/* ---------- tables ---------- */
/* `contain:paint` is doing real work here, not tidiness. A wide table
   inside `overflow-x:auto` still pushed the *document's* scroll width out
   — 23px on the rights screen at 390px — so the whole page slid sideways
   under a thumb while the table it belonged to had a scrollbar of its own.
   Declaring that this box paints nothing outside itself is what confines
   the scrolling to the table. */
.scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;contain:paint;
        border:1px solid var(--rule);border-radius:var(--r3)}
table{width:100%;border-collapse:collapse;font-size:var(--t3)}
thead th{text-align:left;padding:var(--s2) var(--s3);font:600 var(--t1)/1.3 var(--mono);
         letter-spacing:.1em;text-transform:uppercase;color:var(--ink-faint);
         background:var(--sunk);border-bottom:1px solid var(--rule);white-space:nowrap}
tbody td{padding:var(--s2) var(--s3);border-bottom:1px solid var(--rule-soft);
         vertical-align:middle}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover{background:var(--sunk)}
tr.grp td,tr.grp:hover td{background:var(--sunk);font:600 var(--t1)/1.3 var(--mono);
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink-soft);
  padding:5px var(--s3)}
/* A table cell holding nothing to say says so once, centred on its own
   row, rather than leaving an operator to wonder whether it is loading. */
td.empty{padding:var(--s6) var(--s3);text-align:center;color:var(--ink-soft)}

/* ---------- product cell ---------- */
.pcell{display:flex;align-items:center;gap:var(--s3);text-decoration:none;color:inherit}
.pcell:hover{text-decoration:none}
.pcell:hover .pname{color:var(--accent);text-decoration:underline}
.thumb{width:44px;height:44px;flex:0 0 auto;border:1px solid var(--rule);
       border-radius:var(--r1);background:var(--sunk);display:grid;place-items:center;
       overflow:hidden}
/* Intrinsic size on every thumbnail: without it the row height is unknown
   until the bytes land, and a 50-row queue reflowed under the pointer
   every time one arrived. */
.thumb img{width:100%;height:100%;object-fit:contain;aspect-ratio:1}
.thumb .ph{font:600 var(--t1)/1 var(--mono);color:var(--ink-faint)}
/* No picture, and why. Three states from `partials/noimage.html`: the
   vendor published none (brand mark — never a fact, so it borrows the
   mark tokens and not the semantic colours), a real candidate was never
   archived (warn tone: the one state a Re-fetch repairs), or nothing is
   archived to say. The logo sits over the monogram so a blocked or dead
   image degrades to letters, never to a broken-image icon. */
.noimage{display:grid;place-items:center;width:100%;height:100%;
         font:600 var(--t1)/1 var(--mono);color:var(--ink-faint)}
.noimage.vendor{position:relative;overflow:hidden;
  background:hsl(var(--h) var(--mark-s) var(--mark-l));color:hsl(var(--h) 42% var(--mark-i))}
.noimage.vendor .logo{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;background:#fff;padding:4px}
.noimage.fetch{grid-auto-flow:row;align-content:center;gap:2px;
  background:var(--warn-bg);color:var(--warn)}
.noimage.fetch svg{width:16px;height:16px}
/* Seven hues for a brand mark, far enough apart to be nameable. Chosen by
   `view.hue(slug)` — `sum(bytes) % 7`, never `hash()`, which Python salts
   per process and would recolour every brand on every worker. */
.h0{--h:18deg} .h1{--h:96deg} .h2{--h:150deg} .h3{--h:205deg}
.h4{--h:255deg} .h5{--h:290deg} .h6{--h:340deg}
.pname{display:block;font:600 var(--t3)/1.35 var(--mono);letter-spacing:-.01em}
.ptag{display:block;font-size:var(--t2);color:var(--ink-soft);line-height:1.4;max-width:52ch}
.sku{display:inline-block;font-size:var(--t1);color:var(--ink-faint);font-family:var(--mono);
     border:1px solid var(--rule);border-radius:var(--r1);padding:0 var(--s1);margin:1px 0}

/* ---------- completeness glyph: four facts, one scan ---------- */
/* `.cmp` — the four lettered boxes — is gone; `.rec` above replaced it on
   all four screens that drew it. Nothing else referenced these rules. */

/* ---------- confidence with its cause ---------- */
.conf{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.gauge{width:44px;height:4px;border-radius:var(--r1);background:var(--rule);
       overflow:hidden;flex:0 0 auto}
.gauge i{display:block;height:100%}
.gauge i.t-ok{background:var(--ok)}
.gauge i.t-warn{background:var(--warn)}
.gauge i.t-bad{background:var(--bad)}
.gauge i.t-acc{background:var(--accent)}
.conf .val{font:600 var(--t2)/1 var(--mono)}
/* On its own line under the reading rather than in the sliver beside it:
   "generic adapter caps confidence at 0.70" set four lines deep in a
   hundred-pixel gap, and a row three times its own height for a hint. */
.cause{flex:1 0 100%;font-size:var(--t2);color:var(--ink-soft);line-height:1.4}

/* A bar is 44px wide, so a width carried to the percent would render
   differences no display can show. Quantising to 4% keeps every varying
   length in the stylesheet, where the Content-Security-Policy can reach
   it, instead of in a `style` attribute, where it cannot. */
.w0{width:0} .w4{width:4%} .w8{width:8%} .w12{width:12%} .w16{width:16%}
.w20{width:20%} .w24{width:24%} .w28{width:28%} .w32{width:32%} .w36{width:36%}
.w40{width:40%} .w44{width:44%} .w48{width:48%} .w52{width:52%} .w56{width:56%}
.w60{width:60%} .w64{width:64%} .w68{width:68%} .w72{width:72%} .w76{width:76%}
.w80{width:80%} .w84{width:84%} .w88{width:88%} .w92{width:92%} .w96{width:96%}
.w100{width:100%}

/* ---------- notes ---------- */
.note{border-left:3px solid var(--warn);background:var(--warn-bg);
      border-radius:0 var(--r2) var(--r2) 0;padding:var(--s3);font-size:var(--t3);
      color:var(--ink-soft);margin:var(--s3) 0}
/* The box spans the column; the sentence inside it does not. */
.note>*,.note{max-width:96ch}
.note b,.note strong{color:var(--ink)}
.note.acc{border-left-color:var(--accent);background:var(--accent-bg)}
.note.okn{border-left-color:var(--ok);background:var(--ok-bg)}
/* Used by the discontinued banner: the note default is amber, and a
   product the vendor has withdrawn is not a caution about our data. */
.note.bad{border-left-color:var(--bad);background:var(--bad-bg)}
.note code{font-family:var(--mono);font-size:var(--t2)}
.note p{margin:var(--s2) 0 0}
.note p:first-child{margin-top:0}

/* ---------- flash: one shape for every route that answers in place ------
   Approve, save, arm and re-scrape all reply with a fragment that lands
   in a table cell or a strip beside a button. They used to be hand-built
   HTML strings, so each one styled itself differently and none of them
   escaped what it interpolated. */
.flash{display:inline-flex;align-items:flex-start;gap:var(--s2);
       font-size:var(--t3);line-height:1.45}
.flash .mark{flex:0 0 auto;font:700 var(--t2)/1.5 var(--mono)}
.flash.ok{color:var(--ok)} .flash.warn{color:var(--warn)}
.flash.bad{color:var(--bad)} .flash.info{color:var(--ink-soft)}
.flash ul{margin:var(--s1) 0 0;padding-left:var(--s4);color:var(--ink-soft)}
.flash li{font-family:var(--mono);font-size:var(--t2);line-height:1.5;
          word-break:break-all}
.flash .more{color:var(--ink-faint);font-size:var(--t2)}

/* ---------- bulk bar ---------- */
.bulk{display:none;align-items:center;gap:var(--s3);flex-wrap:wrap;
      padding:var(--s2) var(--s3);border:1px solid var(--accent);
      background:var(--accent-bg);border-radius:var(--r2);margin-bottom:var(--s3);
      position:sticky;top:var(--s2);z-index:20;box-shadow:var(--shadow)}
.bulk.on{display:flex}
.bulk .cnt{font:600 var(--t3)/1 var(--mono);color:var(--accent)}
.bulk .divider{width:1px;height:16px;background:var(--accent);opacity:.4}
.bulk .push{margin-left:auto}

.login{max-width:360px;margin:12vh auto}
.login h2{margin-bottom:var(--s2)}
.login form{margin-top:var(--s4)}
.login label{display:block;margin-bottom:var(--s1)}
.login input{width:100%;font-size:var(--t4);padding:var(--s2)}
.login button{width:100%;margin-top:var(--s4);padding:var(--s2);font-size:var(--t4)}
/* Product workspace shell and shared interaction language. */

body{line-height:1.5}.shell{grid-template-columns:240px minmax(0,1fr);transition:grid-template-columns .16s ease}
.rail{padding:20px 14px;background:var(--card);box-shadow:1px 0 0 var(--rule);overflow:auto}
.rail-brand{padding:0 8px 22px;margin-bottom:10px;border-bottom:0;gap:11px}
.rail-brand .mark{width:34px;height:34px;padding:7px;border-radius:10px;color:#fff;
  background:transparent}
.rail-brand .wm b{font-size:15px}.rail-brand .wm .sub{font-family:var(--sans);
  letter-spacing:0;text-transform:none;font-size:11px;margin-top:2px}
.rail a{min-height:39px;padding:9px 10px;border-left:0;border-radius:9px;font-weight:500;gap:10px}
.rail a .nav-icon{width:18px;height:18px;display:grid;place-items:center;color:var(--ink-faint);flex:0 0 auto}
.rail a .nav-icon svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.rail a .nav-label{min-width:0;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.rail a[aria-current=page] .nav-icon{color:var(--accent)}
.nav-group{margin:18px 10px 6px;color:var(--ink-faint);font:700 10px/1 var(--sans);letter-spacing:.11em;text-transform:uppercase}
.rail a[aria-current=page]{background:var(--accent-bg);color:var(--accent);font-weight:650}
.rail a[aria-current=page]::before{content:"";width:4px;height:18px;border-radius:4px;
  background:var(--accent);margin-left:-10px}
.rail .n{border-radius:999px;padding:3px 7px;font-family:var(--sans)}
.rail-sep{margin:10px 8px}.rail form{margin-top:10px;padding:14px 8px 0}
.shell[data-rail="closed"]{grid-template-columns:72px minmax(0,1fr)}
.shell[data-rail="closed"] .rail{display:flex;padding-inline:10px;overflow-x:hidden}
.shell[data-rail="closed"] .rail-brand{justify-content:center;padding-inline:0}
.shell[data-rail="closed"] .rail-brand .wm,
.shell[data-rail="closed"] .nav-label,
.shell[data-rail="closed"] .nav-group,
.shell[data-rail="closed"] .rail .n,
.shell[data-rail="closed"] .rail form,
.shell[data-rail="closed"] .rail-build{display:none}
.shell[data-rail="closed"] .rail a{justify-content:center;padding-inline:10px}
.shell[data-rail="closed"] .rail a[aria-current=page]::before{position:absolute;left:0;margin:0}
.shell[data-rail="closed"] .rail a{position:relative}
main{padding:26px 30px 80px;max-width:1680px;width:100%;margin:0 auto}
h2{font-size:26px;letter-spacing:-.03em;margin-bottom:4px}.pagesub{font-size:14px;margin-bottom:22px}
.page-tools{height:36px;margin-bottom:16px}.railtoggle,.theme-toggle{margin:0;min-height:34px;
  border-radius:999px;text-transform:none;letter-spacing:0;font-family:var(--sans);font-size:12px;padding:7px 11px}
.toolbar{padding:13px 14px;background:var(--card);border:1px solid var(--rule);
  border-radius:12px;margin-bottom:10px;box-shadow:var(--shadow)}
.toolbar-label{font-family:var(--sans);font-size:11px;font-weight:700;letter-spacing:.07em}
.chip{min-height:30px;padding:5px 10px;border-radius:999px;font-family:var(--sans)}
button,input,select,textarea{min-height:34px;padding:7px 10px;border-radius:8px}
button.primary{background:var(--action);border-color:var(--action);color:#fff;box-shadow:none}
.pill{padding:4px 8px;border:0;border-radius:7px;font-family:var(--sans);font-size:11px}
.scroll{border-radius:12px;background:var(--card);box-shadow:var(--shadow)}
table{font-size:13px}thead th{height:40px;padding:8px 12px;font-family:var(--sans);font-size:10px}
tbody td{padding:10px 12px}.thumb{width:48px;height:48px;border-radius:8px}
.pname{font-family:var(--sans);font-size:13px}.ptag{font-size:12px}
.metric{border-radius:12px!important;padding:16px!important;background:var(--card)!important;
  box-shadow:var(--shadow);border-color:var(--rule)!important}
.metric .v{font-size:26px!important}.metric .k{font-family:var(--sans)!important;font-size:12px!important}
.answer{border-radius:12px!important;padding:16px 18px!important;box-shadow:var(--shadow)}
h3.sec{margin-top:30px;font-family:var(--sans);font-size:12px;letter-spacing:.06em}
.bulk{position:fixed;left:calc(240px + 30px);right:30px;top:auto;bottom:22px;
  max-width:1370px;margin:auto;padding:12px 14px 12px 18px;border:0;border-radius:13px;
  color:#fff;background:#172033;box-shadow:0 16px 50px rgba(0,0,0,.3)}
:root[data-theme="dark"] .bulk{background:#eef2ff;color:#172033}
.shell[data-rail="closed"] .bulk{left:102px}
.bulk .cnt{color:inherit;font-family:var(--sans);font-size:14px}.bulk .divider{opacity:.25}
.bulk button:not(.primary),.bulk input{border-color:#64748b;background:transparent;color:inherit}
.bulk button.primary{background:#16a34a;border-color:#16a34a;color:#fff}
.page-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:22px}
.page-heading h2,.page-heading .pagesub{margin-bottom:0}.page-heading-copy{min-width:0}
.page-heading-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.kpi-grid{display:grid;grid-template-columns:repeat(4,minmax(150px,1fr));gap:12px;margin-bottom:16px}
.kpi-card{position:relative;min-height:112px;padding:17px 18px;background:var(--card);border:1px solid var(--rule);border-radius:14px;box-shadow:var(--shadow);overflow:hidden}
.kpi-card::after{display:none;content:"";position:absolute;inset:auto -24px -32px auto;width:90px;height:90px;border-radius:50%;background:var(--accent-bg)}
.kpi-label{display:block;color:var(--ink-soft);font-size:12px;font-weight:650}.kpi-value{display:block;margin:7px 0 2px;font-size:27px;line-height:1;font-weight:750;letter-spacing:-.04em}.kpi-help{color:var(--ink-faint);font-size:11px}
.notice{display:grid;grid-template-columns:38px minmax(0,1fr) auto;align-items:center;gap:12px;padding:14px 16px;margin-bottom:14px;background:var(--card);border:1px solid var(--rule);border-left:4px solid var(--accent);border-radius:12px;box-shadow:var(--shadow)}
.notice-icon{width:34px;height:34px;display:grid;place-items:center;border-radius:9px;background:var(--accent-bg);color:var(--accent);font-weight:800}.notice-title{display:block;font-size:14px;font-weight:700}.notice-copy{display:block;color:var(--ink-soft);font-size:12px}.notice-actions{display:flex;gap:8px}.notice.warn{border-left-color:var(--warn)}.notice.warn .notice-icon{background:var(--warn-bg);color:var(--warn)}.notice.bad{border-left-color:var(--bad)}.notice.bad .notice-icon{background:var(--bad-bg);color:var(--bad)}.notice.good{border-left-color:var(--ok)}.notice.good .notice-icon{background:var(--ok-bg);color:var(--ok)}
.empty-state{display:grid;place-items:center;text-align:center;min-height:230px;padding:38px;border:1px dashed var(--rule);border-radius:14px;background:var(--card)}.empty-state-icon{width:48px;height:48px;display:grid;place-items:center;margin-bottom:12px;border-radius:14px;background:var(--accent-bg);color:var(--accent);font-size:22px}.empty-state h3{font-size:17px;margin:0 0 5px}.empty-state p{max-width:520px;color:var(--ink-soft);margin:0 0 15px}
.data-card{background:var(--card);border:1px solid var(--rule);border-radius:14px;box-shadow:var(--shadow);overflow:hidden}.data-card-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid var(--rule)}
.toast-stack{position:fixed;right:24px;top:24px;z-index:1000;display:grid;gap:10px;width:min(380px,calc(100vw - 32px))}
@media(max-width:820px){
  /* Keep this selector at the same specificity as the closed desktop
     state above. Without it, the zero-width rail column survives on a
     phone and squeezes main down to its min-content width. */
  .shell,.shell[data-rail="closed"]{grid-template-columns:minmax(0,1fr)}
  .shell[data-rail="closed"] .rail{display:none}.rail{box-shadow:none}.bulk,.shell[data-rail="closed"] .bulk{left:14px;right:14px}
  main{width:auto;max-width:none;margin:0;padding:18px 16px 64px}
}
@media(max-width:900px){.kpi-grid{grid-template-columns:repeat(2,1fr)}.page-heading{align-items:flex-start;flex-direction:column}.notice{grid-template-columns:38px minmax(0,1fr)}.notice-actions{grid-column:2}}
@media(max-width:520px){.kpi-grid{grid-template-columns:1fr 1fr}.kpi-card{min-height:98px;padding:14px}.notice{grid-template-columns:1fr}.notice-icon,.notice-actions{grid-column:1}}

.section-heading{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:28px 0 14px}
.section-heading h3,.seller-source h4,.seller-collect h3{margin:0;font-family:var(--sans)}
.overview-diagnostics{margin-top:28px}.overview-diagnostics>summary{padding:18px 0;border-top:1px solid var(--rule);cursor:pointer;font-weight:600;color:var(--ink-soft)}
.overview-queues{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.overview-queue{position:relative;display:grid;grid-template-columns:1fr auto;gap:12px;padding:22px;border:1px solid var(--rule);border-radius:14px;background:var(--card);text-decoration:none;color:var(--ink)}
.overview-queue:hover{border-color:var(--accent)}
.overview-queue>span{font-weight:600;font-size:14px}.overview-queue>strong{font-size:26px;line-height:1}
.overview-queue>p{grid-column:1/-1;margin:0;color:var(--ink-soft);font-size:13px;line-height:1.5;padding-right:20px}
.overview-queue>b{position:absolute;bottom:18px;right:20px;color:var(--ink-soft)}
.overview-queue.ready{border-color:var(--accent);background:var(--accent-bg)}
.seller-collect{padding:24px}.seller-collect form{max-width:900px}.seller-collect label{display:block;margin:18px 0 8px;font-weight:600}
.seller-url-row{display:flex;gap:12px}.seller-url-row input{flex:1;min-width:0}
.seller-source-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.seller-source{padding:20px;min-width:0}.seller-source p{overflow-wrap:anywhere}.seller-source-heading{display:flex;justify-content:space-between;align-items:center;gap:12px}
.seller-source-metrics{display:flex;gap:24px;margin:18px 0;color:var(--ink-soft);font-size:12px}.seller-source-metrics b{display:block;font-size:22px;color:var(--ink);margin-bottom:4px}
.seller-source details{border-top:1px solid var(--rule);padding-top:12px}.seller-source summary{cursor:pointer;color:var(--ink-soft);font-size:12px}
.product-editor{border:1px solid var(--rule);border-radius:12px;padding:16px;margin:18px 0;background:var(--card)}
.product-editor summary{cursor:pointer;font-weight:650;color:var(--accent)}
.editor-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:16px 0}
.editor-fields label{display:flex;flex-direction:column;gap:7px;font-size:13px;font-weight:600;min-width:0}
.editor-fields input,.editor-fields textarea{width:100%;min-width:0;box-sizing:border-box;font:inherit}
.editor-fields textarea{resize:vertical}.editor-wide{grid-column:1/-1}.editor-fields small{color:var(--ink-soft);font-weight:400}
.editor-learning{display:flex;gap:10px;align-items:flex-start;font-size:13px}.editor-learning input{flex:none;margin-top:3px}
.edit-success{color:var(--ok)}.correction-history{margin:12px 0;color:var(--ink-soft)}.correction-history summary{cursor:pointer;font-size:12px}
@media(max-width:1100px){.overview-queues,.seller-source-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:640px){.overview-queues,.seller-source-grid,.editor-fields{grid-template-columns:1fr}.seller-url-row{flex-direction:column}.seller-collect{padding:18px}.section-heading{align-items:flex-start}.overview-queue{padding:18px}}

/* Shared Obsidian shell. Keep the existing form, table and review contracts. */
.shell{grid-template-columns:220px minmax(0,1fr);transition:none}
.rail{background:var(--side);box-shadow:none;padding:24px 13px 16px}
.rail-brand{gap:11px;padding:0 10px 20px;margin-bottom:5px}
.rail-brand .mark{width:34px;height:34px;padding:0;border-radius:0}
.rail-brand .wm b{font-size:27px;font-weight:650;line-height:1;letter-spacing:-1px}
.rail-brand .wm .sub{font-size:11px;margin-top:6px}
.rail a{min-height:36px;padding:8px 10px;font-size:13px;border-radius:8px}
.rail a[aria-current=page]{box-shadow:inset 0 0 0 1px #3f72ff26}
.rail .n{border-radius:5px;font-size:10px;padding:3px 6px}
.nav-group{font-weight:500;letter-spacing:1.5px;margin-top:22px;font-size:9px}
.rail-build{font-size:10px;padding:16px 8px 0}
main{max-width:none;padding:0 30px 50px}
.page-tools{min-height:68px;height:auto;margin:0 -30px 26px;padding:13px 30px;border-bottom:1px solid var(--rule);gap:16px}
.railtoggle,.theme-toggle{border-radius:7px;border-color:var(--rule);background:transparent;white-space:nowrap}
.panel-breadcrumb{display:flex;align-items:center;gap:12px;color:var(--ink-soft);font-size:12px;min-width:0}
.panel-breadcrumb b{color:var(--ink);font-weight:500;white-space:nowrap}
.panel-search{margin-left:auto;display:flex;align-items:center;gap:8px;min-width:0;width:245px;background:var(--card);border:1px solid var(--edge);border-radius:8px;padding:0 9px}
.panel-search svg{width:15px;height:15px;fill:none;stroke:var(--ink-soft);stroke-width:1.6;flex-shrink:0}
.panel-search input{width:100%;min-width:0;min-height:34px;padding:6px 0;border:0;background:transparent;box-shadow:none;font-size:12px}
.panel-search button{border:0;background:none;color:var(--ink-soft);padding:3px;min-height:28px}
.panel-search input:focus{outline:0}.panel-search:focus-within{outline:2px solid var(--accent);outline-offset:2px}
.page-heading{align-items:center;margin-bottom:22px}.page-heading h2{font-size:30px;font-weight:600;letter-spacing:-1px}
.pagesub{margin-top:8px;font-size:13px}.page-heading .pagesub{margin-top:8px}
button.primary:hover:not(:disabled){color:#fff;filter:brightness(1.07)}
.kpi-card{min-height:105px;border-radius:12px}.kpi-value{font-weight:550;font-size:30px}.kpi-help{color:var(--ink-soft)}
.bulk{left:250px;border:1px solid var(--edge);background:var(--card);color:var(--ink)}
:root[data-theme="dark"] .bulk{background:var(--card);color:var(--ink)}
.bulk button.primary{background:var(--action);border-color:var(--action)}
.chip,.pill{border-radius:7px}.scroll,.data-card{box-shadow:none;border-radius:13px}
.answer{padding:13px 17px!important;background:var(--card);box-shadow:none}
.answer .big{font-size:16px}.answer .why{font-size:12px;max-width:100ch}
.obsidian-eyebrow{font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--ink-soft);margin-bottom:9px}
.obsidian-primary{display:inline-flex;justify-content:center;align-items:center;gap:16px;padding:10px 14px;border:1px solid var(--action);border-radius:8px;background:var(--action);color:#fff;font-size:12px;font-weight:600;text-decoration:none}
.obsidian-primary:hover{color:#fff;filter:brightness(1.1);text-decoration:none}
.obsidian-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin:20px 0}
.obsidian-stat{padding:18px 20px;background:var(--card);border:1px solid var(--rule);border-radius:12px;color:var(--ink);text-decoration:none;min-width:0}
.obsidian-stat:hover{text-decoration:none;border-color:var(--accent)}
.obsidian-stat>span{display:block;font-size:12px;color:var(--ink-soft)}
.obsidian-stat strong{display:block;font-size:34px;font-weight:500;line-height:1.2;letter-spacing:-1px;margin:10px 0}
.obsidian-stat em{font-size:22px;font-style:normal}.obsidian-stat small{display:block;font-size:11px;color:var(--ink-soft)}
.obsidian-overview-grid{display:grid;grid-template-columns:minmax(0,1fr) 310px;gap:20px}
.obsidian-panel{min-width:0;overflow:hidden;background:var(--card);border:1px solid var(--rule);border-radius:13px}
.obsidian-panel-head{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:20px 22px}
.obsidian-panel-head h3{font-size:17px;font-weight:600;letter-spacing:-.3px}
.obsidian-panel-head p{font-size:12px;color:var(--ink-soft);margin:5px 0 0}
.obsidian-panel-head .chip{font-size:11px;white-space:nowrap}
.obsidian-panel-foot{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;padding:13px 22px;border-top:1px solid var(--rule);font-size:10px;color:var(--ink-soft)}
.obsidian-heat-scroll{overflow:auto;max-width:100%;padding:0 16px 12px}
.obsidian-heatmap{table-layout:auto;min-width:640px;width:100%;border-collapse:separate;border-spacing:4px}
.obsidian-heatmap thead th{border:0;background:transparent;height:30px;padding:3px 0 8px;text-transform:none;letter-spacing:0;font-size:10px;font-weight:400;white-space:nowrap}
.obsidian-heatmap td,.obsidian-heatmap tbody th{border:0;padding:0;background:transparent!important;font-size:11px;white-space:nowrap}
.obsidian-heatmap tbody th{font-weight:500;min-width:110px;text-align:left;padding-right:6px}
.obsidian-heatmap td:last-child{padding-left:8px}.obsidian-heatmap tbody tr:hover{background:transparent}
.obsidian-brand{display:flex;align-items:center;gap:9px;color:var(--ink);text-decoration:none;text-transform:capitalize}
.obsidian-brand small{display:block;font-size:9px;text-transform:none;margin-top:2px}
.obsidian-brand-mark{display:grid;place-items:center;width:24px;height:24px;border-radius:6px;background:var(--sunk);color:var(--ink-soft);font-size:9px;flex-shrink:0}
.obsidian-heat{display:block;text-align:center;border-radius:5px;padding:8px 6px;min-width:44px;color:#f0f4ff;background:#202d49;text-decoration:none;font-size:11px;line-height:1.3}
.obsidian-heat:hover{text-decoration:none;outline:1px solid var(--accent);outline-offset:1px;filter:brightness(1.15)}
.heat-1{background:#243961}.heat-2{background:#2b4386}.heat-3{background:#304fa1}.heat-4{background:#365bc7}
.heat-gap{background:var(--warn-bg);color:var(--warn)}.heat-absent{background:var(--sunk);color:var(--ink-soft);border-bottom:1px dashed var(--edge)}
.obsidian-unmeasured{min-height:260px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:25px}
.obsidian-empty-mark{font-size:36px;color:var(--accent)}.obsidian-unmeasured h4{font-size:17px;margin:12px 0 8px;font-weight:500}
.obsidian-unmeasured p{font-size:13px;color:var(--ink-soft);max-width:390px;margin:0 0 18px}
.obsidian-priority{border:1px solid #34476a;border-radius:13px;background:linear-gradient(145deg,#1b2e59,#111928 65%);color:#f3f6ff;overflow:hidden}
.obsidian-priority-copy{padding:22px}.obsidian-priority-copy .obsidian-eyebrow{color:#b6c8fb;font-size:9px}
.obsidian-priority-copy>strong{display:block;font-size:58px;font-weight:450;letter-spacing:-2px;line-height:1.15;margin:15px 0 6px}
.obsidian-priority-copy h3{font-size:20px;font-weight:500}.obsidian-priority-copy p{font-size:12px;color:#b6c1d8;line-height:1.65;margin:10px 0 19px}
.obsidian-priority-copy .obsidian-primary{width:100%;background:#f1f4ff;color:#1c2b50;border-color:#f1f4ff;font-size:12px}
.obsidian-priority-links{border-top:1px solid #ffffff18}.obsidian-priority-links a{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 21px;border-bottom:1px solid #ffffff0d;color:#c7d0e5;font-size:11px;text-decoration:none}
.obsidian-priority-links a:hover{background:#ffffff08}.obsidian-priority-links b{color:#f3f6ff;font-weight:500}
.obsidian-lower{margin-top:20px}.obsidian-link{font-size:12px;white-space:nowrap}
.obsidian-run-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;padding:8px 22px 25px}
.obsidian-run-stats a{border-right:1px solid var(--rule);text-decoration:none;color:var(--ink)}.obsidian-run-stats a:last-child{border:0}
.obsidian-run-stats strong{display:block;font-size:30px;font-weight:500}.obsidian-run-stats span{font-size:12px;color:var(--ink-soft)}
.obsidian-record-bars{display:grid;gap:12px;padding:0 22px 23px}.obsidian-record-bars a{display:grid;grid-template-columns:1fr 68px 35px;align-items:center;gap:10px;text-decoration:none;color:var(--ink-soft);font-size:11px}
.obsidian-record-bars b{text-align:right;font-weight:500;color:var(--ink)}.obsidian-meter{display:block;height:4px;border-radius:3px;overflow:hidden;background:var(--rule)}
.obsidian-meter i{display:block;height:100%;background:var(--action);border-radius:3px}
.obsidian-queue-details{margin-top:24px}.obsidian-queue-details>summary{padding:16px 0;border-top:1px solid var(--rule);font-weight:500;color:var(--ink-soft);cursor:pointer}
.overview-diagnostics:target{scroll-margin-top:20px}
:root[data-rail="closed"] .shell{grid-template-columns:72px minmax(0,1fr)}
:root[data-rail="closed"] .rail .wm,:root[data-rail="closed"] .rail .nav-label,:root[data-rail="closed"] .rail .nav-group,:root[data-rail="closed"] .rail .n,:root[data-rail="closed"] .rail form,:root[data-rail="closed"] .rail-build{display:none}
@media(max-width:1350px){.obsidian-overview-grid{grid-template-columns:minmax(0,1fr) 280px}.obsidian-panel-head{padding:18px}.obsidian-brand-mark{display:none}.obsidian-priority-copy{padding:20px}.panel-breadcrumb{font-size:11px;gap:8px}.page-tools{gap:12px}.panel-search{width:210px}.obsidian-stat{padding:16px}.obsidian-stat strong{font-size:30px}}
@media(max-width:1100px){.obsidian-overview-grid{grid-template-columns:minmax(0,1fr)}.obsidian-priority{display:grid;grid-template-columns:1fr 1fr}.obsidian-priority-links{border-top:0;border-left:1px solid #ffffff18;display:flex;flex-direction:column;justify-content:center}.obsidian-priority-copy>strong{font-size:46px;margin-top:8px}.obsidian-priority-copy p{max-width:360px}.obsidian-record-bars{grid-template-columns:1fr 1fr;gap:16px 32px}.panel-breadcrumb{display:none}.panel-search{width:260px}}
@media(max-width:820px){.shell,.shell[data-rail="closed"],:root[data-rail="closed"] .shell{grid-template-columns:minmax(0,1fr)}:root[data-rail="closed"] .rail{display:none}main{padding:0 18px 50px;max-width:none;width:100%;min-width:0}.page-tools{margin:0 -18px 22px;padding:12px 18px;min-height:60px;gap:10px}.panel-search{width:240px}.railtoggle,.theme-toggle{padding:7px 9px;font-size:11px}.obsidian-stats{grid-template-columns:1fr 1fr;gap:12px}.page-heading{align-items:flex-start}.page-heading h2{font-size:28px}.page-heading .pagesub{font-size:12px}.bulk,.bulk.on,.shell[data-rail="closed"] .bulk{left:14px;right:14px}}
@media(max-width:520px){.panel-search{width:auto;flex:1;gap:5px;padding:0 7px}.panel-search svg{display:none}.panel-search input{font-size:11px}.theme-toggle .theme-icon{display:none}.railtoggle{gap:6px}.obsidian-overview-grid{gap:16px}.obsidian-panel-head{padding:17px 16px;gap:10px}.obsidian-panel-head h3{font-size:16px}.obsidian-panel-head p{font-size:11px}.obsidian-panel-head .chip{font-size:10px;padding:6px 8px}.obsidian-heat-scroll{padding-left:12px;padding-right:12px}.obsidian-priority{grid-template-columns:1fr}.obsidian-priority-links{border-left:0;border-top:1px solid #ffffff18}.obsidian-priority-copy{padding:20px}.obsidian-priority-copy>strong{font-size:48px}.obsidian-record-bars{grid-template-columns:1fr;padding:0 18px 20px}.obsidian-run-stats{gap:10px;padding:5px 18px 22px}.obsidian-run-stats strong{font-size:26px}.obsidian-run-stats span{font-size:11px}.obsidian-stat{padding:15px}.obsidian-stat strong{font-size:28px}.obsidian-stat small{font-size:10px}.obsidian-panel-foot{padding:12px 17px}.obsidian-link{font-size:11px}.obsidian-heat-scroll{border-right:3px solid var(--rule)}.obsidian-unmeasured{min-height:250px;padding:22px}.obsidian-lower{margin-top:16px}}
