﻿/* =====================================================================
   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, while both the deselected month and Annuller were #eff5ff. Graphite is
       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
       cannot drift apart again.
       F39 (Michael 14/9 2026, 1400023): the target was 92 percent of the belt and therefore stopped about 240 px
       short of the right edge on Konto-opsætning, while Firma-opsætning's own content went all the way. The two pages
       now measure the same: the page container fills the belt, and the content stops at the same edge as
       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): the action buttons in the section headers on Koncerner & Grupperinger
   measure the same, whether they say Opret, Eksportér or Importér. The buttons sit in SEPARATE
   sections, so a grid cannot tie them together; the measure is therefore one number in one place. 6rem holds the
   longest text ("Eksportér", about 63 px) plus the button's own padding. */
.ops-sect-button { 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; }

/* ===== The row of analysis panels (Kunder, Produkter, Likviditet) ===== */
.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; }
/* 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-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; }

    /* 1600044: the tile row stays put under the toolbar on the operating pages, and the content below
       the tiles scrolls. On Resultatoverblik, Salgsoverblik and Omkostningsoverblik this happens by
       itself, because the table card (.table-responsive) shrinks and scrolls in its own frame, so .content
       never has anything to scroll. Balance consists of a chart and a statement that do not shrink, and
       the whole page therefore scrolled along. The two now sit in the same kind of frame with the same
       height calculation and the same scrollbar: it shrinks (flex-shrink 1), has the house's same
       minimum height and scrolls internally. The frame has no surface of its own, the chart's panel and the section
       keep their own. On mobile the rule does not exist, and everything scrolls with the page (1600018). */
    .content > .kt-page-scroll { flex-shrink: 1; min-height: 9rem; overflow: auto; }

    /* 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); clip-path: inset(0 -.85rem -.85rem -.85rem); }

    /* F248, F249 and F250 (AppTest 1907): THE EDGE COVERS ONLY WHAT SCROLLS PAST, NEVER A NEIGHBOUR
       THAT STANDS STILL. The fixed toolbar, tab bar and tile row each carry a solid edge in the page's
       background, and the edge may reach only into the element's OWN air, which lies in the flow:
       - The toolbar's air is its margin below. Its edge reached .85rem UP as well and covered what
         stands right above it: the heading "Audit log" (4 px above), and in the same way a note or
         a banner above the line. The edge is therefore clipped at the toolbar's own top (clip-path
         inset 0 at the top, .85rem out at the sides and below). The rounded top corners stay filled,
         because they lie inside the toolbar's box; nothing needs the edge above it: stuck at the top
         of the scroller there is nothing above, and under the tab bar the bar's own edge covers the
         air between them. An open popover in the toolbar lifts the clip, as it lifts the layer
         (the rule for .toolbar:has(.kt-pop) and its family).
       - The tile row's air is its margin below; the holder's air lies inside the holder (F248, the
         rule below the fixed row); the heading of a row stands in its holder (F249, Noegletal).
       - The tab bar stands first and its air is its margin below, which its edge covers exactly. */

    /* 1600044: THE TILE ROW STAYS PUT UNDER THE TOOLBAR (F217, the test on 1897: .kpi-row
       was position static on all eight operating pages, and there was no rule). The pattern is
       the toolbar's own: the row is sticky in the scroller, with its top set to the bar's MEASURED height
       (--kt-toolbar-h, written by kt-ui.js, because css cannot itself tell whether the bar has wrapped onto
       two rows), and with the same solid edge in the page background, so no content can be seen sliding
       past in the air under the tiles. Charts and tables scroll underneath.

       The row stands either as the page's own child or in a wrapper with the mark (fliser), and both
       forms are covered. On mobile the rule does not exist, and everything scrolls along (1600018). */
    .content > .kpi-row,
    .content > div:has(> .kpi-row) {
        position: sticky; top: var(--kt-toolbar-h, 0px); z-index: 5;
        background: var(--bg); box-shadow: 0 0 0 .85rem var(--bg);
    }

    /* F248 (AppTest 1907, Kunder and Produkter): THE EDGE HIDES WHAT SCROLLS PAST, NEVER WHAT STANDS
       STILL BELOW THE ROW. In the holder form the row's own air (its margin-bottom .85rem) lies INSIDE
       the holder, because the holder is a flex item of the scroller, and the holder's background
       already covers it. The solid edge all round reached .85rem further down and covered the top of
       the section that begins right at the holder's bottom (the title "Top 10, bevaegelser og
       koncentration"). In the holder form the edge is therefore drawn only upwards and to the sides:
       four copies of the holder's own shape moved .85rem up, left, right and into the two upper
       corners, and none below. The air between tiles and content is the same .85rem as before. The
       bare row keeps the edge all round: its margin lies outside the row, and the edge covers
       exactly that margin, so nothing below it is covered either. */
    .content > div:has(> .kpi-row) {
        box-shadow: 0 -.85rem 0 0 var(--bg), -.85rem 0 0 0 var(--bg), .85rem 0 0 0 var(--bg),
                    -.85rem -.85rem 0 0 var(--bg), .85rem -.85rem 0 0 var(--bg);
    }

    /* Only the TOP tile row stays put. Noegletal has two rows (Indtjening and Penge nu), and
       two fixed rows would land on top of each other; the lower one scrolls along like the rest of the page's
       indhold. */
    .content > .kpi-row ~ .kpi-row,
    .content > .kpi-row ~ div:has(> .kpi-row),
    .content > div:has(> .kpi-row) ~ .kpi-row,
    .content > div:has(> .kpi-row) ~ div:has(> .kpi-row) { position: static; box-shadow: none; z-index: auto; }

    /* F249 (AppTest 1907, Noegletal): the lower row rolls UNDER the fixed row, never over it. A flex
       item takes its z-index also when it is static, so the second row (Penge nu) kept the 5 of the
       shared rule, and as the later of two equal layers it slid up OVER the fixed first row. The rule
       above gives the lower rows z-index auto: the fixed row is the one layer over the content. */

    /* 1600059: THE HEAD OF FORBINDELSER STANDS STILL, AND THE LIST SCROLLS UNDER IT. Same pattern as
       the tile row (1600044): sticky in the scroller, its top the measured heights of what stands
       fixed above it (the tab bar, --kt-tabs-h, and a toolbar, --kt-toolbar-h, 0 on Konto-opsaetning).
       The head lies inside its card, so it carries no edge of its own: the tab bar's edge covers the
       air above it, and nothing standing still is covered. The head leaves with the card when the
       card's end scrolls past. On a phone the rule does not exist, and the head scrolls with the page. */
    .content .acc-item.fp-card > .fp-head {
        position: sticky; top: calc(var(--kt-tabs-h, 0px) + var(--kt-toolbar-h, 0px)); z-index: 4;
    }

    /* 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); }
/* 1500115 (Michael 13/10 2026): the three budget types Enkelt, Tilbagevendende and Tilpasset stand as three equally
   wide buttons at the top of the budget line's card and of the what-if dialog. The group is a grid of three equal
   columns, so the widest word sets the width of all three. */
.btn-group.kt-three-types { display: inline-grid; grid-template-columns: repeat(3, 1fr); }
.btn-group.kt-three-types > .btn { width: 100%; }
/* 1500129 (Michael 20/10 2026): two buttons that sit together as one choice (Reguleret and Fast, Kundens faktiske and
   Angiv betingelser, Enkelt and Tilbagevendende) are equally wide after the longest text, same mechanics as 1500115. */
.btn-group.kt-equal-two { display: inline-grid; grid-template-columns: repeat(2, 1fr); }
.btn-group.kt-equal-two > .btn { width: 100%; }
/* 1500129: the same mechanics for a choice of four buttons (Budgetafstemning's Vis: Alle, Ikke afstemte, Afstemte, Forslag). */
.btn-group.kt-equal-four { display: inline-grid; grid-template-columns: repeat(4, 1fr); }
.btn-group.kt-equal-four > .btn { width: 100%; }
/* The longest text sets the width, so a word never breaks inside a button of the group. */
.btn-group.kt-three-types > .btn, .btn-group.kt-equal-two > .btn { white-space: nowrap; }
.btn-group.kt-equal-four > .btn { white-space: nowrap; }
/* 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
   the Annuller button, which sits three centimetres away in the same 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
   read as state, not as action. Before, it was blue-soft like Annuller, and the result was
   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.

   NO COLOURS HERE: the role tags (kt-valgt, kt-not-chosen, 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: the picker's footer is the same line in all panels: Vælg and Annuller, centred, with the
   same divider above. The width comes from .kt-dialogbuttons, like the buttons in a dialog. */
.kt-pickerfoot { padding: 10px 6px 2px; border-top: 1px solid #f1f5f9; margin-top: 6px; flex: none; }

/* The footer in a popover without a divider (the column filter, the selection picker): only the air above. */
.kt-popoverfoot { margin-top: .7rem; }

/* 1600026: the group header LOOKS the same everywhere. Where only one company can be chosen, the header is not a
   choice, and then it must not respond to mouse or keyboard either, but it is the same line, and it
   stands in the same place. */
.kt-grouphead { pointer-events: none; }

/* FUND 119 (1600026 rev 2, Michael's ruling 16/9 2026): "Har to firmaer samme navn, står udbyderen som
   undertekst under hvert af dem."
   The choice cell was one line with truncation (text-overflow: ellipsis). With a subtitle the cell must
   carry TWO lines, and the truncation therefore moves down to the name itself, so a long name still
   ends with dots instead of bursting the panel's width. The subtitle appears only on the cells
   that HAVE one, so the unambiguous names look exactly as before (1600026: the picker is one and the same). */
.kt-companychoice { display: block; overflow: hidden; }
.kt-companychoice-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kt-companychoice-sub {
    display: block; font-size: .72rem; opacity: .7; line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Michael's finding 16/9 2026 (Salgsbudget): the company picker's panel lay SQUEEZED under the toolbar with
   Opret ny. The cause is the stacks: both toolbars are sticky with z-index 6, and the panel is
   drawn inside the TOP one of them. The panel's own 1050 applies only within that bar's own
   stacking context, so the NEXT toolbar (same z-index, later in the document) painted over
   the top part of the panel, exactly where the search field is.
   A toolbar with an open popover is therefore lifted above its siblings. The lift applies only while
   the popover is open; when it closes, the bar drops back into place. The selector list is the same
   family that the mechanics in kt-ui.js know. */
.toolbar:has(.kt-pop),
.toolbar:has(.kt-vaelgerpanel),
.toolbar:has(.colfilter-pop),
.toolbar:has(.dropdown-menu.show) { z-index: 1051; clip-path: none; }

/* 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; }

/* The button group in a dialog (1600022, 1600023 rev 2, 1600025; Michael's rulings 15/9 and 16/9 2026):
   OK or the primary action stands to the LEFT of Annuller, the buttons are EQUAL IN SIZE within
   the individual dialog, and the group stands CENTRED under the text.

   The width is the WIDEST button in this very group, not a fixed number for all dialogs (1600023
   rev 2: "størrelsen gælder inden for den enkelte dialog, ikke på tværs af dialoger"). The old
   fixed min-width of 9.5rem made all dialogs equally wide and forced narrow dialogs, such as Log ud,
   to be wider than their content (1600025).

   The mechanics: a grid with equally wide columns that only fills its own content. The grid's
   max-content is the number of buttons times the widest, so each button gets exactly the widest
   button's width, without anyone knowing the number in advance. minmax(0, 1fr) lets the buttons shrink
   together on a narrow screen instead of running past the card's edge.

   The group holds ONLY buttons. A footer with other content (status, help choice) puts its buttons in
   a .kt-dialogbuttons inside the footer; otherwise the text would become an equally wide column. */
.kt-dialogbuttons {
    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-dialogbuttons > .btn { min-width: 0; width: 100%; text-align: center; }
/* 1600058: action buttons side by side in a toolbar or in a row's action column are equally wide,
   measured within the one group. Same mechanism as .kt-dialogbuttons (equal grid columns, the
   widest button sets the width), but the group stands where it is placed: no centring and no auto
   margins, inline next to the fields around it. The group holds ONLY the buttons. A button keeps
   its own min-width (.ops-sect-button), so the widest of min-width and text sets the pair (F121). */
.kt-button-row {
    display: inline-grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
    gap: .5rem; align-items: center; width: max-content; max-width: 100%; vertical-align: middle;
}
.kt-button-row > .btn { width: 100%; text-align: center; white-space: nowrap; margin: 0; }
/* 1600058, 1500128 rev 2: the licence button on Firmaer is as wide as its widest text on every row. The shown text and
   the two hidden sizers share one grid cell, so the cell is as wide as Tilføj licens whatever the row says; Synk in the
   same kt-button-row takes the same width, and every row's buttons stand on the same x. */
.kt-licence-label { display: inline-grid; justify-items: center; }
.kt-licence-label > span { grid-area: 1 / 1; }
.kt-licence-label > .kt-licence-sizer { visibility: hidden; }

/* É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; }
/* M5 (Michael 15/10 2026): the icon's larger font must never make its label taller than the label beside it. Without
   this, a field label or a tile label with the icon stood about 4px taller, and its field or value sat lower than the
   neighbour's (Gentagelse and Slut against Beløb and Start, Betalingsbetingelser against Kunde, the tiles Gab, Laveste
   saldo and Planen flytter against their row). The icon keeps its size; only its own line height is taken out. */
.bud-label .kt-hint, .kpi-label .kt-hint { line-height: 0; }

/* 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): the label "Dimensioner" was half hidden under
       the toolbar's card. The cause is the pinned toolbar: .content > .toolbar is sticky
       with z-index 6 and a SOLID shadow of .85rem in the page background colour (B69, see the rule further
       up), which covers the air under the card. The box began exactly where the shadow ended, and
       the label sticks .55em UP above the box's edge, that is, up into the shadow, which paints over it.
       The box therefore gets enough air for the label to stand COMPLETELY free under the toolbar with the same
       spacing as the other card headings. */
    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; }

/* 1600052: DENSITY ON COMPUTER SCREENS. Table rows are about 30 px high with 13 px type (13 px x 1.4
   line plus 2 x .34rem padding plus the 1 px line = 30 px), on every page with a table. At 1600 px
   and wider an overview page's tiles stand in ONE row and are about 72 px high: 11 px label, 22 px
   figure, a little less air. The row is kept one row by css, whatever width the layout script wrote
   on the tiles; MoneyFit shows the short figure when the full one has no room. Colours, buttons and
   texts are unchanged, and a phone keeps its own sizes (1600018). */
@media (min-width: 641px) {
    .table { font-size: 13px; }
    .table > :not(caption) > * > * { padding: .34rem .65rem; }
    .table thead tr:nth-child(2) th { top: 1.66rem; }   /* the first header row grew by the padding */
}
@media (min-width: 1600px) {
    .kpi-row { flex-wrap: nowrap; }
    .kpi-row > * { flex-basis: 0 !important; }
    .kpi-row .kpi-card { padding: .75rem 1rem .8rem 1.15rem; gap: .25rem; }
    .kpi-row .kpi-label { font-size: 11px; }
    .kpi-row .kpi-value { font-size: 22px; }
}
.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, Michael's measurement at 1600 px): an item name that does not fit in its column
   is clipped with ellipsis, and the full name appears on mouseover (title is set in Balance.razor). Without it
   long account names pushed the amounts out of view.
   1600052: every label (section rows and account lines) lives in .bal-navn's flex row, which makes
   it a flex item that the ellipsis can measure; it is never display: block, because a block label
   pushed the section row's fold button onto its own line (49.5 px rows instead of ~30 px).
   F253 (1500047): the section names are italic, and an italic last letter leans up to about 2.4 px
   past the text's advance width. overflow: hidden clips at the padding box, so the label keeps
   .25em of air on the right inside its own box (the ink is never clipped when the name fits), and
   the equal negative margin gives that air back to the row, so "+" and the ellipsis of a long name
   stand exactly where they stood. Horizontal only: the row height is unchanged. */
.bal-tabel .bal-etiket {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    padding-right: .25em; margin-right: -.25em;
}
/* 1500048 (F50): the table stays within the frame at ALL widths. The columns are percentages of
   .bal-side, which is itself at most 100 % of the frame, so the table can never be wider than the page;
   on a phone smaller font and spacing make room for the amounts, and a long number would rather wrap than
   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; }
/* 1400023 (B70, round 1897): the name fills the rest of the column and is CLIPPED with ellipsis. Wrapping
   would give the row a new height and push the action, and a long name must never move the button.
   The action also has a fixed minimum width: without it the browser measured the button's text 1.6 px
   differently on rows with and without the expand plus, so its left edge sat in two places. */
.navn-celle > .navn-navn { flex: 1 1 0; min-width: 0; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.navn-celle > .navn-handling { flex: 0 0 auto; min-width: 4rem; margin-left: auto; text-align: center; 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 (Michael's ruling 16/9 2026): A DIALOG IS NO WIDER THAN ITS CONTENT REQUIRES.
   The card always used to fill its max-width (width: 100%), so a short message like Log ud stood in a
   window of 440 px with the buttons pushed out to the right edge. The width is now the content's own:
   the text, the fields and the button group decide, max-width sets the ceiling, and the minimum keeps the
   very short dialogs from becoming narrower than their own buttons.
   fit-content never goes beyond the space the overlay gives (the screen minus its padding), so a
   dialog with an inline max-width of 520 px still copes with a phone. */
.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; }
/* The design of 29/9: the dialogs Forbind e-conomic, Forbind Billy and Tilføj projektmodul. The
   layout follows the design; sizes follow the app's own standards (the house's dialog frame above,
   .form-label's small heading, btn-sm buttons, the body text's .86rem), and colours the tokens. */
.kt-connect { font-size: .86rem; }
.kt-connect-head { display: flex; align-items: flex-start; gap: .75rem; margin-bottom: .6rem; }
.kt-connect-mark {
    position: relative; flex: none; width: 2.4rem; height: 2.4rem; display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--accent-border); background: var(--accent-soft); color: var(--accent-hover);
    border-radius: var(--radius-xs); font-weight: 700; font-size: 1.05rem;
}
.kt-connect-plus {
    position: absolute; right: -.35rem; bottom: -.35rem; width: 1rem; height: 1rem; display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; background: var(--accent); color: #fff; font-size: .7rem; box-shadow: 0 0 0 2px var(--surface);
}
.kt-connect-heading { flex: 1 1 auto; min-width: 0; }
.kt-connect-kicker { font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); font-weight: 600; }
.kt-connect-title { font-weight: 600; font-size: 1.05rem; color: var(--text); }
.kt-connect-close { flex: none; }
.kt-connect-intro { color: var(--text-muted); margin-bottom: .6rem; }
.kt-connect-badges { display: flex; flex-wrap: wrap; gap: .35rem; margin-bottom: .8rem; }
.kt-connect-badge {
    display: inline-flex; align-items: center; gap: .3rem; padding: .15rem .55rem; border-radius: 999px;
    background: var(--state-soft); color: var(--text-muted); font-size: .76rem; white-space: nowrap;
}
.kt-connect-badge > .kt-connect-svg { color: var(--accent); }
.kt-connect-link {
    display: flex; align-items: center; gap: .5rem; padding: .45rem .65rem; margin-bottom: .8rem;
    border-radius: var(--radius-sm); background: var(--state-soft); color: var(--text-muted);
}
.kt-connect-link-text { flex: 1 1 auto; min-width: 0; }
.kt-connect-link-text > b { color: var(--text); }
.kt-connect-number { display: inline-block; padding: 0 .35rem; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); font-size: .78rem; }
.kt-connect-ok { display: inline-flex; align-items: center; gap: .25rem; color: var(--positive); font-weight: 600; white-space: nowrap; }
.kt-connect-icon { display: inline-flex; align-items: center; color: var(--text-muted); }
.kt-connect-steps { list-style: none; counter-reset: kt-connect-step; padding: 0; margin: 0; }
.kt-connect-step { position: relative; counter-increment: kt-connect-step; padding: 0 0 .85rem 2.1rem; }
.kt-connect-step::before {
    content: counter(kt-connect-step); position: absolute; left: 0; top: 0; width: 1.45rem; height: 1.45rem;
    display: inline-flex; align-items: center; justify-content: center; border-radius: 50%;
    border: 1px solid var(--border-strong); background: var(--state-soft); color: var(--text-muted); font-size: .76rem; font-weight: 600;
}
.kt-connect-step.is-first::before { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 0 0 3px var(--accent-soft); }
.kt-connect-step:not(:last-child)::after { content: ""; position: absolute; left: .7rem; top: 1.7rem; bottom: .25rem; width: 2px; background: var(--border); }
.kt-connect-step-title { font-weight: 600; color: var(--state); line-height: 1.45rem; }
.kt-connect-step.is-first .kt-connect-step-title { color: var(--text); }
.kt-connect-step-text { color: var(--text-muted); }
.kt-connect-step-text > b { color: var(--text); }
.kt-connect-path { display: inline-block; padding: 0 .35rem; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--state-soft); color: var(--text); font-weight: 600; }
.kt-connect-sep { color: var(--text-muted); }
.btn.kt-connect-provider { display: inline-flex; align-items: center; gap: .4rem; margin-top: .45rem; }
.kt-connect-label { display: block; font-weight: 600; color: var(--text); margin: .55rem 0 .25rem; }
.kt-connect-field {
    display: flex; align-items: center; gap: .35rem; padding: .15rem .2rem .15rem .55rem;
    border: 1px solid var(--border-strong); border-radius: var(--radius-xs); background: var(--surface);
}
.kt-connect-field:focus-within { border-color: var(--accent); box-shadow: 0 0 0 .2rem var(--accent-soft); }
.kt-connect-field > .form-control { flex: 1 1 auto; min-width: 0; border: 0; box-shadow: none; padding-left: .2rem; font-size: .86rem; }
.btn.kt-connect-paste { flex: none; display: inline-flex; align-items: center; gap: .3rem; background: var(--state-soft); color: var(--state); font-weight: 600; border: 0; }
.btn.kt-connect-paste:hover { background: var(--state-rest); color: var(--state-hover); }
.kt-connect-note { display: flex; align-items: center; gap: .35rem; margin-top: .35rem; color: var(--text-muted); font-size: .8rem; }
.kt-connect-foot {
    margin: .4rem -1.4rem -1.25rem; padding: .8rem 1.4rem; border-top: 1px solid var(--border);
    background: var(--state-soft); border-radius: 0 0 var(--radius) var(--radius);
}
.kt-connect-foot .btn { display: inline-flex; align-items: center; justify-content: center; gap: .3rem; white-space: nowrap; }
/* 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; }

/* ===== THE TOUR'S SHARED PARTS (1600039 rev 2) =====
   1000009: the image carousel is a SUPERSEDED path, and its popover, frame, images and dimming are gone.
   What remains are the parts of the look that the tour's text card itself uses: the header's icon, title and
   counter, the cross, the progress bar, the dots and the footer. The colours and sizes are unchanged, so
   the look is the same as before. */
.guide-icon { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px; background: var(--accent-soft); color: var(--accent-hover); display: grid; place-items: center; font-weight: 700; font-size: 15px; }
.guide-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 600; }
/* The counter uses tabular figures, so "3 af 11" does not jump in width when the number changes. */
.guide-counter { font-size: 12px; font-weight: 500; color: var(--text-muted); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.guide-close { border: 0; background: transparent; color: var(--text-muted); font-size: 20px; line-height: 1; cursor: pointer; padding: 4px 6px; border-radius: 6px; flex: 0 0 auto; }
.guide-close:hover, .guide-close:focus-visible { background: var(--bg); color: var(--text); }

/* The progress bar is drawn by the BROWSER: the width is a css animation with the step's own seconds
   as duration, so the six seconds do not cost six hundred round trips over the wire. */
.guide-bar { position: relative; height: 3px; background: var(--border); flex: 0 0 auto; }
.guide-bar > i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--accent); animation-name: guide-bar; animation-timing-function: linear; animation-fill-mode: forwards; }
@keyframes guide-bar { from { width: 0; } to { width: 100%; } }
@media (prefers-reduced-motion: reduce) { .guide-bar > i { animation: none; } }

/* Fixed width, so the button does not jump when Pause turns into Afspil. */
.guide-play { min-width: 5.4rem; text-align: center; }

/* The dots: how far the customer has come, and a shortcut to a specific step. */
.guide-dots { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 18px 14px; flex: 0 0 auto; }
.guide-dot { width: 26px; height: 6px; border: 0; padding: 0; border-radius: 3px; background: var(--border); cursor: pointer; }
.guide-dot.done { background: var(--accent-border); }
.guide-dot.on { background: var(--accent); }
/* The footer is a reminder, not an explanation: small and muted, and it must never take space from
   underteksten. */
.guide-foot { padding: 0 18px 12px; font-size: 12px; color: var(--text-muted); flex: 0 0 auto; }

/* ===== THE LIVE TOUR (1600039, trial 1885) =====
   The tour runs on the page. The layer dims the page and cuts a hole around the current field; the hole
   is drawn and moved by guide-tour.js, because it must follow the element on every scroll. The colours are
   the carousel's own, so the two guides look the same.
   The dimming is FOUR panels, not a box-shadow with a huge spread (F196). */
/* F205 (Michael 22/9): the frame is drawn ON the object, not by a layer that measures coordinates. A measured
   frame is always an estimate, and it landed askew on the panels. Now the dimming is ONE fixed area over
   the whole view, and what the step points at is lifted above it and gets its own outline. The edge is
   the element's own and follows it pixel for pixel on scroll, resize and a panel that expands. */
.tour-dim { position: fixed; inset: 0; background: rgba(14, 21, 37, .42); pointer-events: none; z-index: 1070; }
.kt-tour-front {
    outline: 2px solid var(--accent); outline-offset: 0;
    border-radius: 8px; box-shadow: 0 0 0 4px rgba(37, 99, 235, .25);
}
/* F440 (Michael 1/10, AppTest 1948): THE RING IS DRAWN WHOLE, ALSO WHERE A FRAME CLIPS. The ring above
   lies OUTSIDE the element, and a frame that scrolls by itself (overflow auto or hidden)
   clips everything outside its box: the equity chart's panel on Balance lies edge to edge with
   .kt-page-scroll, and the ring did not show on any side. If the ring would be clipped,
   guide-tour.js draws it INSIDE the element's own edge (kt-tour-inset): same stroke and same band, just
   inward, still the element's own (F205), so no ancestor's clip can reach it. */
.kt-tour-front.kt-tour-inset { outline-offset: -2px; box-shadow: inset 0 0 0 4px rgba(37, 99, 235, .25); }
/* F440: an inward ring on an element in block flow gets the ring's bottom as a sticky child: it
   stands at the element's own bottom when that is in view, and at the frame's visible end when the element reaches
   below what the frame shows (the chart is taller than the frame on a screen with the browser's own
   bars), and it follows every scroll by itself (position sticky, the layer does not listen to scroll).
   The child is 0 high and moves nothing. The stroke reaches out to the element's edge with the padding and
   the border, the bottom is rounded like the element's own corners, and the offset gives back the frame's bottom padding
   (the browser subtracts it from the sticky area, and the layer borrows the frame's bottom space, 1600044).
   The layer writes the numbers into the variables on the child. */
.kt-tour-bottom {
    position: sticky; bottom: var(--kt-edge-stick, 0px); display: block; height: 0; margin: 0; padding: 0;
    pointer-events: none;
}
.kt-tour-bottom::before {
    content: ""; position: absolute;
    left: calc(-1 * var(--kt-edge-l, 0px)); right: calc(-1 * var(--kt-edge-r, 0px)); bottom: calc(-1 * var(--kt-edge-b, 0px));
    height: max(var(--kt-edge-rad, 0px), 6px);
    border: 2px solid var(--accent); border-top: 0; border-radius: 0 0 var(--kt-edge-rad, 0px) var(--kt-edge-rad, 0px);
    box-shadow: inset 0 -2px 0 0 rgba(37, 99, 235, .25);
}
/* F208 (Michael's finding on 1887): a lifted ancestor (e.g. the toolbar, which is sticky and creates its
   own stacking context) took all its content with it above the dimming, so all the bar's other fields
   stood clear. The lifted ancestor therefore gets its own dim layer as a child in exactly the same colour as
   .tour-dim. The layer measures nothing: inset 0 covers the ancestor, and the corners are set to
   the ancestor's own, so it never stands outside a rounded frame. z-index lies above the ancestor's
   other children and below the highlighted one (1072), which is therefore the only thing that stands clear. */
.kt-tour-veil { position: absolute; inset: 0; background: rgba(14, 21, 37, .42); pointer-events: none; z-index: 1071; }
/* F209 (Michael's ruling 22/9): the field's HEADING gets no ring, but a faint accent tone like a
   highlighter, with a little air around the text. The ring belongs to the control alone, so the eye lands on what
   actually happens. The negative margin keeps the line in place when the air is added. */
.kt-tour-tone {
    background: var(--accent-soft); border-radius: 6px;
    padding: 2px 6px; margin: -2px -6px;
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* The text card stands FIXED: same width, same height and same place, regardless of the step. Michael's ruling on
   a fixed card means that the card never moves; if the field lies behind it, the PAGE is scrolled instead. */
.tour-card {
    /* 1600073: the card stands above every open picker and dialog (they lie at 1080 to 2100), so its tour can be read and closed. */
    position: fixed; left: 50%; transform: translateX(-50%); bottom: 1.5rem; z-index: 2200;
    width: min(46rem, 94vw); height: 16.5rem;
    display: flex; flex-direction: column; overflow: hidden; padding: 0;
    background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
    box-shadow: 0 18px 50px rgba(14, 21, 37, .18), 0 2px 6px rgba(14, 21, 37, .08);
}
.tour-card:focus { outline: none; }
.tour-head { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; padding: 12px 16px; border-bottom: 1px solid var(--border); }
/* The subtitle has the same look as the carousel's and room for its three lines, so the card has a fixed
   height, however long the text is. */
.tour-text { display: flex; align-items: center; gap: 16px; padding: 16px 18px 14px; flex: 1 1 auto; }
.tour-text p { margin: 0; flex: 1; min-width: 0; font-size: 1.05rem; line-height: 1.45; max-width: 80ch; text-wrap: balance; }
.tour-text p b { font-weight: 600; color: var(--accent-hover); }
/* D2: the buttons in two rows, Tilbage and Næste on top, Pause and Luk below. The rows are equally
   wide, so the four buttons stand in a grid and do not jump when Pause turns into Afspil. */
.tour-buttons { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.tour-buttonrow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tour-buttonrow .btn { font-size: 13px; font-weight: 600; border-radius: 7px; padding: 8px 14px; }
/* 1600045: on a WAITING STEP the card is locked, and Luk is the only button. The row therefore has one track,
   so the button does not stand as half a row with an empty cell beside it. */
.tour-buttonrow.tour-waiting { grid-template-columns: 1fr; min-width: 6.5rem; }

@media (max-width: 899.98px) {
    .tour-card { width: calc(100% - 16px); bottom: 8px; height: auto; }
    .tour-text { flex-direction: column; align-items: stretch; }
}

/* The help button in the top band (1600040): the band's left end, that is, the same place on every page.
   margin-right: auto pushes the rest of the band out to the right, where it stood before. */
.guide-button { margin-right: auto; display: inline-flex; align-items: center; gap: .4rem; }
.guide-button-icon { display: grid; place-items: center; width: 1.1rem; height: 1.1rem; border-radius: 999px; background: var(--accent); color: #fff; font-size: .72rem; font-weight: 700; line-height: 1; }
/* The menu's Kom i gang (1600040). The look used to be a style attribute on the link in NavMenu; it
   has been moved here, because the item is now either a button (the carousel exists) or a link (it does
   not), and the two must look the same. */
.nav-komigang { color: inherit; text-decoration: none; border: 1px solid currentColor; border-radius: 5px; padding: .12rem .45rem; }
.nav-getstarted-button { background: none; font: inherit; line-height: inherit; cursor: pointer; }

/* 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: when the mouse is in the multi-series chart's band, the curve nearest the mouse
   comes forward, and the others are dimmed. The band itself says WHICH series it highlights (.kt-slice-N), and
   the rule applies only as long as the mouse is in the band: when the mouse leaves, all curves are equal again.
   There is one rule per slot in the series palette (AnalysePalet.Loft), because the chart never carries more
   curves than the palette has colours. */
.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; }
}

/* F230 (1600008): Log ud is its own component (LogoutLink, 1600021), so the icon rules in
   NavMenu.razor.css are scoped away from it and never reached its span. The rules live here instead.
   Unfolded, Log ud shows its text as always and no icon. Folded, it shows an arrow pointing left
   (white, the size and opacity of the other menu icons) and hides the text; the name stays as the
   mouseover. */
.kt-logout .kt-logout-icon { display: none; }

@media (min-width: 641px) {
    html.nav-foldet .kt-logout .kt-logout-icon {
        display: inline-block;
        position: relative;
        top: -1px;
        width: 1.1rem;
        height: 1.1rem;
        background-size: cover;
        opacity: 0.75;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z'/%3E%3C/svg%3E");
    }

    html.nav-foldet .kt-logout .nav-tekst { display: none; }
}

/* ===== 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); }

    /* 6c) THE TILE ROW SCROLLS ALONG (1600044, 1600018). On the computer it stays put under
       the toolbar; on a phone everything scrolls with the page, and the row has no edge in
       the background. The same selectors as the computer's, so it is the order that decides. */
    .content > .kpi-row,
    .content > div:has(> .kpi-row) { position: static; box-shadow: none; }
    /* 1600059 and 1600018: on a phone the head of Forbindelser scrolls with the page. */
    .content .acc-item.fp-card > .fp-head { position: static; }

    /* 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, .kt-page-scroll,
    .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; }

    /* THE GUIDE (1600039 rev 2) on a phone: the help button in the band shows only its icon, so
       it does not push the page's own actions past the edge. The tour's own text card has its
       own rule for narrow screens (below 900 px) in one place, at .tour-card. */
    .guide-button-text { display: none; }
}

/* ==========================================================================
   AI-ADGANGENS FIRE FELTER (1800047; runde 27's opstilling, runde 31's stil)
   The approval page and Desktop Edition's issuing dialog draw the SAME four
   rows, and they must look the same. The rules therefore live in one place, not in each surface:
   label in fixed width with its single (i) button on the left, the field on the right, and
   the boundary line flush with the fields. Mobile: stacked, never horizontal
   scrolling (memory html-faste-bredder applies to the FRAME, not to a frame that is
   narrower than its content).
   ========================================================================== */
.ai-fields { border: 1px solid var(--border); border-radius: var(--radius-xs); padding: .2rem .9rem .7rem; }
.ai-row { display: grid; grid-template-columns: 11rem minmax(0, 1fr); align-items: center; gap: 1rem; padding: .55rem 0; border-top: 1px solid var(--border); }
.ai-row:first-child { border-top: 0; }
.ai-row .ai-lab { font-size: .86rem; font-weight: 600; }
.ai-limit { font-size: .8rem; margin: 0 0 .2rem; padding-left: 12rem; }
/* RUNDE 49 (1800055): THE CONNECTION'S PERMISSIONS in the list. The cell carries the short sum, and both
   mouseover and click open the house's popover with the actual permissions. The panel is kt-vaelgerpanel,
   like the app's other popovers, and lies over the row without making the cell wider. */
.ai-right { position: relative; display: inline-block; cursor: help; }
.ai-rightpanel { 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-rightline { display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: .5rem; padding: .22rem 0; }
.ai-rightline + .ai-rightline { border-top: 1px solid var(--border); }
.ai-rightlabel { font-size: .76rem; font-weight: 600; }
.ai-retval { font-size: .76rem; }
.ai-rightfoot { position: fixed; inset: 0; z-index: 1040; }

/* RUNDE 49 (1800047 rev 4): the three GROUP HEADINGS Generelt, Skrive adgange and Token. The same
   muted uppercase heading that the house's picker panels use over their groups, so a group looks the same
   whether it stands in a picker or in a field list. The row after a heading carries no
   line: the heading is itself the separation. */
.ai-group { font-size: .72rem; font-weight: 600; color: var(--muted, #64748b); text-transform: uppercase; letter-spacing: .02em; padding: .8rem 0 .15rem; }
.ai-fields > .ai-group:first-child { padding-top: .5rem; }
.ai-group + .ai-row { border-top: 0; }

/* The approval page itself (runde 31): a narrow frame in the middle of an empty page, like the
   other pages without app navigation. */
.ai-approve { max-width: 34rem; margin: 2rem auto; }
.ai-approve > .card { padding: 1.25rem 1.4rem; }
.ai-approve h1 { font-size: 1.25rem; margin: 0 0 .8rem; }
.ai-approve .ai-client { margin: 0 0 .6rem; font-size: 1.05rem; }
.ai-approve .ai-info { font-size: .86rem; line-height: 1.45; }
/* RUNDE 49 (1800047 rev 4): Forbind and Annuller stand AT THE BOTTOM RIGHT and are EQUALLY WIDE. The width
   comes from the house's .kt-dialogbuttons (1600023 rev 2: equal in size within the individual dialog), and
   the outer row pushes the group to the right. The group's own auto margins are reset on the right side;
   otherwise they would centre it instead. */
.ai-approve .ai-buttons { display: flex; justify-content: flex-end; margin-top: .9rem; }
.ai-approve .ai-buttons > .kt-dialogbuttons { margin-right: 0; }

@media (max-width: 576px) {
    .ai-row { grid-template-columns: minmax(0, 1fr); gap: .25rem; }
    .ai-limit { padding-left: 0; }
    .ai-approve { margin: 1rem auto; }
}

/* B124 (1800042 rev 4, 1800098): REDIGER BUDGETPOSTER AS FIVE SWITCHES (AiBudgetActionsField), verbatim from
   the mockup C:\Claude Code\_planning\sprint8\mockups-b124-budgetadgang\css\side-godkendelse.css. An action is
   a line with the name on the left and the house's YesNoSegment on the right. The name wraps when there is no room
   (minmax(0, 1fr) and overflow-wrap: anywhere), and the spacing of .6rem to the button is fixed, so the name never touches
   it. No indentation: the four under Læs budget stand in line with it. The three after Opret are muted and
   locked at Nej until Opret is Ja. */
.ai-act { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: .6rem; padding: .16rem 0; }
.ai-act-name { font-size: .86rem; line-height: 1.25; white-space: normal; overflow-wrap: anywhere; min-width: 0; }
.ai-act.ai-dimmed .ai-act-name { color: var(--text-muted); }
/* The label is flush with the first line (Læs budget), not with the middle of the lines. */
.ai-row.ai-budget-a { align-items: start; }
.ai-row.ai-budget-a > .ai-lab { padding-top: .3rem; }

/* B124 (1800047 rev 7): THE APPROVAL PAGE'S CARD (ai-oauth: AiGodkendelse.razor hosted AND Desktop Edition's page after
   login from the bridge, AiDesktopGodkendelse.razor; same rules, never a copy). The card is about 816 px
   (51rem); the label column 14rem. The card is at most the window's height minus the page margin and scrolls itself. The heading
   and the client line (.ai-head) stay fixed at the top and the button line (.ai-buttons) fixed at the bottom with the surface's background,
   the house's technique from Budgetafstemning's headers; only what lies between scrolls. Forbind and Annuller stand centred.
   All Ja/Nej switches on the page are equally wide (8.75rem) and share the same right edge. */
.ai-approve.ai-oauth { max-width: 51rem; }
@media (min-width: 577px) {
    .ai-oauth .ai-row { grid-template-columns: 14rem minmax(0, 1fr); }
    .ai-oauth .ai-limit { padding-left: 15rem; }
}
.ai-oauth > .card.ai-card-fixed { padding: 0; max-height: calc(100vh - 4rem); overflow-y: auto; }
.ai-oauth .ai-head { position: sticky; top: 0; z-index: 2; background: var(--surface);
    padding: 1.25rem 1.4rem .6rem; border-bottom: 1px solid var(--border); }
.ai-oauth .ai-head .ai-client { margin: 0; }
.ai-oauth .ai-card-fixed form { padding: .8rem 1.4rem 0; }
.ai-oauth .ai-buttons { position: sticky; bottom: 0; z-index: 2; background: var(--surface);
    margin: .9rem -1.4rem 0; padding: .7rem 1.4rem 1.1rem; border-top: 1px solid var(--border); justify-content: center; }
.ai-oauth .ai-buttons > .kt-dialogbuttons { margin-left: auto; margin-right: auto; }
.ai-oauth .kt-yesno { width: 8.75rem; }
.ai-oauth .kt-yesno > .btn { flex: 1 1 0; }
.ai-oauth .ai-row > .kt-yesno { justify-self: end; }
/* 1800100 rev 3: the pickers for Firmaer, Læse adgange and Levetid are equally wide and share the right edge of the Ja/Nej
   switches. The width is the longest of the values the three show closed (the unseen .ai-target lines in each picker carry the
   same values, so the field takes its width from them, measured so the text stands without cutting). */
.ai-oauth .ai-row > div[style*="position:relative"] { justify-self: end; }
.ai-oauth .ai-target { display: grid; height: 0; overflow: hidden; visibility: hidden; pointer-events: none; }
.ai-oauth .ai-target-line { white-space: nowrap; padding-right: 2.6rem; border-width: 1px; }
/* 1800102: an opened panel on the approval page is as wide as its longest value needs, in one column. The search field and
   the help line take the panel's width and do not set it. */
.kt-panel-content-width .kt-panel-follows { contain: inline-size; min-width: 0; }
@media (max-width: 576px) {
    .ai-oauth > .card.ai-card-fixed { max-height: calc(100vh - 2rem); }
}

/* B136 (app 2011): THE COST REPORT AND THE PROJECT BUDGET, 1:1 after mockups A, B and C (sprint9\mockups-b136-kostrapport\css\mockup-kostrapport.css). */
.cr-head{display:flex;align-items:baseline;gap:1rem;flex-wrap:wrap;margin:.2rem 0 .6rem}
.cr-head h1{font-size:1.35rem;margin:0}
.cr-path{color:var(--text-muted,#6b7280);font-size:.85rem}
.cr-line{background:#eff6ff;border:1px solid #bfdbfe;color:#1e3a8a;border-radius:8px;padding:.5rem .8rem;font-size:.88rem;margin-bottom:.8rem}
.cr-line.gul{background:#fffbeb;border-color:#fde68a;color:#92400e}
.cr-table th,.cr-table td{font-variant-numeric:tabular-nums}
.cr-table td.num,.cr-table th.num{text-align:right;white-space:nowrap}
.cr-table tr.sek td{font-weight:600;background:var(--surface-2,#f3f4f6)}
.cr-table tr.lin td:first-child{padding-left:1.2rem}
.cr-table tr.tot td{font-weight:700;background:#e5e7eb;border-top:2px solid #94a3b8}
.cr-table tr.sub td{font-weight:600;border-top:1px solid #94a3b8}
.cr-table tr.post td{font-size:.82rem;color:#4b5563;background:#fafafa}
.cr-table tr.post.kladde td{color:#92400e;background:#fffbeb}
.cr-table .neg{color:#b91c1c}
.cr-table a.bilag{color:#1d4ed8;text-decoration:underline}
.cr-table input.form-control{text-align:right;min-width:7.5rem;font-variant-numeric:tabular-nums}
.cr-table input.form-control:disabled{background:#f1f5f9;color:#475569}
/* 700113: Kolonner on the cost report, the house's multi-select popover (colfilter-pop) with a check box per column and a
   grip for drag and drop; Nr. and Omkostning stand first without check box and grip; the divider is a fixed line in the list. */
.cr-col-wrap{position:relative;display:inline-block}
.cr-col-button{min-width:7rem;display:inline-flex;align-items:center;justify-content:space-between;gap:.5rem}
.cr-col-pop{left:0;width:320px}
.cr-col-list{display:flex;flex-direction:column;gap:1px}
.cr-col-row{display:flex;align-items:center;gap:.55rem;padding:5px 6px;border-radius:7px;margin:0}
.cr-col-row[draggable="true"]{cursor:grab}
.cr-col-row[draggable="true"]:hover{background:var(--surface-2)}
.cr-col-row.cr-col-dragging{opacity:.5}
.cr-col-grip{display:inline-flex;width:14px;color:var(--text-muted)}
.cr-col-check{margin:0;flex:none}
.cr-col-name{flex:1;font-size:.85rem;color:var(--text);margin:0;cursor:inherit}
.cr-col-off .cr-col-name{color:var(--text-muted)}
.cr-col-divider{display:flex;align-items:center;gap:.5rem;padding:4px 6px}
.cr-col-divider::before,.cr-col-divider::after{content:"";flex:1;border-top:2px solid var(--accent-border)}
.cr-col-divider span{font-size:.68rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em}
/* 700117 (mockups-kostrapport-tabel, 6.75rem from app 2067 so Nr., the sort arrow and the fold-all grip stand on one line
   in the head): the cost report's Nr. column is narrow, right-aligned and one fixed width on all
   rows; the fold button stands in its left edge, the number to the right (the group's bold and blue, the cost's muted). */
.cr-table col.cr-col-nr{width:6.75rem}
.cr-table td.cr-nr,.cr-table tr.lin td.cr-nr{text-align:right;padding-left:.25rem}
.cr-nr-cell{display:flex;align-items:center;justify-content:space-between;gap:.4rem}
.cr-nr-num{font-variant-numeric:tabular-nums}
/* The house marks a drill-down row's first cell italic; the Nr. cell carries the fold button itself and stays upright. */
.cr-table.cr-report tbody tr > td.cr-nr{font-style:normal}
.cr-table tr.sek .cr-nr-num{color:var(--accent-hover)}
.cr-fold{display:inline-flex;align-items:center;justify-content:center;flex:none;width:20px;height:20px;padding:0;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--text-muted);font-size:14px;line-height:1;font-family:inherit;cursor:pointer}
.cr-fold:hover{border-color:var(--accent-border);color:var(--accent-hover)}
.cr-fold-space{display:inline-block;flex:none;width:20px}
/* 700121: the grip that folds all groups stands in the Nr. head in the same left edge as the group's fold button below. */
.cr-table.cr-report thead th:first-child{padding-left:.25rem}
/* 700118: the cost report's group row in bold on one line with the muted blue background (the house's accent-soft and
   accent-border); the cost rows' names indented under the group, so the hierarchy reads downwards. Scoped to the cost
   report (cr-report), the project budget keeps its rows. */
.cr-report tr.sek td{font-weight:700;background:var(--accent-soft);border-bottom:1px solid var(--accent-border);white-space:nowrap}
.cr-report tr.sek td:nth-child(2){overflow:hidden;text-overflow:ellipsis}
.cr-report td.cr-indent{padding-left:1.9rem}
/* 700119 rev 2: the cost report's Subtotal, totals and result carry the house's line above (state-border) and the muted
   grey background (state-rest); only the two totals (cr-caps) in capitals by CSS, the result without, so the markup, the
   tour, the search and Excel keep the same words. */
.cr-report tr.sub td{font-weight:600;background:var(--state-rest);border-top:1px solid var(--state-border)}
.cr-report tr.tot td{font-weight:700;background:var(--state-rest);border-top:2px solid var(--state-border)}
.cr-report tr.cr-caps td:nth-child(2){text-transform:uppercase}
.cr-grid{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:1.2rem;align-items:start}
.cr-card{border:1px solid var(--border-strong,#cbd5e1);border-radius:10px;padding:.8rem 1rem;background:#fff}
.cr-card h2{font-size:1rem;margin:0 0 .6rem}
.cr-card table{width:100%;font-size:.88rem}
.cr-table th{white-space:normal;vertical-align:bottom}
.cr-table thead th{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;letter-spacing:0!important}
@media (max-width: 900px) { .cr-grid { grid-template-columns: minmax(0,1fr); } }
.cr-pct{display:flex;gap:1.2rem;flex-wrap:wrap;margin:.6rem 0}
.cr-pct label{font-size:.85rem;color:#475569;display:block}
.cr-pct input{width:6rem;text-align:right}

/* 1600040 rev 3 and 1600071: the button Hvordan bruger jeg denne side stands PRESSED while the help is on,
   filled in the house accent like the menu's chosen item (the approved mockup of B182). */
.btn.kt-navigation.guide-button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.kt-navigation.guide-button[aria-pressed="true"]:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.guide-button[aria-pressed="true"] .guide-button-icon { background: #fff; color: var(--accent); }
