﻿/* =====================================================================
   KlareTal — designsystem (moderne, stilrent fintech-dashboard)
   Kun præsentation. Bygger oven på Bootstrap, men overstyrer udseendet.
   ===================================================================== */

:root {
    --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

    --bg: #f4f6fb;
    --surface: #ffffff;
    --surface-2: #f8fafc;
    --text: #0f172a;
    --text-muted: #475569;
    --border: #e7ebf3;
    --border-strong: #d6dce8;

    /* HANDLING — "her sker der noget når du klikker". Brand-blå, uændret.
       Gem, Vælg, Opdatér, links, fokus, KPI-streger, søjler i graferne. */
    --accent: #2563eb;
    --accent-hover: #1d4ed8;
    --accent-soft: #eff5ff;
    --accent-border: #bfd4fe;

    /* TILSTAND — "dette er valgt lige nu". Grafit (besluttet 2026-07-28).
       Før bar --accent BEGGE betydninger, og de stod få centimeter fra hinanden
       i det samme panel: i en PillPicker var både den valgte måned og Vælg-knappen
       #2563eb, mens både den fravalgte måned og Annuller var #eff5ff. Grafit er
       valgt frem for en tredje kulør, fordi appen allerede bruger grøn og rød til
       tal (--positive/--negative) — en ny kulør ville begynde at betyde noget. */
    --state: #334155;
    --state-hover: #1e293b;
    --state-soft: #f1f5f9;
    --state-border: #94a3b8;

    /* TILSTAND I HVILE — ikke valgt. Egen token, fordi --surface IKKE duer:
       KlareTals flader er hvide (.card, .panel, .table-responsive, .colfilter-pop
       er alle #ffffff), så en pille med hvid bund forsvinder ned i fladen og har
       kun en 1px kant tilbage at være knap på. Hvide knapper på hvid flade er
       forbudt (bruger-standard 2026-07-21). */
    --state-rest: #e8ecf3;
    --state-rest-border: #cdd6e4;

    --positive: #15a34a;
    --negative: #dc2626;

    /* Analyse-redesignet: SERIEFARVERNE til multi-serie-graferne (Kunder, senere Produkter).
       TOLV farver, ét pr. plads i grafen (K-5, Michaels dom C6, 7/9 2026): loftet er tolv kunder, og
       hver kunde i udvalget skal have SIN egen farve. Var der kun seks, gentog farverne sig fra den
       syvende kunde, og to linjer i samme graf bar samme farve.

       1 til 6 er husets egne, uændrede: accent, amber (Likviditet og Debitorer), positiv, indigo,
       negativ og sky (Performance-paletten).

       7 til 12 er valgt efter to akser på én gang, fordi farvetone alene ikke rækker til tolv:
       - FARVETONE i de huller, de seks efterlader: teal (175°), pink (333°), lilla (275°) og
         oliven (80°) er kulører, siden ikke havde i forvejen.
       - LYSSTYRKE, så de par, der ligger tættest for farvesvage, alligevel kan skilles ad: de seks
         gamle ligger lyst (L* 47 til 64), de seks nye mørkt (L* 36 til 55), og rust, petroleum og
         oliven er direkte mørke modstykker til amber, sky og positiv.
       Farverne betyder KUN "hvilken serie": grafen farver aldrig efter fortegn, så positiv og negativ
       bærer ikke godt og skidt her. Rækkefølgen er valgt efter indbyrdes afstand, så tre valgte
       kunder får de tre mest forskellige farver. Kundens navn står desuden i mouseover på hver prik,
       hver celle og hver række, så tolv linjer kan skilles ad uden at kende farverne. */
    --serie-1: #2563eb;   /* blå (accent) */
    --serie-2: #d97706;   /* amber */
    --serie-3: #15a34a;   /* grøn (positiv) */
    --serie-4: #6366f1;   /* indigo */
    --serie-5: #dc2626;   /* rød (negativ) */
    --serie-6: #0ea5e9;   /* sky */
    --serie-7: #0d9488;   /* teal: mellem grøn og sky, men klart køligere end begge */
    --serie-8: #db2777;   /* pink: den eneste magenta, og langt fra rød */
    --serie-9: #7e22ce;   /* lilla: mørkere og mere magenta end indigo */
    --serie-10: #9a3412;  /* rust: amber-tonen, men meget mørkere (huset bruger den i plan-senere) */
    --serie-11: #155e75;  /* petroleum: sky-tonen, men den mørkeste farve i paletten */
    --serie-12: #4d7c0f;  /* oliven: gulgrøn og mørkere end den grønne */

    /* Likviditetsplanens datofelt (fixrunde 2, punkt 2, 7/9 2026): retningen i forhold til den
       forventede dato. Ikke tilstandsfarverne (blå = ønsket, grøn = aftalt), for retning og tilstand
       er to forskellige ting. Tidligere = violet; senere = samme orange familie som "forfalden"
       (kt-forfalden), fordi senere og overskredet er samme retning. Ens dato = neutral, ingen farve. */
    --plan-tidligere: #5b21b6;
    --plan-tidligere-bg: #ede9fe;
    --plan-senere: #9a3412;
    --plan-senere-bg: #ffedd5;

    --sidebar-bg: #0e1525;
    --sidebar-text: #94a3b8;
    --sidebar-muted: #5b6b86;


    /* FUND 157: opsætningens sektionskort havde to bredder — .acc-item stoppede ved 1500 px, mens
       .ops-sekt fyldte hele indholdsbæltet (1744 px ved 2048 px vindue). Skiftede kunden fane,
       hoppede kortene 244 px midt på samme side. ÉT mål for alle syv faner bor derfor her, så de
       ikke kan drifte fra hinanden igen.
       F39 (Michael 14/9 2026, 1400023): målet var 92 procent af bæltet og stoppede derfor ca. 240 px
       før højre kant på Konto-opsætning, mens Firma-opsætnings eget indhold gik helt ud. De to sider
       måler nu ens: sidebeholderen fylder bæltet, og indholdet stopper ved samme kant som
       Opdatér-knappen. */
    --sekt-bredde: 100%;
    --radius: 16px;
    --radius-sm: 10px;
    --radius-xs: 7px;

    --shadow-sm: 0 1px 2px rgba(15, 23, 42, .05);
    --shadow: 0 1px 3px rgba(15, 23, 42, .07), 0 1px 2px rgba(15, 23, 42, .04);
    --shadow-lg: 0 16px 40px -12px rgba(15, 23, 42, .25);
}

/* ===== Base ===== */
html, body {
    font-family: var(--font-sans);
    color: var(--text);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body { font-size: 0.85rem; line-height: 1.5; }

h1 { font-size: 1.35rem; font-weight: 650; letter-spacing: -0.02em; margin: 0 0 .1rem; }
h2 { font-size: 1.1rem; font-weight: 600; letter-spacing: -0.01em; }

/* ===== Kort / paneler (opsætningssider, wizard m.m.) ===== */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
.card-header { background: var(--surface-2); border-bottom: 1px solid var(--border); font-weight: 600; }
.card-body { padding: 1rem 1.1rem; }
/* Sektion på opsætningssider: hvidt panel med luft */
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); padding: 1rem 1.1rem; margin-bottom: 1rem; }
.panel > h2:first-child, .panel > .panel-title:first-child { margin-top: 0; }
.panel-title { font-size: .95rem; font-weight: 650; margin-bottom: .75rem; }

/* ===== OPSÆTNINGENS SEKTIONSKORT (fund 124) =====
   Én fane kan bære to selvstændige flader (Koncerner & Grupperinger). De må ikke stables råt oven
   på hinanden: hver flade er sit EGET kort med sin egen overskrift og sin egen værktøjslinje i
   hovedet. Formen er husets egen — samme kort-hoved som Min konto-sidens sektioner (.acc-item /
   .acc-head), bare uden folden, fordi de to flader ikke er noget, man folder væk. */
/* FUND 133: luft mellem sektionskortene. To kort, der næsten rører hinanden, læses som ét — og på
   Koncerner & Grupperinger var det netop dét, der gjorde fanen svær at overskue. */
.ops-sekt { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; margin-bottom: 1rem; max-width: var(--sekt-bredde); }
/* Fund 126: hoved og krop har PRÆCIS samme mål og streger som Min konto-sektionernes .acc-head og
   .acc-body — så en sektion ser ens ud, uanset om den kan foldes eller ej. */
.ops-sekt-hoved { display: flex; align-items: center; gap: .5rem .8rem; flex-wrap: wrap; padding: .8rem 1.1rem; border-bottom: 1px solid var(--border); }
/* FUND 153: et foldbart hoved er klikbart i FULD BREDDE, ikke kun på chevronen. Markør og hover er
   de samme som Min konto-akkordionens .acc-head, så et fold-hoved opfører sig ens overalt i huset.
   Et hoved UDEN fold får hverken markør eller hover — det ville love et klik, der ikke findes
   (fund 126's regel, uændret). */
.ops-sekt-hoved-klik { cursor: pointer; }
.ops-sekt-hoved-klik:hover { background: var(--surface-2); }
/* Værktøjslinjens knapper er deres egne handlinger — markøren må ikke arve fold-hånden. */
.ops-sekt-hoved-klik .ops-sekt-vaerktoej { cursor: default; }
.ops-sekt-titel { font-size: .95rem; font-weight: 650; margin: 0; }
/* Resuméet er sektionens nøgletal — samme rolle og samme mål som .acc-sum på Min konto. */
.ops-sekt-resume { color: var(--text-muted); font-size: .82rem; }
.ops-sekt-resume strong { color: var(--text); font-weight: 650; }
/* Værktøjslinjen står yderst til højre i hovedet og ombryder under det på en smal skærm — den må
   aldrig skubbe hovedet ud i vandret scroll (UX-regel 1). */
.ops-sekt-vaerktoej { margin-left: auto; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
/* F121 (Michael 16/9 2026): handlingsknapperne i sektionshovederne på Koncerner & Grupperinger
   måler det samme, uanset om der står Opret, Eksportér eller Importér. Knapperne står i HVER SIN
   sektion, så et gitter kan ikke binde dem sammen; målet er derfor ét tal ét sted. 6rem rummer den
   længste tekst ("Eksportér", cirka 63 px) plus knappens egen polstring. */
.ops-sekt-knap { min-width: 6rem; text-align: center; }
/* Fund 126: chevronen er sin egen knap yderst i hovedet — samme plads og samme rotation som
   .acc-chev på Min konto. Hovedet kan ikke selv være en knap, for det bærer værktøjslinjens
   rigtige knapper. */
.ops-sekt-fold { background: none; border: 0; padding: .1rem .3rem; line-height: 1; cursor: pointer; color: var(--text-muted); }
.ops-sekt-fold:hover { color: var(--text); }
.ops-sekt-fold .acc-chev { transition: transform .15s ease; display: inline-block; }
.ops-sekt.open .ops-sekt-fold .acc-chev { transform: rotate(180deg); }
.ops-sekt-krop { padding: 1.15rem 1.3rem 1.25rem; }   /* FUND 133: mere luft i kroppen */
.ops-sekt-krop > :last-child { margin-bottom: 0; }

/* ===== Performance-grafer (inline, samme farveskema) ===== */
.perf-charts { margin-bottom: 1rem; }
.perf-row { display: flex; gap: .85rem; flex-wrap: wrap; align-items: stretch; }
.perf-row > .panel { flex: 1 1 240px; margin-bottom: 0; }
.perf-row > .perf-top10 { flex: 1.7 1 360px; }
/* Fund 117: pladsen efter et element, en bank-deling har fravalgt. Den bærer panelets flex-klasser
   og dermed dets bredde, men tegner intet — naboerne står derfor præcis, hvor de står på ejerens
   egen side, i stedet for at flyde ud over den ledige plads. */
.panel.bank-plads { background: none; border: 0; box-shadow: none; padding: 0; min-height: 0; }
/* SCENARIEPANELETS SKYDER-RÆKKER (Prognose, "Scenarie, hvad nu hvis?").
   Fund 167 (Michaels stikprøve på AppTest 714): værdi-kolonnen har FAST bredde og ombryder ALDRIG,
   så panelet står bomstille, når en værdi skifter bredde. 5 rem rummer den længste værdi, "+45 dage",
   med luft, og de tre rækker deler bevidst ÉN bredde, så skydernes højre kant flugter.
   Runde 8, fund F2 (RC-testen 10/9: Prognose rullede 92 px vandret på en telefon): reglen stod som
   tre inline-stile på siden og kunne derfor ikke ombryde på en smal ramme. Den bor nu ét sted
   (1600006), med de samme tal som før på computeren; ombrydningen står i mobilblokken. */
.sc-linje { display: flex; align-items: center; gap: .5rem; }
.sc-navn { flex: 0 0 200px; font-size: .8rem; }
.sc-skyder { flex: 1; accent-color: var(--accent); min-width: 0; }
.sc-vaerdi { flex: 0 0 5rem; text-align: right; white-space: nowrap; font-weight: 600; font-size: .8rem; }
/* trend-kortet er en kolonne, så søjle-området kan fylde resthøjden */
.perf-trend { display: flex; flex-direction: column; }
.perf-trend .bars { flex: 1 1 auto; }
/* lodrette søjler (trend) — fylder højden via %-højde på søjlerne */
.bars { display: flex; align-items: stretch; gap: .4rem; min-height: 96px; }
.bar-col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-width: 0; }
.bar-val { font-size: .68rem; color: var(--text-muted); margin-bottom: .15rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.bar { width: 72%; max-width: 56px; min-height: 2px; background: var(--accent); border-radius: var(--radius-xs) var(--radius-xs) 0 0; display: flex; flex-direction: column; }
.bar-budget { width: 100%; background: var(--accent-border); border-radius: var(--radius-xs) var(--radius-xs) 0 0; }
.bar-lbl { font-size: .68rem; color: var(--text-muted); margin-top: .3rem; white-space: nowrap; }
/* vandrette søjler (top-N) */
.hbar-row { display: flex; align-items: center; gap: .5rem; margin: .28rem 0; font-size: .78rem; }
.hbar-name { flex: 0 0 40%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hbar-track { flex: 1; height: 13px; background: var(--surface-2); border-radius: 6px; overflow: hidden; }
.hbar-fill { display: flex; justify-content: flex-end; height: 100%; background: var(--accent); border-radius: 6px; overflow: hidden; }
.hbar-budget { height: 100%; background: var(--accent-border); }
.hbar-val { flex: 0 0 auto; min-width: 50px; text-align: right; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* 1500009 rev 2 (runde 2, punkt 5): aldersfordelingens søjler er AKTIVE og filtrerer debitorlisten.
   Den valgte række markeres med husets egen fremhævning, ikke med en ny farve: farverne i søjlen
   betyder allerede noget (dybere forfald, varmere farve), og en sjette kulør ville tale imod dem.
   Markeringen sidder på rækken, så navnet, søjlen og beløbet står frem sammen. */
.hbar-row.kt-klikbar { border-radius: 6px; padding: .1rem .3rem; margin-left: -.3rem; margin-right: -.3rem; }
.hbar-row.kt-klikbar:hover { background: var(--surface-2); }
.hbar-row.hbar-valgt { background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border-strong); }
.hbar-row.hbar-valgt .hbar-name, .hbar-row.hbar-valgt .hbar-val { color: var(--text); font-weight: 600; }
/* stablet andel (koncentration) */
.stack { display: flex; height: 18px; border-radius: 6px; overflow: hidden; background: var(--surface-2); }
.stack > span { display: block; height: 100%; }
.conc-item { display: flex; align-items: center; gap: .45rem; font-size: .78rem; margin: .25rem 0; }
.conc-dot { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 3px; }
.conc-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.conc-pct { flex: 0 0 auto; color: var(--text-muted); font-variant-numeric: tabular-nums; }
/* vækst-highlights */
.growth-item { display: flex; align-items: center; gap: .5rem; margin: .4rem 0; font-size: .82rem; }
.growth-arrow { font-size: .8rem; }
.growth-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.growth-pct { font-weight: 600; font-variant-numeric: tabular-nums; }
h3 { font-size: 1rem; font-weight: 600; }

a, .btn-link { color: var(--accent); text-decoration: none; }
a:hover, .btn-link:hover { color: var(--accent-hover); }

.text-muted { color: var(--text-muted) !important; }
.text-success { color: var(--positive) !important; }
.text-danger { color: var(--negative) !important; }
.text-primary { color: var(--accent) !important; }

/* Tabular lining-tal overalt i tabeller, så tusindtals-separatorer flugter lodret (F1, testfeedback).
   font-feature-settings er fallback for ældre rendering af Inter. */
.table td, .table th { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: "tnum" 1; }
/* Fælles utility til taltunge celler/elementer udenfor .table (KPI'er har egen regel): højrestil + tabular. */
.num { text-align: right; font-variant-numeric: tabular-nums lining-nums; font-feature-settings: "tnum" 1; }

/* ===== Sideindhold ===== */
/* Top-luft der holder sideindholdet FRI af de faste "opdatér"-knapper i øverste højre hjørne
   (bruger-fund 2026-07-23): da sideoverskrifterne (h1) blev fjernet, forsvandt luften de gav, og
   toolbaren gik ind UNDER knapperne. 3.25rem rydder knap-kassen (top .8rem + 2rem højde). */
.content { padding-top: 3.25rem; padding-bottom: 2rem; max-width: none; }
/* Nulstil top-margin på FØRSTE indholds-element, så top-luften altid gælder — Bootstrap-rækker
   (.row.g-*) har en NEGATIV margin-top, der ellers trak toolbaren op i knap-zonen (fx Kontrakter). */
.content > :first-child { margin-top: 0; }
/* Fast luft under SIDSTE element på alle sider (bruger 2026-07-14: grafer/tabeller må ikke røre
   browserbunden). Container-padding-bottom medregnes IKKE i scrollhøjden når .content er
   flex+overflow (Chrome) — margin på sidste barn tæller altid med. */
.content > :last-child { margin-bottom: 2rem; }
/* Intro-tekst lige under titlen */
.content > h1 + p { color: var(--text-muted); font-size: .85rem; margin-bottom: .9rem; max-width: 75ch; }

h1:focus { outline: none; }

/* Kompakt filter-/værktøjsområde øverst — så tabellen er helten, ikke kontrollerne */
.content > .row.g-3 { --bs-gutter-x: 1rem; --bs-gutter-y: .55rem; margin-bottom: .55rem !important; align-items: end; }
.content > .mb-2 { margin-bottom: .55rem !important; }
.content > .mb-3 { margin-bottom: .7rem !important; }
/* Den grå "X firma(er) · år … " caption gøres diskret */
.content > p.text-muted { font-size: .78rem; margin-bottom: .7rem; }

/* App-shell (desktop): indholdet fylder præcis viewporten. Overskrift/værktøjslinje/KPI bevarer
   deres højde, og kun tabel-kortet krymper og scroller internt — så kortets bund (inkl. "I alt"
   og vandret scrollbar) altid lander ved skærmkanten i stedet for at skubbe siden ned under folden.
   Sider uden tabel (formularer) scroller bare hele indholdet. */
@media (min-width: 641px) {
    /* RC-fix 10/9 (Michaels fund: indhold og bannere rullede synligt ind under de svaevende knapper oeverst).
       Top-luften bor nu paa <main>, ikke paa .content: bannere OG rulleren starter under bjaelken, og bjaelken
       er et taet baand over hele indholdskolonnen (se main > .sync-fab). Intet ruller ind under noget. */
    main { height: 100vh; overflow: hidden; }

    /* RC-fix 10/9 (3), efterproevningen: baandet og dets luft hoerer til den <main>, der HAR en topbjaelke,
       altsaa app-shellen (MainLayout) og bank-visningen (BankVis). De anonyme sider (Login, Opret, Glemt
       password, Velkommen) bruger BlankLayout, som ingen topbjaelke har; med luften paa bare "main" stod de
       med et tomt 3,25rem-baand oeverst. :has er husets egen mekanik (se kolonnefilterets loeft nedenfor).

       <main> er samtidig en lodret flex-kolonne, saa rulleren faar den plads, der er tilbage EFTER bannerne.
       Med .content paa height: 100 procent blev summen af bannerhoejden og rulleren hoejere end main, og
       mains overflow: hidden klippede praecis bannerhoejden af i bunden: paa et firma med support-, proeve-
       eller licensbaand laa tabelkortets "I alt"-linje og den vandrette rullebjaelke uden for skaermen. */
    main:has(> .sync-fab) { position: relative; padding-top: 3.25rem; display: flex; flex-direction: column; }
    main > * { flex-shrink: 0; }

    .content { padding-top: 0; }
    main > .sync-fab { position: absolute; top: 0; left: 0; right: 0; height: 3.25rem; padding: 0 1.5rem; justify-content: flex-end; background: var(--bg); border-bottom: 1px solid var(--border); }   /* main > : vinder over .sync-fab-reglen laengere nede */
    .content { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; }
    .content > * { flex-shrink: 0; }
    .content > .table-responsive { flex-shrink: 1; min-height: 9rem; }

    /* B69 (Michael 11/9 2026, prod 2.0.0.1516): VAERKTOEJSLINJEN BLIVER STAAENDE VED RUL (1600018).
       Maalt headless ved 1600, 1920 og 2560 px: topbjaelken (main > .sync-fab) staar fast paa alle sider,
       og hverken dokumentet eller <main> ruller nogensinde. Det, der forsvandt paa Kunder, Produkter,
       Noegletal og Tilgodehavender, var vaerktoejslinjen: den var et almindeligt element i rulleren
       (.content) og fulgte med op, saa snart siden var hoejere end rulleren. Paa Resultatoverblik,
       Salgsoverblik og Omkostningsoverblik holdt den kun, fordi tabelkortet krymper i sin egen ramme
       (1500017), saa .content aldrig har noget at rulle (maalt: scrollHeight = clientHeight). Betingelsen
       var altsaa sidens hoejde, ikke bredden: de fire sider bestaar af sektioner, der ikke krymper.

       Linjen er nu sticky i rulleren, oeverst under topbjaelken, paa alle sider paa een gang (ingen side
       har sin egen udgave). Den ydre skygge er husets egen; den anden skygge er en massiv kant i sidens
       baggrund, som daekker luften under kortet (margin-bottom .85rem) og hjoernerne uden for radius, saa
       intet indhold kan ses glide forbi i sprækken. Sektionslinjen (Kunder, Produkter) staar under den:
       dens top er vaerktoejslinjens maalte hoejde, som kt-ui.js skriver i --kt-toolbar-h paa rulleren
       (CSS kan ikke selv laese, om linjen er brudt over een eller to raekker); se .sektionslinje og
       .kt-sektion laengere nede. Paa mobil er linjen et almindeligt element igen (mobilblokken nederst,
       1600018). */
    .content > .toolbar { position: sticky; top: 0; z-index: 6; box-shadow: var(--shadow), 0 0 0 .85rem var(--bg); }

    /* 1600030: on the setup pages the tab bar stays at the top, and the toolbar parks right BELOW it
       instead of behind it. The offset is the bar's measured height (kt-ui.js writes --kt-tabs-h on
       the scroller, because CSS cannot read how many rows the tabs have wrapped over). */
    .content:has(> .ops-faner) > .toolbar { top: var(--kt-tabs-h, 0px); }
}

/* ===== Knapper ===== */
.btn { border-radius: var(--radius-xs); font-weight: 500; transition: background-color .12s ease, color .12s ease, border-color .12s ease, box-shadow .12s ease; }
/* WCAG 2.4.7 (design-kritik 2026-07-23): synlig tastatur-fokus-ring på ALLE knapper app-bredt.
   Bootstrap's --bs-btn-focus-box-shadow var overskrevet til transparent → :focus-visible fik ingen ring. */
.btn:focus-visible { outline: none; box-shadow: 0 0 0 .25rem rgba(37, 99, 235, .35); }
.btn-sm { font-size: .8rem; }

.btn-primary { background: var(--accent); border-color: var(--accent); }
.btn-primary:hover, .btn-primary:focus { background: var(--accent-hover); border-color: var(--accent-hover); }

/* Knap-hierarki (bruger-standard 2026-07-21): solid blå = primær, BLÅ-SOFT = sekundær handling,
   RØD-SOFT = destruktiv — hvide knapper på hvid flade er forbudt. Undtagelse: VÆLGER-grupper
   (btn-group: år/måneder/firma m.fl.) er tilstand, ikke handlinger — de beholder neutral hvile. */
.btn-outline-primary, .btn-outline-secondary { color: var(--accent-hover); border-color: var(--accent-border); background: var(--accent-soft); font-weight: 600; }
.btn-outline-primary:hover, .btn-outline-secondary:hover { background: #dbe7ff; border-color: var(--accent); color: var(--accent-hover); }
/* VÆLGER-CELLER I HVILE — btn-group-segmenter (Vis, Periode, Type) og PillPickerens
   piller. Neutralt fyld, IKKE hvidt: fladen bagved er hvid de fleste steder, og en hvid
   pille med kun en 1px kant er ikke en knap. Tekst --text-muted (7,3:1 på #e8ecf3).
   Uden denne regel arvede pillerne blå-soft fra reglen ovenfor og lignede dermed
   Annuller-knappen, som står tre centimeter derfra i det samme panel.
   En VALGCELLE er altid et <label> (parret med en skjult .btn-check), mens en HANDLING altid
   er et <button>. Den skelnen er gratis og kræver ingen ekstra klasser — den fanger PillPicker,
   CompanyPicker og enhver fremtidig vælger bygget over samme mønster. .pill-grid og .btn-group
   er med som eksplicitte kroge for de tilfælde hvor markup'en ikke bruger label+btn-check. */
.btn-group > .btn-outline-primary, .btn-group > .btn-outline-secondary,
.pill-grid > .btn-outline-primary, .pill-grid > .btn-outline-secondary,
label.btn-outline-primary, label.btn-outline-secondary {
    color: var(--text-muted); border-color: var(--state-rest-border);
    background: var(--state-rest); font-weight: 500;
}
.btn-group > .btn-outline-primary:hover, .btn-group > .btn-outline-secondary:hover,
.pill-grid > .btn-outline-primary:hover, .pill-grid > .btn-outline-secondary:hover,
label.btn-outline-primary:hover, label.btn-outline-secondary:hover {
    background: #dde3ee; border-color: var(--state-border); color: var(--text);
}
/* VALGT — grafit, ikke blå (farvesplit 2026-07-28). Dette er hele forskellen: det eneste
   stærkt blå i et panel er nu den ene knap der afslutter handlingen (Vælg/Gem).
   Samme "valgt-farve" på tværs af alle vælgere: Visning, Periode, Måneder, År, Firma. */
.btn-outline-primary.active, .btn-check:checked + .btn-outline-primary,
.btn-outline-secondary.active, .btn-check:checked + .btn-outline-secondary { background: var(--state); border-color: var(--state); color: #fff; }
.btn-outline-primary.active:hover, .btn-check:checked + .btn-outline-primary:hover,
.btn-outline-secondary.active:hover, .btn-check:checked + .btn-outline-secondary:hover { background: var(--state-hover); border-color: var(--state-hover); color: #fff; }

/* POPOVER-TRIGGER (PillPicker, CompanyPicker, Firmaers konto-filter, Budgets firmavælger).
   Knappens TEKST er den nuværende tilstand — "2026", "Alle måneder", firmanavnet — så den skal
   læses som tilstand, ikke som handling. Før var den blå-soft ligesom Annuller, og resultatet var
   en værktøjslinje hvor "Visning: Regnskab" (blå kasse) og "Medregn budget: Nej" (grafit pille)
   så ud som to vidt forskellige slags kontrol, selvom de viser præcis det samme (fund 2026-07-28
   ved gennemgang i browser). Klikbarheden bæres af chevronen, ikke af farven. */
.kt-vaelger.btn-outline-primary,
.kt-vaelger.btn-outline-secondary {
    background: var(--state-rest);
    border-color: var(--state-rest-border);
    color: var(--text);
    font-weight: 500;
}
.kt-vaelger.btn-outline-primary:hover,
.kt-vaelger.btn-outline-secondary:hover {
    background: #dde3ee; border-color: var(--state-border); color: var(--text);
}
/* Åbent panel: markér HVILKEN trigger der hører til panelet — ellers svæver popoveren løsrevet. */
.kt-vaelger-aaben.btn-outline-primary,
.kt-vaelger-aaben.btn-outline-secondary {
    border-color: var(--state); background: var(--state-soft);
}
/* Chevron som inline SVG. Bootstrap Icons er IKKE indlæst i appen (verificeret 2026-07-28:
   ingen bootstrap-icons.css blandt stylesheets, ingen fil i wwwroot), så <i class="bi bi-*">
   tegnede 0x0 pixels — alle fire vælgere stod uden nogen antydning af at de kan åbnes.
   Sidebaren gik fri, fordi NavMenu.razor.css tegner sine egne ikoner som baggrunds-SVG. */
.picker-chevron { width: .68em; height: .68em; flex: none; opacity: .5; }

/* ===== VÆLGER-PANELET =====================================================
   Placeringen (bruger-regel 2026-07-29): CENTRÉR under egen knap, og lad aldrig
   panelet gå ud over indholdskolonnens kanter. Kan det ikke centreres indenfor,
   skubbes det ind — højst til det flugter med kanten.

   CSS kan kun det første led: centreringen. Kolonnens kant kendes først når
   panelet er målt, så selve klampningen sker i kt-ui.js (ktKlampVaelgerpanel),
   som overskriver `left` og nulstiller transform. Uden centreringen herunder
   ville panelet blinke i venstre position i det ene billede før JS'en rammer.

   INGEN FARVER HER — rolle-tagene (kt-valgt, kt-ikke-valgt, kt-hjaelpevalg,
   kt-valg-annuller, kt-valg-accepter) er sat i markup, men får først farve når
   hele appen er gennemgået (bruger 2026-07-29).
   ========================================================================== */
/* position: FIXED, ikke absolute (bruger 2026-07-29: "filter boksen må gerne gå ned over bunden
   af tabellen"). Et absolut placeret panel klippes af tabellens scroll-container, og forsøget på
   at slå klipningen fra virkede aldrig: CSS tillader ikke overflow-y:visible sammen med
   overflow-x:auto — browseren laver stille visible om til auto. Et fast placeret panel har
   viewporten som ramme og klippes derfor slet ikke.

   BEMÆRK: fixed løser IKKE lag-problemet. En fast placeret efterkommer males stadig inde i den
   stakke-kontekst en forfader danner — og kolonneoverskriften danner én med z-index:3, mens den
   faste sum-linje ligger på 4. Derfor løftes overskriften separat nedenfor.

   top/left sættes af kt-ui.js, som også skal sætte min-width: på et fast placeret element ville
   min-width:100% betyde SKÆRMENS bredde, ikke knappens. */
/* HUSETS POPOVER-MÆRKAT (fund 123). `.kt-pop` bærer REGLEN, ikke udseendet: den binder popoveren
   til den fælles positionerings-mekanik i kt-ui.js, som holder den inde i viewporten. Udseendet
   kommer fortsat fra den flade, popoveren hører til (.kt-vaelgerpanel, .colfilter-pop,
   .dropdown-menu). Enhver NY popover skal bære mærkatet — værnet i DialogVaernTests måler det. */
.kt-pop { z-index: 1050; }

/* FUND 134 (Michael, AppTest 649: "popoveren HOPPER"). MÅL OG PLACÉR FØR FØRSTE VISNING: en popover
   er usynlig, indtil mekanikken i kt-ui.js har set den og sat `data-kt-placeret`. Uden dette blev
   den tegnet dér, hvor markup'en tilfældigvis lagde den, og flyttede sig først bagefter — det var
   selve hoppet.

   VÆRNET mod at det bliver værre end sygdommen: reglen gælder KUN under `html.kt-ui`, og den klasse
   sættes af kt-ui.js selv. Indlæses scriptet ikke, findes klassen ikke, og popovers vises som før i
   stedet for at forsvinde. Flaget sættes desuden FØR alle tidlige returer i mekanikken, så en
   popover uden anker eller ramme heller ikke kan blive hængende usynlig.

   Selektorlisten skal være PRÆCIS den samme som KT_POPOVERE i kt-ui.js — samme regel, to sprog.
   DialogVaernTests holder de to op mod hinanden. */
html.kt-ui .kt-pop:not([data-kt-placeret]),
html.kt-ui .kt-vaelgerpanel:not([data-kt-placeret]),
html.kt-ui .colfilter-pop:not([data-kt-placeret]),
html.kt-ui .dropdown-menu.show:not([data-kt-placeret]) { visibility: hidden; }

.kt-vaelgerpanel {
    position: fixed;
    z-index: 1050;
    width: max-content;
    background: var(--surface);
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    box-shadow: 0 8px 24px rgba(15, 21, 37, .12);
    padding: 8px;
}
/* 1600026: vælgerens fod er den samme linje i alle paneler — Vælg og Annuller, centreret, med den
   samme skillelinje over. Bredden kommer fra .kt-dialogknapper, som knapperne i en dialog. */
.kt-vaelgerfod { padding: 10px 6px 2px; border-top: 1px solid #f1f5f9; margin-top: 6px; flex: none; }

/* Foden i en popover uden skillelinje (kolonnefilteret, udvalgsvælgeren): kun luften over. */
.kt-popoverfod { margin-top: .7rem; }

/* 1600026: koncernhovedet SER ens ud alle steder. Hvor kun ét firma kan vælges, er hovedet ikke et
   valg, og så må det heller ikke svare på mus eller tastatur — men det er den samme linje, og den
   står det samme sted. */
.kt-koncernhoved { pointer-events: none; }

/* FUND 119 (1600026 rev 2, Michaels dom 16/9 2026): "Har to firmaer samme navn, står udbyderen som
   undertekst under hvert af dem."
   Valgcellen var én linje med afkortning (text-overflow: ellipsis). Med en undertekst skal cellen
   bære TO linjer, og afkortningen flytter derfor ned på navnet selv, så et langt navn stadig
   stopper med prikker i stedet for at sprænge panelets bredde. Underteksten står kun på de celler,
   der HAR en, så de entydige navne ser ud præcis som før (1600026: vælgeren er én og samme). */
.kt-firmavalg { display: block; overflow: hidden; }
.kt-firmavalg-navn { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kt-firmavalg-under {
    display: block; font-size: .72rem; opacity: .7; line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Michaels fund 16/9 2026 (Salgsbudget): firmavælgerens panel lå KLEMT under værktøjslinjen med
   Opret ny. Årsagen er stakkene: begge værktøjslinjer er sticky med z-index 6, og panelet er
   tegnet inde i den ØVERSTE af dem. Panelets egne 1050 gælder kun inde i den linjes egen
   stakke-kontekst, så den NÆSTE værktøjslinje (samme z-index, senere i dokumentet) malede hen
   over panelets øverste del, netop dér hvor søgefeltet står.
   En værktøjslinje med en åben popover løftes derfor over sine søskende. Løftet gælder kun mens
   popoveren er åben; lukkes den, falder linjen tilbage på plads. Selektorlisten er den samme
   familie, som mekanikken i kt-ui.js kender. */
.toolbar:has(.kt-pop),
.toolbar:has(.kt-vaelgerpanel),
.toolbar:has(.colfilter-pop),
.toolbar:has(.dropdown-menu.show) { z-index: 1051; }

/* De tre placerings-varianter. Selve tallene regnes i kt-ui.js — klasserne er kun mærkater,
   så reglen står ét sted og JS kan kende den:
     (ingen)                centreret under egen knap
     .kt-panel-kolonnekant  flugter med indholdskolonnens venstre kant   (Firma)
     .kt-panel-knapkant     flugter med knappens egen venstre kant       (kolonnefilter)
   Alle tre klampes mod rammens højre kant. */

/* Kolonnefilterets panel skal over den faste sum-linje (z-index 4/5). Panelet står selv på 1050,
   men det tal gælder kun INDE i overskriftens stakke-kontekst (z-index 3), så sum-linjen malede
   henover. Løftet gælder kun mens et filter er åbent — ellers skal sum-linjen blive liggende
   over de almindelige rækker som hidtil.

   TO selektorer, fordi den første kolonnes overskrift allerede sættes af
   .sticky-first thead tr:first-child th:first-child (specificitet 0,3,3). En enkelt
   .table thead th:has(...) (0,2,2) TABER den kamp og gjorde ingenting — målt: z-index blev
   ved med at være 3. Anden linje matcher derfor den eksisterende selektor plus :has. */
.table thead th:has(.colfilter-pop),
.sticky-first thead tr:first-child th:first-child:has(.colfilter-pop) { z-index: 20; }

/* SLÅET FRA (bruger-fund 2026-07-29). Bootstrap tegner en deaktiveret .btn-primary med sin EGEN
   --bs-btn-disabled-bg (#0d6efd) i fuld styrke — altså en anden blå end appens, og den så mere
   fremtrædende ud end en aktiv knap. En deaktiveret .btn-outline-* blev omvendt helt gennemsigtig
   og forsvandt på den hvide flade. Begge dele rettes ét sted: slået fra er ALTID dæmpet grå med
   samme fyld som en ikke-valgt celle, så den læses som "kan ikke bruges lige nu". */
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
    background: var(--state-rest) !important;
    border-color: var(--state-rest-border) !important;
    color: var(--text-muted) !important;
    opacity: .65;
    box-shadow: none;
}

/* FILUPLOAD er en HANDLING, ikke en valgcelle (bruger-fund 2026-07-29). Man kan ikke style et
   <input type="file">, så knappen bygges som et <label> der dækker over et skjult felt — præcis
   det mønster som regel-linjen "en valgcelle er altid et <label>" ovenfor ellers fanger. Uden
   denne undtagelse så "Importér" grå og inaktiv ud ved siden af "Eksportér". */
label.btn-outline-primary:has(input[type="file"]),
label.btn-outline-secondary:has(input[type="file"]) {
    color: var(--accent-hover);
    border-color: var(--accent-border);
    background: var(--accent-soft);
    font-weight: 600;
}

.btn-outline-danger { color: #b91c1c; border-color: #fecaca; background: #fef2f2; font-weight: 600; }
.btn-outline-danger:hover { background: #fee2e2; border-color: #fca5a5; color: #991b1b; }

/* ===== FUND 102: KNAPPENS ROLLE BESTEMMER FARVEN (Michaels dom B, 2026-08-22) =====

   Farven følger knappens ROLLE, ikke et antal pr. side. Tre roller, og kun tre:

     kt-handling            UDFØRER noget (Opdatér, Hent Excel, Gem, Opret, Eksportér, Slå op).
                            Blå og solid. ALLE handlinger har SAMME vægt - det er netop dét, der
                            fjerner vilkårligheden i fund 102, hvor to nabo-handlinger på samme
                            flade havde hver sin vægt uden at nogen havde besluttet det.
     kt-navigation          FØRER ET ANDET STED HEN (Firmaer, Regnskabsforbindelser, Se loggen,
                            Angiv likviditetskonti). Outline og lys.
     kt-destruktiv          SLETTER eller LUKKER noget. Outline på fladen ...
     kt-destruktiv-bekraeft ... og solid KUN i selve bekræftelses-dialogen.

   Klasserne er skrevet, så en knap VÆLGER en rolle i stedet for at vælge en farve. Deklarationerne
   er med vilje de samme som de bootstrap-klasser, de afløser: skiftet må ikke i sig selv ændre,
   hvordan en knap SER ud - kun hvilke knapper der har hvilken vægt.

   Uden for de tre roller står de familier, huset allerede skelner (se VÆLGER-CELLER ovenfor):
   valgceller og tilstands-kontakter (Ja/Nej, periode, firmavælger), hjælpevalg i en popover
   (Vælg alle, Ryd), luk-krydset og rækkernes ⋯-menu. De udfører ikke noget og fører ingen steder
   hen; de siger, hvad man ser på. Værn: KnapRolleTests. */
.btn.kt-handling { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.kt-handling:hover, .btn.kt-handling:focus { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }

.btn.kt-navigation { color: var(--accent-hover); border-color: var(--accent-border); background: var(--accent-soft); font-weight: 600; }
.btn.kt-navigation:hover { background: #dbe7ff; border-color: var(--accent); color: var(--accent-hover); }

.btn.kt-destruktiv { color: #b91c1c; border-color: #fecaca; background: #fef2f2; font-weight: 600; }
.btn.kt-destruktiv:hover { background: #fee2e2; border-color: #fca5a5; color: #991b1b; }

.btn.kt-destruktiv-bekraeft { background: #dc3545; border-color: #dc3545; color: #fff; }
.btn.kt-destruktiv-bekraeft:hover, .btn.kt-destruktiv-bekraeft:focus { background: #bb2d3b; border-color: #b02a37; color: #fff; }

/* Knapgruppen i en dialog (1600022, 1600023 rev 2, 1600025; Michaels domme 15/9 og 16/9 2026):
   OK eller den primære handling står til VENSTRE for Annuller, knapperne er LIGE STORE inden for
   den enkelte dialog, og gruppen står CENTRERET under teksten.

   Bredden er den BREDESTE knap i netop denne gruppe, ikke et fast tal for alle dialoger (1600023
   rev 2: "størrelsen gælder inden for den enkelte dialog, ikke på tværs af dialoger"). Den gamle
   faste min-width på 9.5rem gjorde alle dialoger lige brede og tvang smalle dialoger, som Log ud,
   til at være bredere end deres indhold (1600025).

   Mekanikken: et gitter med lige brede kolonner, der kun fylder sit eget indhold. Gitterets
   max-content er antallet af knapper gange den bredeste, så hver knap får præcis den bredeste
   knaps bredde — uden at nogen kender tallet på forhånd. minmax(0, 1fr) lader knapperne krympe
   sammen på en smal skærm i stedet for at løbe ud over kortets kant.

   Gruppen rummer KUN knapper. En fod med andet indhold (status, hjælpevalg) lægger sine knapper i
   en .kt-dialogknapper inde i foden — ellers ville teksten blive en lige så bred kolonne. */
.kt-dialogknapper {
    display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
    gap: .5rem; align-items: center; justify-content: center;
    width: fit-content; margin-left: auto; margin-right: auto;
}
.kt-dialogknapper > .btn { min-width: 0; width: 100%; text-align: center; }

/* Én pill-stil for ALLE badges (global — afløser rå Bootstrap bg-*-badges) */
.kt-pill { display: inline-flex; align-items: center; border-radius: 999px; padding: .14rem .6rem; font-size: .72rem; font-weight: 600; white-space: nowrap; line-height: 1.25; }
.kt-ok { background: #dcfce7; color: #166534; }
.kt-warn { background: #fef3c7; color: #92400e; }
.kt-bad { background: #fee2e2; color: #b91c1c; }
.kt-info { background: #dbeafe; color: #1d4ed8; }
.kt-mute { background: #e2e8f0; color: #475569; }
/* M-2 (release 4): FORFALDEN momsafregning i likviditets-drilldownen. Samme advarsels-familie som
   sidens gule banner, men et trin kraftigere end .kt-warn, som al anden beregnet moms bruger — det
   er netop forskellen på den kommende og den overskredne afregning, der skal kunne ses i et blik.
   Ikke .kt-bad: en forfalden angivelse er en advarsel, ikke en fejl. */
.kt-forfalden { background: #fed7aa; color: #9a3412; }
.kt-light { background: var(--surface); color: var(--text-muted); border: 1px solid var(--border); }
/* FIRMAMÆRKET (runde 9, B75; 1500026, Michael 12/9 2026): firmaets forkortelse i firmaets egen farve,
   som Firmaer-sidens avatar viser den, på linjer, der ellers ikke kan kendes fra hinanden i en
   koncernvisning (balancens kontolinjer). Baggrunden sættes inline af firmaets farve; teksten er hvid
   som i avataren. Mærket står SIDST i postnavnets celle, højrestillet med margin-left: auto i
   navnecellens flex-række (.bal-navn), aldrig foran nummeret, så kontonumrene flugter i venstre kant.
   Fast mindstebredde, så mærkerne er lige brede, når koderne er af forskellig længde. */
.firma-maerke { color: #fff; min-width: 3.4rem; justify-content: center; padding: .1rem .45rem; font-size: .66rem; letter-spacing: .03em; margin-left: auto; }
.bal-navn { display: flex; align-items: center; column-gap: .5rem; min-width: 0; }
.bal-navn > .bal-etiket { min-width: 0; }

/* E4 (fund 83): en tabelrække, der ÅBNER noget. Markøren er hele markeringen — rækken er allerede
   table-hover, og en ekstra farve ville konkurrere med de røde tal i de samme rækker. */
.kt-klikbar { cursor: pointer; }

/* E1 (fund 76): en post, der er FRAVALGT af analysen. Den står stadig i tabellen med sit beløb —
   Michaels dom er, at man skal kunne se, hvad der er sat til side — men gennemstreget og dæmpet, så
   den ikke kan læses som et tal, der er talt med. Gennemstregningen sættes på cellerne og ikke på
   rækken: en <tr> med text-decoration slår ikke igennem på cellernes indhold i alle browsere. */
.kt-udeladt, .kt-udeladt > td { text-decoration: line-through; color: var(--text-muted); }
/* Mærket siger hvad posten ER, og det er stadig sandt — en streg tværs over en pille gør den kun
   svær at læse. */
.kt-udeladt .kt-pill { text-decoration: none; }

/* Regnskabsudbyder-tags (2026-07-23): fast, distinkt farve PR. UDBYDER — bevidst uden for de
   semantiske licens-farver (grøn=licens, gul=prøve, rød=fejl), så udbyder aldrig forveksles med
   status. En lille farvet prik + navn. */
/* Forenklet (bruger-ønske 2026-07-23): NEUTRAL pille (tom baggrund + fast grå ramme, mørk tekst),
   hvor KUN farveprikken varierer pr. udbyder — mindre farvelade, prikken er den eneste type-markør. */
.kt-prov { gap: .35rem; background: var(--surface); border: 1px solid var(--border); color: var(--text); }
.kt-prov::before { content: ""; width: .5rem; height: .5rem; border-radius: 999px; background: var(--prov-dot, #94a3b8); }
/* Tydeligt adskilte prik-farver (bruger-ønske 2026-07-23): grøn / blå / rød — de tre mest
   forskellige kulører, umiskendelige selv ved lille prik-størrelse. */
/* Prikken skal ADSKILLE regnskabssystemer, ikke sige noget om deres tilstand (bruger-fund
   2026-07-29). Før var Dinero grøn og Billy rød, og det blev læst som "Dinero kører, Billy er
   nede" — en betydning der slet ikke findes i data. e-conomic var desuden præcis appens
   handlingsblå. Nu tre mættede kulører langt fra hinanden, ingen af dem i god/dårlig-båndet
   (grøn/rød/gul) og ingen af dem #2563eb. Systemets navn står ved siden af prikken, så farven
   er en støtte og ikke den eneste oplysning. */
.prov-dinero { --prov-dot: #7c3aed; }    /* violet */
.prov-economic { --prov-dot: #0891b2; }  /* cyan */
.prov-billy { --prov-dot: #db2777; }     /* magenta */
.prov-other { --prov-dot: #64748b; }     /* skifergrå */

/* ⓘ-hint: forklaringer bor i tooltips, aldrig som permanent brødtekst */
/* Info-ikonet er ALTID et lille i (bruger-regel): text-transform:none på SELVE ikonet, så en
   uppercase-forælder (tb-label, bud-label, …) aldrig kan gøre ⓘ til Ⓘ igen (fund 2026-07-25 ×2). */
.kt-hint { margin-left: .15rem; color: var(--text-muted); cursor: help; font-weight: 500; font-size: .85rem; text-transform: none; letter-spacing: normal; }

/* Segmenterede grupper får luft + bløde ender */
.btn-group > .btn { font-weight: 500; }

/* Fokus-ring i accentfarve */
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus,
.form-control:focus, .form-select:focus, .form-check-input:focus {
    box-shadow: 0 0 0 .2rem var(--accent-soft);
    border-color: var(--accent);
}

/* ===== Formularer ===== */
.form-label { font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); font-weight: 600; margin-bottom: .25rem; }
.form-select, .form-control { border-radius: var(--radius-xs); border-color: var(--border-strong); color: var(--text); font-size: .84rem; box-shadow: var(--shadow-sm); }
.form-select:hover, .form-control:hover { border-color: var(--border-strong); }
.form-check-input { border-color: var(--border-strong); }
/* Afkrydsning og kontakter er TILSTAND, ikke handling — grafit (farvesplit 2026-07-28). */
.form-check-input:checked { background-color: var(--state); border-color: var(--state); }
.form-switch .form-check-input:checked { background-color: var(--state); border-color: var(--state); }
/* Likviditetsplanens "Egen dato" (punkt 2): feltet bærer retningens farve; ordet kommer fra kernen
   (LikviditetsPlan.DatoRetning), tokens i :root. */
.form-control.likplan-dato-tidligere { background: var(--plan-tidligere-bg); color: var(--plan-tidligere); border-color: var(--plan-tidligere); font-weight: 600; }
.form-control.likplan-dato-senere { background: var(--plan-senere-bg); color: var(--plan-senere); border-color: var(--plan-senere); font-weight: 600; }

/* ===== Filter-værktøjslinje (samlet kort med kontroller) ===== */
.toolbar {
    display: flex;
    flex-direction: column;
    gap: .6rem;
    width: 100%;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: .7rem .85rem;
    margin-bottom: .85rem;
}

/* .graf-udvalg står i listerne herunder, fordi udvalget på Kunder-siden er FLYTTET ind i grafens
   sektion (K-4). Felterne skal se ud præcis som i en toolbar-række; værdierne må derfor kun stå ét
   sted, og linjen låner reglerne frem for at kopiere dem. */
/* Fixrunden efter nattesten 10/9, fund F5: luften MELLEM felterne er sat ned fra 1,1rem til 0,6rem,
   og luften inde i et felt fra 0,45rem til 0,35rem. Omkostningsoverblikkets værktøjslinje brækkede
   over to linjer ved 1920 px, hvor kravet er én, og luften er den ene af de tre lovlige veje til
   pladsen (kortere etiketter og kompakte vælgere er de to andre; et felt skjules aldrig).
   De to linjer holdes ens, fordi grafudvalgets felter SKAL se ud som en værktøjslinjes. */
.toolbar .tb-row, .graf-udvalg { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .6rem; }
.toolbar .tb-field, .graf-udvalg .tb-field { display: flex; align-items: center; gap: .35rem; }
.toolbar .tb-label, .graf-udvalg .tb-label { font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); line-height: 1; white-space: nowrap; }
.toolbar .tb-right { margin-left: auto; display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
/* Ens font på ALLE kontroller i værktøjslinjen (dropdowns, knapper, selects) */
.toolbar .btn, .toolbar .form-select, .toolbar .form-control,
.graf-udvalg .btn, .graf-udvalg .form-control { font-size: .82rem; }
/* N16-dimensionskassen (Michael 2026-08-11, 2. iteration): dimensionerne bor i deres EGEN kasse
   lige under værktøjslinjen — samme visuelle familie (surface/ramme/radius/skygge), lavere profil —
   med "Dimensioner"-mærkat PÅ rammen (fieldset/legend-udtryk). Trækkes en anelse op mod toolbaren,
   så de læses som hørende sammen uden at bo i samme kasse. */
.dim-box {
    position: relative;
    /* 3. iteration (Michaels feedback 2026-08-11: "det ser ikke godt ud"): kassen KLÆBEDE op ad
       toolbaren (negativ margin = to rammer oven i hinanden) og spændte tom over hele bredden.
       Nu: normal luft til toolbaren og en ramme der KRYMPER til indholdet. */
    display: inline-flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.1rem;
    width: fit-content; max-width: 100%;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: .85rem .95rem .6rem;
    /* F24 (Michael 14/9 2026, AppTest 1643): mærkatet "Dimensioner" stod halvt skjult under
       værktøjslinjens kort. Årsagen er den fastgjorte værktøjslinje: .content > .toolbar er sticky
       med z-index 6 og en MASSIV skygge på .85rem i sidens baggrundsfarve (B69, se reglen længere
       oppe), som dækker luften under kortet. Kassen begyndte præcis dér, hvor skyggen slap, og
       mærkatet rager .55em OP over kassens kant — altså op i skyggen, som maler over det.
       Kassen får derfor luft nok til, at mærkatet står HELT frit under værktøjslinjen med samme
       afstand som de øvrige kortoverskrifter. */
    margin: .55rem 0 .85rem;
}
.dim-box .btn, .dim-box .form-select { font-size: .82rem; }   /* samme kontrol-skala som toolbaren */
.dim-box-label {
    position: absolute; top: -.55em; left: .7rem;
    background: var(--surface); padding: 0 .35rem;
    border-radius: var(--radius-xs);
    font-size: .62rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em;
    color: var(--text-muted); line-height: 1; white-space: nowrap;
}
/* Ens rækkehøjde i budgettabellen (Michael 2026-08-11): manuelle rækker har en ⋯-knap, synkede
   har kun et badge — uden fast højde blev rækkerne forskellige. Fast celle-højde + kompakt knap,
   så alle rækker måler det samme uanset indhold. */
.budget-table tbody td { height: 2.15rem; }
.bud-menu-btn { padding: 0 .5rem; line-height: 1.45; }
/* Kilde-cellens faste slots (Michael 2026-08-11): kilde-mærket, !-flaget og ⋯-knappen har hver
   deres kolonne med fast bredde, så mærkerne står lodret under hinanden på tværs af rækkerne —
   også når en række kun har nogle af dem.
   FUND 179 punkt 2 (2026-08-23): dimensions-slottet er væk. Dimensionen er sin EGEN kolonne
   (.col-dim) og har derfor sin egen lodrette linje af sig selv. */
.bud-actions { display: inline-flex; align-items: center; gap: .35rem; }
/* FUND 179 punkt 3 (2026-08-23): periodiserings-advarslen KLISTRER på "Synkroniseret"-mærket i
   stedet for at have sin egen slot. Den kan pr. definition kun findes på en synkroniseret linje, og
   den koster nu ingen bredde: ikonet ligger uden for tekstflowet i mærkets øverste højre hjørne. */
.bud-sync { position: relative; display: inline-block; }
.bud-sync .bud-accrue {
    position: absolute; top: -.3rem; right: -.28rem;
    color: #b91c1c; font-weight: 700; font-size: .72rem; line-height: 1; cursor: help;
}
/* FUND 179: "Synkroniseret" er et længere ord end det gamle udbyder-mærke, og slottet er nu det
   ENESTE i kilde-cellen. Bredden er derfor en MINDSTE-bredde: mærkerne flugter stadig lodret på
   tværs af rækkerne, men det længste af dem bliver ikke klippet af en fast bredde. */
.bud-actions .slot-src  { min-width: 5.4rem; text-align: center; }
.bud-actions .slot-menu { width: 2rem;   text-align: right; }
/* Samme indkapsling i budget-formularen (Michael 2026-08-11): dimension-vælgerne i opret/redigér
   står i deres egen tynde ramme med mærkat på rammen — genbruger .dim-box-label. */
.bud-dim-group {
    position: relative;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: .85rem .75rem .6rem;
    margin-top: .45rem;   /* luft til mærkatten der rager op over rammen */
}

/* ===== Nøgletal-kort ===== */
/* S1.5-12 (bruger-fund 2026-07-25): ALLE brikker på en side skal have SAMME bredde — flex lod sidste
   rækkes brikker (fx Resultatgrad) vokse op mod 1/3-cappen når rækken ombrød. Grid med auto-fill giver
   identiske spor uanset antal (fleksibelt, ikke hardcodet), og en enlig brik fylder ét spor — dermed
   dækkes også bruger-punkt 1 (2026-07-20: enlig brik må ikke fylde hele bredden). */
/* UI-fixrunde 1, punkt 3 (Michaels dom 9/9): BREDDER REGNES UD FRA RAMMEN, ALDRIG UD FRA INDHOLDET.
   auto-fill lagde et fast spor-mindstemaal (180 px) til grund og brød derfor rækken til to linjer,
   så snart rammen blev for smal til n spor — og analysesidernes auto-fit lukkede godt nok de tomme
   spor, men begge regnede stadig i indhold. */
/* UI-fixrunde 2, punkt 1 (beslutning 1400024): den tvungne ene række (grid-auto-flow column) er ude
   igen. Den var rigtig på en bred skærm og forkert på en smal: syv fliser på en telefon blev syv
   ubrugelige strimler. Reglen er nu: ÉN række, når rammen giver hver flise mindst dens
   minimumsbredde, ellers så få LIGE STORE rækker som muligt, og aldrig én flise alene på en række.
   Valget kræver en måling af rammen og af flisernes egen tekst og bor derfor i kt-ui.js
   (ktKpiLaegUd), som skriver flex-basis på fliserne. Her står KUN udgangspunktet, og det er med
   vilje ÉN række: uden JavaScript (første server-tegning) står fliserne som før, så siden aldrig
   hopper synligt, og skiftet sker før første maling, hvor det kan.
   1400022 gælder uændret: en fravalgt flise renderes slet ikke, efterlader intet hul og tælles ikke
   med, og de øvrige deler rammen. */
.kpi-row { display: flex; flex-wrap: wrap; gap: .85rem; margin-bottom: .85rem; }
/* flex-basis 0 + grow 1 = lige store fliser på én række, uanset hvor mange der er. Rækkeopdelingen
   sætter et andet flex-basis pr. flise (rækkens andel), og grow deler resten ligeligt inden for
   RÆKKEN, så en række med tre fliser er lige så bred som en række med fire. */
.kpi-row > * { flex: 1 1 0; min-width: 0; }
.kpi-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: .8rem 1rem .85rem 1.15rem;
    display: flex; flex-direction: column; gap: .3rem;
    position: relative; overflow: hidden;
}
.kpi-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--kpi, var(--accent)); }
/* RC1-7: brikken klipper sit indhold (overflow:hidden bærer den farvede kant), og en lang
   etiket som PERSONALEOMKOSTNINGER er ET ord — uden en brydning kunne den ikke ombryde og blev
   vist som "PERSONALEOMKOSTNINGE". Etiketten må hellere fylde to linjer end at lyve om sit
   navn. (hyphens:auto blev prøvet og gjorde intet i Chrome, så den står ikke her.)
   FUND 148: brydningen blev grim ("…NINGE / R"), fordi break-word deler MIDT i ordet. De faste
   etiketter bærer derfor en blød bindestreg (&shy; / \u00AD) på ordgrænsen — "PERSONALE-/
   OMKOSTNINGER" — og browseren bruger den FØRST. overflow-wrap står tilbage som fallback for de
   etiketter, der ikke har en ordgrænse at dele ved.
   UI-fixrunde 1, punkt 3 (Michaels dom 9/9): ombrydningen er væk igen. Etiketten må KLIPPES med
   ellipsis, men aldrig bryde til en ny linje — en brik, der bliver to linjer høj, fordi netop dens
   etiket er lang, er præcis den "bredde efter indholdet", dommen forbyder. De bløde bindestreger i
   etiketterne står tilbage uden virkning (de gør intet ved white-space:nowrap) og er harmløse; de
   koster ingenting, og de er der, hvis reglen en dag skal om igen. */
.kpi-label { font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Værdien bryder aldrig: MoneyFit skifter til t.kr., når det fulde beløb ikke kan stå på én linje
   (se .money-fit nedenfor), og de brikker, der bærer et antal eller en procent, klippes hellere end
   at vælte brikken. */
.kpi-value { font-size: 1.5rem; font-weight: 650; letter-spacing: -.02em; line-height: 1.1; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.kpi-delta { font-size: .85rem; font-weight: 600; font-variant-numeric: tabular-nums; margin-left: .4rem; }

/* MoneyFit (bruger-regel 2026-07-16): beløb i KPI-brikker må ALDRIG ombryde "kr." til næste linje.
   Begge varianter renderes (fuld + t.kr.); money-fit.js måler den usynlige probe mod pladsen og
   toggler .is-compact. Proben er absolute (påvirker ikke layout) men altid målbar — den synlige
   fulde variant er display:none i kompakt tilstand og kan derfor ikke selv måles. */
.money-fit { position: relative; display: block; white-space: nowrap; overflow: hidden; }
.money-fit .mf-probe { position: absolute; left: 0; top: 0; visibility: hidden; pointer-events: none; white-space: nowrap; }
.money-fit .mf-compact { display: none; }
.money-fit.is-compact .mf-full { display: none; }
.money-fit.is-compact .mf-compact { display: inline; }

/* ===== Dropdown ===== */
.dropdown-menu { border-radius: var(--radius-sm); border: 1px solid var(--border); box-shadow: var(--shadow-lg); padding: .4rem; font-size: .86rem; }
.dropdown-item { border-radius: 6px; padding: .4rem .6rem; }
.dropdown-item:hover { background: var(--surface-2); }
/* Det valgte punkt i en menu er TILSTAND. */
.dropdown-item.active, .dropdown-item:active { background: var(--state); color: #fff; }

/* ===== Badges ===== */
.badge { font-weight: 600; border-radius: 6px; }
.badge.bg-secondary { background: var(--text-muted) !important; }
.badge.bg-light { background: var(--surface-2) !important; color: var(--text-muted) !important; border: 1px solid var(--border); }

/* ===== Blazors fejlbanner (FUND 170) =====
   Elementet har et FAST id og tegnes af BEGGE layouts (MainLayout og BankLayout). Reglerne lå
   indtil RUL3-BC i MainLayout.razor.css — en SCOPED fil, som Blazor binder til MainLayouts egen
   markup. Bank-visningen arvede dem derfor ikke, "display:none" gjaldt ikke der, og banneret
   "Der opstod en uventet fejl" stod permanent på hver eneste bank-side, uden at noget var galt.
   En regel om et element, to layouts deler, hører i den fælles css. Blazor tænder selv banneret
   med en inline style, når der FAKTISK sker en fejl — den vinder over reglen her. */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

/* ===== Kort + tabeller ===== */
.table-responsive {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    overflow: auto;
    /* Tabellen scroller i sit eget kort (app-shell-flex nedenfor styrer højden, så kortets bund
       altid lander ved skærmkanten — ingen side-scroll oveni tabel-scroll). */
}

/* Når et kolonne-filter er åbent: lad kortet flyde ud, så popoveren må gå ned under nederste
   række (ellers klipper kortets scroll den væk på korte tabeller). Bruger-fund 2026-07-21:
   overflow:visible alene lod TABELLENS EGNE rækker male sig ud over rammen uden at rammen selv
   voksede (.content > .table-responsive har flex-shrink:1 og krymper under indholdets naturlige
   højde) — pagineringslinjen derunder blev så positioneret ved den krympede (for lave) kant og
   overlappede de sidste rækker. flex-shrink:0 tvinger rammen til at vokse til rækkernes fulde
   højde i stedet, så intet efterfølgende element ligger oven i noget.
   Bruger-fund 2026-07-21 (nr. 2 — "horisontalt"): den brede overflow:visible-shorthand fjernede
   OGSÅ overflow-x, så brede tabeller (fx Budgetposter m. 10 kolonner) malede sig ud til højre for
   kortet i stedet for at forblive vandret scrollbare i det. overflow-x:auto genindsat eksplicit —
   kun lodret (popoveren nedad) skal undslippe, ikke vandret (tabellens egen bredde). */
/* AFLIVET 2026-07-29. Reglen kunne aldrig gøre det den lovede: CSS tillader ikke overflow-y:visible
   sammen med overflow-x:auto — browseren laver stille visible om til auto, og målingen bekræftede
   det (computed overflowY = auto). Klipningen forsvandt altså aldrig; til gengæld fjernede
   max-height:none tabellens højde-loft, så hele tabellen HOPPEDE hver gang et filter blev åbnet.
   Panelet er nu position:fixed og klippes slet ikke, så der er intet at slå fra.
   .table-responsive:has(.colfilter-pop) { overflow-y: visible; overflow-x: auto; max-height: none; flex-shrink: 0; } */

/* Tabeller med få, smalle kolonner (fx Budgetposter) skal tilpasse sig deres indhold i stedet for
   at strække ud over hele bredden med store mellemrum mellem kolonnerne. */
.table-responsive.table-fit { width: max-content; max-width: 100%; }

/* Budgetposter: fyld bredden, men hold rækkerne på én linje (ens højde) og lad Notat-kolonnen
   opsuge den ekstra plads, så de øvrige kolonner står tæt i stedet for at sprede sig jævnt. */
.budget-table { width: 100%; }
/* Én linje pr. række. Cifre er TABULAR (F1, testfeedback): beløbskolonner skal flugte lodret —
   det tidligere "proportionale cifre for datoernes skyld" gav hoppende tusindtals-separatorer. */
.budget-table td, .budget-table th { white-space: nowrap; }
/* Notat-kolonnen opsuger den ekstra bredde (men forbliver én linje, så rækkehøjden er ens).
   FUND 88: vælgeren var POSITIONEL (nth-last-child(2)) og pegede derfor på en ny kolonne, så snart
   tabellen fik en — og den fik en, da Kilde blev sin egen. Kolonnen har nu sin egen klasse.
   Samtidig: HEADEREN må ikke klemmes med. Det var netop den, Michael så som "N:" — "Notat" skåret
   ned til ét bogstav plus filter-tragten. Sammenklemningen gælder nu kun cellerne. */
.budget-table td.col-notat { width: 100%; max-width: 0; overflow: hidden; text-overflow: ellipsis; }
.budget-table th.col-notat { width: 100%; }
/* Kilde-kolonnen: smal og fast, så mærkerne står lodret under hinanden på tværs af rækkerne. */
.budget-table td.col-kilde, .budget-table th.col-kilde { width: 1px; white-space: nowrap; }
/* FUND 179 punkt 2: dimensions-kolonnen er SMAL — den bærer kun "Ja" eller "–", og svaret står
   centreret under sin egen overskrift. Kolonnen findes kun på firmaer med dimensionsdata. */
.budget-table td.col-dim, .budget-table th.col-dim { width: 1px; white-space: nowrap; text-align: center; }

.table { margin: 0; color: var(--text); font-size: .76rem; }
.table > :not(caption) > * > * { padding: .32rem .65rem; background: transparent; line-height: 1.4; }

.table thead th {
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    border-top: none;
    color: var(--text-muted);
    font-weight: 600;
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .045em;
    white-space: nowrap;
    vertical-align: bottom;
    /* Kolonne-overskrifter altid centreret (også på tal-kolonner m. .text-end) */
    text-align: center !important;
    /* Fastlåste kolonne-overskrifter ved scroll i tabellen */
    position: sticky;
    top: 0;
    z-index: 2;
}

/* Anden header-række (måned×metrik / måned×år) lægges under den første */
.table thead tr:nth-child(2) th { top: 1.62rem; z-index: 1; }

.table tbody td, .table tbody th { border-top: 1px solid var(--border); vertical-align: middle; }

/* Tydelig lodret skille-streg mellem grupper (fx år-kolonnerne under samme måned hører sammen) */
.table .border-start { border-left: 2px solid #9aa6bd !important; }
.table thead .border-start { border-left-color: #8793ac !important; }
/* Tabeller med synligt afgrænsede kolonner (bruger 2026-07-25, fx Debitorer): lodret streg mellem
   ALLE kolonner — samme visuelle sprog som overbliks-tabellernes gruppe-afgrænsning, blot 1px. */
.table.cols-divided th + th, .table.cols-divided td + td { border-left: 1px solid var(--border); }
.table > :not(:first-child) { border-top: none; }
.table-hover > tbody > tr:hover > * { background: var(--surface-2); }

/* Rækker med drill-down (børn) markeres med KURSIV navn frem for FED */
.table tbody tr:has(button) > * { font-weight: 400; }
.table tbody tr:has(button) > td:first-child { font-style: italic; }

/* Total/aggregat-rækker */
.table-secondary, .table-secondary > * { background: var(--accent-soft) !important; color: var(--text) !important; }
/* Sektions-overskrifts-rækker (Indtægter/Udgifter i Regnskab) */
.table-light, .table-light > * { background: var(--surface-2) !important; color: var(--text) !important; }

/* Budget-/prognose-tal (fx i Sammenligning) — accentfarve, så de tydeligt adskiller sig fra faktiske tal */
.budget-fig { color: var(--accent); }
/* Bruger-krav 2026-07-30: kun PARENTESERNE er blå (og FEDE, så de er tydelige) — tallet imellem dem
   er sort, eller rødt når det er negativt, og beholder cellens vægt. Spans'ene sættes af
   BudgetTal-komponenten; reglerne her vinder over .budget-fig-arven. */
.budget-fig .budget-paren { font-weight: 700; }
.budget-fig .budget-tal { color: var(--text); }
/* F2 fra testen af 1554: de negative tal står ikke kun inde i BudgetTal-komponenten, men også i
   budgettabellernes egne celler, der ingen .budget-fig-forfader har. Reglen er derfor husets ene
   regel for negative tal, uanset hvor de står; en egen farve i cellen slår altid .budget-fig-arven.
   F3 fra eftertesten af 1558: den rene klasse var ikke nok i TABELLEN. Bootstraps egen
   `.table > :not(caption) > * > *` sætter color fra --bs-table-color (#000) og har højere
   specificitet end en klasse alene, så cellen blev ved med at stå sort uanset rækkefølgen i filen.
   Tabel-leddet hæver derfor specificiteten (klasse + klasse + type) og vinder; spans'ene inde i
   BudgetTal beholder deres eget led. Stadig ÉN regel, én farve. */
.budget-fig .budget-tal-neg,
.budget-table td.budget-tal-neg { color: var(--negative); }

/* ===== Kolonne-filter (popover pr. kolonne) ===== */
/* Usynlig baggrund bag åbne filter-popovers/dropdowns: klik udenfor lukker (bevarer input) */
.cf-backdrop { position: fixed; inset: 0; z-index: 999; background: transparent; }
/* Dropdown-menuer følger appens tekstskala — Bootstraps default (1rem) stak ud fra resten af UI'et. */
.dropdown-menu { font-size: .84rem; }
.dropdown-menu .form-check-label { font-size: .84rem; }
/* Modal-backdrop: DÆMPET (modsat .cf-backdrop, som bevidst er usynlig klikfanger til dropdowns) —
   hvid modal på hvid side fungerer ikke (bruger-fund 2026-07-12). Modal-panelet får ekstra kant+skygge. */
.modal-backdrop-dim { position: fixed; inset: 0; z-index: 1040; background: rgba(15, 23, 42, .45); }
.modal-pop { border: 1px solid var(--border-strong); box-shadow: 0 18px 50px -12px rgba(15, 23, 42, .5), 0 4px 16px rgba(15, 23, 42, .2); }
.colfilter { position: relative; display: inline-block; }
/* Tragten sidder i et tabelhoved, altså på hvid — derfor eget hvile-fyld, ikke --surface. */
.colfilter-trigger {
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--state-rest-border); background: var(--state-rest); color: var(--text-muted);
    border-radius: var(--radius-xs); padding: .2rem .38rem; line-height: 1; cursor: pointer;
}
.colfilter-trigger:hover { color: var(--text); border-color: var(--state-border); background: #dde3ee; }
/* Et aktivt filter er en TILSTAND ("her er skruet på noget"), ikke en handling. */
.colfilter-trigger.active { color: #fff; background: var(--state); border-color: var(--state); }
.colfilter-trigger.active:hover { background: var(--state-hover); border-color: var(--state-hover); }
/* Mens popoveren er åben skal knappen ligge OVER .cf-backdrop (999) — ellers sluger backdroppen
   klikket, og filteret kan ikke lukkes igen ved at klikke på ikonet (bruger-fund 2026-07-28). */
.colfilter-trigger-open { position: relative; z-index: 1000; }
.colfilter-pop {
    position: absolute; z-index: 1050; top: calc(100% + .3rem); left: 0;
    /* +40 % (bruger 2026-07-29): 240→336 og 420→588. Værdierne i filteret er navne — kunder,
       leverandører, betalingsbetingelser — og de blev klemt i den gamle bredde, nu hvor de vises
       som pille-knapper i stedet for afkrydsnings-rækker. */
    width: max-content; min-width: 336px; max-width: 588px; background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-sm); box-shadow: 0 12px 32px rgba(15, 23, 42, .18);
    padding: .75rem;
    /* nulstil thead-arv (uppercase/fed/lille) inde i popoveren */
    text-transform: none; letter-spacing: 0; font-weight: 400; font-size: .8rem; color: var(--text); white-space: normal; text-align: left;
}
.colfilter-pop-end { left: auto; right: 0; }
/* Performance-tabellen er en scroll-container; giv plads så et åbent kolonne-filter ikke klippes når tabellen er kort */
.perf-tablewrap { min-height: 20rem; }
/* Interne scroll-containere ved mange rækker (design-kritik 2026-07-21, 50-rækkers-testen).
   S1 (sprint H): det faste 560px-loft gjaldt også på desktop og gav halvtomme sider med indre
   scroll. På desktop styrer app-shell-flexen højden (.content > .table-responsive, flex-shrink:1)
   — tabellen fylder viewporten og scroller først indre, når vinduet reelt er for lavt. Loftet
   består kun på mobil, hvor .content ikke er højdestyret. Selve loftet står i mobilblokken nederst
   i filen (1600018): betingelsen for, hvad en mobiltelefon er, skal kun findes ét sted. */
.perf-tablewrap, .salg-scroll, .deb-scroll { overflow-y: auto; }
.perf-tablewrap thead th, .salg-scroll thead th, .deb-scroll thead th { position: sticky; top: 0; background: var(--surface); z-index: 2; }
/* Excel-frys (bruger 2026-07-26): på oversigtstabeller med vandret scroll (fx pr. måned) fastholdes
   FØRSTE kolonne, resten scroller — som frosne kolonner i Excel. Kun 1. HEADER-RÆKKES første celle
   (grid-visningernes 2. header-række starter med en data-celle, jf. .overview-grp-fundet). Hjørnecellen
   får z-index 3 (over både sticky thead(2) og række-celler(1)). Solid baggrund er nødvendig — ellers
   ses de scrollende kolonner bag den frosne; total-/sektionsrækker matcher deres egen række-baggrund. */
.sticky-first thead tr:first-child th:first-child { position: sticky; left: 0; z-index: 3; background: var(--surface); }
.sticky-first tbody > tr > :first-child { position: sticky; left: 0; z-index: 1; background: var(--surface); }
.sticky-first tr.table-secondary > :first-child, .sticky-first tr.table-light > :first-child { background-color: var(--bs-table-bg); }
/* Fast sum-linje (bruger 2026-07-27): totalen skal blive stående i bunden mens rækkerne scroller —
   samme idé som den frosne thead, bare i den anden ende. Sættes eksplicit med .sticky-total (IKKE
   "sidste fede række": Posteringer har flere sektionsrækker med samme stil, som ikke er totalen).
   Virker både i tabeller med egen scroll (.salg-scroll m.fl.) og på sider hvor .content scroller —
   sticky binder sig til nærmeste scrollende forfader og stopper ved tabellens egen bund.
   z-index 4 = over frossen kolonne (1), thead (2) og thead-hjørnet (3). Solid baggrund er
   nødvendig, ellers ses de scrollende rækker igennem. UNDTAGELSE: mens et kolonnefilter er åbent,
   fjerner :has(.colfilter-pop)-reglen klipningen, og så holder sticky op med at virke — bevidst
   fravalg frem for at komplicere popover-håndteringen. */
.sticky-total > td, .sticky-total > th { position: sticky; bottom: 0; z-index: 4; background-color: var(--bs-table-bg, var(--surface)); }
.sticky-first tr.sticky-total > :first-child { left: 0; z-index: 5; }

/* FUND 87 + 99 (Michaels regel): en HANDLINGS-kolonne må ALDRIG gemme sig bag vandret scroll.
   Rækkens egen knap er dét, brugeren kom efter — den fastholdes yderst til højre, mens
   datakolonnerne ruller, præcis som .sticky-first fastholder nøglen i den anden ende.
   Solid baggrund er nødvendig: ellers ses de rullende kolonner igennem den fastholdte celle.
   z-index følger .sticky-first's trappe (thead 3, rækkeceller 1), så hjørnerne ikke slås. */
.sticky-last thead tr:first-child th:last-child { position: sticky; right: 0; z-index: 3; background: var(--surface-2); }
.sticky-last tbody > tr > :last-child { position: sticky; right: 0; z-index: 1; background: var(--surface); }
.sticky-last tbody > tr.table-active > :last-child { background: var(--bs-table-bg, var(--surface-2)); }
/* Sektions-, total- og markerede rækker har deres egen baggrund; den fastholdte celle skal bære den
   samme, ellers ses de rullende kolonner igennem den. Spejlbilledet af .sticky-first's regler. */
.sticky-last tr.table-secondary > :last-child, .sticky-last tr.table-light > :last-child { background-color: var(--bs-table-bg); }
/* Hjørnet mellem den fastholdte sidste kolonne og den fastholdte sum-linje: over begge (jf. trappen). */
.sticky-last tr.sticky-total > :last-child { right: 0; z-index: 5; }

/* FUND 184 (Michael, AppTest 759: "menuen ligger BAG de andre rækkers ⋯-knapper").
   Frysningen ovenfor giver HVER række-celle `position: sticky` + `z-index: 1` + solid baggrund, og
   en positioneret celle med z-index danner sin egen STAKKE-KONTEKST. Rækkemenuens `z-index: 1050`
   gælder derfor kun INDE i dens egen celle; udadtil deltager menuen med cellens 1. De efterfølgende
   rækkers frosne celler ligger på samme lag, men senere i DOM'en, og malede derfor henover.

   Løftet er husets kendte mønster fra kolonnefilteret (.table thead th:has(.colfilter-pop) → 20), et
   trin højere: en ÅBEN menu er det øverste på fladen, også over et løftet filter-hoved. Det er
   selve CELLEN, der løftes, og KUN mens en menu står åben — `.kt-pop` findes først i DOM'en, når den er
   det. Resten af tiden er trappen (thead 3, rækkeceller 1, sum-linje 4, sum-hjørner 5) urørt, så
   den vandrette scroll-visning ser præcis ud som før.

   Alle fire frysnings-varianter er med, selv om menuerne i dag kun bor yderst til højre: mekanikken
   er identisk i hver af dem, og en menu i nøglekolonnen ville ellers gentage nøjagtig samme fejl. */
.sticky-last tbody > tr > :last-child:has(.kt-pop),
.sticky-first tbody > tr > :first-child:has(.kt-pop),
.sticky-second tbody > tr > :nth-child(2):has(.kt-pop),
.sticky-third tbody > tr > :nth-child(3):has(.kt-pop) { z-index: 21; }

/* Nogle tabeller har en smal MARKERINGS-kolonne før nøglen (budgetternes afkrydsningsfelt).
   Så er nøglen kolonne nummer to, og den fastholdes ved siden af den første. Bredden på den
   første låses med --frys-1, fordi den anden kolonnes venstre-kant skal kende den præcist;
   uden låsen ville de to fastholdte celler kunne overlappe hinanden. */
.sticky-second thead tr:first-child th:first-child,
.sticky-second tbody > tr > :first-child { width: var(--frys-1); min-width: var(--frys-1); max-width: var(--frys-1); }
.sticky-second thead tr:first-child th:nth-child(2) { position: sticky; left: var(--frys-1); z-index: 3; background: var(--surface-2); }
.sticky-second tbody > tr > :nth-child(2) { position: sticky; left: var(--frys-1); z-index: 1; background: var(--surface); }
.sticky-second tbody > tr.table-active > :nth-child(2) { background: var(--bs-table-bg, var(--surface-2)); }

/* MICHAELS DOM 5 (2026-08-23): budgetternes KILDE-kolonne skal altid kunne ses, og står derfor ved
   siden af nøglekolonnen INDE i den fastfrosne zone. Zonen er dermed tre kolonner bred:
   markering (--frys-1) · nøgle (--frys-2) · kilde. Kun de to FØRSTE låses i bredde — den tredje
   skal kende deres samlede venstrekant, men ingen kender dens, og den beholder derfor sin egen
   data-drevne bredde (efterfixet fra build 745: intet tomt slot, ingen tom bredde). */
.sticky-third thead tr:first-child th:nth-child(2),
.sticky-third tbody > tr > :nth-child(2) { width: var(--frys-2); min-width: var(--frys-2); max-width: var(--frys-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sticky-third thead tr:first-child th:nth-child(3) { position: sticky; left: calc(var(--frys-1) + var(--frys-2)); z-index: 3; background: var(--surface-2); }
.sticky-third tbody > tr > :nth-child(3) { position: sticky; left: calc(var(--frys-1) + var(--frys-2)); z-index: 1; background: var(--surface); }
.sticky-third tbody > tr.table-active > :nth-child(3) { background: var(--bs-table-bg, var(--surface-2)); }
/* Sektions-, total- og markerede rækker bærer deres egen baggrund; ellers ses de rullende kolonner
   igennem den fastholdte celle. Spejlbilledet af .sticky-first/.sticky-last's regler. */
.sticky-third tr.table-secondary > :nth-child(3), .sticky-third tr.table-light > :nth-child(3) { background-color: var(--bs-table-bg); }
.sticky-third tr.sticky-total > :nth-child(3) { left: calc(var(--frys-1) + var(--frys-2)); z-index: 5; }
.colfilter-label { display: block; font-size: .62rem; text-transform: uppercase; letter-spacing: .05em; color: var(--text-muted); font-weight: 600; margin: 0 0 .15rem; }
.colfilter-list { max-height: 210px; overflow: auto; margin-top: .15rem; padding-right: .15rem; }
.colfilter-check { display: flex; align-items: center; gap: .45rem; padding: .12rem 0; cursor: pointer; }
.colfilter-check input { margin: 0; flex: 0 0 auto; }
.colfilter-actions { display: flex; align-items: center; gap: .4rem; margin-top: .7rem; }

/* Analyse-redesignets udvalgs-vælger (UdvalgVaelger). Panelet ER husets .kt-vaelgerpanel — det er
   derfor dækket af den fælles popover-mekanik i kt-ui.js — og reglerne her giver kun de to ting,
   vælgeren har ud over PillPicker: en bredde, der kan rumme kundenavne, og en fod, der siger hvad
   valget gør. Bredden er kolonnefilterets (336-588 px), så et flervalg med navne er lige bredt,
   uanset hvor i appen man møder det. */
.udvalg-panel { min-width: 336px; max-width: 588px; }
.udvalg-hoved { display: flex; align-items: center; gap: 8px; padding: 2px 2px 8px; white-space: nowrap; font-size: .8rem; }
/* K-4: udvalget stod som en egen linje under toolbaren og så dermed ud til at gælde hele siden.
   Michael 7/9: udvalget hører til grafen. Linjen bor nu ØVERST I GRAFENS PANEL, over selve grafen,
   adskilt fra den med en tynd streg, så det er tydeligt, hvad de to piller styrer. Den er ingen ny
   værktøjslinje: felterne låner toolbarens egne regler (se .tb-field og .tb-label ovenfor). */
/* P-2 og P-3 (Michael 8/9): linjen har FIRE led — vælg, afgræns, vis som, Årligt/Månedligt — og
   forklaringssætningen står UNDER dem i lille skrift, ikke som et femte led i rækken. Stregen sidder
   derfor under sætningen, så den skiller hele linjen fra grafen. */
/* P-11 (Michael 8/9): analysesidernes fliser fylder HELE rammen. Den delte .kpi-row brugte auto-fill,
   som lagde fire fliser i de fire første af syv spor og lod resten stå tom (Michaels "de fylder 40
   procent"), og analysesiderne lukkede de tomme spor med auto-fit i deres egen klasse.
   UI-fixrunde 1, punkt 3 (Michaels dom 9/9): den delte .kpi-row deler nu selv rammen mellem præcis de
   viste fliser, og analysesidernes egen override er dermed overflødig og fjernet — reglen står ÉT
   sted for alle tolv sider (1600006). UI-fixrunde 2, punkt 1 (1400024): rækken er en flex-række, og
   rækkeopdelingen på en smal ramme sker på den målte bredde i kt-ui.js, også her.
   Underteksten er en oplysning og skrives derfor mindre end værdien; navne-fliser (Største kunde,
   Største produkt) bærer et NAVN og ikke et tal, og navnet klippes frem for at vælte kortet. */
.analyse-fliser .kpi-sub { font-size: .78rem; color: var(--text-muted); }
/* Tabellen Nøgletal over tid (runde 3, punkt 5). Faste kolonnebredder (1400023), så tabellen ikke
   hopper, når visningen skifter, og TABULAR-tal, så cifrene står i lodret flugt fra kolonne til
   kolonne — det er hele pointen med at stille fire nøgletal op ved siden af hinanden.
   Månedligt kan blive mange kolonner: rammen ruller vandret, mens nøgletallets navn står fast i
   venstre kant, så man altid kan se, hvilken række man læser (samme greb som ranglisternes faste
   nøglekolonne, 1500017). */
.nt-scroll { overflow-x: auto; }
.nt-tabel { table-layout: fixed; width: 100%; font-variant-numeric: tabular-nums; margin-bottom: 0; }
.nt-tabel th, .nt-tabel td { white-space: nowrap; }
/* Nøglekolonnen holdes fast til venstre. Natterunden 10/9, punkt 2: Månedligt har nu TO
   overskriftsrækker, og nøglecellen står med rowspan i den FØRSTE. Reglen peger derfor på første
   header-række alene — ellers ville anden rækkes første måned (fx "Jan") arve fastholdelsen og
   lægge sig oven på nøglekolonnen. Samme afgrænsning som .overview-grp har haft siden 2026-07-30. */
.nt-tabel thead tr:first-child th:first-child, .nt-tabel tbody td:first-child {
    position: sticky; left: 0; background: var(--surface); text-align: left;
    overflow: hidden; text-overflow: ellipsis;
}
/* Den SENESTE kolonne er den, læseren måler de øvrige mod, og står derfor fed. */
.nt-tabel .nt-seneste { font-weight: 650; }
/* Årstallet over månederne (natterunden 10/9, punkt 2). Det ordner kolonnerne og er ikke selv et
   tal: dæmpet og let spærret som husets øvrige gruppe-overskrifter, med en kant der viser, hvor et
   årsskifte falder. Ingen ny farve. */
.nt-tabel .nt-aar {
    font-weight: 700; font-size: .72rem; letter-spacing: .04em; color: var(--text-muted);
    border-left: 1px solid var(--border-strong);
}

/* Månedens drilldown på Nøgletal (fixrunde 1, punkt 2). Samme tabelstandard som sidens øvrige:
   faste bredder og tabular-tal, så månedens tal og tallene til dato kan læses lodret mod hinanden.
   Afsnitsrækkerne (måneden og "til dato") står fed, som balanceopstillingens, og budgetkolonnen
   dæmpet, fordi den er sammenligningen og ikke svaret. */
.nd-kort { width: 92vw; max-width: 820px; }
.nd-tabel { table-layout: fixed; width: 100%; font-variant-numeric: tabular-nums; margin-bottom: 0; }
.nd-tabel th, .nd-tabel td { white-space: nowrap; }
.nd-tabel .nd-afsnit > td { font-weight: 650; background: var(--surface-2); }
.nd-tabel .nd-budget { color: var(--text-muted); }
/* Tilstandslinjen under overskriften (runde 6, punkt 2, 1500012 rev 4): den siger, hvilke valg
   tallene er regnet med, og står derfor dæmpet lige under måneden, som en undertekst hører til. */
.nd-tilstand { color: var(--text-muted); font-size: .78rem; margin: -.35rem 0 .6rem; }

/* Balanceopstillingen (runde 3, punkt 9). Samme tabelstandard som Nøgletal over tid: faste bredder
   og tabular-tal, så aktiver og passiver kan læses lodret mod hinanden. Afsnitsrækkerne (Aktiver,
   Passiver) og totalerne står fed, kontirækkerne dæmpet, så fold-ud læses som et underniveau og
   ikke som endnu en kategori — samme greb som ranglisternes fold-ud. */
/* Fixrunde 1, punkt 3 (Michaels dom 9/9): aktiver og passiver er TO tabeller i én sektion. De står
   side om side, når rammen har plads til begge i mindst 480 px, og falder ellers under hinanden.
   Reglen er ren CSS: flex-wrap bryder selv, når 2 × 480 px ikke længere kan være der, og der er
   derfor hverken en måling i JavaScript eller en tilstand, siden skal holde styr på.
   min-width: min(480px, 100%) er nødvendig: 480 px alene ville lade tabellen stikke uden for en
   endnu smallere ramme, i stedet for at rulle inde i sin egen .nt-scroll. */
.bal-sider { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; }
.bal-sider > .bal-side { flex: 1 1 480px; min-width: min(480px, 100%); }
/* Tabellens navn står som CAPTION over kolonnenavnene og ikke som en række under dem: "Aktiver" er
   overskriften på tabellen, ikke en post i den. */
.bal-tabel { table-layout: fixed; width: 100%; font-variant-numeric: tabular-nums; margin-bottom: 0; }
.bal-tabel > caption.bal-afsnit {
    caption-side: top; font-weight: 650; background: var(--surface-2); color: var(--text);
    padding: .35rem .5rem; text-align: left;
}
.bal-tabel .bal-afsnit > td { font-weight: 650; background: var(--surface-2); }
.bal-tabel .bal-total > td { font-weight: 650; border-top: 1px solid var(--border-strong); }
.bal-tabel .bal-konto > td { color: var(--text-muted); }
/* Den beregnede linje er ikke en saldo, og den skrives derfor i kursiv, så den ikke kan forveksles
   med en post i balancen. Navnet siger det samme med ord. */
.bal-tabel .bal-beregnet > td { font-style: italic; color: var(--text-muted); }
/* 1500047 (F50, Michaels måling ved 1600 px): et postnavn, der ikke får plads i sin kolonne,
   beskæres med ellipsis, og hele navnet står i mouseover (title sættes i Balance.razor). Uden det
   skubbede lange kontonavne beløbene ud af syne. Etiketten er block, så beskæringen kan måle en
   bredde; i kontolinjerne bor den i .bal-navns flex-række og får min-width: 0 ovenfor. */
.bal-tabel .bal-etiket {
    display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 1500048 (F50): tabellen holder sig inden for rammen på ALLE bredder. Kolonnerne er procenter af
   .bal-side, som selv er højst 100 % af rammen, så tabellen kan aldrig blive bredere end siden;
   på en telefon gør mindre skrift og luft plads til beløbene, og et langt tal bryder hellere end
   at skubbe kolonnen ud. */
.bal-tabel td, .bal-tabel th { overflow-wrap: anywhere; }
@media (max-width: 575.98px) {
    .bal-tabel { font-size: .78rem; }
    .bal-tabel td, .bal-tabel th { padding-left: .25rem; padding-right: .25rem; }
}

/* Referencefliserne (1500020, 1500023): etiketten er et link til ejersiden. Den skal LÆSES som en
   etiket og ikke som en knap, så den arver .kpi-label uændret og får kun linkets farve, når musen er
   over den. Uden det ville de tre referencefliser i Penge nu se anderledes ud end de fire i
   Indtjening til dato, og forskellen ville se ud som en betydning, den ikke har. */
.kpi-label.kpi-ejer { display: block; text-decoration: none; color: var(--text-muted); cursor: pointer; }
.kpi-label.kpi-ejer:hover { color: var(--accent); text-decoration: underline; }
/* Runde 3 (Nøgletal, punkt 2 og 3): rækkens overskrift. Nøgletal har TO fliserækker med hvert sit
   tidsbegreb, og overskriften er det ene sted, tidsbegrebet står — derfor står det ikke i fliserne
   (1500023). Skriften er toolbar-etiketternes små kapitæler, så overskriften læses som et navn på
   rækken og ikke som en sidetitel; den er ingen ny kontrol og ingen forklaring. */
.kpi-raekkenavn {
    font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
    color: var(--text-muted); line-height: 1; margin: .2rem 0 .5rem;
}
.analyse-fliser .kpi-navn { font-size: 1.15rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* P-14 (Michael 8/9): forklaringssætningen under vælgerne er væk. Stregen mod grafen sad på
   sætningen og sidder nu på linjen selv, så båndet over grafen ser ud som før. */
.graf-udvalg { row-gap: .45rem; padding-bottom: .6rem; margin-bottom: .7rem; border-bottom: 1px solid var(--border); }

/* SEKTIONSLINJEN på Kunder-siden (kickoff punkt 3): tynd, fastgjort under toolbaren, så man altid
   kan hoppe til den sektion, man vil se. Den ruller med indholdskolonnen, ikke med vinduet — på
   desktop er .content selv rulleren.
   B69: toppen er værktøjslinjens målte højde (--kt-toolbar-h, skrevet af kt-ui.js på rulleren), fordi
   værktøjslinjen selv står fast øverst i rulleren (se app-shell-blokken). Uden variablen, og på mobil,
   hvor linjen ikke er fastgjort, er værdien 0. */
.sektionslinje {
    position: sticky; top: var(--kt-toolbar-h, 0px); z-index: 5;
    display: flex; flex-wrap: wrap; align-items: center; gap: .1rem;
    background: var(--bg); border-bottom: 1px solid var(--border);
    padding: .3rem 0 .35rem; margin-bottom: .85rem;
}
.sekt-anker {
    font-size: .78rem; font-weight: 600; color: var(--text-muted); text-decoration: none;
    padding: .2rem .55rem; border-radius: var(--radius-xs); white-space: nowrap;
}
.sekt-anker:hover { color: var(--accent); background: var(--accent-soft); }
.sekt-anker.aktiv { color: var(--accent); background: var(--accent-soft); }
/* Rullemålet må ikke lande under den fastgjorte linje. B69: heller ikke under værktøjslinjen over den,
   så margenen er linjens 3rem plus værktøjslinjens målte højde. */
.kt-sektion { scroll-margin-top: calc(var(--kt-toolbar-h, 0px) + 3rem); margin-bottom: 1rem; }
/* K-3: Bevægelser og Koncentration er ankre INDE i panelrækken og har ikke sektionens klasse. Uden
   samme rullemargen ville de to lande under den fastgjorte linje, mens de tre andre ikke gør. */
.perf-row > .panel[id] { scroll-margin-top: calc(var(--kt-toolbar-h, 0px) + 3rem); }
.sekt-hoved { display: flex; align-items: flex-start; gap: .75rem; }
.sekt-ht { flex: 1; min-width: 0; }
.sekt-titel { font-size: .95rem; font-weight: 650; margin: 0; }
.sekt-under { font-size: .78rem; color: var(--text-muted); margin-top: .15rem; }
/* Fold-pilen tegnes af CSS, så knappen ikke bærer et symbol som tekst (husets knap-hygiejne). */
.sekt-fold {
    flex: 0 0 auto; width: 1.6rem; height: 1.6rem; padding: 0; cursor: pointer;
    background: none; border: 1px solid var(--border); border-radius: var(--radius-xs); position: relative;
}
.sekt-fold:hover { border-color: var(--border-strong); background: var(--surface-2); }
.sekt-fold::before {
    content: ""; position: absolute; left: 50%; top: 50%; width: .42rem; height: .42rem;
    border-right: 2px solid var(--text-muted); border-bottom: 2px solid var(--text-muted);
    transform: translate(-50%, -70%) rotate(45deg);
}
.sekt-fold-lukket::before { transform: translate(-50%, -50%) rotate(-45deg); }
/* Sammenfoldet viser kun overskriften: kroppen er væk, og sektionen bliver en enkelt linje. */
.sekt-krop { margin-top: .85rem; }
.sekt-handling { flex: 0 0 auto; display: flex; align-items: center; gap: 1.1rem; }
/* P-26 (Michael 8/9): "Vis stort". Ikonet står ved siden af fold-pilen og har samme mål og ramme som
   den, så de to knapper er ét par og ikke to slags. Ikonet er en svg, som vælgernes chevron er det. */
.sekt-stor {
    flex: 0 0 auto; width: 1.6rem; height: 1.6rem; padding: 0; cursor: pointer;
    background: none; border: 1px solid var(--border); border-radius: var(--radius-xs);
    display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted);
}
.sekt-stor:hover { border-color: var(--border-strong); background: var(--surface-2); color: var(--text); }
.sekt-stor svg { width: .72rem; height: .72rem; display: block; }
/* Selve overlayet står nedenfor, LIGE efter .reauth-overlay og .reauth-card: det er de to, det
   ændrer størrelse på, og en regel med samme vægt skal stå efter den, den skal vinde over. */
/* P-24 (Michael 8/9): grafens ramme. Bredden her er den, browseren måler og melder til komponenten,
   så Årligt kan tegnes 1 til 1 i pixel i stedet for at blive skaleret. Den skal derfor være rammens
   fulde bredde og ikke krympe om sit indhold, hvis den en dag lander i en flex-beholder. */
.serie-graf { display: block; width: 100%; }
/* Serieforklaringen: farveprikker i ÉN række under grafen, med navnet i mouseover. Tolv navne som
   tekst ville tage grafens plads (Michaels dom 7/9, punkt 2).
   P-25 (Michael 8/9): rækken CENTRERES under grafen. Den ligger uden for rullerammen i markup'en, så
   den hverken ruller med aksen i Månedligt eller står klemt ude i venstre hjørne, hvor den ene prik
   ved tomt udvalg var svær at få øje på. Afstanden er sat op, så prikkerne kan rammes med musen. */
.serie-forklaring { display: flex; flex-wrap: wrap; justify-content: center; gap: .55rem; margin-top: .6rem; }
/* P-22 (Michael 8/9): prikken er en KNAP, der fremhæver sin linje i grafen. Knappens egen ramme og
   polstring ryddes, så den ser ud som prikken gjorde, og den fremhævede bærer en ring. Ringen er
   tegnet med to skygger, ikke med en kant: en kant ville gøre prikken større og flytte de øvrige.
   P-25: prikken er 18 px mod ranglistens 10 px, og hjørnets runding følger med, så formen er den
   samme. Ringen er samtidig gjort TYDELIG: 2 px streg med 3 px luft ind til prikken, så den kan ses
   på den større flade. Den er stadig tegnet med skygger og ikke med en kant, så rækken ikke flytter
   sig, når man klikker rundt. */
.serie-forklaring .serie-prik { width: 18px; height: 18px; border-radius: 5px; padding: 0; border: 0; cursor: pointer; }
.serie-forklaring .serie-prik-valgt { box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--text); }
.serie-forklaring .serie-prik:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Ranglistens handlinger ved overskriften: søgning, flere kolonner og Hent Excel. */
.tabel-handlinger { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }

/* ANALYSE-REDESIGNET, runde 1, punkt 4: drill-kædens handlinger i en tabelrække. Knapperne er
   husets egne navigations-knapper (1600007) i lav højde, så rækken ikke vokser, og de står samlet
   til højre i deres egen celle. */
.raekke-handlinger { display: inline-flex; align-items: center; gap: .35rem; justify-content: flex-end; }
.raekke-handlinger .btn { white-space: nowrap; }

/* B70 (Michael 11/9 2026): NAVNECELLEN MED FOLD-UD. Navnet fylder resten, rækkens handling ("Se kunden"
   på Salgsoverblik) står i en fast kolonne højrestillet FØR plusset, og plusset har sin egen faste plads
   yderst til højre, også på rækker uden underrækker. Før stod handlingen lige efter navnet og hoppede
   vandret fra række til række. Pladsen til plusset er reserveret, så handlingen står på samme x, uanset
   om rækken kan foldes ud. Samme greb i ranglisternes fold-ud (Rangliste): plusset står yderst i
   navnekolonnen og ikke lige efter navnet. */
.navn-celle { display: flex; align-items: center; column-gap: .5rem; min-width: 0; }
.navn-celle > .navn-navn { min-width: 0; }
.navn-celle > .navn-handling { margin-left: auto; white-space: nowrap; }
.navn-celle > .fold-plads { flex: 0 0 1.4rem; display: inline-flex; justify-content: flex-end; margin-left: auto; }
.navn-celle > .navn-handling ~ .fold-plads { margin-left: 0; }

/* 1500022 og 1500023: en referencecelle er den almindelige celle, hvor VÆRDIEN er et link til
   ejersiden. Farven er cellens egen (adfærdens grøn, gul eller rød), så tallet stadig kan læses på
   farven; det er understregningen, der siger, at der er en vej videre. */
.kt-reference { color: inherit; text-decoration: underline dotted; text-underline-offset: 2px; }
.kt-reference:hover { color: inherit; text-decoration: underline; }
/* Faste bredder (1400023): tabellen må ikke hoppe, når indholdet skifter. Klassen er analysesidernes
   fælles rangliste (Kunder og Produkter deler komponenten), ikke Kunder-sidens egen. */
.analyse-tabel { table-layout: fixed; width: 100%; min-width: 54rem; }
.analyse-tabel td:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Runde 2, punkt 6: debitorlisten har FASTE bredder i procent (1400023), sat i tabellens colgroup.
   Mindstebredden er ranglisternes, fordi kolonnesættet er lige så bredt: ni kolonner med kundenavn,
   fire beløb, to dage-kolonner og en handling. Under den ruller rammen vandret med kunden fast. */
/* Natterunden 10/9, punkt 4 (Michaels dom): overskrifterne må ikke klippes ved 1600 px. Bredderne i
   procent (Debitorer.razor) giver hver kolonne dens overskrifts plads i rammen, og mindstebredden er
   hævet fra 70rem til 78rem, så rammen ruller vandret i stedet for at presse "Betalingsadfærd
   (12 mdr.)" sammen på en smallere skærm. Overskrifterne står på ÉN linje — samme greb som
   .nt-tabel — og knapperne i handlings-kolonnen brydes ikke.
   Fixrunden efter nattesten 10/9, fund F3: mindstebredden er hævet fra 78rem til 80rem. Procenterne
   er regnet ud af den MÅLTE overskriftstekst ved rammens 1281 px, og med 78rem (1248 px) gav de
   fire pixels for lidt til "Betalingsadfærd (12 mdr.)" i netop det punkt, hvor rammen begynder at
   rulle. 80rem er 1280 px, altså den ramme, procenterne er regnet for, så kolonnen har sin
   overskrifts plads hele vejen ned. */
.deb-tabel { table-layout: fixed; width: 100%; min-width: 80rem; }
.deb-tabel thead th { white-space: nowrap; }
.deb-tabel td .btn { white-space: nowrap; }
.deb-tabel td:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Fold-ud-rækken: dæmpet, så den læses som et underniveau og ikke som endnu en rangliste-række. */
.analyse-barn > td { color: var(--text-muted); }
/* Runde 5: fakturaens fold-ud i Detaljer. To blokke, Linjer og Posteringer, side om side når rammen
   har plads til begge i mindst 320 px, ellers under hinanden. Reglen er en BREDDE og bor derfor i
   stilarket som balanceopstillingens to sider — og den er skrevet med SAMME greb, en flex-række med
   et flex-basis-mål, fordi husets stilark ikke bruger auto-fill eller auto-fit (1400024). */
.fak-udfold { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; padding: .4rem .2rem .6rem; }
.fak-udfold > .fak-blok { flex: 1 1 320px; min-width: min(320px, 100%); }
.fak-blok-titel { font-size: .78rem; font-weight: 600; letter-spacing: .02em; color: var(--text-muted); margin-bottom: .25rem; }
.fak-blok table { font-size: .82rem; }
/* Forløbet: en miniature-kurve uden akse. Den svarer på op eller ned; tallene står ved siden af. */
.kt-forloeb { width: 84px; height: 20px; display: block; margin: 0 auto; }

.udvalg-fod { font-size: .72rem; line-height: 1.35; white-space: normal; padding: .5rem 2px 0; border-top: 1px solid #f1f5f9; margin-top: .5rem; }

/* Søgbar enkelt-valg dropdown (SearchSelect) — genbruger filter-popoverens liste-stil.
   FUND 2026-07-21 (bruger: "danser i bredde"): outer-div'en har OGSÅ .colfilter (display:inline-block,
   beregnet til et lille filter-ikon) → hele kontrollen krympede til teksten i stedet for at fylde
   feltet, og "dansede" i bredde når valgt værdi skiftede længde. .ss-wrap overstyrer til fuld bredde. */
.ss-wrap { display: block; width: 100%; }
.ss-trigger { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Fund 2026-07-21 (bruger: "popover danser i størrelse"): .colfilter-pop's egen bredde er
   content-drevet (width:max-content, 240-420px) — designet til det lille filter-ikon, hvor
   popoveren SKAL være bredere end triggeren. For SearchSelect skal listen derimod følge FELTETS
   faste bredde, ikke skifte efter den længste valgmuligheds tekst. */
/* Bruger 2026-07-26: popover-boksen 25 % bredere end triggeren (lange kundenavne) — stadig FAST
   bredde relativt til feltet, så den ikke "danser" (jf. fundet 2026-07-21). */
.ss-pop { width: 125%; min-width: 0; max-width: none; }
.ss-list { max-height: 240px; }
.ss-item { display: block; width: 100%; text-align: left; border: 0; background: none; padding: .22rem .4rem; border-radius: var(--radius-xs); font-size: .84rem; color: var(--text); cursor: pointer; }
.ss-item:hover { background: var(--surface-2); }
/* Valgt række i en søgeliste = svag TILSTAND. Tekstfarven er --text, IKKE tilstands-farven:
   tilstands-farve oven på sin egen lyse variant ryger under 4,5:1 (målt 2026-07-28). */
.ss-item.active { background: var(--state-soft); color: var(--text); font-weight: 600; }

/* Klikbare celler/links i tabeller (uden text-reset) vises diskret */
/* :not(.btn) tilføjet 2026-07-21: uden den vandt denne regel (2 klasser) over Bootstraps .btn
   (1 klasse) og gjorde "Forbind igen" (btn-primary i en tabelcelle) usynlig — blå tekst på blå bund. */
.table a:not(.text-reset):not(.btn) { color: var(--accent); text-decoration: none; }
.table a:not(.text-reset):not(.btn):hover { text-decoration: underline; }

/* Små +/− udvid-knapper — fast kompakt størrelse, så rækker med knap ikke bliver højere end rene tekst-rækker */
.btn-outline-secondary.btn-sm.py-0 {
    color: var(--text-muted);
    border-color: var(--border);
    background: var(--surface);
    height: 1.2rem;
    min-width: 1.4rem;
    padding: 0 .3rem;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.btn-outline-secondary.btn-sm.py-0:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-border); }

/* ===== Alerts ===== */
.alert { border-radius: var(--radius); border: 1px solid var(--border); font-size: .9rem; box-shadow: var(--shadow-sm); }
.alert-info { background: var(--accent-soft); border-color: var(--accent-border); color: #3730a3; }
.alert-warning { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.alert-success { background: #f0fdf4; border-color: #bbf7d0; color: #166534; }
.alert-danger { background: #fef2f2; border-color: #fecaca; color: #991b1b; }

/* ===== Forbindelse: status-prik, re-auth-modal, API-test ===== */
.conn-dot { width: .7rem; height: .7rem; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
.conn-dot.conn-ok { background: var(--positive); box-shadow: 0 0 0 3px rgba(21, 163, 74, .18); }

/* Modal der "griber" brugeren når Dinero-tokenet er udløbet */
.reauth-overlay { position: fixed; inset: 0; z-index: 1080; background: rgba(15, 23, 42, .45); display: flex; align-items: center; justify-content: center; padding: 1rem; }
/* 1600025 (Michaels dom 16/9 2026): EN DIALOG ER IKKE BREDERE, END INDHOLDET KRÆVER.
   Kortet fyldte før altid sin max-width (width: 100%), så en kort besked som Log ud stod i et
   vindue på 440 px med knapperne trykket ud mod højre kant. Bredden er nu indholdets egen:
   teksten, felterne og knapgruppen bestemmer, max-width sætter loftet, og mindstemålet holder de
   helt korte dialoger fra at blive smallere end deres egne knapper.
   fit-content går aldrig ud over den plads, overlayet giver (skærmen minus dets padding), så en
   dialog med en inline max-width på 520 px klarer stadig en telefon. */
.reauth-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 1.25rem 1.4rem; max-width: 440px; width: fit-content; min-width: min(20rem, 100%); max-height: 88vh; overflow-y: auto; }
.reauth-title { font-weight: 600; font-size: 1.05rem; margin-bottom: .5rem; }
/* P-26 (Michael 8/9): "Vis stort" — analysesidernes sektion i husets egen modale ramme, blot på
   cirka 95 procent af skærmen. Rammen er .reauth-overlay + .reauth-card (huset bygger ikke sit eget
   modale lag), og de fire klasser her sætter KUN størrelsen og deler kortet i et fast hoved og en
   rullende krop. De står lige efter de to, de skriver om: to regler med samme vægt afgøres af
   rækkefølgen, og kortets 440 px og 88 vh ville ellers vinde over de 95 procent.
   Overlayets egen polstring nulstilles, fordi de 2,5 procent luft til hver side ER kortets margen;
   uden det ville kortet blive smallere end de 95 procent, det er bedt om. */
.stor-overlay { padding: 0; }
/* Bredden er fast 95 procent: det er den, en graf og en tabel har brug for. HØJDEN er indholdets og
   højst 95 procent. Målt i browseren: Udvikling er 350 px høj (P-24's faste højde), og et kort på
   950 px ville stå med 600 px hvid bund under grafen. En sektion, der er højere end skærmen
   (ranglisten), fylder de 95 procent og ruller i kroppen. */
.stor-kort {
    width: 95vw; max-width: 95vw; height: auto; max-height: 95vh;
    display: flex; flex-direction: column; overflow: hidden;
}
.stor-hoved { display: flex; align-items: center; gap: 1.1rem; flex: 0 0 auto; }
.stor-titel { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* min-height: 0 er det, der gør rulningen mulig i en flex-kolonne: uden den vokser kroppen i stedet
   for at rulle, og kortets bund havner uden for skærmen. */
.stor-krop { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* FUND 151: behandlings-kortet (HandlingsStatus). Samme kort som husets dialoger, men uden
   overskrift og knapper — spinneren og den korte tekst på én linje er hele beskeden. */
.kt-behandler { display: flex; align-items: center; gap: .9rem; }
.kt-behandler .spinner-border { flex: 0 0 auto; width: 1.6rem; height: 1.6rem; border-width: .2em; }
.kt-behandler p { font-size: .95rem; }

.probe-result { max-height: 320px; overflow: auto; background: var(--surface-2); padding: .6rem; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: .75rem; margin: 0; }

/* Grupperinger: kompakt gruppering-boks — navn, +konto og firmafarvede konto-chips på linje */
.grp-item { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .5rem .7rem; margin-bottom: .45rem; background: var(--surface); }
.grp-item.grp-system { background: var(--surface-2); }
.grp-head { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; }
.grp-chip { display: inline-flex; align-items: center; gap: .25rem; font-size: .72rem; font-weight: 600; padding: .05rem .5rem; border: 1px solid; border-radius: 999px; white-space: nowrap; line-height: 1.6; }
.grp-chip-x { background: none; border: 0; padding: 0; font-size: .95rem; line-height: 1; cursor: pointer; opacity: .5; }
.grp-chip-x:hover { opacity: 1; }
/* Fund 2026-07-21: egen padding gjorde knappen lavere end nabo-knappen "Slet" (uens højde). Kun
   font-weight tilbage — standard btn-sm-padding deles med Slet, så begge har samme størrelse. */
.grp-add-btn { font-weight: 600; }
.grp-add { margin-top: .55rem; padding-top: .55rem; border-top: 1px dashed var(--border); }
.grp-acct-list { display: flex; flex-wrap: wrap; gap: .1rem 1.1rem; max-height: 190px; overflow: auto; padding: .1rem .1rem .1rem 0; }
.grp-acct-check { display: flex; align-items: center; gap: .45rem; font-size: .8rem; cursor: pointer; padding: .12rem 0; min-width: 230px; }
.grp-acct-check input { margin: 0; flex: 0 0 auto; }

/* ===== Diverse ===== */
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--positive); }
.invalid { outline: 1px solid var(--negative); }
.validation-message { color: var(--negative); }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
    border-radius: var(--radius-sm);
}

    .blazor-error-boundary::after { content: "Der opstod en fejl."; }

.darker-border-checkbox.form-check-input { border-color: #929292; }

/* FUND 2026-07-21 (bruger: "danser i toppen af mange sider"): den faste synk-knap (top højre,
   position:fixed) overlappede geometrisk Budget/Grupperingers højrestillede header-handlinger, da
   de sad i samme række som h1. Løst ved at fjerne h1-rækkens højrestillede indhold helt (Eksportér/
   Importér flyttet ned i værktøjslinjen/panelet i stedet) — ingen global klasse behøves længere.
   Grupperinger har sin egen lokale .grp-toolbar-top til samme formål (sidste ramme uden h1 foran). */

/* ===== Synk-knap (altid synlig, øverste højre hjørne) ===== */
.sync-fab {
    position: fixed;
    top: .8rem;
    /* 1.5rem = 24px = samme som .content px-4 (bruger-fund 2026-07-28). Med 1.1rem stak Opdatér-
       knappen 6,4px længere ud end værktøjslinjen, KPI-rækken og tabellen, som alle flugter på
       indholds-kolonnens højre kant. Den er position:fixed, så den skal måles mod VIEWPORTEN og
       have samme tal som indholdets vandrette padding — ikke et løsrevet skøn. */
    right: 1.5rem;
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: .4rem;
}
.sync-fab .sync-ico { display: inline-block; font-size: 1rem; line-height: 1; vertical-align: -1px; }
.sync-fab .btn-primary { box-shadow: var(--shadow); }
/* Fremdrifts-boks under synk — hvid baggrund så teksten kan læses oven på sideindholdet */
.sync-fab-box {
    display: flex;
    align-items: center;
    gap: .55rem;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    padding: .35rem .65rem;
    box-shadow: var(--shadow-lg);
    font-size: .82rem;
    max-width: 24rem;
}
.sync-fab-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.sync-fab-sub { font-size: .7rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sync-fab-cancel { color: var(--text-muted); text-decoration: none; font-weight: 600; }
.sync-fab-cancel:hover { color: var(--negative); }
.sync-fab-badge { font-weight: 700; font-size: 1rem; }
.sync-fab-ok { color: var(--positive); }
.sync-fab-err { color: var(--negative); }

/* "Sidst opdateret"-stempel til venstre for Refresh — boks i ~90% af knappens højde, lodret
   centreret (via .sync-fab align-items:center). Ramme + tekst farves efter datafriskhed. */
/* Sammensmeltet "stempel + Opdatér" (bruger-ønske 2026-07-23): ét segmenteret element, samme
   højde, delt ramme. Stempel-segmentet farves efter datafriskhed; knap-segmentet er den blå CTA. */
.refresh-group {
    display: inline-flex;
    align-items: stretch;
    height: 2rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    background: var(--surface);
}
.refresh-seg {
    display: inline-flex;
    align-items: center;
    padding: 0 .6rem;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    /* Stemplet må give sig, knappen må ikke. Uden dette kunne en lang tekst ("Aldrig opdateret")
       presse knap-segmentet sammen, så de to lagde sig oven i hinanden (bruger-fund 2026-08-07). */
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.refresh-btn {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;   /* knappen beholder altid sin fulde bredde */
    padding: 0 .95rem;
    border: 0;
    border-left: 1px solid var(--border-strong);
    background: var(--accent);
    color: #fff;
    font-size: .8rem;
    font-weight: 600;
    cursor: pointer;
}
.refresh-btn:hover { filter: brightness(.94); }
/* Stempel-farverne efter alder. FUND 141c: firma-raekkens eget stempel (.firma-synk paa
   Firmaer-siden) deler PRAECIS disse deklarationer med stemplet oeverst paa siden - een farve pr.
   tilstand, saa de to flader ikke kan drifte. Alders-REGLEN bor tilsvarende eet sted, i
   SynkStempelTekst.Farve. */
.refresh-group.stamp-green  .refresh-seg,
.firma-synk.stamp-green  { color: var(--positive); }
.refresh-group.stamp-yellow .refresh-seg,
.firma-synk.stamp-yellow { color: #a16207; }
.refresh-group.stamp-red    .refresh-seg,
.firma-synk.stamp-red    { color: var(--negative); }

/* ===== Graf-hover (inline SVG): oejeblikkelige, stylede vaerdier - ren CSS, ingen JS (ChartTooltip.cs) ===== */
.kt-pt .kt-band { opacity: 0; }
.kt-pt:hover .kt-band { opacity: .08; }
.kt-pt .kt-tip { opacity: 0; pointer-events: none; transition: opacity .06s ease; }
.kt-pt:hover .kt-tip { opacity: 1; }

/* 1500040: staar musen i flerserie-grafens baand, traeder den kurve frem, der ligger naermest
   musen, og de oevrige daempes. Baandet siger selv, HVILKEN serie det fremhaever (.kt-slice-N), og
   reglen gaelder kun, saa laenge musen staar i baandet: slipper musen, staar alle kurver lige igen.
   Der er een regel pr. plads i seriepaletten (AnalysePalet.Loft), fordi grafen aldrig baerer flere
   kurver end paletten har farver. */
.serie-graf svg:has(.kt-slice:hover) .kt-series { transition: opacity .06s ease; }
.serie-graf svg:has(.kt-slice-0:hover) .kt-series:not(.kt-series-0) { opacity: .18; }
.serie-graf svg:has(.kt-slice-0:hover) .kt-series-0 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-1:hover) .kt-series:not(.kt-series-1) { opacity: .18; }
.serie-graf svg:has(.kt-slice-1:hover) .kt-series-1 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-2:hover) .kt-series:not(.kt-series-2) { opacity: .18; }
.serie-graf svg:has(.kt-slice-2:hover) .kt-series-2 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-3:hover) .kt-series:not(.kt-series-3) { opacity: .18; }
.serie-graf svg:has(.kt-slice-3:hover) .kt-series-3 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-4:hover) .kt-series:not(.kt-series-4) { opacity: .18; }
.serie-graf svg:has(.kt-slice-4:hover) .kt-series-4 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-5:hover) .kt-series:not(.kt-series-5) { opacity: .18; }
.serie-graf svg:has(.kt-slice-5:hover) .kt-series-5 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-6:hover) .kt-series:not(.kt-series-6) { opacity: .18; }
.serie-graf svg:has(.kt-slice-6:hover) .kt-series-6 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-7:hover) .kt-series:not(.kt-series-7) { opacity: .18; }
.serie-graf svg:has(.kt-slice-7:hover) .kt-series-7 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-8:hover) .kt-series:not(.kt-series-8) { opacity: .18; }
.serie-graf svg:has(.kt-slice-8:hover) .kt-series-8 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-9:hover) .kt-series:not(.kt-series-9) { opacity: .18; }
.serie-graf svg:has(.kt-slice-9:hover) .kt-series-9 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-10:hover) .kt-series:not(.kt-series-10) { opacity: .18; }
.serie-graf svg:has(.kt-slice-10:hover) .kt-series-10 polyline { stroke-width: 3; }
.serie-graf svg:has(.kt-slice-11:hover) .kt-series:not(.kt-series-11) { opacity: .18; }
.serie-graf svg:has(.kt-slice-11:hover) .kt-series-11 polyline { stroke-width: 3; }

/* Side-specifikt hjælpe-ikon i topbaren, til venstre for "sidst opdateret" (bruger 2026-07-27).
   Samme diskrete stil som ⓘ-ikonerne inde på siderne, bare med luft ud til stemplet. */
.topbar-hint { margin-right: .55rem; font-size: 1rem; line-height: 1; cursor: help; }

/* ===== FUND 166: sidebarens bredde, når menuen er foldet ind (Michaels dom D, 2026-08-22) =====

   Alt andet ved foldningen bor i NavMenu.razor.css. BREDDEN kan ikke: sidebaren er MainLayouts
   (og BankLayouts) element, og Blazors isolerede CSS kan ikke række opad ud af komponenten.
   Derfor står de to linjer her — begge flader, samme tal, ét sted, så de ikke kan drifte.

   Indholdsfladen vokser af sig selv: <main> er flex:1 i begge layouts.
   Kun fra 641px, hvor sidebaren OVERHOVEDET er en søjle; under den folder hamburgeren allerede.

   FUND 166b (Michaels tillæg 2026-08-22): logoet er væk i sammenfoldet tilstand, og bjælken er
   smallere tilsvarende — 5rem var logoets bredde (30px + luft), ikke ikonernes. 3.5rem = 56px
   rummer et 1.1rem-ikon centreret med luft til begge sider og fold-ud-knappens 1.75rem. */
@media (min-width: 641px) {
    html.nav-foldet .sidebar,
    html.nav-foldet .bank-sidebar { width: 3.5rem; }
}

/* ===== MOBILBETINGELSEN (1600018, Michaels fund M-1 den 9. september 2026) =====================

   REGLEN: linjer, der bliver stående ved rul, findes kun på computerskærme. Topbjælken (Hent Excel,
   ⓘ, stemplet "I dag hh.mm" og Opdatér), værktøjslinjen og tabellernes frosne kolonner er
   computerens. På en mobiltelefon ruller topbjælken og værktøjslinjen med siden, så knapperne
   aldrig ligger hen over indholdet. Michaels billeder viste det modsatte i BEGGE retninger: både på
   højkant og i landskab gled fliserne ind under Hent Excel og Opdatér.

   BETINGELSEN STÅR HER OG KUN HER (1600006). CSS har ingen variabel for en media query, så "ét
   sted" er én blok frem for et navn. Skal en regel gælde en mobiltelefon, skrives den herinde, og
   ingen side laver sin egen udgave af den.

   To led, fordi en telefon holdes på to leder:
     (pointer: coarse) and (hover: none)   en skærm uden mus, altså også landskab (ca. 930 px)
     (max-width: 640px)                    appens egen mobilgrænse, som resten af filen bruger

   Blokken står SIDST i filen med vilje: reglerne herinde skal vinde over de tilsvarende regler
   ovenfor, og de er skrevet med præcis de samme selektorer, så det er rækkefølgen og ikke en
   oppustet specificitet, der afgør kampen. */
@media (pointer: coarse) and (hover: none), (max-width: 640px) {

    /* 1) APP-SHELLEN SLIPPES. På computeren er <main> 100vh med overflow:hidden, og .content er
       selv rulleren (se app-shell-blokken ved .content ovenfor). Netop dét gør topbjælken og
       værktøjslinjen faste: indholdet ruller inde i .content, mens alt uden for den bliver
       stående. På en telefon ruller SIDEN i stedet, og så følger bjælken og værktøjslinjen med af
       sig selv. Uden denne løsning ville en statisk topbjælke oven i købet skubbe .contents fulde
       100 procent ned under mains skjulte kant, så bunden af siden blev klippet væk.

       RC-fix 10/9 (2): top-luften bor nu på <main> og ikke på .content (se app-shell-blokken), så
       den skal slippes HER, hvor bjælken ikke er et bånd. Uden den ville en telefon i landskab
       (ca. 930 px, som rammes af BEGGE blokke) stå med et tomt 3,25rem-bånd øverst på hver side. */
    main { height: auto; overflow: visible; padding-top: 0; }
    /* Samme vælger som app-shellens egen, ellers vinder den på specificitet (0-1-1 mod 0-1-0) og
       efterlader både top-luften og flex-kolonnen på en telefon i landskab. */
    main:has(> .sync-fab) { padding-top: 0; display: block; }
    .content { height: auto; overflow: visible; display: block; }

    /* 2) TOPBJÆLKEN RULLER MED. På computeren er den et tæt bånd over indholdskolonnen
       (main > .sync-fab, absolut placeret i mains top-luft), og her står den som et almindeligt
       element øverst i <main>, med sit indhold højrestillet som før og med samme vandrette luft som
       indholdskolonnens px-4 (1,5rem), så knapperne flugter med værktøjslinjen og tabellen
       nedenunder.

       VÆLGEREN SKAL VÆRE main > .sync-fab, ordret som båndets egen. En telefon i landskab rammes af
       begge blokke, og en vælger med lavere specificitet (bare .sync-fab, 0-1-0) ville tabe til
       båndet (0-1-1), uanset at denne blok står sidst i filen. Båndets bundne udseende ophæves
       samtidig: højden er igen indholdets egen, og baggrund og understreg hører til båndet. */
    main > .sync-fab {
        position: static;
        height: auto;
        background: none;
        border-bottom: 0;
        justify-content: flex-end;
        flex-wrap: wrap;
        gap: .4rem .55rem;
        padding: .6rem 1.5rem .5rem;
    }

    /* 3) TOP-LUFTEN UDGÅR. De 3,25rem øverst i .content er ren kompensation for den faste bjælke
       (se .content ovenfor). Er bjælken ikke fast, er luften et tomt bånd øverst på hver side. */
    .content { padding-top: 0; }

    /* 4) TABELRAMMER MED EGEN RULNING beholder deres loft. Loftet hørte før til (max-width: 640px)
       og skal nu gælde hele mobilbetingelsen: uden .contents højdestyring har rammerne ingen anden
       grænse, og uden en grænse ruller de ikke i sig selv. Det er netop den indre rulning, der
       giver overskriftsrækken lov til at blive stående på mobil (1600018). */
    .perf-tablewrap, .salg-scroll, .deb-scroll { max-height: 560px; }

    /* 5) FROSNE KOLONNER UDGÅR. Excel-frysningen til venstre (.sticky-first, .sticky-second,
       .sticky-third), handlings-kolonnen til højre (.sticky-last) og den faste sum-linje
       (.sticky-total) er computerens: på en telefon er skærmen så smal, at de fastholdte celler
       optager den plads, de rullende kolonner skulle vises i. Cellerne beholder deres baggrund og
       deres bredde-låse, så tabellen ser ud som før, blot uden fastholdelsen.

       OVERSKRIFTSRÆKKEN BLIVER (1600018). Den sættes af .table thead th og af rammernes egne
       thead-regler længere oppe, og de er med vilje IKKE nævnt her: en tabel, der ruller i sin
       egen ramme, skal beholde sin overskrift, også på en telefon. */
    .sticky-first thead tr:first-child th:first-child,
    .sticky-first tbody > tr > :first-child,
    .sticky-second thead tr:first-child th:nth-child(2),
    .sticky-second tbody > tr > :nth-child(2),
    .sticky-third thead tr:first-child th:nth-child(3),
    .sticky-third tbody > tr > :nth-child(3),
    .sticky-last thead tr:first-child th:last-child,
    .sticky-last tbody > tr > :last-child,
    .sticky-total > td,
    .sticky-total > th { position: static; }

    /* 6) SEKTIONSLINJEN RULLER MED. Den er fastgjort under værktøjslinjen på analysesiderne
       (sticky, top 0) og hører til den samme familie af linjer, der bliver stående. Markeringen af
       den aktive sektion virker uændret: mekanikken i kt-ui.js leder selv op ad træet efter den
       rulle-beholder, linjen ligger i, og falder tilbage på dokumentet, når .content ikke ruller. */
    .sektionslinje { position: static; }

    /* 6b) VÆRKTØJSLINJEN RULLER MED (B69, 1600018). På computeren står den fast øverst i rulleren
       (app-shell-blokken, .content > .toolbar); på en telefon er den et almindeligt kort igen med kun
       husets egen skygge. Samme vælger som computerens, så det er rækkefølgen, der afgør det. */
    .content > .toolbar { position: static; box-shadow: var(--shadow); }

    /* 7) SIDEN BLIVER ALDRIG BREDERE END SKÆRMEN (fixrunden efter nattesten 10/9, fund F6).
       Nattesten målte fire af fem sider med vandret rulning på selve siden ved 375 px: Kunder 502,
       Tilgodehavender 1202, Detaljer 405 og Nøgletal 377 mod skærmens 375. Balance opførte sig
       rigtigt. Det er ikke ét element, der stikker ud, men den samme kæde tre steder, og reglerne
       står derfor her og ikke pr. side (1600006).

       a) SEKTIONSHOVEDET OMBRYDER. Hovedet er en flex-række med titlen (flex: 1, min-width: 0),
          sektionens handling (flex: 0 0 auto) og de to knapper. Handlingen kan IKKE krympe, og
          bærer den to knapper som "Flere kolonner" og "Hent Excel", bliver rækken bredere end
          skærmen — så løber fold-knappen uden for kanten, og hele siden bliver bredere. Handlingen
          får derfor en linje for sig selv UNDER titlen og de to knapper (order: 1), så rækken
          aldrig kan blive bredere end sin ramme. */
    .sekt-hoved { flex-wrap: wrap; }
    .sekt-handling { order: 1; flex: 1 1 100%; flex-wrap: wrap; min-width: 0; gap: .5rem .8rem; }

    /*  b) TABELRAMMERNE RULLER I SIG SELV, OG BREDDEN SLÅR IKKE IGENNEM PÅ SIDEN. Rammerne ruller
          ganske rigtigt allerede (målt: debitorlisten 326 px synlig af 1251), men tabellens
          mindstebredde slår alligevel igennem, hvis bare ét led i kæden op til <main> må vokse om
          sit indhold. Hvert led får derfor max-width 100 procent og min-width 0: et led med
          min-width auto (flex- og grid-børns standard) nægter at blive smallere end sit indhold, og
          dét er præcis den vej, en 80rem bred tabel kommer ud på siden. */
    .table-responsive, .perf-tablewrap, .salg-scroll, .deb-scroll { overflow-x: auto; }
    main, .content, .content > *, .kt-sektion, .sekt-krop, .sekt-ht,
    .panel, .card, .toolbar, .table-responsive,
    .perf-tablewrap, .salg-scroll, .deb-scroll { max-width: 100%; min-width: 0; }

    /*  c) SKYDER-RÆKKERNE OMBRYDER (RC-testen 10/9, fund F2). Scenariepanelet på Prognose har tre
          rækker med et navn på 200 px, en skyder og en værdi på 5 rem. De tre led kræver tilsammen
          mere end de 290 px, panelet har på en telefon, og rækken kunne ikke ombryde: værdierne stod
          fra 387 til 467 px, altså 92 px uden for skærmen.

          Navnet får derfor en linje for sig selv, og skyderen og værdien deler den næste. Skyderen må
          krympe (den er et mål, ikke en tekst), mens værdien beholder sin faste bredde, så de tre
          rækker stadig flugter — netop dét, fund 167 handlede om. Reglen står her og ikke på siden. */
    .sc-linje { flex-wrap: wrap; }
    .sc-linje > * { min-width: 0; max-width: 100%; }
    .sc-navn { flex: 1 1 100%; }
    .sc-skyder { flex: 1 1 6rem; }

    /*  d) AI-ADGANGENS FORBINDELSESLISTE RULLER I SIN EGEN RAMME (RC-testen 10/9, fund F3).
          Listen er den ene tabel i huset, der med vilje IKKE ligger i en rulleramme: bredderne er
          faste i procent og summer til 100, og en ramme ville klippe kolonnefiltrenes popover. På en
          telefon slår dét fejl. Handlingskolonnens 14 procent er 37 px af en tabel på 261 px, og
          cellen har synligt overløb, så knapperne står på én linje: knappen Afbryd endte 33 px uden
          for skærmkanten og kunne ikke rulles frem, fordi sidens egen bredde er skærmens.

          Rammen får derfor sin egen vandrette rulning her, som husets øvrige tabeller har den
          (1600018), og tabellen en mindstebredde på 44 rem. Handlingskolonnen måler da 98 px og
          rummer sine knapper, når de får lov at ombryde i cellen. Vælgeren bærer .ai-liste, så den
          vinder over sidens egen regel om synligt overløb, og computeren er urørt: dér er der ingen
          ramme, ingen mindstebredde og intet, der klipper en popover. */
    .ai-liste { overflow-x: auto; }
    .ai-liste > .ai-tabel { min-width: 44rem; }
    .ai-liste .ai-tabel td.ai-handling { white-space: normal; overflow: hidden; }
    .ai-liste .ai-tabel td.ai-handling .btn { margin-left: 0; margin-top: .15rem; }
}

/* ==========================================================================
   AI-ADGANGENS FIRE FELTER (1800047; runde 27's opstilling, runde 31's stil)
   Godkendelsessiden og Desktop Editions udstedelsesdialog tegner de SAMME fire
   rækker, og de skal se ens ud. Reglerne bor derfor ét sted, ikke i hver flade:
   etiket i fast bredde med sin ene (i)-knap til venstre, feltet til højre, og
   grænselinjen flugtende med felterne. Mobil: under hinanden, aldrig vandret
   rulning (memory html-faste-bredder gælder RAMMEN, ikke en ramme, der er
   smallere end sit indhold).
   ========================================================================== */
.ai-felter { border: 1px solid var(--border); border-radius: var(--radius-xs); padding: .2rem .9rem .7rem; }
.ai-raekke { display: grid; grid-template-columns: 11rem minmax(0, 1fr); align-items: center; gap: 1rem; padding: .55rem 0; border-top: 1px solid var(--border); }
.ai-raekke:first-child { border-top: 0; }
.ai-raekke .ai-lab { font-size: .86rem; font-weight: 600; }
.ai-graense { font-size: .8rem; margin: 0 0 .2rem; padding-left: 12rem; }
/* RUNDE 49 (1800055): FORBINDELSENS RETTIGHEDER i listen. Cellen bærer den korte sum, og både
   mouseover og klik åbner husets popover med de faktiske rettigheder. Panelet er kt-vaelgerpanel,
   som appens øvrige popovers, og lægger sig over rækken uden at gøre cellen bredere. */
.ai-ret { position: relative; display: inline-block; cursor: help; }
.ai-retpanel { position: absolute; left: 0; top: 1.3rem; z-index: 1050; min-width: 22rem; max-width: 30rem;
    padding: .55rem .7rem; cursor: default; white-space: normal; text-align: left; }
.ai-retlinje { display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: .5rem; padding: .22rem 0; }
.ai-retlinje + .ai-retlinje { border-top: 1px solid var(--border); }
.ai-retlab { font-size: .76rem; font-weight: 600; }
.ai-retval { font-size: .76rem; }
.ai-retbund { position: fixed; inset: 0; z-index: 1040; }

/* RUNDE 49 (1800047 rev 4): de tre GRUPPEOVERSKRIFTER Generelt, Skrive adgange og Token. Samme
   dæmpede versal-overskrift, husets vælgerpaneler bruger over deres grupper, så en gruppe ser ens
   ud, uanset om den står i en vælger eller i en feltliste. Rækken efter en overskrift bærer ingen
   streg: overskriften er selv adskillelsen. */
.ai-gruppe { font-size: .72rem; font-weight: 600; color: var(--muted, #64748b); text-transform: uppercase; letter-spacing: .02em; padding: .8rem 0 .15rem; }
.ai-felter > .ai-gruppe:first-child { padding-top: .5rem; }
.ai-gruppe + .ai-raekke { border-top: 0; }

/* Godkendelsessiden selv (runde 31): en smal ramme midt på en tom side, som de
   øvrige sider uden app-navigation. */
.ai-godkend { max-width: 34rem; margin: 2rem auto; }
.ai-godkend > .card { padding: 1.25rem 1.4rem; }
.ai-godkend h1 { font-size: 1.25rem; margin: 0 0 .8rem; }
.ai-godkend .ai-klient { margin: 0 0 .6rem; font-size: 1.05rem; }
.ai-godkend .ai-oplys { font-size: .86rem; line-height: 1.45; }
/* RUNDE 49 (1800047 rev 4): Forbind og Annuller står NEDERST TIL HØJRE og er LIGE BREDE. Bredden
   kommer fra husets .kt-dialogknapper (1600023 rev 2: lige store inden for den enkelte dialog), og
   den ydre række skubber gruppen til højre. Gruppens egne auto-margener nulstilles i højre side;
   ellers ville de centrere den i stedet. */
.ai-godkend .ai-knapper { display: flex; justify-content: flex-end; margin-top: .9rem; }
.ai-godkend .ai-knapper > .kt-dialogknapper { margin-right: 0; }

@media (max-width: 576px) {
    .ai-raekke { grid-template-columns: minmax(0, 1fr); gap: .25rem; }
    .ai-graense { padding-left: 0; }
    .ai-godkend { margin: 1rem auto; }
}
