/*
 * spx-explainer.css
 *
 * ⚠️ WOERTLICH aus validierungsbericht-erklaerer.html uebernommen, nicht nachgebaut.
 *
 * Zwei Versuche, das Design des Prototyps mit den Tokens des eInvoice Viewer zu verschmelzen, sind
 * gescheitert - beide Male wurde es unruhiger statt klarer. Der Prototyp ist ein fertiges,
 * abgestimmtes System: Inter / Space Grotesk / JetBrains Mono auf einer echt neutralen Grauskala.
 * Daran wird nichts geaendert.
 *
 * Eigene Ergaenzungen stehen ausschliesslich am Ende dieser Datei unter "ERGAENZUNGEN" und sind
 * einzeln begruendet. Alles darueber ist Original.
 *
 * Die Angleichung an den Viewer erfolgt spaeter in der ANDEREN Richtung: der Viewer uebernimmt diese
 * Typografie, nicht dieses Stylesheet die des Viewers.
 */

  /*
 * ⚠️ SELEKTOR-ANPASSUNG FUER DAS SHADOW DOM - so wenig wie moeglich.
 *
 *     :root, :host              ( die Tokens )
 *     .spx-root                 ( Grundtypografie )
 *     .spx-root, .spx-root *    ( der Reset, frueher ungescoptes * )
 *
 * Der Prototyp setzt die Tokens auf :root und die Grundtypografie auf html, body. Dieselbe Datei
 * traegt jetzt die Vorschau ( LAYOUT-MOCKUP.html, ohne Shadow DOM ) UND das Plugin ( im Shadow
 * Root ). Im normalen Dokument greift :root, im Shadow DOM :host - beide definieren dieselben
 * Tokens. Die Grundtypografie haengt an .spx-root ( im Mockup eine Klasse am Wrapper, im Plugin
 * der Wurzel-<div> der Vorlage ), nicht mehr an html, body.
 *
 * ⚠️ DAS RESET * IST AUF .spx-root EINGEGRENZT. spx-explainer.css wird nicht nur im Shadow Root,
 * sondern auch auf Dokumentebene eingebunden - die @font-face-Regeln muessen dort stehen, weil
 * sie die Shadow-Grenze nicht ueberqueren. Ein ungescoptes * { margin:0; padding:0 } wuerde
 * damit jede Seite zuruecksetzen, auf der der Shortcode steht.
 */

 /* ============================================================================
   SCHRIFTEN - mitgeliefert, nicht nachgeladen
   ----------------------------------------------------------------------------
   Inter, Space Grotesk und JetBrains Mono, alle drei unter der SIL Open Font
   License. Die Lizenztexte liegen als OFL.txt neben den Schriftdateien.

   NICHT VON EINEM FREMDEN SERVER LADEN. wordpress.org untersagt das, und ein
   Aufruf zu fonts.googleapis.com uebertraegt die IP jedes Besuchers an einen
   Dritten - bei einem Werkzeug, in das man Rechnungsdaten hochlaedt, waere das
   besonders unpassend.

   font-display: swap IST ABSICHT. Ein Pruefbericht ist Text, den man lesen will;
   ihn unsichtbar zu lassen, waehrend eine Schrift laedt, waere der schlechtere
   Tausch. Der Bericht erscheint sofort und wechselt die Schrift, sobald sie da ist.

   NUR DER ZEICHENSATZ latin. Ein polnischer oder tschechischer Lieferantenname
   faellt fuer die betroffenen Zeichen auf die Systemschrift zurueck - der Browser
   macht das glyphenweise, es bricht also nichts. Wer es sauber will, laedt
   dieselben Familien zusaetzlich als latin-ext.

   NUR DIE SCHNITTE, DIE DAS STYLESHEET BENUTZT. Kursiv braucht es lediglich bei
   Inter 400 und JetBrains Mono 400 - fuer .doc-elem-attr, .doc-elem-truncated,
   .doc-elem-val.is-missing und das <em> im Hinweis 'keine Erklaerung vorhanden'.
   Space Grotesk hat gar keinen Kursivschnitt.
   ========================================================================= */

@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url( '../fonts/inter-v20-latin/inter-v20-latin-regular.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url( '../fonts/inter-v20-latin/inter-v20-latin-500.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url( '../fonts/inter-v20-latin/inter-v20-latin-600.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap; src: url( '../fonts/inter-v20-latin/inter-v20-latin-700.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Inter'; font-style: italic; font-weight: 400; font-display: swap; src: url( '../fonts/inter-v20-latin/inter-v20-latin-italic.woff2' ) format( 'woff2' ); }

@font-face { font-family: 'Space Grotesk'; font-style: normal; font-weight: 400; font-display: swap; src: url( '../fonts/space-grotesk-v22-latin/space-grotesk-v22-latin-regular.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Space Grotesk'; font-style: normal; font-weight: 500; font-display: swap; src: url( '../fonts/space-grotesk-v22-latin/space-grotesk-v22-latin-500.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Space Grotesk'; font-style: normal; font-weight: 600; font-display: swap; src: url( '../fonts/space-grotesk-v22-latin/space-grotesk-v22-latin-600.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'Space Grotesk'; font-style: normal; font-weight: 700; font-display: swap; src: url( '../fonts/space-grotesk-v22-latin/space-grotesk-v22-latin-700.woff2' ) format( 'woff2' ); }

@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url( '../fonts/jetbrains-mono-v24-latin/jetbrains-mono-v24-latin-regular.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url( '../fonts/jetbrains-mono-v24-latin/jetbrains-mono-v24-latin-500.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url( '../fonts/jetbrains-mono-v24-latin/jetbrains-mono-v24-latin-600.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url( '../fonts/jetbrains-mono-v24-latin/jetbrains-mono-v24-latin-700.woff2' ) format( 'woff2' ); }
@font-face { font-family: 'JetBrains Mono'; font-style: italic; font-weight: 400; font-display: swap; src: url( '../fonts/jetbrains-mono-v24-latin/jetbrains-mono-v24-latin-italic.woff2' ) format( 'woff2' ); }

/*
 * ⚠️ DIE SCHRIFTEN SIND MITGELIEFERT ( @font-face oben ), NICHT NACHGELADEN. Der Prototyp laedt
 * Inter, Space Grotesk und JetBrains Mono im <head> von fonts.googleapis.com; das darf ein Plugin
 * auf wordpress.org nicht. Die drei Familien liegen als .woff2 unter assets/fonts/ und werden
 * ueber die @font-face-Bloecke am Anfang dieser Datei eingebunden. Diese Datei wird zusaetzlich
 * auf Dokumentebene enqueued, damit die Regeln die Shadow-Grenze erreichen.
 */
:root, :host {
    --paper: #ECEEF2;
    --panel: #FFFFFF;
    --panel-alt: #F7F8FA;
    --ink: #0B1220;
    --ink-2: #4A5468;
    --ink-3: #7A8399;
    --rule: #D5D8DE;
    --rule-strong: #B8BDC7;
    --navy: #1E3A8A;
    --navy-2: #172554;
    --navy-soft: #EEF2FF;
    --error: #B42318;
    --error-bg: #FEF3F2;
    --error-strong: #7F1D1D;
    --warn: #B54708;
    --warn-bg: #FFFAEB;
    --ok: #067647;
    --ok-bg: #ECFDF3;
    --info: #175CD3;
    --info-bg: #EFF8FF;
    --highlight: #FEF08A;
    --highlight-strong: #FACC15;
  }

  .spx-root, .spx-root * { box-sizing: border-box; margin: 0; padding: 0; }
  .spx-root {
    background: var(--paper);
    color: var(--ink);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
  }
  code, .mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }

  /* --------- Top strip --------- */
  .top {
    border-bottom: 1px solid var(--rule);
    background: var(--panel);
    position: sticky;
    top: 0;
    z-index: 50;
  }
  .top-inner {
    max-width: 1400px;
    margin: 0 auto;
    padding: 14px 32px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
  }
  .brand {
    display: flex;
    align-items: center;
    gap: 12px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    letter-spacing: -0.01em;
  }
  .brand-mark {
    width: 28px;
    height: 28px;
    background: var(--navy);
    color: var(--panel);
    display: grid;
    place-items: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 13px;
    font-weight: 700;
  }
  .brand-text { font-size: 15px; }
  .brand-tag {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    border-left: 1px solid var(--rule);
    padding-left: 12px;
    margin-left: 4px;
  }
  .top-meta {
    display: flex;
    gap: 20px;
    align-items: center;
    font-size: 12px;
    color: var(--ink-3);
    font-family: 'JetBrains Mono', monospace;
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  main {
    max-width: 1400px;
    margin: 0 auto;
    padding: 40px 32px 96px;
  }

  /* --------- Hero / Start view --------- */
  .hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 64px;
    margin-bottom: 40px;
    align-items: end;
  }
  .hero-eyebrow {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--navy);
    margin-bottom: 20px;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .hero-eyebrow::before {
    content: '';
    display: block;
    width: 24px;
    height: 1px;
    background: var(--navy);
  }
  .hero h1 {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 500;
    font-size: 40px;
    line-height: 1.08;
    letter-spacing: -0.02em;
  }
  .hero h1 em {
    font-style: normal;
    color: var(--navy);
  }
  .hero-lede {
    color: var(--ink-2);
    font-size: 16px;
    line-height: 1.55;
    max-width: 44ch;
  }
  .hero-lede strong { color: var(--ink); font-weight: 600; }

  /* --------- Upload --------- */
  .drop {
    background: var(--panel);
    border: 1px dashed var(--rule-strong);
    padding: 40px;
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 28px;
    align-items: center;
    transition: border-color 0.15s, background 0.15s;
    cursor: pointer;
  }
  .drop:hover, .drop.drag {
    border-color: var(--navy);
    background: #F8FAFF;
  }
  .drop-icon {
    width: 56px;
    height: 56px;
    border: 1px solid var(--rule);
    display: grid;
    place-items: center;
    background: var(--panel-alt);
  }
  .drop-icon svg { width: 22px; height: 22px; stroke: var(--navy); }
  .drop-text .drop-title {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 17px;
    margin-bottom: 4px;
  }
  .drop-text .drop-sub {
    color: var(--ink-2);
    font-size: 13px;
  }
  .drop-text .drop-sub code {
    background: var(--panel-alt);
    padding: 1px 6px;
    font-size: 12px;
    border: 1px solid var(--rule);
  }
  .btn {
    font-family: 'Inter', sans-serif;
    font-weight: 500;
    font-size: 14px;
    padding: 10px 18px;
    border: 1px solid var(--rule-strong);
    background: var(--panel);
    color: var(--ink);
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s;
    display: inline-flex;
    align-items: center;
    gap: 8px;
  }
  .btn:hover { background: var(--panel-alt); border-color: var(--ink-3); }
  .btn.primary {
    background: var(--navy);
    color: var(--panel);
    border-color: var(--navy);
  }
  .btn.primary:hover { background: var(--navy-2); border-color: var(--navy-2); }

  .samples {
    margin-top: 20px;
    display: flex;
    gap: 8px;
    align-items: center;
    font-size: 13px;
    color: var(--ink-2);
    flex-wrap: wrap;
  }
  .samples-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-3);
    padding-right: 4px;
  }
  .chip-btn {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    padding: 6px 10px;
    background: var(--panel);
    border: 1px solid var(--rule);
    cursor: pointer;
    color: var(--ink);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background 0.12s, border-color 0.12s;
  }
  .chip-btn:hover { background: var(--panel-alt); border-color: var(--ink-3); }

  /* --------- Result view --------- */
  #results { display: none; }
  #results.active { display: block; }

  /* Verdict banner */
  .verdict {
    padding: 24px 28px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 20px;
    color: var(--panel);
    background: var(--ink);
    margin-bottom: 24px;
  }
  .verdict.pass { background: var(--ok); }
  .verdict.fail { background: var(--error); }
  .verdict.warn { background: var(--warn); }
  .verdict-title {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 22px;
    letter-spacing: -0.01em;
  }
  .verdict-desc {
    font-size: 14px;
    opacity: 0.92;
    margin-top: 4px;
    max-width: 60ch;
  }
  .verdict-stamp {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    padding: 8px 14px;
    border: 1px solid rgba(255,255,255,0.4);
  }

  /* Metadata card */
  .meta-card {
    background: var(--panel);
    border: 1px solid var(--rule);
    padding: 20px 24px;
    margin-bottom: 24px;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
  }
  .meta-item .meta-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-3);
    margin-bottom: 6px;
  }
  .meta-item .meta-value {
    font-size: 14px;
    color: var(--ink);
    font-weight: 500;
    word-break: break-word;
  }

  /* Split view */
  .split {
    display: grid;
    grid-template-columns: 480px 1fr;
    gap: 24px;
    align-items: start;
  }

  /* --------- Left: findings --------- */
  .panel {
    background: var(--panel);
    border: 1px solid var(--rule);
  }
  .panel-head {
    padding: 14px 20px;
    border-bottom: 1px solid var(--rule);
    background: var(--panel-alt);
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ink-2);
  }
  .panel-head h2 {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 14px;
    text-transform: none;
    letter-spacing: -0.01em;
    color: var(--ink);
  }

  .finding {
    padding: 18px 20px;
    border-top: 1px solid var(--rule);
    cursor: pointer;
    transition: background 0.12s;
  }
  .finding:first-child { border-top: none; }
  .finding:hover { background: #FAFBFF; }
  .finding.active { background: var(--navy-soft); border-left: 3px solid var(--navy); padding-left: 17px; }

  .finding-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 8px;
  }
  .finding-severity {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    padding: 3px 8px;
    border: 1px solid;
  }
  .finding-severity.error { color: var(--error); border-color: var(--error); background: var(--error-bg); }
  .finding-severity.warn { color: var(--warn); border-color: var(--warn); background: var(--warn-bg); }
  .finding-severity.info { color: var(--info); border-color: var(--info); background: var(--info-bg); }

  .finding-rule {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    color: var(--ink-2);
    font-weight: 500;
  }

  .finding-title {
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 600;
    font-size: 15px;
    margin-bottom: 6px;
    color: var(--ink);
    line-height: 1.35;
  }
  .finding-bt {
    display: inline-block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--navy);
    background: var(--navy-soft);
    padding: 2px 8px;
    margin-bottom: 8px;
    border: 1px solid #C7D2FE;
  }
  .finding-explain {
    font-size: 13px;
    color: var(--ink-2);
    line-height: 1.5;
    margin-bottom: 10px;
  }
  /* suite-todo 2.8 (c): a rule text shown untranslated, not styled as an error/warning - just a
     quiet note, same tone as .finding-original-label below. */
  .finding-explain-notice {
    font-size: 12px;
    font-style: italic;
    color: var(--ink-2);
    margin: -6px 0 10px;
  }
  .finding-fix {
    background: var(--panel-alt);
    border-left: 3px solid var(--navy);
    padding: 10px 14px;
    font-size: 13px;
    color: var(--ink);
  }
  .finding-fix-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--navy);
    margin-bottom: 4px;
    font-weight: 600;
  }
  .finding-fix code {
    background: var(--panel);
    padding: 1px 5px;
    border: 1px solid var(--rule);
    font-size: 12px;
  }
  .finding-original {
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px dashed var(--rule);
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--ink-3);
    line-height: 1.5;
    /* ⚠️ The Clark-notation XPath this holds ( "Q{urn:...}Element[1]/Q{urn:...}Next[1]/..." ) is ONE
       unbroken run with no spaces or hyphens for the browser's default wrapping to break on - without
       this, .finding-original (and its .spx-root/.panel/.finding ancestors, none of which constrain
       width on their own) stretched to the text's full length, ~3x the panel width, pushing the whole
       report into a horizontal scrollbar that hid most of the path off-screen. overflow-wrap: anywhere
       breaks at any character when a word has nowhere else to wrap, unlike word-break: break-all it
       still prefers a normal boundary first - found live, 10.09.2026, scrollWidth 2905px vs
       clientWidth 898px on a real XRechnung-CII findings report. */
    overflow-wrap: anywhere;
  }
  .finding-original-label {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 4px;
    color: var(--ink-3);
  }

  /* --------- Right: document --------- */
  .doc-search {
    padding: 12px 20px;
    border-bottom: 1px solid var(--rule);
    display: flex;
    gap: 12px;
    align-items: center;
    background: var(--panel);
  }
  .doc-search input {
    flex: 1;
    padding: 8px 12px;
    border: 1px solid var(--rule);
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    color: var(--ink);
    background: var(--panel);
  }
  .doc-search input:focus {
    outline: none;
    border-color: var(--navy);
  }
  .doc-toggle {
    display: flex;
    gap: 4px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
  }
  .toggle-btn {
    padding: 4px 10px;
    border: 1px solid var(--rule);
    background: var(--panel);
    cursor: pointer;
    color: var(--ink-2);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
  .toggle-btn.on {
    background: var(--navy);
    color: var(--panel);
    border-color: var(--navy);
  }

  .doc-body {
    max-height: 78vh;
    overflow-y: auto;
    background: var(--panel);
  }

  .doc-row {
    display: grid;
    grid-template-columns: 60px 1fr;
    gap: 12px;
    padding: 6px 20px 6px 12px;
    border-bottom: 1px solid #F1F2F5;
    font-size: 13px;
    line-height: 1.4;
  }
  .doc-row.hidden-empty { display: none; }
  .doc-row.error-row {
    background: var(--error-bg);
    border-left: 3px solid var(--error);
    padding-left: 9px;
  }
  .doc-row.error-row:hover { background: #FEE4E2; }
  .doc-row.highlight-search {
    background: var(--highlight);
  }
  .doc-row:hover { background: #FAFBFF; }
  .doc-row.error-row.highlighted {
    background: #FEE4E2;
    border-left: 3px solid var(--error-strong);
    animation: pulse 1.2s ease-out;
  }
  @keyframes pulse {
    0% { background: #FCA5A5; }
    100% { background: #FEE4E2; }
  }

  .doc-pos {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--ink-3);
    padding-top: 2px;
    user-select: none;
  }
  .doc-element {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
  }
  .doc-level-1 { padding-left: 0; }
  .doc-level-2 { padding-left: 16px; }
  .doc-level-3 { padding-left: 32px; }
  .doc-level-4 { padding-left: 48px; }
  .doc-level-5 { padding-left: 64px; }
  .doc-level-6 { padding-left: 80px; }
  .doc-level-7 { padding-left: 96px; }
  .doc-level-8 { padding-left: 112px; }

  .doc-elem-name {
    color: var(--ink-2);
    font-weight: 500;
  }
  .doc-row.error-row .doc-elem-name {
    color: var(--error-strong);
    font-weight: 600;
  }
  .doc-elem-val {
    color: var(--ink);
    font-weight: 600;
    background: var(--panel-alt);
    padding: 1px 6px;
    border: 1px solid var(--rule);
  }
  .doc-row.error-row .doc-elem-val {
    background: var(--panel);
    border-color: var(--error);
    color: var(--error-strong);
  }
  .doc-elem-attr {
    color: var(--ink-3);
    font-style: italic;
    font-size: 11px;
  }
  .doc-elem-bt {
    display: inline-block;
    font-size: 10px;
    color: var(--navy);
    background: var(--navy-soft);
    padding: 1px 6px;
    border: 1px solid #C7D2FE;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 600;
  }
  .doc-row.error-row .doc-elem-bt {
    background: var(--error);
    color: var(--panel);
    border-color: var(--error);
  }
  .doc-elem-truncated {
    color: var(--ink-3);
    font-size: 11px;
    font-style: italic;
  }

  .doc-error-note {
    grid-column: 2;
    margin-top: 6px;
    padding: 8px 12px;
    background: var(--panel);
    border: 1px solid var(--error);
    border-left: 3px solid var(--error);
    font-family: 'Inter', sans-serif;
    font-size: 12px;
    color: var(--error-strong);
    line-height: 1.45;
  }
  .doc-error-note-title {
    font-weight: 700;
    display: block;
    margin-bottom: 3px;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 13px;
  }

  /* --------- Reset row --------- */
  .reset-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 32px 0 0;
    padding-top: 24px;
    border-top: 1px solid var(--rule);
  }

  /* Empty findings state */
  .empty-note {
    text-align: center;
    padding: 40px 24px;
    color: var(--ink-3);
    font-size: 14px;
  }

  /* Scope note */
  .scope {
    background: var(--warn-bg);
    border: 1px solid #FCD34D;
    padding: 14px 20px;
    margin-bottom: 24px;
    font-size: 13px;
    color: #7C2D12;
    display: flex;
    gap: 12px;
    align-items: flex-start;
  }
  .scope-mark {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 600;
    background: #FCD34D;
    color: #7C2D12;
    padding: 2px 6px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    flex-shrink: 0;
  }

  footer {
    max-width: 1400px;
    margin: 0 auto;
    padding: 24px 32px;
    border-top: 1px solid var(--rule);
    color: var(--ink-3);
    font-size: 12px;
    font-family: 'JetBrains Mono', monospace;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    display: flex;
    justify-content: space-between;
    gap: 20px;
  }

  @media (max-width: 1100px) {
    .split { grid-template-columns: 1fr; }
    .doc-body { max-height: 60vh; }
    .meta-card { grid-template-columns: repeat(2, 1fr); }
  }
  @media (max-width: 700px) {
    .hero { grid-template-columns: 1fr; gap: 32px; }
    .hero h1 { font-size: 30px; }
    .drop { grid-template-columns: 1fr; padding: 24px; }
    main { padding: 24px 16px; }
    .top-inner { padding: 12px 16px; flex-wrap: wrap; }
    .meta-card { grid-template-columns: 1fr; }
    footer { flex-direction: column; padding: 24px 16px; }
  }
  /* --------- Rule browser trigger --------- */
  .top-action {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    margin-left: 12px;
    background: var(--navy);
    color: #fff;
    border: none;
    border-radius: 999px;
    font: 500 12px/1 'Inter', sans-serif;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: background 0.15s;
  }
  .top-action:hover { background: var(--navy-2); }
  .top-action svg { flex-shrink: 0; }

  .link-btn {
    background: none;
    border: none;
    padding: 0;
    color: var(--navy);
    font: inherit;
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
  }
  .link-btn:hover { color: var(--navy-2); }

  /* --------- Rule Browser Modal --------- */
  .modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(11, 18, 32, 0.55);
    backdrop-filter: blur(4px);
    z-index: 100;
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding: 40px 20px;
  }
  .modal-backdrop.show { display: flex; }
  .modal {
    background: var(--panel);
    border-radius: 12px;
    width: 100%;
    max-width: 900px;
    max-height: calc(100vh - 80px);
    display: flex;
    flex-direction: column;
    box-shadow: 0 20px 60px rgba(0,0,0,0.25);
    overflow: hidden;
  }
  .modal-head {
    padding: 20px 24px 16px;
    border-bottom: 1px solid var(--rule);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
  }
  .modal-title-block h2 {
    font: 600 20px/1.2 'Space Grotesk', sans-serif;
    color: var(--ink);
    margin: 0 0 4px;
  }
  .modal-title-block p {
    font-size: 13px;
    color: var(--ink-3);
    margin: 0;
  }
  .modal-close {
    background: var(--panel-alt);
    border: 1px solid var(--rule);
    width: 32px;
    height: 32px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--ink-2);
    flex-shrink: 0;
  }
  .modal-close:hover { background: var(--rule); }
  .modal-controls {
    padding: 16px 24px;
    background: var(--panel-alt);
    border-bottom: 1px solid var(--rule);
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .modal-search {
    width: 100%;
    padding: 14px 18px;
    border: 1.5px solid var(--rule-strong);
    border-radius: 10px;
    font: 500 17px/1.4 'Inter', sans-serif;
    background: var(--panel);
    color: var(--ink);
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
  }
  .modal-search::placeholder {
    color: var(--ink-3);
    font-weight: 400;
  }
  .modal-search:focus {
    border-color: var(--navy);
    box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.12);
  }
  .modal-cat-filter {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
  }
  .cat-chip {
    padding: 6px 12px;
    background: var(--panel);
    border: 1px solid var(--rule);
    border-radius: 999px;
    font: 500 12px/1 'Inter', sans-serif;
    color: var(--ink-2);
    cursor: pointer;
    transition: all 0.15s;
  }
  .cat-chip:hover { border-color: var(--navy); color: var(--navy); }
  .cat-chip.active {
    background: var(--navy);
    color: #fff;
    border-color: var(--navy);
  }
  .modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 12px 24px 24px;
  }
  .modal-stats {
    font: 500 12px/1 'Inter', sans-serif;
    color: var(--ink-3);
    padding: 12px 0;
    border-bottom: 1px solid var(--rule);
    margin-bottom: 8px;
  }
  .rule-item {
    padding: 14px 0;
    border-bottom: 1px solid var(--rule);
  }
  .rule-item:last-child { border-bottom: none; }
  .rule-item-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    cursor: pointer;
    user-select: none;
  }
  .rule-id {
    font: 600 13px/1.4 'JetBrains Mono', monospace;
    background: var(--navy-soft);
    color: var(--navy-2);
    padding: 2px 8px;
    border-radius: 4px;
    flex-shrink: 0;
    letter-spacing: -0.01em;
  }
  .rule-title {
    font: 500 14px/1.4 'Inter', sans-serif;
    color: var(--ink);
    flex: 1;
  }
  .rule-bt {
    font: 500 11px/1 'JetBrains Mono', monospace;
    color: var(--ink-3);
    padding: 2px 6px;
    border: 1px solid var(--rule);
    border-radius: 3px;
    flex-shrink: 0;
  }
  .rule-details {
    display: none;
    margin-top: 12px;
    padding-left: 12px;
    border-left: 2px solid var(--rule);
  }
  .rule-item.expanded .rule-details { display: block; }
  .rule-details-block {
    margin-bottom: 12px;
  }
  .rule-details-block:last-child { margin-bottom: 0; }
  .rule-details-label {
    font: 600 11px/1 'Inter', sans-serif;
    color: var(--ink-3);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 6px;
  }
  .rule-details-text {
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--ink);
  }
  .rule-details-text code {
    background: var(--panel-alt);
    color: var(--navy-2);
    padding: 1px 5px;
    border-radius: 3px;
    font-size: 12px;
  }
  .no-results {
    text-align: center;
    padding: 40px 20px;
    color: var(--ink-3);
    font-size: 14px;
  }
  @media (max-width: 700px) {
    .top-action span { display: none; }
    .top-action { padding: 6px; }
  }


/* ============================================================================
   ERGAENZUNGEN - alles darueber ist Original aus dem Prototyp
   ========================================================================= */

/*
 * Der Prototyp kennt in der Dokumentansicht nur .error-row. Ein Pruefbericht hat aber auch
 * Warnungen, und die duerfen nicht wie Fehler aussehen. Aufgebaut wie .error-row, nur mit den
 * Warnfarben, die im :root schon stehen - keine neuen Farbwerte.
 */

.doc-row.warn-row { background: var(--warn-bg); border-left: 3px solid var(--warn); padding-left: 9px; }
.doc-row.warn-row:hover { background: #FEF0C7; }
.doc-row.warn-row .doc-elem-name { color: var(--warn); font-weight: 600; }

.doc-warn-note {
	grid-column: 2;
	margin-top: 6px;
	padding: 8px 12px;
	background: var(--panel);
	border: 1px solid var(--warn);
	border-left: 3px solid var(--warn);
	font-family: 'Inter', sans-serif;
	font-size: 12px;
	color: var(--warn);
	line-height: 1.45;
}

.doc-warn-note-title { font-weight: 700; display: block; margin-bottom: 3px; font-family: 'Space Grotesk', sans-serif; font-size: 13px; }

/*
 * Zwei Urteilsbalken untereinander statt eines. Der Prototyp zeigt genau einen; hier stehen Fehler
 * und Warnungen getrennt, weil die Warnung eine andere Aussage traegt.
 */

.verdict + .verdict { margin-top: -16px; }
.verdict-count { font-family: 'Space Grotesk', sans-serif; font-size: 34px; font-weight: 700; line-height: 1; letter-spacing: -0.02em; margin-right: 18px; }
.verdict-main { display: flex; align-items: center; }

/*
 * Der faellige Betrag. Im Pruefbericht ist das die Zahl, die zuerst gesucht wird - als normales
 * .meta-item ginge sie zwischen den anderen unter.
 */

.meta-item.meta-amount .meta-value { font-family: 'Space Grotesk', sans-serif; font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }

/*
 * In der Fundstelle steht neben der BT-Marke der tatsaechliche Wert. Dafuer wird .doc-elem-val aus
 * der Dokumentansicht wiederverwendet, damit die Optik dieselbe ist. Nur die Zeilenanordnung ist neu.
 */

.finding-values { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.finding-value-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; }
.finding-value-name { font-size: 12px; color: var(--ink-3); min-width: 190px; }
.finding-value-jump { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--navy); text-decoration: none; border-bottom: 1px solid #C7D2FE; }
.finding-value-jump:hover { border-bottom-color: var(--navy); }

.doc-elem-val.is-missing { background: transparent; border-style: dashed; color: var(--ink-3); font-family: 'Inter', sans-serif; font-weight: 400; font-style: italic; }

/* Ansichtsoptionen */
.doc-body.hide-bt .doc-elem-bt { display: none; }

/*
 * Upload-Dialog wie im einvoice-viewer ( .spev-dropzone ), auf den Tokens des Explainers.
 *
 * Der Prototyp-Dialog oben ( .drop / .drop-icon / .drop-text .drop-title / .btn.primary ) ist eine
 * dreispaltige Grid-Zeile mit Icon-Kachel und eigenem "Durchsuchen"-Knopf - dafuer fehlt im
 * tatsaechlichen Markup ( class-spx-plugin.php::render_shortcode() ) sowohl das Icon als auch der
 * Knopf, es gibt nur .drop > .drop-title + .drop-sub. ".drop-text .drop-title" trifft deshalb nie -
 * ohne diese Ergaenzung liefe der Titel im Browser-Standardtext, ungestylt.
 *
 * Der Viewer loest dieselbe Aufgabe einfacher: eine zentrierte Flaeche, gestrichelter Rahmen,
 * Titel + Hinweis untereinander, kein Icon, kein zweiter Knopf - .drop wird deshalb hier zum
 * Flex-Container mit den beiden Textzeilen als einzige sichtbare Kinder ( das <input hidden>
 * nimmt an keinem Layout teil ). Farben ausschliesslich aus dem :root oben, keine neuen Werte -
 * das Viewer-Blaugrün/Orange wird hier bewusst NICHT uebernommen, siehe STATUS.md §8
 * ( "ein fertiges, abgestimmtes Designsystem wird uebernommen, nicht nachgebaut" ); genau das
 * gilt in dieser Reihenfolge auch fuer den Viewer als Vorbild.
 */

/*
 * ⚠️ max-width/margin ADDED 10.09.2026 - Ralf: "die Grösse des Upload-Dialogs vereinheitlichen" über
 * alle drei Upload-Werkzeuge ( Viewer, Validator, hier ). Vorher fehlte hier jede Begrenzung, obwohl
 * min-height/padding/gap schon immer identisch zum Viewer waren ( siehe Kommentar direkt oberhalb,
 * "genau das gilt ... auch fuer den Viewer als Vorbild" ) - auf einer sehr breiten Seite waere diese
 * gestrichelte Box unbegrenzt mitgewachsen, ein bereits im selben Breiten-Audit beim Validator/Viewer
 * vermiedenes Problem ( siehe deren STATUS.md ), hier nur noch nicht behoben gewesen. 900px, nicht
 * irgendein Wert - dieselbe Zahl, die Validator und Viewer jetzt beide auch tragen, und die dieses
 * Plugin selbst schon für sein Rule-Browser-Modal ( .modal weiter unten ) verwendet.
 */
.drop {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 5px;
	min-height: 150px;
	padding: 28px;
	max-width: 900px;
	margin: 0 auto;
	border: 2px dashed var(--rule-strong);
	background: var(--panel-alt);
	text-align: center;
}

.drop:hover, .drop:focus, .drop.drag {
	border-color: var(--navy);
	background: var(--navy-soft);
	outline: none;
}

.drop-title { font-family: 'Space Grotesk', sans-serif; font-weight: 600; font-size: 16px; color: var(--ink); }
.drop-sub   { font-size: 13px; color: var(--ink-3); }

/*
 * Ladezustand waehrend des Uploads - im Viewer .spev-busy, hier .drop.busy, damit sich "es wird
 * gerade hochgeladen" optisch von "eine Datei wird gerade darueber gezogen" ( .drop.drag )
 * unterscheidet. spx-uploader.js setzt beide Klassen getrennt.
 *
 * ⚠️ DER SPINNER HAT KEIN top/left. Er ist ein abgeloest positioniertes Kind eines Flex-Containers
 * ohne eigene inset-Werte - dadurch richtet ihn align-items/justify-content von .drop trotzdem
 * mittig aus ( CSS Flexbox Level 1, "static position" eines abspos-Flex-Kindes ). Genau derselbe
 * Kniff steht so auch im Viewer-CSS.
 */

.drop.busy { opacity: 0.6; pointer-events: none; }

.drop.busy::after {
	content: '';
	position: absolute;
	width: 26px;
	height: 26px;
	border: 3px solid var(--navy-soft);
	border-top-color: var(--navy);
	border-radius: 50%;
	animation: spx-spin 0.8s linear infinite;
}

@keyframes spx-spin { to { transform: rotate(360deg); } }

/*
 * Die Statuszeile unter dem Dialog ( spx-message ) trug bisher nur .empty-note - dessen 40px
 * Innenabstand und Zentrierung sind fuer eine "leere Fundstellenliste" gedacht, nicht fuer eine
 * einzeilige Meldung wie "Verbleibende Uploads heute: 3". Kompakt wie .spev-message im Viewer;
 * :empty blendet die Zeile aus, statt einen leeren gepolsterten Kasten stehen zu lassen, wenn
 * say( '' ) nach einem erfolgreichen Upload die Meldung leert.
 */

.spx-message {
	margin: 10px 2px 0;
	padding: 0;
	text-align: left;
	font-size: 13px;
	color: var(--ink-3);
}

.spx-message.error { color: var(--error-strong); }
.spx-message:empty { display: none; margin: 0; }

/*
 * Der Dokumentinhalt sollte vollstaendig sichtbar sein, ohne eigene Bildlaufleiste - der Prototyp
 * war fuer eine Ansicht NEBEN der Fundstellenliste gebaut ( .split, siehe STATUS.md §8 ), wo eine
 * begrenzte Hoehe mit eigenem Scrollen sinnvoll war. Hier stehen Fundstellen und Dokument
 * untereinander; ein 78vh-Kasten mit innerem Scrollbalken mitten auf einer ohnehin scrollenden
 * Seite ist dort nur verwirrend - zwei Scrollbereiche uebereinander. Die Regel steht bewusst NACH
 * der Media-Query oben ( die .doc-body bei schmaler Ansicht auf 60vh begrenzt ) und gewinnt damit
 * unabhaengig von der Fensterbreite, weil bei gleicher Spezifitaet die spaetere Regel in der
 * Kaskade zaehlt, nicht die speziellere Bedingung.
 */

.doc-body { max-height: none; overflow-y: visible; }

/*
 * Suchfeld im Dokumentinhalt, wie im Prototyp ( #docSearchInput ). Der Prototyp benutzt fuer die
 * beiden Umschalter daneben <button class="toggle-btn">, dieser Renderer Checkboxen in .doc-toggle
 * ( damit ein Klick auf das Label reicht, kein eigenes Klick-Handling noetig ) - beide liegen als
 * Nachfahren von .doc-search, und ".doc-search input" oben ist ein reiner Nachfahren-Selektor, trifft
 * also auch die Checkboxen, nicht nur das neue Textfeld. Auf Text-Inputs eingegrenzt, die Checkboxen
 * zurueckgesetzt auf ihre native Darstellung.
 */

.doc-search input[type="checkbox"] { flex: none; width: auto; padding: 0; border: 0; background: none; font-family: inherit; }

/*
 * Ein Attributwert ( unitCode, schemeID, currencyID - z. B. "H87", "VA", "9930" ) stand bisher als
 * blosser kursiver Text neben dem umrahmten Wert, ohne selbst als eigene Information erkennbar zu
 * sein. .doc-elem-attr traegt aber ZWEI verschiedene Inhalte unter derselben Klasse: hier den
 * kurzen Attributcode aus dem Dokument (row(), class-spx-renderer.php), in values() dagegen einen
 * Prosahinweis ("312 Zeichen insgesamt", "und 4 weitere Positionen"). Ein einheitlicher Rahmen fuer
 * beides saehe bei der Prosa unpassend aus - deshalb ein Modifier ".is-code" statt einer Aenderung
 * an .doc-elem-attr selbst, angelehnt an .doc-elem-val, nur kleiner/blasser, weil es eine
 * Nebeninformation zum Wert ist, nicht der Wert selbst.
 */

.doc-elem-attr.is-code {
	background: var(--panel-alt);
	border: 1px solid var(--rule);
	padding: 1px 6px;
	font-style: normal;
	font-family: 'JetBrains Mono', monospace;
}
.doc-row.error-row .doc-elem-attr.is-code,
.doc-row.warn-row .doc-elem-attr.is-code { background: var(--panel); }

/*
 * Die BT-Marken einer Fundstelle standen bisher als EIN Span mit " · " getrennt - ein Rahmen um die
 * ganze Liste, nicht um jede Marke. Jetzt eine Zeile aus einzelnen .finding-bt-Badges (Klasse
 * unveraendert, nur nicht mehr zusammengefasst), je mit dem tatsaechlichen Feldwert direkt daneben
 * (.doc-elem-val, aus der Dokumentansicht wiederverwendet - siehe Kommentar weiter oben zu
 * .finding-values), wenn SPX_Report::resolve_field() ihn eindeutig findet.
 */

.finding-bt-list { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-bottom: 8px; }
.finding-bt-list .finding-bt { margin-bottom: 0; }
.finding-bt-more { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); }

/*
 * Eine BT-/BG-Referenz MITTEN IM FLIESSTEXT der Regelerklaerung ( "...Seller VAT Identifier (BT-31),
 * the Seller tax registration identifier (BT-32)..." ) - kleiner als .finding-bt, weil sie inline im
 * Satz steht statt in einer eigenen Zeile, sonst dieselbe Familie ( Rahmen, Monospace, Navy ).
 */

.finding-bt-inline {
	display: inline-block;
	font-family: 'JetBrains Mono', monospace;
	font-size: 11px;
	color: var(--navy);
	background: var(--navy-soft);
	padding: 0 5px;
	border: 1px solid #C7D2FE;
	white-space: nowrap;
}
.doc-error-note .finding-bt-inline,
.doc-warn-note .finding-bt-inline { color: inherit; background: var(--panel); }

/*
 * Trefferfarbe fuer die Suche: .highlight-search und .hidden-empty standen schon im Prototyp-Teil
 * oben ( unveraendert uebernommen, nie benutzt, bis jetzt ) - keine neue Regel noetig, nur die
 * JS-Verdrahtung in spx-uploader.js.
 *
 * ⚠️ DIE ALTE "NUR FEHLER"-REGEL IST DESHALB WEG ( war unter "Ansichtsoptionen" weiter oben:
 * ".doc-body.errors-only .doc-row:not(.error-row):not(.warn-row) { display: none; }" ). Sie blendete
 * per CSS aus, unabhaengig von der Suche - zwei Filter, die sich nicht kombinieren liessen, weil eine
 * Teilstring-Suche kein CSS-Selektor ist. applyDocFilters() in spx-uploader.js entscheidet jetzt beides
 * zusammen, Zeile fuer Zeile, ueber dieselbe .hidden-empty-Klasse: eine "nur Fehler"-Zeile, die auch
 * noch zur Suche passen muss, blieb vorher unerreichbar falsch sichtbar oder unsichtbar, je nachdem
 * welche der zwei Klassen zuletzt gesetzt wurde.
 */

/*
 * Pruefschritt-Uebersicht ( class-spx-renderer.php::steps() ), neu 10.09.2026 - der Prototyp kennt
 * diese Tabelle nicht, $report->steps wurde bisher gar nicht gerendert. An .meta-card angelehnt
 * ( gleicher Rahmen/Hintergrund ), aber als <table> statt Grid, weil hier vier feste Spalten mit
 * Zahlen stehen, kein Label/Wert-Paar.
 */

.steps-card {
	background: var(--panel);
	border: 1px solid var(--rule);
	padding: 16px 20px;
	margin-bottom: 24px;
}

.steps-title {
	font-family: 'JetBrains Mono', monospace;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--ink-3);
	margin-bottom: 10px;
}

.steps-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 13px;
}

.steps-table th,
.steps-table td {
	text-align: left;
	padding: 6px 10px;
	border-bottom: 1px solid var(--rule);
}

.steps-table th {
	font-family: 'JetBrains Mono', monospace;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: var(--ink-3);
	font-weight: 600;
}

.steps-table tr:last-child td { border-bottom: none; }

/* ⚠️ :nth-child COUNTS <td>s, NOT SEMANTIC MEANING - see the identical comment in
   libs/einvoice-report/assets/css/einvoice-report.css's own .ereport-steps rules, which this mirrors
   for the Explainer's own steps table. */
.steps-row-error td:nth-child(2) { color: var(--error); font-weight: 700; }
.steps-row-warn td:nth-child(3) { color: var(--warn); font-weight: 700; }