/* ============================================================================
   FORTA KERNE @1.2. ALT ikke-brand: ink-skala, semantik (green/amber/red),
   flader, radius, typografi-tokens + kerne-komponenter (.pill, .side, .topbar,
   .lucide, .call-card, .pal-* …). Brand-farverne bor i forta-theme-crm.css
   (8 variabler). De gamle variabelnavne bevares HER som ALIASER → tema-vars, så
   ingen eksisterende komponent-CSS knækker. Indlæses core→theme→app.css.
   (Splittet ud af det tidligere forta-tokens.css — nul visuel ændring.)

   CHANGELOG
   ---------
   @1.0  D.7 Del A: kerne/tema-split.
   @1.1  Semantik-piller (.p-wait/.p-ok/.p-due) får kant-tokens (border:1px solid
         var(--*-bd)) jf. §1 — retter Bronze/Smaragd-vagtpost-kollision
         (accent-soft ≈ amber-bg), fundet af Ejendom. .p-info/.p-draft er
         fortsat kantløse (transparent kant → ens højde). Dark: -bd-tokens
         defineret i forta-dark.css.
   @1.2  §23-designreview (11/7): AA-tokens (mørkere grad-slut/ink-500/amber-tx),
         color-mix-afledte dark-accenter, chip-kant (.chip/.chip.on), samlet
         fokus-ring, solid .btn-danger, .tag-badge, note-panel, samt nye kerne-
         komponenter (toast/tooltip/skeleton/disabled/motion). Dark-QA-rettelser:
         systemisk thead-baggrund (var(--bg-panel)), dark-scrollbars.

   BINDENDE DISTRIBUTIONS-REGEL (Ejendom-feedback 12/7): DENNE fil er APP-kernen
   (Tailwind-afhængig: @apply + app-selektorer + --c-*-palette-kanaler) og kan
   IKKE kopieres standalone. Det kanoniske distributions-artefakt er
   `static/css/forta-core-dist.css` (ren CSS, nul Tailwind). HVERT kerne-bump
   SKAL regenerere dist-filen + bumpe dens header — et bump uden opdateret dist
   er UFULDSTÆNDIGT. Se docs/design-coverage.md + FORTA-PLATFORM-TEMA.md §4.
   ============================================================================ */

/* ============================================================================
   SELF-HOSTEDE SKRIFTER (D.12). Tidligere hentet fra Google Fonts CDN, men
   prod-serveren har begrænset egress → Sora/Inter/JetBrains Mono loadede aldrig,
   og Display-rollen faldt tilbage til system-sans (Sora "ikke aktiv"). Nu
   bundtet lokalt (latin-subset, variable woff2) så de ALTID loader uanset
   egress. latin-subset dækker æøå (U+00C0–00FF). ========================== */
@font-face {
  font-family:'Sora'; font-style:normal; font-weight:100 800; font-display:swap;
  src:url('/static/fonts/sora.woff2') format('woff2');
}
@font-face {
  font-family:'Inter'; font-style:normal; font-weight:100 900; font-display:swap;
  src:url('/static/fonts/inter.woff2') format('woff2');
}
@font-face {
  font-family:'JetBrains Mono'; font-style:normal; font-weight:100 800;
  font-display:swap; src:url('/static/fonts/jetbrains-mono.woff2') format('woff2');
}

:root {
  /* Brand-ALIASER → forta-theme-crm.css (bagudkompatibilitet; ingen komponent
     skal ændres). De orphan-toner (blue-800/teal-300/-200/-100) er ubrugte og
     kollapses trygt til nærmeste tema-var. */
  --blue-900:var(--b-mid);   --blue-800:var(--b-mid);
  --blue-700:var(--accent-link); --blue-500:var(--accent);
  --teal-400:var(--accent);  --teal-300:var(--accent);
  --teal-200:var(--accent-soft); --teal-100:var(--accent-soft);
  /* Neutraler (ink-skala — non-brand) */
  --ink-900:#0B1B2B; --ink-800:#1A2D40; --ink-700:#2C4458; --ink-600:#4A6378;
  /* §23/10a: --ink-500 mørknet #6B829A→#5C748C (labels/hjælpetekster består AA
     mod hvid flade). NY --ink-400 = den GAMLE ink-500-tone, KUN til dekorativt
     brug (fx delta-glyffer) — flyt IKKE eksisterende ink-500-brug hertil blindt.
     🔴 MØRKNET IGEN 21-08 #5C748C→#50657A: «mod hvid flade» ovenfor var netop
     problemet. Appen maler tekst på 16 lyse flader, og på den mørkeste
     (#e3e6ea, sidefoden) gav #5C748C 3,87 — målt renderet på .setting-section-h
     («Kommunikation» på /mere). Ny værdi: 4,81 dér, 6,03 på hvid.
     Værn: tests/test_tonet_flade_kontrast.py. Rapport: rapporter/gatede/. */
  --ink-500:#50657A; --ink-400:#6B829A;
  --ink-300:#C5D2DD; --ink-200:#E2E9EF; --ink-100:#F1F5F8; --ink-50:#F8FAFC;
  /* 🔴 MØRK INK PÅ LYS ACCENT — navngivet efter ROLLEN, ikke farven.
     Værdien #08131F er IKKE en vilkårlig mørk navy og IKKE --bg-app (#081320,
     forta-dark.css:40). Den er valgt fordi HVID tekst på den lyse teal-gradient
     falder §23/AA: målt pr. gradient-stop (#1E96B0 / #2BB3B8 / #43E4E4) giver
     hvid 3,47 / 2,55 / 1,56 mod AA's krav på 4,50, mens #08131F giver
     5,38 / 7,34 / 11,98. forta-dark.css skriver reglen selv: «hvid tekst på
     lys teal er FORBUDT (består aldrig §23)».
     Brug den til tekst OG ikoner der ligger på en accent-fyldt flade:
     .btn-primary, .filter-pill-selected, .topnav-mark, .save-bar, .mnav-scan-
     knap, .pos-btn-card. Ændr den ikke uden at måle de tre stop igen.
     🔴 DEFINERET PÅ BAR :root — ikke i @media/[data-theme]. En custom property
     opløses hvor den DEFINERES; en tema-scopet definition ville være usynlig
     for de regler der bruger den.
     Værn: tests/test_kontrast_token_literal.py */
  --tekst-paa-lys-accent:#08131F;
  /* Semantik (green/amber/red — non-brand) */
  /* 🔴 --green-tx mørknet 21-08 #0E7C66→#0D705D. FOREBYGGENDE: målt renderet
     ligger den kun på #e7f7ee (4,63), #fafefe (5,05) og hvid (5,13) — den
     faldt ikke. Men et token der er godkendt mod HVID falder den dag nogen
     sætter det på en tonet flade. Nu 4,80 på husets mørkeste flade. */
  --green-bg:#E7F7EE; --green-bd:#9ADBB5; --green-tx:#0D705D;
  /* §23/10a: --amber-tx mørknet #946B00→#8A6300 (AA på amber-bg-flade).
     🔴 MØRKNET IGEN 21-08 #8A6300→#815C00: stod på 4,54 mod den tonede
     #d5f0f1 — 0,04 over kravet er et sammenfald, ikke en margin. Nu 4,84 på
     den mørkeste flade. Falder ikke i dag på de flader den FAKTISK ligger på
     (#fdf4e3 4,97) — ændringen er forebyggende. Se test_tonet_flade_kontrast. */
  --amber-bg:#FDF4E3; --amber-bd:#F0D9A6; --amber-tx:#815C00;
  --red-bg:#FDF0EF;   --red-bd:#F2B8B5;   --red-tx:#B3261E;
  /* Info-flade = accent-soft (alias → tema) */
  --info-bg:var(--accent-soft);  --info-tx:var(--accent-soft-tx);
  /* BS-pillen «BS-trækkes DD-MM» (25-09-2026). Andreas: «Brug en mørkere blå
     på BS så den ikke har samme farve som Bogført». Begge var `.p-info`, og
     --info-* er ALIAS for tenantens accent — derfor en FAST, ikke-brand blå
     her (som green/amber/red), mørkere og blåere end accent-soft. Målt på
     malede pixels i rapporter/bsfarve/. Regel: `.p-info[data-bs-booket]`. */
  --bs-bg:#C4D5F5; --bs-tx:#16347A;
  /* Flader */
  /* §24.2 CC·lys: tonet app-bg (#EDF3F6) bag HVIDE paneler (--c-surface=255
     nedenfor) — den adskillelse Command Center bygger på. --bg-panel forbliver
     SOLID: 5 komponenter sætter background-color:var(--bg-panel) (en gradient-
     værdi ville dér blive ugyldig→transparent). Panel-gradienten fra prototypen
     er en CC.2-flade-adoption, ikke en token-redefinition. */
  --bg-app:#EDF3F6; --bg-panel:#fff; --bd-panel:var(--ink-200);
  /* --papir (24-09-2026): underlaget bag en UNDERSKRIFTS-tegning. Hvidt i
     BEGGE temaer med vilje, og derfor IKKE overstyret i forta-dark.css:
     PNG'en har gennemsigtig bund og moerk pen, som forsvinder paa
     --bg-panel i moerkt tema. Papir er hvidt. Et token frem for #fff i
     skabelonen, saa hensigten staar ét sted (test_dark_kontrast). */
  --papir:#fff;
  /* §24.2 CC — global app-baggrund m. radial glød (0d). To dobbelt-radials
     over --bg-app (tonet, IKKE hvid). Static teal-fallback FØR color-mix-linjen
     (white-label: en tenants egen --accent farver gløden; de 8 tema-var urørte).
     background-attachment:fixed sættes på body i app.src.css. */
  --bg-grad:radial-gradient(1100px 640px at 82% -10%,rgba(43,179,184,.18),transparent 58%),radial-gradient(820px 560px at 2% 112%,rgba(30,150,176,.12),transparent 55%),var(--bg-app);
  --bg-grad:radial-gradient(1100px 640px at 82% -10%,color-mix(in srgb,var(--accent) 18%,transparent),transparent 58%),radial-gradient(820px 560px at 2% 112%,color-mix(in srgb,var(--accent) 12%,transparent),transparent 55%),var(--bg-app);
  --radius-panel:16px; --radius-control:9px; --radius-pill:999px;

  /* ── 0e KOMPLET TOKEN-PORT (byggeplan 23/7) — prototypens surface-token-sæt
     ORDRET (LYS). Brand-tonede literals re-afledt af var(--accent*)-parret via
     color-mix m. STATIC fallback FØR mix-linjen (§24.1); de 8 tema-var urørte.
     Accent-mapping: prototype var(--accent) LYS → --accent-strong (fyldt) /
     --accent (link); MØRK → --accent-bright (se forta-dark.css). ───────────── */
  --panel:linear-gradient(180deg,#FFFFFF,#FAFEFE);   /* kort/panel-flade (LYS) */
  --panel-solid:#FFFFFF;
  --panel-2:var(--bg-panel-2);
  --border:#D6E5E9; --border-strong:#BDD5DB;
  --ink:#0C2231; --ink-2:#4A6676; --ink-3:#7B95A3;
  --glow:0 16px 36px -24px rgba(20,70,90,.40),0 0 40px -30px rgba(27,90,110,.5);
  --shadow:0 16px 34px -22px rgba(30,80,100,.34);
  --shadow-float:0 22px 50px -20px rgba(30,80,100,.44);
  --radius:var(--radius-panel); --radius-sm:11px;
  --font-display:'Sora',-apple-system,'Segoe UI',system-ui,sans-serif;
  --font-mono:'JetBrains Mono','SF Mono',Consolas,ui-monospace,monospace;
  --chip:#FFFFFF; --chip-bd:#C3DAE0;
  --num-glow:none;
  --tbl-hover:rgba(20,110,126,.07);
  --tbl-hover:color-mix(in oklab,var(--accent-strong) 8%,transparent);
  --grad-btn:linear-gradient(135deg,#15495D,#1C6C7C);
  --grad-btn:linear-gradient(135deg,var(--accent-strong),color-mix(in oklab,var(--accent-strong),var(--accent) 40%));

  /* ── §24 COMMAND CENTER — surface-tokens (LYS). ────────────────────────────
     Nye kerne-tokens (§24.2). Brand-bærende (--card-top/--accent-strong/
     --accent-bright) AFLEDES af var(--accent) via color-mix — HVER med en
     statisk fallback FØR color-mix-linjen (samme mønster som forta-dark.css:
     45-56). White-label bevares: en anden tenants --accent giver automatisk
     nye surfaces. De 8 tema-variabler (--accent, --grad, --b-deep …) er URØRTE.
     Admin arver disse gennem sin egen --accent (slate) → coherent, ikke teal. */
  --bg-panel-2:#EBF4F6;                 /* sænket sekundær-flade (§24.2 lys) */
  --elev-card:0 16px 34px -22px rgba(30,80,100,.34);   /* kort-elevation (lys) */
  --elev-float:0 22px 50px -20px rgba(30,80,100,.44);  /* svævende (modal/dropdown) */
  --card-top:linear-gradient(90deg,transparent,rgba(27,110,126,.5),transparent);
  --card-top:linear-gradient(90deg,transparent,color-mix(in oklab,var(--accent) 82%,#06222E) 50%,transparent);
  --accent-strong:#15495D;              /* mørknet accent — fyldte elementer i LYS */
  /* 🔴 40 %, IKKE 55 % — TOKENETS EGEN KONTRAKT (maalt 21-08-2026).
     --accent-strong bruges som BAGGRUND med color:#fff elleve steder
     (.mc-send, .pc-add, .trk-ud_til_levering, .pd-reladd m.fl.), og den
     blander MOD noget meget moerkt. Kontrakten ER «hvid tekst er laesbar paa
     mig». Ved 55 % faldt 163 af 899 proevede accenter under AA — de LYSE,
     fordi mere accent = lysere flade = mindre kontrast med hvid. Vores egen
     bestod med 5,25:1, og det er grunden til at ingen har set det.

     TO KNAPPER, BEGGE MAALT:
       forholdet        bestaaende interval 0-45 %.
       moerkningsfarven kun ren `black` bestaar ved 55 %; #04161e og #020a0e
                        falder stadig. `black` ville ogsaa fjerne en BRANDET
                        literal (#06222E er en moerk teal, som drejer kuloeren
                        for en tenant med fx orange accent) — men den koster
                        vores egen flade meget: 55 % mod black giver 11,37:1
                        mod dagens 7,31, altsaa en markant moerkere knap.
                        Det er en designbeslutning, ikke en tilgaengelig-
                        hedsrettelse, og den skal traeffes for sig.

     VALGT: forholdet, og 40 og ikke 45. 45 bestaar med 4,57:1 — 0,07 over AA
     paa et gitter af 899 punkter i et kontinuum. Det er ikke en margin, det
     er et sammenfald. 40 giver 5,32:1 (+0,82). Samme argument som 45 frem for
     47 og 55 frem for 58.

     🔴 PRISEN: vores egen knap bliver moerkere. Lys #135e72 -> #104d5e
     (7,31 -> 9,35:1), moerk #1c7780 -> #165e69 (5,25 -> 7,40:1). Mindre
     accent = mindre identitet, som de to foregaaende gange.

     Literalen ovenfor er IKKE regnet om: dens kontrakt er «≈», ikke «=» (se
     forta-dark.css' egen note), og den er stadig paa den sikre side —
     #15495D giver 9,80:1 mod formlens 9,35. Vaern:
     test_hvid_tekst_er_laesbar_paa_accent_strong_for_hele_gamuttet. */
  --accent-strong:color-mix(in oklab,var(--accent) 40%,#06222E);
  --accent-bright:#43E4E4;              /* lysnet accent — glød/aktiv-tekst i MØRK */
  --accent-bright:color-mix(in oklab,var(--accent) 70%,white);
  --bd-control:#A9C3CB;                 /* §24.3: tydelig sekundærknap-/kontrol-kant (lys) */

  /* ── §24.2 CC — SIDEBAR-IDENTITET: ALTID near-black, i BEGGE modes ─────────
     Prototypens --sb-* (Command near-black, 180deg #050D16→#07131F). Sidebaren
     følger IKKE lys/mørk-toggle — den er en fast mørk identitet (§24.2). Tokens
     er mode-UAFHÆNGIGE (defineret her i :root, IKKE i forta-dark.css) → ingen
     mode kan gøre den lys.
     Aktiv-tekst = accent-bright (CC.1-afledt af var(--accent), white-label-sikker).
     🔴 CC.7 0b (2026-07-23): --sb-bg er nu AFKOBLET fra --b-deep/--b-mid og sat
     til den faste Command near-black. Tidligere afledte vi sidebaren af de to
     brand-navy-tokens (white-label-drevet), men live-auditten (§24.2/GLOBAL-1)
     viste at facit vil have den ægte near-black — ikke tenantens lysere brand-
     navy. Bevidst white-label-afvejning besluttet af Andreas: sidebar-fladen er
     Command-identitet, ikke brand-flade. De 8 tema-var (--b-deep/--b-mid inkl.)
     er STADIG URØRTE — vi bruger dem bare ikke længere til sidebar-baggrunden.
     Solid #050D16-fallback FØR gradienten → kan aldrig falde til hvid. */
  --sb-bg:linear-gradient(180deg,#050D16 0%,#07131F 100%);
  --sb-ink:#CFE0EC;                     /* nav-tekst (blød lys på mørk) */
  --sb-ink-dim:#6F8AA1;                 /* gruppe-labels/dæmpet */
  --sb-hover:rgba(255,255,255,.06);     /* hover-flade */
  --sb-active-tx:var(--accent-bright);  /* aktiv nav-tekst = accent-bright */

  /* D.11 (§20): RGB-KANALER for Tailwind-paletten (torp/surface/border/
     neutral/success/warning/danger). tailwind.config.js peger colors mod
     rgb(var(--c-x) / <alpha-value>). LYS = PRÆCIS de gamle hex-kanaler →
     lyst tema er byte-identisk. body.dark (forta-dark.css) omdefinerer disse
     → hele Tailwind-fladen flipper fra ét sted. */
  --c-torp-navy:14 42 71;   --c-torp-blue:30 74 122;
  --c-torp-light:57 112 168; --c-torp-bg:230 240 250;
  --c-surface:255 255 255;  /* §24.2 CC·lys: rene HVIDE paneler på tonet --bg-app */
  --c-border:238 242 246;   --c-border-2:216 222 229;
  /* Semantik-kanalerne var DRIFTET fra §1's egne green/amber/red-tokens:
     to parallelle paletter for samme betydning. Målt i lys mode blev
     Tailwind-parrene liggende under AA (success 4,10 · warning-på-danger-bg
     4,27 · danger 4,65), mens §1-parrene består. Kanalerne er nu SAT LIG
     §1-tokens (--green-tx/-bg, --amber-tx/-bg, --red-tx/-bg) → én palet,
     og alle tre par kommer over 4,5 (4,63 · 4,89 · 5,88). MØRK var allerede
     afstemt (forta-dark.css) og er urørt. */
  --c-success:13 112 93;   --c-success-bg:231 247 238;  /* #0D705D / #E7F7EE */
  --c-warning:129 92 0;     --c-warning-bg:253 244 227;  /* #815C00 / #FDF4E3 */
  --c-danger:179 38 30;     --c-danger-bg:253 240 239;   /* #B3261E / #FDF0EF */
  --c-neutral:90 107 124;   --c-neutral-strong:45 62 82; --c-neutral-bg:241 243 245;
}

/* ── Typografi-roller (§3). Skrifterne loades via <link> i base.html. ───────
   Display = Sora, Data = JetBrains Mono. UI (Inter) sættes på body i app.css. */
.font-display { font-family:'Sora',-apple-system,'Segoe UI',system-ui,sans-serif; }

/* Data: ordrenr./fakturanr./varenr./CVR/S/N/snapshot-id */
.mono-id {
  font-family:'JetBrains Mono','SF Mono',Consolas,ui-monospace,monospace;
  font-weight:500;
  font-variant-numeric:tabular-nums;
  letter-spacing:-0.01em;
}

/* KPI-tal: Sora 600, clamp(26–32px), tabular-nums (§3)
   🔴 INGEN letter-spacing på kortet (designens F3, 24-09-2026). Den stod her
   som −0,02em, og en em-værdi ARVES SOM SIN BEREGNEDE PX: 32 px × −0,02 =
   −0,64 px på ALT i kortet, også en 11 px «→ se alle», der så ud som ét ord
   («→sealle»). Målt 24-09 (designens_maal.py): negativ spatiering på tekst
   uden for tallet på 3 af 18 flader — tech-dashboardet og admins dashboard
   og virksomhedsside, i admin også på 393. Tallets egen
   spatiering bor på tallet — `.kpi-value` (tracking-tight, app.src.css) og
   `.kpi .val` (nedenfor) — og ingen .kpi-skabelon har et tal uden for de
   to (skannet 24-09: 38 skabeloner). */
/* 🔴 INGEN Sora på kortet (designvalg 26-09-2026, designens (b)).
   FORTA-DESIGNSYSTEM §3: Sora er «sidetitler, hilsner, KPI-tal, kundenavn»,
   Inter er «alt andet: labels, knapper, tabeller, brødtekst». Kortet satte
   Sora på ALT i sig, så labels og underlinjer arvede displayskriften —
   målt: 94 tekstnoder på 15 flader (40 × .kpi-label, 17 × delta-linjer …).
   Tallene bærer Sora selv: `.kpi-value` (app.src.css) og `.kpi .val`
   (var(--font-display)); målt 0 tal-elementer uden Sora før og efter. Samme
   form som `.uds-kpi`-rettelsen 23-09, nu for hele huset. */
.kpi {
  font-weight:600;
  font-size:clamp(26px,4vw,32px);
  font-variant-numeric:tabular-nums;
  line-height:1.05;
}
/* D.9/D.12: MRR-KPI'ens gradient-tal defineres nu i app.src.css som
   .kpi-value.kpi-value-grad (højere specificitet end .kpi-value's color). */
/* D.9: rigt tomt-tilstands-ikon — Lucide i en afrundet ink-100-boks.
   .empty-ic = kompakt (34px, i kort/paneler); .empty-ic-lg = 44px til
   fuld-side/fane-tomme-tilstande (D.8-polish). */
.empty-ic {
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:9px;
  background:var(--ink-100); color:var(--ink-500); margin-bottom:8px;
}
.empty-ic-lg { width:44px; height:44px; border-radius:11px; margin-bottom:10px; }

/* ============================================================================
   D.12 — Dashboard-workbench visuel finish.
   ========================================================================= */
/* "Min dag"-rækker: farvet ikon-chip + titel/undertekst + handling. */
.day-row { display:flex; align-items:center; gap:11px; padding:11px 2px; }
.day-row + .day-row { border-top:1px solid var(--ink-100); }
.day-chip { flex:0 0 auto; width:34px; height:34px; border-radius:9px;
  display:flex; align-items:center; justify-content:center;
  background:var(--ink-100); color:var(--ink-600); }
.day-chip.is-amber { background:var(--amber-bg); color:var(--amber-tx); }
.day-chip.is-info  { background:var(--accent-soft); color:var(--accent-soft-tx); }
.day-chip.is-green { background:var(--green-bg); color:var(--green-tx); }
.day-chip.is-red   { background:var(--red-bg);   color:var(--red-tx); }
.day-body { flex:1 1 auto; min-width:0; }
.day-title { font-weight:600; font-size:13.5px; color:var(--ink-800); }
.day-sub { font-size:12px; color:var(--ink-500); }
.day-action { flex:0 0 auto; }

/* "Seneste aktivitet"-rækker: farve-dot + tekst + højrestillet relativ tid. */
.act-row { display:flex; align-items:center; gap:9px; padding:6px 0; }
.act-row + .act-row { border-top:1px solid var(--ink-100); }
.act-dot { flex:0 0 auto; width:8px; height:8px; border-radius:999px;
  background:var(--ink-300); }
.act-dot.is-green  { background:var(--green-tx); }
.act-dot.is-accent { background:var(--accent); }
.act-body { flex:1 1 auto; min-width:0; }
.act-body strong { font-weight:600; color:var(--ink-800); }
.act-time { flex:0 0 auto; margin-left:auto; font-size:11.5px; color:var(--ink-500);
  font-variant-numeric:tabular-nums; white-space:nowrap; }

/* Ensartet "Se alle →"-link på alle paneler (§7). */
.see-all { font-size:12.5px; font-weight:600; color:var(--accent-link);
  text-decoration:none; white-space:nowrap; }
.see-all:hover { text-decoration:underline; }

/* Kasse-kortets kv-linjer (§5). */
.kv-line { display:flex; align-items:center; justify-content:space-between;
  font-size:12.5px; padding:2px 0; }
.kv-line .kv-k { color:var(--ink-500); }
.kv-line .kv-v { color:var(--ink-700); font-variant-numeric:tabular-nums; }

/* Kompakt sekundær pille-knap (selvstændig — ingen .btn-afhængighed). */
.btn-mini { display:inline-flex; align-items:center; gap:5px; padding:5px 12px;
  border-radius:999px; border:1px solid var(--bd-panel); background:var(--bg-panel);
  font-size:12px; font-weight:600; color:var(--ink-700); text-decoration:none;
  cursor:pointer; white-space:nowrap;
  transition:border-color .12s ease, background .12s ease; }
.btn-mini:hover { border-color:var(--accent); background:var(--ink-50); }
.btn-block { display:flex; width:100%; justify-content:center; }

/* Liste-navn med undertekst-mønster (§6): navn 600 + "By · CVR"-linje. */
.list-name { font-weight:600; color:var(--ink-800); }

/* Kunde-/entitet-avatar på detaljesider (§7): initial på gradient, Sora. */
.detail-avatar { width:56px; height:56px; border-radius:50%; background:var(--grad);
  color:#fff; display:flex; align-items:center; justify-content:center;
  font-family:'Sora',-apple-system,'Segoe UI',system-ui,sans-serif;
  font-weight:600; font-size:20px; flex:0 0 auto; }

/* Beløb/taltabeller: tabular-nums + højrestillet (§3). */
.tnum { font-variant-numeric:tabular-nums; }
.amount { font-variant-numeric:tabular-nums; text-align:right; }

/* ── Statuspiller — ét semantisk system (§5) ───────────────────────────────
   Selve .pill-basen (layout + 5px dot) defineres i app.src.css (Tailwind-laget,
   indlæses sidst → kanonisk), så den deles af BÅDE de eksisterende .pill-active/
   -pending/-overdue/-neutral/-info OG de nye .p-*-varianter herunder. Her står
   kun farve-varianterne (semantik-tokens). */
/* forta-core@1.1 (§1/§5): semantik-piller (p-wait/p-ok/p-due) får en 1px kant i
   deres -bd-token — retter Bronze/Smaragd-vagtpost-kollisionen (accent-soft ≈
   amber-bg), fundet af Ejendom. p-info/p-draft forbliver KANTLØSE (accent-chip-
   reglen: semantik-pille = bg+kant+dot · accent-chip = kantløs uden dot). De
   får en TRANSPARENT 1px kant, så alle piller har samme højde (ingen synlig
   højde-ændring — border-box). */
.p-draft { background:var(--ink-100);  color:var(--ink-600); border:1px solid transparent; } /* Kladde/Inaktiv/neutral */
.p-wait  { background:var(--amber-bg); color:var(--amber-tx); border:1px solid var(--amber-bd); } /* Afventer/Rykker */
.p-info  { background:var(--info-bg);  color:var(--info-tx); border:1px solid transparent; } /* Bekræftet/Info */
.p-info[data-bs-booket] { background:var(--bs-bg); color:var(--bs-tx); } /* BS-trækkes — IKKE Bogført-blå, se --bs-bg */
.p-ok    { background:var(--green-bg); color:var(--green-tx); border:1px solid var(--green-bd); } /* Betalt/Aktiv/OK */
.p-due   { background:var(--red-bg);   color:var(--red-tx);   border:1px solid var(--red-bd); }   /* Forfalden/Fejl */
/* Nøgletal i alarmtilstand — `kpi--alert` stod på FEM flader (webshop-overblik,
   -afstemning, -status, lageroversigt) uden én regel, så alarmen var usynlig.
   Fundet 24-09-2026 da døde-CSS-værnet lærte at se klasser i {% if %}-blokke.
   Samme tokens som .p-due; de findes i lyst, mørkt og mobil-laget. */
.kpi.kpi--alert { border-color:var(--red-bd); }
.kpi.kpi--alert .kpi-value { color:var(--red-tx); }
/* Dashboardets fire topfliser (Andreas 24-09-2026, «dashfliser»): hver
   sammenligning på EGEN linje. `.kpi-delta-*` er inline-flex (app.src.css),
   så to korte linjer lagde sig side om side når flisen var bred nok — målt
   ved 1920: «+37 vs. samme dag i august» og «+642 vs. september 2025» på
   samme y. Scopet til krogen, fordi ti andre flader bruger .kpi-strip og
   ikke er bedt om at ændre sig. Specificitet 0,2,0 slår app.css' 0,1,0. */
[data-dash-fliser] .kpi-delta-positive,
[data-dash-fliser] .kpi-delta-negative,
[data-dash-fliser] .kpi-delta-neutral { display:flex; }
/* Beløbslinjernes tekst efter ikonet (dashfliser, 24-09-2026). Uden denne
   span var «+88.087», «kr» og «vs. …» hver sit flex-barn af linjen, og på 393
   pressede de teksten ned i en smal søjle — «september» løb 14 px ud over
   flisen. Spannen er selv en flex med linjens EGET gap (inherit), så
   afstandene på skrivebordet er de samme som før, og wrap lader «vs. …»
   falde ned som én bid i stedet for at blive en kolonne. */
[data-dash-fliser] .kpi-delta-tekst {
  display:flex; flex-wrap:wrap; align-items:inherit; gap:inherit; min-width:0;
}
/* MRR-broen i «Aktive abonnementer» (designens, 24-09-2026). Den stod som
   ÉN tekstlinje — «September: 0 nye · 0 op · 0 ned · 0 opsagte · +0 kr/md»,
   289 px (306 med rigtige tal) i en flise hvis tekstbredde er 186–318 px
   ved 900–1920 — og brødes derfor midt i et led («0 / kr/md»). Nu to faste
   led: beløbet med måneden, derunder kundefordelingen. Hvert «N ord» er
   nowrap, så et led der alligevel ikke kan være der, brydes ved en «·» og
   aldrig mellem tal og ord. Intet er fjernet; rækkefølgen følger de andre
   linjer i striben (beløbet først). */
/* 0,3,0: forta-mobil.css giver `.kpi-strip .kpi-delta-*` gap:6px (0,2,0) og
   indlæses efter kernen; uden den ekstra klasse fik de to led 6 px luft på 393. */
/* ÉN LINJE NÅR DER ER PLADS (designvalg 26-09-2026, designens (c)). Med to
   faste led var broen to linjer også ved 1920, hvor der er plads til én
   (flise 147 → 159 px, målt). Nu står leddene på én række med wrap: er der
   plads, står de side om side; ellers falder led 2 ned som før.
   Adskilleren «·» står FORAN hvert led, og den foran et led der STARTER en
   linje klippes væk: broen er rykket .9em til venstre (margin) og klippet
   .9em fra venstre (clip-path), så linjestartens adskiller ligger i det
   klippede bånd. Derfor aldrig et «·» i starten eller slutningen af en linje,
   uanset hvor langt tallene bliver. `/ ""` holder tegnet ude af skærmlæserens
   tekst. */
[data-dash-fliser] .kpi-delta-neutral[data-abon-bro] {
  flex-direction:row; flex-wrap:wrap; align-items:baseline; gap:0;
  margin-left:-.9em; clip-path:inset(0 0 0 .9em);
}
/* 🔴 HÆNGENDE INDRYK (protokode, 28-09-2026). Klippet ovenfor antog at en
   linje kun kan STARTE med et led — men et led kan selv brydes INDENI, ved
   et af sine egne «·». Fortsættelseslinjen startede så i det klippede bånd,
   og båndet åd det der stod dér: målt ved 393×852 stod der «opsagte» og
   ikke «0 opsagte» — tallet var væk, ikke adskilleren. `padding-left` +
   negativ `text-indent` lader første linje (med «·»-et) starte i båndet som
   før, og alle fortsættelseslinjer starte .9em inde, uden for det.
   Et led der ikke brydes, tegnes pixel for pixel som før.
   Vagt: tests/test_protokode_r2_kpi_hoejde.py. */
[data-dash-fliser] .kpi-bro-led { display:block; padding-left:.9em; text-indent:-.9em; }
[data-dash-fliser] .kpi-bro-led::before {
  content:"·" / ""; display:inline-block; width:.9em; text-align:center;
  text-indent:0;   /* inline-block arver ledets negative indryk (se nedenfor) */
}
[data-dash-fliser] .kpi-bro-led > span { white-space:nowrap; }
/* Ens flisehøjder (Andreas via forta-56, 24-09-2026). Grid'et strækker
   fliserne i SAMME række, men ved 900–1199 er striben 2×2, og rækkerne
   fik hver sin højde (målt ved 1000: 140 og 123). `grid-auto-rows:1fr`
   giver alle rækker den højeste. Kun fra 900px: under breakpointet er
   striben telefonens vandrette karrusel (§31), og den ejes af app-designet. */
@media (min-width: 900px) {
  [data-dash-fliser] { grid-auto-rows:1fr; }
}

/* ── CC.7 BATCH 2 (Abonnementer, byggeplan ordret) — delta-tal + forecast-grid.
   .fc-grid: 4 måneds-celler pr. række; .fc-m.now = indeværende måned fremhævet
   (accent-kant + accent-soft-flade). ────────────────────────────────────────── */
.delta { font-weight:700; font-size:12px; }
.delta.up   { color:var(--green-tx); }
.delta.down { color:var(--red-tx); }
.fc-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
@media (max-width:1100px) { .fc-grid { grid-template-columns:repeat(2,1fr); } }
@media (max-width:560px)  { .fc-grid { grid-template-columns:1fr; } }
.fc-m { border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:11px 13px; background:var(--panel-2); min-width:0; }
.fc-m.now { border-color:var(--accent); background:var(--accent-soft); }
/* Sekundaerteksten i «nu»-cellen foelger FLADEN: --accent-soft bevaeger sig
   med tenanten, saa teksten bruger det par der er bygget til den —
   --accent-soft-tx, maalt over 899 accenter (test_accent_soft_tx_formel).
   Samme greb som .pal-row-meta. Maalt 26-09: `text-neutral` #7d94a9 paa
   #174052 = 3,53 i moerkt tema (/abonnementer/forecast). */
.fc-m.now .text-neutral { color:var(--accent-soft-tx); }
/* Kundekortets enheder («kr», «dage») og tomt-tegnet «—»: --ink-2, ALDRIG
   --ink-3 (se «SEKUNDAER TEKST ER --ink-2» laengere nede). Stod inline som
   --ink-3 i kunder/_tab_oversigt.html — maalt 26-09 paa pixels: 3,11 lys,
   3,91 moerk. (Placeret her fordi reglen skal staa FOER mobil-laget.) */
.kd-enhed { color:var(--ink-2); }
.fc-m .fc-mlabel { font-size:10.5px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-2); }
.fc-m .fc-mval { font-family:'JetBrains Mono','SF Mono',Consolas,ui-monospace,monospace;
  font-size:16px; font-weight:700; color:var(--ink); margin-top:3px;
  font-variant-numeric:tabular-nums; }

/* ── Filter-chips (§23/10c/K4) — ALTID synlig kant: inaktiv 1px ink-200,
   aktiv (.chip.on) 1.5px solid var(--accent). Bruges i list_toolbar (afløser
   p-pill p-info/p-draft på chips), så status-pillerne ikke arver chip-
   interaktion. box-sizing:border-box (global reset) → 1px↔1.5px giver ingen
   layout-hop. ──────────────────────────────────────────────────────────── */
.chip { display:inline-flex; align-items:center; gap:5px; padding:4px 11px;
  border-radius:var(--radius-pill); border:1px solid var(--ink-200);
  background:var(--bg-panel); color:var(--ink-600); font-size:12.5px;
  font-weight:600; line-height:1.4; cursor:pointer; text-decoration:none;
  white-space:nowrap;
  transition:border-color .15s ease, background .15s ease, color .15s ease; }
.chip:hover { border-color:var(--ink-300); color:var(--ink-800); }
.chip.on { border:1.5px solid var(--accent); background:var(--accent-soft);
  color:var(--accent-soft-tx); }

/* 🔴 .chips HAVDE INGEN REGEL — KUN EN OMTALE I KOMMENTAREN OVENFOR.
   Tre skabeloner (ordrer/list, sager/list, regnskab/landing) bruger
   beholderen til deres filter-chips, og uden reglen stod chippene som
   inline-elementer uden mellemrum. Vaernet test_doede_css_klasser saa den som
   "defineret", fordi det laeste CSS'en raat og talte navnet i kommentaren med
   — se rettelsen i samme commit.

   Reglen ligger i forta-core (ikke i mobil-laget), fordi beholderen bruges paa
   BEGGE bredder. NB: app-merge-runde-2 har en identisk regel i
   forta-mobil.css, altsaa kun under 899px. Ved merge skal den ene fjernes —
   to regler for samme selektor er en tavs dublet hvor den sidste vinder. */
/* 🔴 DENNE REGEL GÆLDER OGSÅ ADMIN — den er bare uden virkning DER I DAG.
   Målt i den kørende app 15-08: /admin/ laster forta-core.css (men hverken
   forta-mobil.css eller forta-dark.css). Reglen her lander altså i
   admin-fladen. Den gør ingenting, fordi `class="chips"` forekommer 0 gange i
   admin/templates/ — ikke fordi den er afgrænset.

   Det er en garanti med en udløbsdato ingen kan se: den dag en admin-skabelon
   får `class="chips"`, arver den denne regel uden at nogen har besluttet det,
   og der er ingen test der bliver rød. Skriver du en chips-beholder i admin,
   så ved du nu hvad du arver. */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* `.chips-rad` er en beholder om chip-striben OG «Flere filtre», indfoert
   fordi en `overflow-x:auto`-stribe klipper skuffens absolut placerede panel
   (maalt 25-08-2026: x=616 paa en 393px skaerm). Paa skrivebordet maa den
   ikke kunne ses: wrapperen baerer selv den wrappende flex-raekke, og
   `.chips` traeder ud af layoutet med `display:contents`, saa chips og
   <details> er de SAMME flex-elementer i den SAMME raekke som foer.
   Maalt: skuddet ved 1280x900 er pixel-identisk foer og efter. */
.chips-rad { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.chips-rad > .chips { display: contents; }

/* ── REGNSKAB-KOMPONENTER (regnskabdesign R0, 03-10-2026) ────────────────────
   Makroerne bor i tech/templates/regnskab/_ui/ (R0: periodevælger og eksport;
   R9: tom-tilstand; beløbscellen kommer med sin første bruger i R1/R3 — ikke
   som død kode før). Begge bredder, derfor her og
   ikke i mobil-laget. Periodevælgeren er prototypens chips (skærm 07) + et
   «Tilpas …» der folder husets to datofelter ud; summary'en ER en chip, så
   egen periode og forvalg står i samme række med samme form. */
.rd-periode { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.rd-tilpas { position: relative; }
.rd-tilpas > summary { list-style: none; }
.rd-tilpas > summary::-webkit-details-marker { display: none; }
.rd-tilpas-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; margin-top: 8px; }
/* Spejlets rapportvælger, foldet til én række (designkritik §22). «Andre
   rapporter …» er en <details>; åben tager den hele bredden, så panelet med de
   andre grupper står samlet under rækken i stedet for at klemme sig ind i den. */
.rd-rapportvaelger { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.rd-rapport-flere > summary { list-style: none; }
.rd-rapport-flere > summary::-webkit-details-marker { display: none; }
.rd-rapport-flere[open] { flex-basis: 100%; }
.rd-rapport-flere-panel { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
/* R5-1 (designkritik §23): spejlets rapportside på telefonen. «⋯ Del og gem»
   samler eksport og Gem; på skrivebordet står panelet åbent uden summary. */
.rd-del > summary { list-style: none; display: none; }
.rd-del > summary::-webkit-details-marker { display: none; }
.rd-rapport-select { display: flex; align-items: center; gap: 8px; }
/* Momssidens ene svarkort (designkritik §27): hensættelsen som én talrække
   under tallet, adskilt af en hårstreg — ikke et kort mere. */
.moms-hens { border-top: 1px solid var(--chip-bd); padding-top: 12px; }
.moms-hens-tal { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: 12px; margin-top: 6px; }
.moms-forklaring > summary { list-style: none; cursor: pointer; display: inline-flex; min-height: 32px; align-items: center; }
.moms-forklaring > summary::-webkit-details-marker { display: none; }
@media (max-width: 899px) {
  .rd-del > summary { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; }
  .rd-del[open] > .header-actions { margin-top: 8px; }
  /* De to infokort (fravalgte rapporter, Opsætning) er LUKKET to chips på én
     række; åbnet er de et helt kort. Før: ~240 px før første tal. */
  #fravalgte-rapporter:not([open]), #rapport-opsaetning:not([open]) {
    display: inline-flex; vertical-align: top; padding: 0; margin: 0 6px 12px 0;
    border: 0; background: none; box-shadow: none; }
  #fravalgte-rapporter:not([open]) > summary, #rapport-opsaetning:not([open]) > summary {
    min-height: 44px; padding: 0 14px; border: 1px solid var(--chip-bd); border-radius: 999px;
    background: var(--bg-panel); font-size: 13px; }
  #fravalgte-rapporter:not([open]) > summary .text-xs,
  #rapport-opsaetning:not([open]) > summary .text-xs { display: none; }
}
/* Kassekladdens to tabeller (kladder og bogførte) står lige under hinanden og
   skal have SAMME kolonner (designkritik §17: Dato stod ved x=148 mod x=131).
   Kun på skrivebordet — på telefonen er rækkerne kort (data-app-raekke). */
@media (min-width: 900px) {
  .kladde-tabel { table-layout: fixed; }
  .kladde-tabel th:nth-child(1) { width: 7rem; }
  .kladde-tabel th:nth-child(2) { width: 8rem; }
  .kladde-tabel th:nth-child(4) { width: 6rem; }
  .kladde-tabel th:nth-child(5) { width: 11rem; }
}
/* Tom-tilstand §17.7: ikon i tonet boks + én sætning + højst én handling.
   Første bruger: cockpittets «Forbind banken» (R9, 03-10). */
.rd-tom { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rd-tom-ikon { width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center;
  background: var(--ink-100); color: var(--ink-600); flex: none; }
.rd-tom-tekst { margin: 0; flex: 1 1 260px; color: var(--ink-600); }
.rd-tom-tekst strong { color: var(--ink-900); }
/* Regnskabets menu (R1, 04-10-2026, `regnskab/_regnskab_menu.html`): grupperne
   er husets .subnav-chip, gruppens sider husets .chip (§8c) på rækken under.
   Telefonen får ÉN række der folder en hub ud (MØNSTERBOG §7); den er
   .kun-app og skjules derfor over 899 px af laget længere nede. */
.rd-menu { margin-bottom: 18px; }
/* V2 (designkritik F2): grupperne er FANER, ikke piller. Aktiv = --ink + 2 px
   accent-understregning (§6 budgetpost 2, «aktiv navigation-markering»); en
   --bd-panel-linje under hele rækken. Undersiderne er tekst. */
.rd-faner { display: flex; align-items: flex-end; gap: 4px 22px; flex-wrap: wrap; border-bottom: 1px solid var(--bd-panel, var(--chip-bd)); }
.rd-fane { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 10px 0 11px;
  font-size: 14px; font-weight: 600; color: var(--ink-2); text-decoration: none; white-space: nowrap; }
.rd-fane:hover { color: var(--ink); }
.rd-fane.on { color: var(--ink); }
.rd-fane.on::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px; background: var(--accent); }
.rd-fane-guide { margin-left: auto; font-weight: 500; color: var(--ink-2); }
.rd-undersider { display: flex; flex-wrap: wrap; gap: 4px 20px; padding-top: 10px; }
.rd-underside { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); text-decoration: none; }
.rd-underside:hover { color: var(--ink); }
.rd-underside.on { color: var(--ink); font-weight: 600; }
.rd-taeller { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--chip); color: var(--ink-2); font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; }
.rd-hub-raekke { display: flex; align-items: flex-start; gap: 8px; }
.rd-hub-raekke .rd-hub { flex: 1 1 auto; min-width: 0; }
.rd-hub-soeg { display: grid; place-items: center; flex: none; width: 44px; height: 44px; border: 1px solid var(--chip-bd);
  border-radius: 12px; background: var(--bg-panel); color: var(--ink-2); }
.rd-hub-knap { width: 100%; border: 0; background: transparent; text-align: left; font: inherit; cursor: pointer; gap: 8px; }
.rd-hub > summary { list-style: none; }
.rd-hub > summary::-webkit-details-marker { display: none; }
.rd-hub-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 0 14px; border: 1px solid var(--chip-bd); border-radius: 12px;
  background: var(--bg-panel); cursor: pointer; }
.rd-hub-sti { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rd-hub-mere { display: inline-flex; align-items: center; gap: 6px; flex: none; font-size: 14px;
  font-weight: 600; color: var(--accent-link, var(--accent)); }
.rd-hub[open] > .rd-hub-summary { border-color: var(--accent); }
.rd-hub-liste { margin-top: 8px; padding: 4px 0 8px; border: 1px solid var(--chip-bd); border-radius: 12px;
  background: var(--bg-panel); }
.rd-hub-titel { margin: 12px 14px 2px; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-2); }
.rd-hub-gruppe { padding-bottom: 4px; }
.rd-hub-gruppe.aktiv .rd-hub-titel { color: var(--accent-link, var(--accent)); }
.rd-hub-punkt { display: flex; align-items: center; min-height: 44px; padding: 0 14px;
  color: var(--ink); text-decoration: none; }
.rd-hub-punkt.on { background: var(--accent-soft); color: var(--accent-soft-tx); font-weight: 700; }

/* ── OVERBLIK — flagskibet (regnskabdesign R1, 04-10-2026, `regnskab/landing.html`
   + `_overblik_svar/_liste/_naeste.html`). Ingen nye tokens: statusfladerne er
   pillernes par (--red-bg/--red-tx …, §5), tallene Sora (--font-display, §3).
   Luften er bevidst større end husets standardkort: siden er det første man
   ser, og den skal kunne læses på tre sekunder (Andreas 04-10: «simpelt,
   professionelt og super indbydende»). Mobil-laget står i forta-mobil.css. */
.ov-synk { display: inline-flex; align-items: center; gap: 6px; color: var(--green-tx); font-weight: 600; font-size: 12.5px; }
/* BANKNEM punkt 4 (05-10-2026): bankens statuslinje (`regnskab/_bankstatus.html`).
   Grøn = synket inden for 24 t; gul = synken står stille eller samtykket udløber
   inden 14 dage. Pillernes tekstfarver (§5), ingen nye tokens. Skrivebordets kopi
   står i undertitlen; telefonens (`-mobil`) under svaret, som `.ov-synk-mobil`. */
.ov-bankstatus { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px; margin-top: 4px;
  color: var(--green-tx); font-weight: 600; font-size: 12.5px; }
.ov-bankstatus[data-bank-status="advarsel"] { color: var(--amber-tx); }
.ov-bankstatus > svg { flex: none; }
/* Teksten må krympe og ombryde INDE i sin egen boks — ellers lagde flex-wrap
   ikonet alene på én linje og teksten på den næste (målt 393 px, 05-10). */
.ov-bankstatus > span { flex: 1 1 14rem; min-width: 0; }
.ov-bankstatus-mobil { grid-column: 1 / -1; margin: 0; font-size: 12px; }
.ov-handlinger { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ov-find { position: relative; }
.ov-find .form-input { padding-left: 34px; min-width: 240px; }
.ov-find-ikon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--ink-2); pointer-events: none; display: inline-flex; }

.ov-svar { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 32px; align-items: center;
  padding: 26px 28px; margin-bottom: 16px; }
.ov-svar[data-ov-svar="ukendt"] { grid-template-columns: minmax(0, 1fr); }
.ov-svar.ov-svar--kompakt { grid-template-columns: minmax(0, 1fr); gap: 14px; }
.ov-graf-mobil { display: none; }
.ov-svar-linje { margin: 0; font-size: 15px; color: var(--ink); line-height: 1.5; }
.ov-svar-linje strong { font-family: var(--font-display); font-size: 18px; }
.ov-svar-linje-tal { color: var(--ink-2); }
.ov-svar-tekst { min-width: 0; }
.ov-svar-spm { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink-2); }
.ov-svar-hoved { margin: 6px 0 18px; font-family: var(--font-display); font-size: 30px; line-height: 1.15;
  font-weight: 700; letter-spacing: -.015em; color: var(--ink); }
.ov-svar-tal { display: flex; flex-wrap: wrap; gap: 14px 30px; margin: 0 0 14px; }
.ov-svar-tal dt { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.ov-svar-tal dd { margin: 4px 0 0; font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--ink); }
.ov-svar-hvem { display: block; margin-top: 2px; font-family: inherit; font-size: 12px; font-weight: 500; color: var(--ink-2); }
.ov-svar-graf svg { display: block; width: 100%; height: auto; overflow: visible; }
.ov-graf-y { font-size: 11px; fill: var(--ink-2); font-variant-numeric: tabular-nums; }
/* Egen bogs forløb uden bank (designkritik 6.2-f): tre trin i §33's
   tilstandssprog — gjort (grøn ✓ + facit), næste (accent + handling),
   venter (dæmpet nummer). */
.ov-trin { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; }
.ov-trin-r { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-top: 1px solid var(--chip-bd); }
.ov-trin-r:first-child { border-top: 0; }
.ov-trin-mk { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
  font-size: 13px; font-weight: 700; border: 1.5px solid var(--bd-panel); color: var(--ink-2); }
.ov-trin-gjort .ov-trin-mk { background: var(--green-bg); border-color: transparent; color: var(--green-tx); }
.ov-trin-venter .ov-trin-mk { border-style: dashed; }
.ov-trin-naeste .ov-trin-mk { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-soft-tx); }
.ov-trin-tekst { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: 15px; }
.ov-trin-under { font-size: 13px; color: var(--ink-2); }
.ov-trin-gjort .ov-trin-tekst > strong { font-weight: 600; color: var(--ink-2); }
@media (max-width: 899px) { .ov-trin-r { flex-wrap: wrap; } .ov-trin-tekst { flex-basis: calc(100% - 40px); }
  .ov-trin-r > .btn-primary { flex-basis: 100%; justify-content: center; min-height: 44px; }
  .ov-trin-r > .see-all { margin-left: 40px; } }
.ov-svar-akse { display: flex; justify-content: space-between; margin-top: 6px; font-size: 11px; color: var(--ink-2); }
/* V2 (designkritik F9): svaret er sidens ENE fremhævede sted — en accent-tonet
   kant og gradient-teksten (§6 budgetpost 3). Mørkt tema slår gradient-teksten
   fra af hensyn til læsbarheden, som `.kpi-value-grad` (forta-dark.css §4). */
.ov-svar { border-color: color-mix(in oklab, var(--accent) 40%, var(--bd-panel)); }
/* `.ov-grad` (gradient-TEKST, background-clip:text) står i app.src.css ved husets
   `.kpi-value-grad` — pakke 120: kontrast_grad_flade måler tekst PÅ en --grad-flade,
   og her ER gradienten teksten (samme undtagelse som .kpi-value-grad, med grund). */
body.dark .ov-grad { background: none; -webkit-background-clip: border-box; background-clip: border-box;
  color: var(--ink); -webkit-text-fill-color: var(--ink); }
/* F5: legenden er tilbage (§25), «i dag» står ved sin streg. */
.ov-graf-etiket { font-size: 11px; fill: var(--ink-3); }
.ov-graf-legende { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 6px; font-size: 11.5px; color: var(--ink-2); }
.ov-graf-legende span { display: inline-flex; align-items: center; gap: 6px; }
.ov-lg { display: inline-block; width: 16px; height: 0; border-top: 3px solid var(--accent); }
.ov-lg-fuld { border-top-style: solid; }
.ov-lg-stiplet { border-top-style: dashed; }
.ov-lg-punkt { width: 10px; height: 10px; border: 3px solid var(--accent); border-radius: 50%; }
.ov-lg-nul { border-top: 1px dashed var(--ink-3); }
.ov-lg-prik { width: 9px; height: 9px; border: 0; border-radius: 50%; background: var(--accent); }
.ov-kasse-del { display: block; font-size: 12px; font-weight: 400; color: var(--ink-2); line-height: 1.5; }  /* §21: 400, kun beløbet bærer 600 */
.ov-kasse-del .num { color: var(--ink-2); font-weight: 600; }
.ov-lg-spids { color: var(--ink-2); }
.ov-brief { grid-column: 1 / -1; margin: 4px 0 0; padding-top: 14px; border-top: 1px solid var(--bd-panel); font-size: 14px; color: var(--ink-2); }
.ov-brief-maerke { display: inline-block; margin-right: 6px; padding: 1px 8px; border-radius: 999px; background: var(--accent-soft);
  color: var(--accent-soft-tx); font-size: 11.5px; font-weight: 700; }
.ov-synk-mobil { grid-column: 1 / -1; margin: 0; font-size: 12px; color: var(--ink-2); }
/* F8: den tomme tilstand siger næste skridt i --ink, ikke et gråt «nej». */
.ov-svar-tom { grid-template-columns: minmax(0, 1fr); }
.ov-svar-tom-h { margin: 6px 0 6px; font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--ink); }
.ov-svar-tom-tekst { margin: 0 0 14px; color: var(--ink-2); }

/* F6: KPI-kortene har samme rytme — label · tal · status · links nederst. */
.ov-kpi .kpi { display: flex; flex-direction: column; }
.ov-kpi-status { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 26px; margin-top: 8px; }
.ov-kpi-status .pill { white-space: nowrap; }
.ov-kpi-links { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: auto; padding-top: 12px; }
.ov-kpi-periode { white-space: nowrap; }
.ov-kpi-label { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.ov-ikonknap { display: inline-grid; place-items: center; width: 28px; height: 28px; margin: -6px -6px -6px 0; border: 0;
  border-radius: 8px; background: transparent; color: var(--ink-2); cursor: pointer; }
.ov-ikonknap:hover { background: var(--chip); color: var(--ink); }
.ov-liste { margin-bottom: 16px; padding: 20px 22px 6px; }
.ov-liste-hoved { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.ov-liste-hoved h2, .ov-kort-titel { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--ink); }
.ov-liste-antal { display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px;
  background: var(--chip); color: var(--ink-2); font-size: 12px; font-weight: 700; }
.ov-opgaver { list-style: none; margin: 0; padding: 0; }
.ov-opgave { display: grid; grid-template-columns: 40px minmax(0, 1fr) 150px 150px; align-items: center; gap: 14px;
  padding: 14px 0; border-top: 1px solid var(--chip-bd); }
.ov-opgave:first-child { border-top: 0; }
.ov-ikon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 11px; flex: none; }
.ov-ikon-due  { background: var(--red-bg);   color: var(--red-tx); }
.ov-ikon-wait { background: var(--amber-bg); color: var(--amber-tx); }
.ov-ikon-info { background: var(--info-bg);  color: var(--info-tx); }
.ov-ikon-ok   { background: var(--green-bg); color: var(--green-tx); }
.ov-opgave-tekst { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ov-opgave-tekst strong { font-size: 15px; font-weight: 600; color: var(--ink); }
.ov-opgave-tekst span { font-size: 13px; color: var(--ink-2); }
.ov-opgave-hoejre { grid-column: 3; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.ov-opgave-frist { white-space: nowrap; }
/* Forta Calls svævende knap ligger i højre hjørne; listen giver den plads (F7). */
@media (min-width: 900px) { .card.ov-liste { padding-right: 76px; } }
/* Samme plads til Forta Calls svævende knap på Pengestrøms dagbog
   (designkritik §13): ved 1440 stod den oven på nederste rækkes øje-ikon. */
@media (min-width: 900px) { #dagbog.card { padding-right: 76px; } }
.ov-opgave-valg { grid-column: 2 / -1; display: flex; justify-content: flex-end; align-items: center; gap: 4px; margin-top: -6px; }
.ov-opgave-valg .btn-ghost { color: var(--ink-2); font-weight: 500; }
.ov-opgave-valg .btn-ghost:hover { color: var(--ink); }
.ov-valg-tekst { font-size: 12.5px; color: var(--ink-2); margin-right: 6px; }
.ov-opgave-udsat > :not(.ov-opgave-valg) { opacity: .55; }
.ov-skjult-linje { margin: 4px 0 12px; font-size: 12.5px; color: var(--ink-2); }
.ov-intet-h { margin: 0; font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--ink); }
.ov-intet-t { margin: 2px 0 0; font-size: 13.5px; color: var(--ink-2); }
/* F9: ikonfladerne kan ses i mørkt tema — pillens egen kant. */
.ov-ikon-due { border: 1px solid var(--red-bd); } .ov-ikon-wait { border: 1px solid var(--amber-bd); } .ov-ikon-ok { border: 1px solid var(--green-bd); }
.ov-opgave-refs { font-size: 12.5px; }
.ov-opgave-beloeb { text-align: right; font-family: var(--font-display); font-weight: 700; color: var(--ink); white-space: nowrap; }
.ov-opgave-h { grid-column: 4; justify-self: stretch; justify-content: center; text-align: center; }
.ov-intet { display: flex; align-items: center; gap: 14px; padding: 8px 0 14px; }

.ov-par { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-bottom: 16px; }
.ov-kort { padding: 20px 22px; }
.ov-kort-titel { margin-bottom: 14px; font-size: 15px; }
.ov-bar-raekke { display: grid; grid-template-columns: 172px minmax(0, 1fr) auto; align-items: center; gap: 12px; margin-bottom: 10px; }
.ov-bar-navn { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); }
.ov-bar { height: 10px; border-radius: 999px; background: var(--chip); overflow: hidden; }
.ov-bar-fyld { display: block; height: 100%; border-radius: 999px; }
.ov-bar-ind { background: var(--green-tx); }
.ov-bar-ud  { background: var(--ink-3); }
.ov-bar-beloeb { min-width: 112px; text-align: right; font-family: var(--font-display); font-weight: 700; color: var(--ink); }
.ov-kort-under { margin: 10px 0 12px; font-size: 12.5px; color: var(--ink-2); }
.ov-kort-links { display: flex; flex-wrap: wrap; gap: 16px; }
.ov-linjer { margin: 0 0 12px; }
.ov-linjer > div { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0; border-top: 1px solid var(--chip-bd); }
.ov-linjer > div:first-child { border-top: 0; padding-top: 0; }
.ov-linjer dt { font-size: 13.5px; color: var(--ink-2); }
.ov-linjer dd { display: flex; align-items: baseline; gap: 8px; margin: 0; }
.ov-linjer .num { font-family: var(--font-display); font-weight: 700; color: var(--ink); }
.ov-delta { padding: 1px 7px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.ov-delta.op { background: var(--green-bg); color: var(--green-tx); }
.ov-delta.ned { background: var(--red-bg); color: var(--red-tx); }
.ov-delta.neutral { background: var(--chip); color: var(--ink-2); }

/* Kildevalget (R4, 04-10-2026): kun når både e-conomic og Forta-bogen har data. */
.rd-kilde { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.rd-kilde-label { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
/* Kassekladdens bilag (R3, 04-10-2026): én arbejdsflade — linjer, én række
   til en ny linje, en bund med status og handlinger. */
.kl-ny-knap { white-space: nowrap; }
.kl-ny-fold { margin-bottom: 16px; }
.bf-kontonr { color: var(--ink-2); margin-right: 6px; font-variant-numeric: tabular-nums; }
.bf-ny .card-title { margin-bottom: 10px; }
.bf-ny-raekke { display: grid; grid-template-columns: minmax(0, 2.2fr) minmax(0, .9fr) minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1.8fr) auto;
  gap: 10px; align-items: end; }
.bf-felt { display: flex; flex-direction: column; gap: 4px; margin: 0; min-width: 0; }
.bf-ny-knap { white-space: nowrap; }
.bf-ny-knap-bund { display: contents; }
/* Kontoplanens sammenfoldning (R10 «til 9»): overskriften er knappen.
   Pilen er en ren CSS-trekant, så den følger tekstfarven i begge temaer. */
.kp-fold { display: inline-flex; align-items: center; gap: 8px; min-height: 32px; padding: 0;
  background: none; border: 0; font: inherit; font-weight: 600; color: inherit; cursor: pointer; text-align: left; }
.kp-fold-pil { width: 0; height: 0; border-left: 5px solid currentColor; border-top: 4px solid transparent;
  border-bottom: 4px solid transparent; transition: transform .15s; }
.kp-fold[aria-expanded="true"] .kp-fold-pil { transform: rotate(90deg); }
.kp-fold-antal { font-size: 12px; font-weight: 400; color: var(--ink-2); }
.kp-tabel tr.kp-overskrift > td { vertical-align: middle; }
/* Regnskabsår (designkritik2 1d): «Lås» stod en halv række under sin periode,
   fordi husets tabelceller er top-justeret (`.data-table tbody td`), og
   knappens tekst sidder længere nede i den højere knap. Midterjusteret står
   den på rækken. */
table.aar-perioder tbody td { vertical-align: middle; }   /* slår `.data-table tbody td` (align-top, 0,1,2) */
.bf-mere { margin-top: 10px; }
.bf-mere > summary { list-style: none; cursor: pointer; display: inline-flex; min-height: 32px; align-items: center; }
.bf-mere > summary::-webkit-details-marker { display: none; }
.bf-bund { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 20px; }
.bf-bund-tekst { font-size: 14px; }
.bf-bund-knapper { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.btn-ghost.bf-kasser { color: var(--red-tx); }
.bf-fjern { min-width: 36px; color: var(--ink-2); }
.bf-fjern:hover, .bf-fjern:focus-visible { color: var(--red-tx); }
.bf-modal-tal { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 0 0 14px; }
.bf-modal-tal dt { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); }
.bf-modal-tal dd { margin: 4px 0 0; font-weight: 700; color: var(--ink); }
/* Kontoplanen (R10, 04-10-2026): en læst liste med grupper og sumlinjer. */
.kp-soeg { min-height: 40px; width: 16rem; }
.kp-kort { padding-top: 6px; }
.kp-tabel td, .kp-tabel th { padding-top: 7px; padding-bottom: 7px; }
.kp-tabel .kp-nr { width: 4.5rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.kp-tabel .kp-art, .kp-tabel .kp-moms { color: var(--ink-2); }
.kp-tabel .kp-saldo { width: 9rem; text-align: right; font-variant-numeric: tabular-nums; }
.kp-ny-knap { white-space: nowrap; }
.kp-tabel .kp-handling { width: 3.5rem; text-align: right; }
.kp-tabel .kp-handling a { color: var(--ink-2); font-size: 12.5px; }
.kp-tabel tr:hover .kp-handling a, .kp-tabel .kp-handling a:focus-visible { color: var(--accent-link, var(--accent)); }
/* K5 (R10-kritik): «Ret» på overskrifter og sumlinjer står først ved hover/fokus
   på skrivebordet — 65 × «Ret» var støj. Telefonen viser det altid (ingen hover). */
@media (hover: hover) {
  .kp-tabel tr.kp-ret-skjult .kp-handling a { opacity: 0; }
  .kp-tabel tr.kp-ret-skjult:hover .kp-handling a, .kp-tabel tr.kp-ret-skjult .kp-handling a:focus-visible { opacity: 1; }
}
.kp-tabel tr.kp-overskrift td { padding-top: 18px; font-weight: 700; color: var(--ink); border-bottom: 1px solid var(--chip-bd); }
.kp-tabel tr.kp-overskrift td[data-stack-title] { text-transform: uppercase; letter-spacing: .06em; font-size: 12px; }
.kp-tabel tr.kp-sum td { font-weight: 700; border-top: 1px solid var(--chip-bd); }
.kp-tabel tr.kp-sum .kp-art { font-weight: 400; font-size: 12px; }
.kp-tabel tr.kp-konto td[data-stack-title] { font-weight: 500; color: var(--ink); }
.kp-tabel tr.kp-spaerret td { color: var(--ink-2); }
.kp-ny { scroll-margin-top: 96px; }
.kp-tabel tr.kp-ret td { background: var(--bg-panel-2); }   /* pakke 120: et fladt token der findes i begge temaer */
.kp-ret-felter { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 16px; justify-content: space-between; }
.kp-ret-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; margin: 0; }
.kp-ret-form .form-label { display: flex; flex-direction: column; gap: 4px; margin: 0; }
.kp-moms-felt { width: 6rem; }
/* Pengestrøms dagbog (R12, 04-10-2026): én linje pr. post. */
.rd-dag { display: grid; grid-template-columns: 76px minmax(0, 1fr) 128px 104px 44px; align-items: center; gap: 12px;
  min-height: 44px; padding: 6px 0; border-top: 1px solid var(--chip-bd); }
.rd-dag-dato { font-size: 12.5px; color: var(--ink-2); }
.rd-dag-tekst { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; }
.rd-dag-navn { font-weight: 600; color: var(--ink); }
.rd-dag-hvorfor { flex-basis: 100%; font-size: 12px; color: var(--ink-2); }
.rd-dag-beloeb { text-align: right; font-weight: 700; }
.rd-dag-saldo { text-align: right; font-size: 12.5px; color: var(--ink-2); }
.rd-dag-x { min-width: 44px; }
/* Egen bog uden kasse (designkritik §27/§28): samme række uden saldo-kolonnen —
   fraværet af saldoen er udsagnet. Talrækken over den: ind · ud · forskel. */
.rd-dag--kendt { grid-template-columns: 96px minmax(0, 1fr) 128px 44px; }
.rd-ps-tal { display: grid; grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr)); gap: 12px; }
.rd-dag-hoved { min-height: 0; padding: 4px 0; border-top: 0; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-2); }
.rd-dag-hoved > span { font-size: 11px; font-weight: 700; color: var(--ink-2); }
.rd-dag > a { color: var(--ink-2); }
.rd-dag > a:hover, .rd-dag > a:focus-visible { color: var(--ink); }
.rd-dagbog-resten > summary { list-style: none; cursor: pointer; margin: 12px 0 4px; }
.rd-dagbog-resten > summary::-webkit-details-marker { display: none; }
.ov-detaljer { margin-bottom: 12px; border: 1px solid var(--chip-bd); border-radius: 14px; background: var(--bg-panel); }
.ov-detaljer > summary { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 18px;
  list-style: none; cursor: pointer; font-weight: 600; color: var(--ink); }
.ov-detaljer > summary::-webkit-details-marker { display: none; }
.ov-detaljer > summary::after { content: '›'; margin-left: auto; font-size: 20px; color: var(--ink-2); transition: transform .15s ease; }
.ov-detaljer[open] > summary::after { transform: rotate(90deg); }
.ov-detaljer-under { font-size: 12.5px; font-weight: 400; color: var(--ink-2); }
.ov-detaljer[open] > summary { border-bottom: 1px solid var(--chip-bd); }
.ov-detaljer > .card, .ov-detaljer > div > .card, .ov-detaljer > section { margin: 0; border: 0; border-radius: 0; box-shadow: none; background: transparent; }

/* ── §24.5 CC — Subview-chip-faner (genbrugelig subnav-kernekomponent) ──────
   CC.7 0c: løftet 1:1 fra prototypens .chips/.chip-mønster. Erstatter de flade
   understregnings-faner (.tab/.tab-active) på subview-navigation. Eget navn
   (.subnav-*) → kolliderer IKKE med filter-.chip ovenfor; de to sameksisterer.
   Aktiv = accent-soft-fyldt pille (white-label-sikker: bruger de 8 tema-var
   --accent-soft/--accent-soft-tx, ændrer dem ikke). Bruges af ordre-detalje
   (BATCH 3), virksomhedsopslag (BATCH 4), kundekort (BATCH 5), regnskab
   (BATCH 1/8). Server er source-of-truth for aktiv fane (aria-current) —
   samme mønster som tabs_nav; FortaSubnav-JS'en er kun til rene klient-
   subview-sider (alle paneler renderet på én gang). */
.subnav { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.subnav-chip {
  display:inline-flex; align-items:center; gap:6px;
  font-size:12.5px; font-weight:600; line-height:1.5;
  padding:7px 13px; border-radius:999px;
  background:var(--chip); border:1px solid var(--chip-bd);
  color:var(--ink-2); cursor:pointer; text-decoration:none; white-space:nowrap;
  transition:border-color .15s ease, background .15s ease, color .15s ease;
}
.subnav-chip:hover { border-color:var(--accent); color:var(--ink); }
.subnav-chip.on,
.subnav-chip[aria-current="page"] {
  background:var(--accent-soft); color:var(--accent-soft-tx);
  /* 🔴 Andreas 24-08-2026: «det er svaert at se at man har trykket paa den».
     MAALT hvorfor: den aktive chip BYTTEDE en synlig kant for en usynlig tone.
       inaktiv kant  #C3DAE0 mod #FFFFFF   1,46:1  (synlig)
       aktiv  bg     #EAF4FB mod #FFFFFF   1,12:1  (naesten intet)
       aktiv  kant   transparent                   (VAEK)
     Nettoresultatet var at den valgte fane var MINDRE markeret end sine
     naboer. Den beholder nu en kant — i accent-farven, saa forskellen
     ligger i FARVE og STYRKE og ikke i om kanten findes:
       aktiv kant #1E96B0 mod #EAF4FB      3,12:1  (2,1x naboens)
       moerk tilstand: accent mod panelet  4,35:1  ✅ */
  border-color:var(--accent); font-weight:700;
}
/* Tæller-badge inde i en chip (fx "Fakturaer 28"). */
.subnav-chip .c { opacity:.7; font-variant-numeric:tabular-nums; font-weight:600; }
/* ── Kundekort etape 1 (27-09-2026): KRAV og GRUPPE i fanerækken ──────────
   `.c` er gråt: hvor meget der er. `.krav` er farvet: nogen skal gøre noget
   («2 forfaldne»). Farverne er statuspillernes egne tokens, så lys/mørk og
   AA følger med dem (se CLAUDE.md, «Statusfarverne i lyst tema»). */
.c.krav { opacity:1; font-weight:700; border-radius:999px; padding:0 7px;
  font-variant-numeric:tabular-nums; }
.c.krav .krav-antal { font-variant-numeric:tabular-nums; }
.krav-due  { background:var(--red-bg);   color:var(--red-tx); }
.krav-wait { background:var(--amber-bg); color:var(--amber-tx); }
/* Gruppen er en <details> med en §33-menu (skal-menu.js placerer panelet). */
.subnav-gruppe { position:relative; display:inline-flex; }
.subnav-gruppe > summary { list-style:none; }
.subnav-gruppe > summary::-webkit-details-marker { display:none; }
.subnav-gruppe[open] > summary { border-color:var(--accent); color:var(--ink); }
/* En prik på «Mere» når noget derinde kræver noget — punktet selv siger hvad. */
.krav-prik { width:8px; height:8px; border-radius:50%; flex:0 0 8px; }
.krav-prik.krav-wait { background:var(--amber-tx); }
.krav-prik.krav-due  { background:var(--red-tx); }
.subnav-gruppe .fx-menu-tekst { flex:1 1 auto; }
.subnav-gruppe .fx-menu-punkt[aria-current="page"] { font-weight:700;
  background:var(--accent-soft); color:var(--accent-soft-tx); }
/* BATCH 8: lodret divider + dæmpede "på vej"-placeholders i regnskab-fanerækken. */
.subnav-div { width:1px; height:20px; background:var(--border); margin:0 4px;
  flex:0 0 auto; }
.subnav-soon { opacity:.55; cursor:default; }
.subnav-soon:hover { border-color:var(--chip-bd); color:var(--ink-2); }
/* Grupperet mega-chip-klynge (BATCH 5: Salg/Økonomi/Kontakt). Gruppe-label +
   under-chips samlet i én pille-ramme. */
.subnav-group { display:inline-flex; align-items:center; gap:2px;
  padding:3px 5px 3px 10px; border-radius:999px;
  background:var(--bg-panel-2); border:1px solid var(--bd-panel); }
.subnav-glabel { font-size:11px; font-weight:700; text-transform:uppercase;
  letter-spacing:.04em; color:var(--ink-500); padding-right:4px; }
.subnav-group .subnav-chip { border:0; background:transparent; padding:5px 10px; }
.subnav-group .subnav-chip.on,
.subnav-group .subnav-chip[aria-current="page"] { background:var(--accent-soft); }
/* Grå "· på vej"-placeholder (BATCH 8: roadmap-faner uden rute endnu). */
.subnav-chip.is-coming,
.subnav-chip[aria-disabled="true"] {
  color:var(--ink-500); background:var(--bg-panel-2); border-style:dashed;
  cursor:default; pointer-events:none; font-weight:600;
}
.subnav-chip.is-coming:hover { border-color:var(--bd-panel); color:var(--ink-500); }
/* Subview-paneler: kun den aktive vises (klient-toggle ELLER server-render). */
.subview { display:none; }
.subview.active { display:block; }

/* ── CC.7 GATE 1 — detalje-komponenter porteret ORDRET fra design-prototypen
   (BATCH 3 ordre-detalje / BATCH 5 kundekort). Tokens fra 0e (--panel, --border,
   --ink-1..3, --grad-btn, --font-display). Prototypens --g-red/--g-green → vores
   --red-tx/--green-tx; --ink-3 uændret. White-label-sikkert: ingen hex, kun
   tokens. ──────────────────────────────────────────────────────────────────── */
.card-pad { padding:20px 22px; }

/* ── To regler der MANGLEDE (25-08-2026). Begge klasser blev brugt i
   skabeloner uden at vaere defineret nogen steder, saa de gjorde INTET —
   fanget af test_doede_css_klasser. De er IKKE omdoebt til noget
   eksisterende, for der fandtes ikke noget der gjorde det rigtige:
   .side-scroll er lodret (overflow-y, sidebjaelke) og ville have vaeret et
   navnesammenfald, ikke en loesning. ───────────────────────────────────── */

/* Vandret rulning for en tabel der er bredere end sin spalte. Uden reglen
   flyder tabellen ud over kortet i stedet for at rulle inde i det. */
.table-scroll { overflow-x:auto; max-width:100%; -webkit-overflow-scrolling:touch; }

/* Modstykke til Tailwinds .text-danger. Bruges hvor et resultat LYKKEDES
   ved siden af en soeskende der fejlede («Virkede sidst …» / «Fejlede …»),
   saa de to skal ligne hinanden paa naer farven — derfor en tekstfarve og
   ikke en pille. */
.text-ok { color:var(--green-tx); }

/* ── SMS-FLADENS FASTE RAMME (25-08-2026) ────────────────────────────────
   Andreas: «naar man trykker mellem Send SMS, SMS-log og Skabeloner hopper
   menuen til hoejre og venstre. Standardisér saa det bliver staaende.»

   🔴 FOERSTE FORKLARING VAR FORKERT, OG DEN STAAR HER FORDI DEN VAR
   OVERBEVISENDE. Her stod: «`sms_send.html` bar `lg:grid-cols-[1.55fr_1fr]`
   — en arbitrary value med NUL forekomster i den byggede app.css». Klassen
   var ganske rigtigt fjernet, men PAASTANDEN om app.css holdt ikke: Tailwind
   ESCAPER klassenavnet i outputtet (`.lg\:grid-cols-\[1\.55fr_1fr\]`), saa
   en `grep -F 'grid-cols-[1.55fr_1fr]'` svarer 0 paa en klasse der ER
   kompileret. Genmaalt 25-08 med escaped opslag OG positiv/negativ kontrol:
   klassen findes (1 forekomst, brugt af landing.html), og NUL af de 27
   arbitrary values i levende markup mangler. Huset har allerede et vaern
   for netop det: test_dark_kontrast.test_arbitrary_value_klasser_er_
   kompileret_ind_i_app_css.

   🔴 DEN AEGTE AARSAG LAA I `base.html`, IKKE I INDHOLDET: de tre faner
   erklaerede hver sin `{% block shell_variant %}`, og de tre varianter har
   hver sin bredde (app.src.css:160-162). Maalt paa den RENDEREDE `#main`:

       Send SMS     page-shell                    1440px
       SMS-log      page-shell page-shell--wide   1760px
       Skabeloner   page-shell page-shell--narrow  820px
       Bulk-send    page-shell                    1440px

   Fane-raekken (`sms/_tabs.html`) staar INDE i `#main`, saa den flyttede sig
   940px mellem to naboklik paa en 1920px-skaerm. Kuren er derfor ikke en ny
   klasse, men at FJERNE de to afvigende blokke: alle fire SMS-flader deler
   husets standard-shell. Vagt: tests/test_sms_flader_ramme.py.

   🔴 OG DERFOR ER `.sms-shell { max-width:1180px }` FJERNET IGEN. Den blev
   skrevet her 25-08 mod den forkerte forklaring, naaede aldrig en eneste
   skabelon (0 forekomster i tech/templates), og var en faelde for den
   naeste: en regel der HEDDER SMS-fladens ramme, men som intet styrer.
   ───────────────────────────────────────────────────────────────────────── */

/* Send-fanen og Bulk-send deler rammen i to; Log og Skabeloner fylder den ud.
   Under 1024px stakker begge, saa telefonen er uaendret. */
.sms-split { display:grid; grid-template-columns:1fr; gap:1.5rem;
  align-items:start; }
@media (min-width:1024px) {
  .sms-split { grid-template-columns:1.55fr 1fr; }
}

/* Trin-tallet i Bulk-sendens tre kort (1 · 2 · 3).
   🔴 AFLOESER `bg-torp-navy text-white`, SOM VAR ET MAALT BRUD: 1,13:1 i
   moerkt tema, fordi `torp-navy` flipper til #EAF2F8 mens `text-white` ikke
   flipper. Det stod som en RAPPORTERET-men-urettet undtagelse i
   tests/test_dark_kontrast.ALLOW_TW siden 21-08 med begrundelsen «rettelsen
   er markup, og skabelonerne deles med andre sessioner». Denne runde ejer
   sms_bulk.html, saa den er rettet frem for rapporteret, og undtagelsen er
   fjernet — ratchetten (`test_hver_undtagelse_undertrykker_noget`) ville
   ellers falde over en post der intet undertrykker.
   Parret er `--blue-700` paa `--accent-soft`: maalt 25-08 til 7,03:1 (lys)
   og 6,59:1 (moerk), AA-tekst kraever 4,50. Det er SAMME par som
   `.sms-num-pill:has(:checked)` paa Send-fanen, saa SMS-fladen bruger én
   markering og ikke to. */
.trin-tal { display:inline-flex; align-items:center; justify-content:center;
  width:1.75rem; height:1.75rem; flex:0 0 auto; border-radius:9999px;
  background:var(--accent-soft); color:var(--blue-700);
  font-size:.875rem; font-weight:600; line-height:1; }

/* Sektions-mikro-overskrift (KUNDE / STATUS / KONTAKT / …). */
.mini-h { font-size:10.5px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-2); margin-bottom:10px; }
/* To-kolonne detalje-layout: venstre stak (340px) + højre indholds-kort. */
.detail-grid { display:grid; grid-template-columns:340px 1fr; gap:20px;
  align-items:start; }
@media (max-width:1050px) { .detail-grid { grid-template-columns:1fr; } }
/* Status-rækker m. farvet prik + valgfri højre-note (.rr). */
.status-row { display:flex; align-items:center; gap:10px; padding:12px 0;
  border-top:1px solid var(--border); cursor:pointer; }
.status-row:first-of-type { border-top:none; }
.s-dot { width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.s-dot.red { background:var(--red-tx);   box-shadow:0 0 8px var(--red-tx); }
.s-dot.grn { background:var(--green-tx); box-shadow:0 0 8px var(--green-tx); }
.s-dot.gry { background:var(--ink-3); }
.status-row .rr { margin-left:auto; color:var(--ink-2); font-size:12.5px;
  font-weight:600; }
/* Totaler i højre-kortet: små rækker + én stor sum-række. */
.totrow { display:flex; justify-content:space-between; font-size:13px;
  color:var(--ink-2); padding:5px 0; }
.totrow.big { font-size:clamp(18px,1.7vw,22px); font-family:var(--font-display);
  font-weight:600; color:var(--ink); padding-top:12px; margin-top:6px;
  border-top:1px solid var(--border); white-space:nowrap; gap:16px;
  align-items:baseline; }
/* Aktivitets-feed (tidslinje-rækker). */
.feed-item { display:flex; gap:12px; padding:12px 0;
  border-top:1px solid var(--border); }
.feed-item:first-child { border-top:none; }
/* Kunde-avatar (initialer på accent-gradient). */
.cc-avatar { width:46px; height:46px; border-radius:12px;
  background:var(--grad-btn); display:grid; place-items:center;
  font-family:var(--font-display); font-weight:700; color:#fff; font-size:18px;
  flex:0 0 auto; }

/* ── §31.7 APP-RÆKKENS ATOMER — porteret fra dok 26 (skærm 03 + 05) ─────────
   Prototypens rækkekomponent: [ikon/avatar] hovedlinje/underlinje [beløb/pille].
   Tallene er prototypens egne; farverne er mappet som resten af CC.7
   (--g-amber/--g-green/--g-red → --amber-tx/--green-tx/--red-tx), så blokken
   er white-label-sikker og flipper med body.dark.

   Kun ATOMERNE bor her. Selve udlægningen (griddet der gør en tabelrække til
   en app-række) er mobil-only og bor i forta-mobil.css §31.7 — skrivebordets
   tabel er urørt (§31.2). ─────────────────────────────────────────────────── */
/* Kundelistens avatar. 40×40/radius 12 er prototypens .avatar; .cc-avatar
   ovenfor er 46×46 på gradient og hører til kundekortets HOVED — to forskellige
   mål, derfor to klasser i stedet for én der passer nogenlunde til begge. */
.app-avatar { width:40px; height:40px; flex:0 0 40px; border-radius:12px;
  display:grid; place-items:center; background:var(--accent-soft);
  color:var(--accent-soft-tx); font-family:var(--font-display);
  font-weight:700; font-size:13px; }
/* Ordre-/faktura-/sagsrækkens ikon-flise. */
.app-row-ic { width:36px; height:36px; flex:0 0 36px; border-radius:11px;
  display:grid; place-items:center; background:var(--accent-soft);
  color:var(--accent-soft-tx); }
.app-row-ic.amber { background:var(--amber-bg); color:var(--amber-tx); }
.app-row-ic.green { background:var(--green-bg); color:var(--green-tx); }
.app-row-ic.red   { background:var(--red-bg);   color:var(--red-tx); }
/* Hoved- og underlinje.

   🔴 TYPOGRAFIEN ER FLYTTET TIL MOBIL-LAGET 25-08-2026 — KOMPONENTENS ANDEN
   DEFEKT. Her stod `font-size:13px; font-weight:600; color:var(--ink)` paa
   `.app-rl-main` og `font-size:11px; color:var(--ink-2)` paa `.app-rl-sub`.
   Begge er APP-RAEKKENS typografi, og de bor i CORE-laget, saa de ramte OGSAA
   skrivebordet. `_components/_app_raekke.html` udsender titel- og sub-cellen
   som ALMINDELIGE tabelceller over 899px (de ER skrivebordets Nr.- og
   Dato-kolonner), saa hver flade der kalder makroen fik app-typografi paa
   skrivebordet uden at nogen bad om det.

   MAALT paa `kunder/_tab_ordrer.html` (husets eneste makro-kalder), 1280x900:
       foer porteringen (fa45616f^)   vaegt 500 · 12px · rgb(30,74,122)
       efter porteringen             vaegt 600 · 13px
       raekkehoejden i BEGGE          159,5 px — IDENTISK

   🔴 HOEJDEN FLYTTEDE SIG IKKE ÉN PIXEL. Et §31.2-vaern der kun maaler px var
   groent paa hele forskellen, og maalingen blev foerst mulig da vaernet ogsaa
   pinnede den COMPUTEDE typografi (`rf-fakturaer`s udvidelse: «ingen maa
   SKIFTE», ikke «ingen maa vaere fed»).

   Samme defektklasse som `.cell-main` (koordineringen `svar-cellmain-laekage.md`)
   — en app-beslutning der bor uden for app-laget. Anden forekomst, og derfor
   loest paa samme maade: reglen bor nu dér hvor den per konstruktion ikke kan
   naa skrivebordet. Se `forta-mobil.css` ved `.app-rl-main`.

   ⚠️ `text-decoration:none` og `line-height` BLEV her: de er ikke
   app-typografi, og et raekke-link skal heller ikke vaere understreget paa
   skrivebordet — det var det ikke foer makroen fandtes. Kun de tre
   egenskaber der MAALT flyttede sig, er flyttet. */
.app-rl-main { line-height:1.3; text-decoration:none; }
.app-rl-sub { }
/* Beløbet i højre kolonne: mono, så cifrene flugter lodret ned gennem listen. */
.app-beloeb { font-family:var(--font-mono); font-size:11.5px;
  letter-spacing:-.02em; font-weight:600; color:var(--ink); }
/* Kort-overskrift MED antal ("ORDRER · 3"). */
.app-kort-t { font-size:11px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2); }
/* Breddeafhængigt indhold i ÉN celle. Bruges hvor app-rækken og skrivebordets
   tabel skal vise samme tal i forskelligt format — beløbet er "kr 30.550,00" i
   tabellen og bart "30.550" i rækken. Alternativet var at lade app-formatet
   gælde begge steder, men så mistede skrivebordet valutaen. Kun de to spans
   dubleres, aldrig rækkens struktur. Modstykket står i forta-mobil.css. */
/* 🔴 SKJULES I ET MIN-WIDTH-LAG, IKKE GLOBALT. Et globalt `.kun-app{display:none}`
   skal laves om igen under 899px, og dét "om igen" må gætte på en display-værdi
   (inline? block? grid?). Første udgave gættede `inline`, og scan-knappens
   `display:grid` tabte til den — knappen blev 46×46 med ucentreret ikon.
   Med reglen i et min-width-lag findes den slet ikke på mobil, og hver
   komponent beholder sin egen display. */
@media (min-width: 900px) { .kun-app { display: none !important; } }

/* 🔴 .filter-skuffe SKAL VÆRE `display:contents` SOM UDGANGSPUNKT (D1).
   Værktøjslinjens vælgere og datofelter fik en <span> omkring sig, så
   mobil-laget kan folde dem væk bag «Filtrér». Uden denne regel er den span
   ÉT flex-element i `.filter-row`, og skrivebordets seks vælgere ville
   klumpe sammen i én kolonne i stedet for at ligge på rækken — en §31.2-brud
   forårsaget af MARKUP, ikke af en CSS-regel der lækkede ud af sit lag.
   Målt med scripts/proto_desktop_uroert.py: uden reglen flyttede 1440px-
   fladen sig; med den er de 577 elementer uændrede.
   Reglen bor her og ikke i app.src.css, fordi app.css er en bygget bundle
   der ikke kan genskabes reproducerbart hos os. Mobil-laget (der loades
   sidst) overskriver den med none/flex. */
.filter-skuffe { display: contents; }
/* 🔴 !important ER IKKE DOVENSKAB HER — DET ER HELE KONTRAKTEN.
   Uden det tabte reglen til `.app-scan-mini{display:grid}` tretten linjer
   længere nede: begge selektorer er ÉN klasse (0,1,0), en media-query giver
   ingen specificitet, og så vinder den SIDSTE. Scan-knappen stod synlig på
   skrivebordet ved 1440px (målt i merge-runde 4: display=grid, 46×46 på
   [884,151], søgefeltet skubbet fra 670px til 616px).

   Rækkefølge er en skrøbelig løsning: den brydes af den næste der indsætter
   en regel imellem, og fejlen er tavs — et element DUKKER OP hvor det ikke må
   være. En synlighedsklasse har en absolut kontrakt ("findes ikke over
   899px"), og den må hverken afhænge af hvem der står sidst eller af hvor
   mange klasser næste mand hænger på sin selektor.

   🔴 ASYMMETRIEN ER GRUNDEN TIL AT NETOP SKJULE-REGLER SKAL HAVE ET VÆRN:
   forsvinder noget der burde være der, ser man det med det samme — der står
   et tomt hul. Dukker noget op på skrivebordet, opdages det først den dag
   nogen kigger på 1440px. Derfor stod min egen kolonnetælling (6/6 og 4/4)
   grøn mens værktøjslinjen var brudt: beviset var sandt om det det målte og
   for smalt om det det påstod.

   Værnet er `tests/test_kun_app_kaskade.py` — den RESOLVERER kaskaden og
   fejler hvis !important fjernes. Kommentaren ovenfor beskrev i forvejen
   præcis denne kollision tre linjer fra fejlen og forhindrede ingenting:
   en kommentar er ikke et værn. */
/* 🔴 DENNE REGEL LANDER I ADMIN — OGSÅ SELVOM DEN IKKE RAMMER NOGET I DAG.
   `forta-core.css` lastes af BEGGE apps (målt i den kørende admin-app:
   core lastet, forta-mobil og forta-dark ikke). Reglen er inert dér, fordi
   nul admin-skabeloner bruger klassen — men det er en garanti med en
   udløbsdato ingen kan se: den dag en admin-skabelon tager `.kun-app` i brug,
   arver den skjulningen over 900px uden at nogen har besluttet det, og uden
   at en test bliver rød.
   Navnet er generisk nok til at det kan ske ved et tilfælde. Skal reglen
   ALDRIG gælde admin, hører den hjemme i forta-theme-crm.css i stedet —
   det er en bevidst flytning, ikke en fejlretning. */

/* Scan-knappen ved søgefeltet (kundelisten). */
.app-scan-mini { width:46px; height:46px; flex:0 0 46px; border-radius:13px;
  display:grid; place-items:center; background:var(--grad-btn); color:#fff;
  border:none; cursor:pointer; box-shadow:var(--shadow); }
  /* 🔴 --shadow, IKKE prototypens --btn-shadow: den token findes ikke i vores
     tokensæt (målt 15-08: 0 definitioner). En var() uden definition falder
     tilbage til ingenting — knappen ville stå helt uden skygge, og CSS'en
     ville se rigtig ud imens. --shadow er den nærmeste vi HAR. */

/* ── §8a/§17.4 TOPZONE — dokument-detaljens sidehoved (ETAPE 1, 25/7) ────────
   Porteret ORDRET fra den godkendte mockup docs/design-prototype/
   ordre-redesign-v3a-final.html (Forslag A-rev2), tokens mappet:
   prototypens --ink-500 → --ink-3, --bd-panel/--bg-panel uændret.

   Hvorfor eget navnerum (.tz-*): topzonen skal kunne bæres UÆNDRET af
   ordre- (Etape 1), faktura- (Etape 2) og tilbud-detaljen (Etape 3). Derfor
   INGEN dokument-specifikke navne her — kun struktur. Markup'en bygges af
   _components/_topzone.html; alt dokument-specifikt bor i kaldende template.

   White-label-sikkert: kun tokens, ingen hex → flipper med body.dark. ──────── */
/* Titel-linjen: H1 + statuspille (§5) + dæmpet subhead, alt på én linje. */
.tz-title { display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  margin:0 0 12px; min-width:0; }
.tz-title h1 { margin:0; white-space:nowrap; }

/* 🔴 FREMMEDDATA I EN OVERSKRIFT — MAIL-EMNET. `white-space:nowrap` ovenfor er
   rigtig for de fire flader hvor titlen er HUSETS egen og kort («Ordre #17156»,
   «Faktura #4402», «Tilbud #4711», «SAG-40122»). Den femte er
   mailind/detalje.html, hvor titlen er et EMNE skrevet af en afsender vi ikke
   styrer, og laengden er derfor vilkaarlig.

   Maalt 17-09-2026 ved 393x852, begge temaer, paa /kunder/100/mail/<id> med et
   emne paa 78 tegn:
       h1 x=18 -> hoejre=741,4   (723,4 px bred i et 393 px vindue)
       body.scrollWidth 741 mod documentElement.clientWidth 393
       body overflow-x: clip
   Emnet var altsaa baade KLIPPET og umuligt at rulle frem til. Brugeren kunne
   ikke se hvad mailen hed.

   🔴 VALGET ER OMBRYDNING, IKKE ELLIPSE. En ellipse kraever at teksten er naabar
   et andet sted, og det er den ikke: listen paa /mail/ubundet klipper emnet til
   ÉN linje med vilje (`-webkit-line-clamp:1`, forta-mobil.css — med sin egen
   skrevne begrundelse), og paa en telefon findes der ingen hover til at hente et
   `title`-attribut frem med. Afkortede vi ogsaa detaljen, ville emnet vaere
   naabart INGEN steder. At rulle vandret er heller ikke en mulighed: `body`
   baerer `overflow-x: clip`, saa overloebet er BORTE og ikke uden for skaermen.

   🔴 OG DEN DELTE REGEL ROERES IKKE. Selektoren er `.tz-title.tz-title-fritekst`
   (0,2,1) og ikke `.tz-title-fritekst` (0,1,1): sidstnaevnte ville vaere LIG med
   `.tz-title h1` i specificitet og dermed afhaenge af raekkefoelgen i filen — en
   senere regel med samme vaegt draeber en tidligere tavst, og CSS-teksten ser
   uaendret ud. Med to klasser vinder den uanset hvor den staar.

   `overflow-wrap:anywhere` og ikke `break-word`: et emne kan vaere ét ubrudt
   token (en URL, et sagsnummer, en base64-streng), og `break-word` bryder ikke
   et ord der staar alene paa sin linje. `min-width:0` fordi h1'en er et
   flex-barn og ellers ikke maa skrumpe under sin indholdsbredde.

   Vagt: tests/test_mail_emne_klip.py (rendret maaling i begge temaer). */
.tz-title.tz-title-fritekst h1 { white-space:normal; overflow-wrap:anywhere;
  min-width:0; }
.tz-subhead { display:inline-flex; align-items:center; gap:6px;
  font-size:12.5px; font-weight:600; color:var(--ink-2); white-space:nowrap; }

/* Info-panelet: ét kort i fuld bredde, kolonner adskilt af hårfine lodrette
   linjer (ikke af luft) — det er dét der giver e-conomic-tætheden.
   position:relative er ANKERET for status-stakkens fold-ud-panel nedenfor. */
.tz { display:grid; background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-radius:var(--radius-panel); padding:14px 0; margin-bottom:14px;
  position:relative; }
.tz-col { padding:2px 16px; border-left:1px solid var(--ink-100);
  font-size:12.6px; min-width:0; }
.tz-col:first-child { border-left:0; }
/* Label/værdi-par (OVERSKRIFT / BETALINGSFRIST / VORES REF. …). */
.tz-kv { margin:0 0 7px; line-height:1.45; }
.tz-kv:last-child { margin-bottom:0; }
/* ÉN felt-label-stil i hele info-panelet (§8a-tillæg 25/7).
   Panelets to midterkolonner blev bygget hver for sig og arvede derfor hver
   sin label-stil: .tz-kv > b her, og .detail-info-label (10px, font-medium,
   tracking-label) fra detaljesidens gamle venstrekolonne. To label-stilarter
   side om side i SAMME panel var utilsigtet — nu deler alle syv felt-labels
   .tz-flabel.
   Typografien er den kolonne-overskrifterne (.mini-h) havde, fordi de netop
   UDGÅR på kolonne 2+3: labelen bærer nu hele den visuelle rolle alene.
   Bevidst IKKE .mini-h genbrugt direkte — den har margin-bottom:10px til at
   sætte afstand ned til et helt kort, hvilket ville gøre panelet HØJERE, og
   det er præcis det modsatte af dette tillægs formål. */
.tz-flabel { display:block; font-size:10.5px; font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; color:var(--ink-2); }

/* Reference-folden (målt 15-08-2026). `<details>` bærer de tre referencefelter
   så telefonen kan folde dem; SKRIVEBORDET SKAL SE PRÆCIS DET SAMME SOM FØR.
   Derfor to ting her og kun to: elementet er gennemsigtigt i layoutet (ingen
   margin/padding/kant), og kontakt-rækken er skjult. Skabelonen skriver `open`
   altid, så indholdet står åbent — hvilket er nøjagtig den tilstand de tre
   .tz-kv'er havde som direkte børn af kolonnen.

   Summary vises KUN når static/js/tz_refs.js har sat data-foldet, og det gør
   den kun under breakpointet (se forta-mobil.css). Uden JavaScript findes
   folden derfor ikke — hverken her eller på telefonen. */
.tz-refs { display: block; margin: 0; padding: 0; border: 0; }
.tz-refs > summary { display: none; }

/* ── SAGSFLADEN (/sager/<nr>) ────────────────────────────────────────────────
   Prototypens `#scr-sagdetalje`. Ruten er ny (15-08-2026), så der findes ingen
   leveret skrivebordsvisning at værne om — derfor bor GRUNDLAYOUTET her og
   ikke i mobil-laget. §31.2's krav om ét media-lag beskytter FLADER DER ER
   LEVERET; en flade der ikke fandtes i går, har ingen tilstand at bevare.
   Tommelmål og fuldbredde-knapper ligger stadig i mobil-laget, hvor de hører.

   🔴 KLASSERNE HER BLEV SKREVET I SKABELONEN FØRST OG GLEMT HER. Fladen stod
   en time i drift med seksten klassenavne uden én regel: kundekortet var
   `display:inline`, så avatar, tekst og chevron lå oven i hinanden. Syv grønne
   tests så det ikke, fordi de asserterede på statuskoder og tekst.
   `tests/test_klasser_har_regler.py` er vagtposten der ville have fanget det.

   Målene er prototypens, ikke skønnede: avatar 36×36/r12, ikonflade 36×36/r11,
   checkboks 22×22/r7, foto-miniature 74×74/r13. */

/* Kundekortet — HELE rækken er målet, som i prototypen. */
/* S · kundekortets polstring er prototypens EGEN, ikke `.mcard`s generelle:
   `#scr-sagdetalje`s foerste kort har `style="padding:11px 15px"`, fordi det
   baerer én raekke og ikke en blok. 15/16 gjorde det til et kort paa hoejde
   med tidslinjen, og saa laeses det som en SEKTION frem for som en genvej. */
/* 🔴 `.card.sag-kunde` OG IKKE `.sag-kunde`. app.css laeses EFTER
   forta-core.css (base.html:23 mod :25), og dens `.card{@apply p-4}` har
   samme specificitet — saa den vandt, og polstringen blev staaende paa
   15/16 selvom reglen her sagde 11/15. Maalt: vagtposten var GROEN, fordi
   den spurgte om reglen STAAR der, ikke om den VINDER. To klasser haever
   specificiteten til (0,2,0) og goer kilde-ordenen ligegyldig. */
.card.sag-kunde { padding:11px 15px; }
.sag-kunde { display:flex; align-items:center; gap:12px; text-decoration:none;
  color:inherit; margin-bottom:12px; }
.sag-kunde:hover { border-color:var(--accent); }
.sag-kunde-av { width:36px; height:36px; flex:0 0 36px; border-radius:12px;
  font-size:13px; background:var(--accent-soft); color:var(--accent-soft-tx);
  background-image:none; }
.sag-kunde-tx { display:flex; flex-direction:column; min-width:0; }
.sag-kunde-chev { margin-left:auto; color:var(--ink-2); display:flex;
  flex:0 0 auto; }

/* Tidslinjen — service-audit. Ikonfladen er prototypens 36×36, ikke en prik. */
.sag-tid { list-style:none; margin:0; padding:0; }
/* S · tidslinjens raekke er TAET (3px), fordi ikonfladen paa 36px allerede
   saetter raekkehoejden. 9px oveni gjorde hver haendelse 46px hoej, og en
   historik paa ti haendelser til en side man skal rulle igennem. */
.sag-tid-r { display:flex; align-items:flex-start; gap:12px; padding:3px 0;
  border-top:1px solid var(--ink-100); }
.sag-tid-r:first-child { border-top:0; padding-top:0; }
.sag-tid-ic { width:36px; height:36px; flex:0 0 36px; border-radius:11px;
  display:grid; place-items:center; background:var(--accent-soft);
  color:var(--accent-soft-tx); }
.sag-tid-tx { display:flex; flex-direction:column; min-width:0; }

/* Checklisten — og S7: en udført linje er BÅDE grøn boks og gennemstregning. */
.sag-chk { list-style:none; margin:0 0 10px; padding:0; }
/* S · checkpunktet baerer selv typografien (13px/600), ikke kun sin tekst.
   Prototypens `.chk` er 13px/600 paa RAEKKEN; hos os laa vaegten kun paa
   `.sag-chk-tx`, saa alt andet i raekken — inklusive et fremtidigt tal eller
   en dato — ville falde tilbage til 12px/400. */
.sag-chk-r { display:flex; align-items:center; gap:11px; padding:10px 0;
  font-size:13px; font-weight:600;
  border-top:1px solid var(--ink-100); }
.sag-chk-r:first-child { border-top:0; }
.sag-chk-box { width:22px; height:22px; flex:0 0 22px; border-radius:7px;
  border:1.5px solid var(--bd-control,#A9C3CB); display:grid;
  place-items:center; color:var(--on-status-fill,#fff); }
.sag-chk-r.is-done .sag-chk-box { background:var(--green-tx);
  border-color:var(--green-tx); }
.sag-chk-tx { font-size:13px; font-weight:600; color:var(--ink); min-width:0;
  /* 1,3 og ikke 1,5: et checkpunkt er en linje man afkrydser, ikke en
     saetning man laeser. Med broedtekst-luft blev to punkter til fire
     linjers hoejde. */
  line-height:1.3; }
.sag-chk-r.is-done .sag-chk-tx { color:var(--ink-2);
  text-decoration:line-through; }

/* Foto — miniature i prototypens mål. */
.sag-foto { display:flex; gap:10px; flex-wrap:wrap; }
.sag-foto-t { width:74px; height:74px; flex:0 0 74px; border-radius:13px;
  display:grid; place-items:center; background:var(--bg-panel-2,var(--ink-100));
  border:1px solid var(--bd-panel);
  /* 🔴 --ink-2, ikke --ink-3. Maalt af test_dark_kontrast paa den fulde
     suite: --ink-3 gav 2,82:1 i lyst og 3,41:1 i moerkt mod panelfladen.
     Glyffen er et ikke-tekst UI-element, hvor AA kraever 3,0 — den lyse
     faldt UNDER selv den graense. En 74px flade med en glyf man ikke kan
     se, er en knap der ligner et hul. */
  color:var(--ink-2); }

/* Handlingerne. Fuldbredde hører i mobil-laget; her kun stakken. */
.sag-akt { display:flex; flex-direction:column; gap:10px; margin-bottom:14px; }
.sag-akt-b { justify-content:center; }

/* Tilbage-knappen i titel-linjen — prototypens `.back-btn` (A1).
   🔴 40×40 I PROTOTYPEN, 44 I PRAKSIS. Mobil-lagets §31.6-regel giver enhver
   knap `min-height:44px` under breakpointet, så den måler 40×44 på telefon.
   Det er ikke en fejl: §31.6 kræver ≥44px for ETHVERT interaktivt element,
   mens prototypens egen designprincip kun nævner bundnav, betalingsknapper
   og ring/SMS. Vores regel er strengere med vilje, og en målt regel vinder
   over en tegning. Målt 15-08 — nævnt her så næste måling ikke melder det
   som en afvigelse. */
.tz-back { width:40px; height:40px; flex:0 0 40px; display:grid;
  place-items:center; padding:0; border-radius:12px; }

/* A2 · chevronen der peger paa kundekortet. Den ER linket (se noten i
   view.html om hvorfor raekken ikke kan vaere det), saa den skal se ud som en
   vej og ikke som pynt: hoejrestillet, daempet, og med en flade der lyser op
   naar man er paa vej. */
.tz-kunde-chev { margin-left:auto; display:grid; place-items:center;
  width:32px; height:32px; flex:0 0 32px; border-radius:10px;
  color:var(--ink-3); text-decoration:none; }
/* 🔴 --accent-link, ikke --accent. Maalt: --accent gav 3,17:1 i lyst og
   3,51:1 i moerkt mod hover-fladen. --accent-link er husets AA-sikrede
   accent — den findes praecis fordi den rene accent ikke baerer tekst. */
.tz-kunde-chev:hover { background:var(--ink-100); color:var(--accent-link); }

/* Status-stakken (§8b) som topzone-kolonne. Rækken ER <summary> — fold-ud er
   ren CSS (<details>), ingen JS. Det åbne panel ankres under HELE topzonen
   (ikke i den smalle kolonne), så betjeningen får fuld bredde. */
.tz-strow { border-bottom:1px solid var(--ink-100); }
.tz-strow:last-of-type { border-bottom:0; }
.tz-strow-sum { display:flex; align-items:center; gap:8px; padding:5px 0;
  font-size:12.6px; cursor:pointer; list-style:none; user-select:none; }
.tz-strow-sum::-webkit-details-marker { display:none; }
.tz-strow-sum::marker { content:''; font-size:0; }
/* Status-prikken. Farven kommer fra `--sdot-farve` i markup'en, og fladen
   laeser den derfra — saa den samme ene farve kan blive
   til en PRIK her og til en 36x36 flade i mobil-laget (C6), uden at
   skabelonen skal vide hvilken. Glyffen indeni er skjult paa skrivebordet:
   §8a's status-stak er leveret med en prik, og den skal blive en prik. */
.tz-sdot { width:8px; height:8px; border-radius:50%; flex:0 0 auto;
  background:var(--sdot-farve); }
.tz-sdot > svg { display:none; }
.tz-strow-lbl { font-weight:600; color:var(--ink); }
/* ORDREFIX (24-09-2026): `white-space:normal` + `min-width:0`. Var `nowrap`,
   og i status-kolonnen (~150 px ved 1400) flød «Afventer kunde» ud over
   kolonnens kant og ind i totalerne — maalt paa /ordrer/30000 foer rettelsen.
   Et kort vaerdi-ord ombryder ikke; et langt ombryder i stedet for at flyde. */
.tz-strow-val { margin-left:auto; color:var(--ink-2); font-size:11.5px;
  white-space:normal; min-width:0; text-align:right; }
/* UNDERSKRIFTSTATUS (01-10-2026): underskrift-raekkens VAERDI maa bryde til sin
   egen linje under etiketten. Kolonnen er 180 px (148 px indhold) ved alle
   skrivebordsbredder; prik + «Underskrift» efterlader ~50 px, og «Underskrevet
   01-10-2026 09:26» er ~160. Maalt foer: fire linjer, datoen brudt i tre, et
   loest «·» og «Underskrevet» 19 px ud over kolonnens kant. Tilstand og tid er
   hver sin `nowrap`-enhed, saa de kun kan bryde MELLEM hinanden.
   Kun `.tz-sig-sum` — Service/Bogfoert er uroerte. */
.tz-sig-sum { flex-wrap:wrap; row-gap:2px; }
.tz-sig-val { display:inline-flex; flex-wrap:wrap; justify-content:flex-end;
  column-gap:6px; max-width:100%; }
.tz-sig-tilstand, .tz-sig-tid { white-space:nowrap; }
/* «Se underskriften»: husets AA-sikrede link-farve (--accent-link, ikke den rene
   accent — se .tz-kunde-chev ovenfor), understregning og et info-ikon. Saettes
   KUN naar der er en underskrift at se (view.html: `data-sig-se`). */
.tz-sig-se { display:inline-flex; align-items:center; gap:4px;
  color:var(--accent-link); text-decoration:underline;
  text-decoration-thickness:1px; text-underline-offset:2px; }
.tz-sig-sum:hover .tz-sig-se { text-decoration-thickness:2px; }
.tz-sig-ikon { flex:0 0 auto; }
.tz-sig-sum:focus-visible { outline:2px solid var(--accent); outline-offset:2px;
  border-radius:4px; }
.tz-strow-panel { position:absolute; left:0; right:0; top:100%; z-index:25;
  margin-top:8px; padding:16px 18px; background:var(--bg-panel);
  border:1px solid var(--bd-panel); border-radius:var(--radius-panel);
  box-shadow:var(--elev-float); }
/* ── UNDERSKRIFTSVINDUET (01-10-2026) ──────────────────────────────────────
   Andreas 01-10 (via forta-d6): «Underskrift skal redesignes i ordre - den ser
   mærkelig ud i toppen når man aktiverer som om der ikke er plads til den, og
   luk funktion er væk». Målt før ved 1280: det ventende kort stod 147 px bredt
   i status-kolonnen; uden underskrift 956 px under topzonen, ikke centreret.

   Panelet er nu et VINDUE i husets modal-mønster (samme overlay som
   ordrer/_create_draft_modal.html): fast over hele siden, mørk baggrund,
   kortet centreret i op til 640 px. Luk/Esc/klik på baggrunden i
   static/js/ordre-underskrift-vindue.js. Åbnes med rækkens <summary> eller
   `?underskrift=1` (Butik-kravets knap).

   🔴 ID-SELEKTOREN ER NØDVENDIG: mobil-lagets
   `.tz-strow-panel:has(#signature-card)` har specificitet (1,1,0) og lægger
   panelet i flowet. (1,3,0) her vinder i begge lag uden !important.

   *(Erstatter blokkene «ORDREFIX 1 (24-09-2026)» og «UNDERSKRIFTKORT
   (28-09-2026)», som foldede den VENTENDE tilstand ud fladt I den 180 px
   kolonne via `data-i-flow`. Den markør sættes ikke længere — kortet har
   fået vinduets plads, og det var den plads Andreas savnede.)*
   Vagt: tests/test_underskrift_vindue.py (rendret, 1280 + 393). */
.tz-strow[data-sig-vindue][open] > #underskrift-vindue {
  position:fixed; inset:0; z-index:70; margin:0;
  display:flex; align-items:flex-start; justify-content:center;
  padding:max(16px, 8vh) 16px 16px; overflow-y:auto;
  background:rgba(0,0,0,.5); border:0; border-radius:0; box-shadow:none; }
.tz-strow[data-sig-vindue][open] > #underskrift-vindue > #signature-card {
  width:100%; max-width:640px; margin:0; box-shadow:var(--elev-float); }
html:has(.tz-strow[data-sig-vindue][open]) { overflow:hidden; }
/* Ikon + destination på ÉN linje (arvet fra 28-09-kolonnen, hvor reglen
   stod under `data-i-flow`). Uden den står ikonet på sin egen linje over
   «Sendt til …». Vagt: tests/test_underskriftkort_28_09.py */
#signature-substatus-text { display:flex; align-items:center; gap:6px; }
#signature-substatus-text > svg { flex:0 0 auto; }
/* «Butik / Kontor» (01-10-2026): knapperne i valgvinduet og i Ordretype-
   rækken. 44 px er §31.6's mål og briefens krav — på begge flader, også
   skrivebordet, fordi valget træffes ved disken, ofte på en tablet.
   Vagt: tests/test_ordre_underskriftskrav.py */
.ordretype-knap { min-height:44px; min-width:96px; justify-content:center; }
.ordretype-valg-knapper > .ordretype-knap { flex:1 1 0; }

/* Total-blokken (yderste kolonne, højrestillet, §3-momsreglen). */
.tz-tot { display:flex; flex-direction:column; gap:3px; align-items:flex-end;
  font-variant-numeric:tabular-nums; }
.tz-tot-row { display:flex; gap:18px; font-size:12.6px; white-space:nowrap; }
.tz-tot-row > span { color:var(--ink-2); }
.tz-tot-sum { font-family:var(--font-display); font-weight:700; font-size:17px;
  margin-top:2px; white-space:nowrap; color:var(--ink); }
.tz-tot-sub { font-size:11px; color:var(--ink-2); }
/* A5 · totalens etiket. Prototypen saetter den som en dæmpet versal-linje
   OVER tallet — den skal kunne skimmes uden at konkurrere med beloebet. */
.tz-tot-lab { font-size:11px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--ink-2); margin-top:6px; }

/* FarPay-raekken i total-blokken (08-09-2026).
   🔴 DEN MAA IKKE VAERE EN `tz-tot-row`. De oevrige raekker er
   «kort etiket + ét tal»; denne er «etiket + dato + pille» og altsaa
   ~2,5x bredere. `.tz-tot-row` har `white-space:nowrap`, og blokken
   staar med `align-items:flex-end` i en kolonne med `min-width:0` —
   en for bred nowrap-raekke kan derfor ikke krympe og floeder UD TIL
   VENSTRE, hen over STATUS-kolonnen. Maalt paa faktura #17334.
   Derfor stables den: etiket paa egen linje, vaerdi+pille under —
   samme form som `tz-tot-lab` + `tz-tot-sum` lige nedenfor. Hver
   linje er kort nok til at holde sig i kolonnen, og pillen maa
   ombryde frem for at skubbe. */
.tz-tot-fp { display:flex; flex-direction:column; align-items:flex-end;
  gap:2px; margin-top:4px; max-width:100%; min-width:0; }
.tz-tot-fp-lab { font-size:11px; color:var(--ink-2); white-space:nowrap; }
.tz-tot-fp-val { display:flex; align-items:center; justify-content:flex-end;
  gap:6px; flex-wrap:wrap; font-size:12.6px; }

/* Handlingsrækken (§8a): ÉN linje, ingen ombrydning, mellem topzone-panelet
   og indholds-kortet. */
.tz-acts { display:flex; align-items:center; gap:8px; flex-wrap:nowrap;
  min-width:0; margin-bottom:14px; }

/* ── BETALINGSLINKETS UDFOLDNING (25-08-2026) ────────────────────────────
   Andreas: «Der gaar ogsaa noget designmaessigt galt naar man trykker paa
   Betalingslink under en ordre.»

   🔴 AARSAGEN: udfoldningen (telefonfelt + Send + Fortryd) ligger som
   soeskende til knappen INDE i `.tz-acts` — en `flex-wrap:nowrap`-raekke.

   ⚠️ 27-08-2026: KNAPPEN ER FLYTTET TIL ⋯-MENUEN, UDFOLDNINGEN ER IKKE.
   Reglerne herunder er derfor UAENDREDE og stadig rigtige — de har altid
   peget paa `[data-betalingslink="felt"]`, aldrig paa knappen. Det der er
   skiftet, er hvad man trykker paa foer panelet kommer: ⋯ i hoejre ende af
   raekken frem for en knap i raekken. Panelet aabner stadig ved `left:0`,
   altsaa i VENSTRE ende — en bevidst uaendret detalje, ikke en overset:
   ankeret er raekken og ikke udloeseren, og et panel der fulgte ⋯ ville
   skulle forankres til et element der lukker sig selv i samme klik.
   Naar `hidden` fjernes, bliver den et flex-ELEMENT i raekken og skubber
   «Konvertér til faktura», «Vis til kunde» og resten sammen. Skaermbilledet
   viser dem overlappe hinanden.

   Kuren er at tage den UD AF FLOWET frem for at kaempe om pladsen i raekken:
   et panel forankret under knappen, som husets popovers. Raekken maerker
   intet, og feltet faar den bredde det har brug for.

   ⚠️ `.tz-acts` faar `position:relative` — den er ankeret. Uden det ville
   panelet forankre sig til naermeste positionerede forfader, og det er
   uforudsigeligt fra denne fil. */
.tz-acts { position:relative; }
.tz-acts [data-betalingslink="felt"]:not(.hidden) {
  position:absolute; top:calc(100% - 6px); left:0; z-index:40;
  background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-radius:12px; padding:10px 12px;
  box-shadow:0 12px 32px -16px rgba(0,0,0,.45);
}
/* Under breakpointet er der ikke plads til et panel ved siden af noget som
   helst — dér fylder det bredden ud og skubber som en almindelig blok. */
@media (max-width:899px) {
  .tz-acts [data-betalingslink="felt"]:not(.hidden) {
    position:static; box-shadow:none; border:0; padding:0;
    background:transparent; }
}
.tz-acts-more { display:inline-block; position:relative; flex:0 0 auto; }
.tz-acts-more > summary { list-style:none; cursor:pointer; user-select:none; }
.tz-acts-more > summary::-webkit-details-marker { display:none; }
/* Etiketten ved ⋯ hoerer KUN til telefonens grid (forta-mobil.css §8a-gridet).
   Paa skrivebordet er raekken ÉN linje og har ikke plads til ordet. */
.tz-mere-etiket { display:none; }
/* ⋯-menuens chrome UDEN FOR topzone-rækken (§8d). .tz-acts-more bærer
   flex:0 0 auto og hører derfor kun hjemme i .tz-acts; alt andet er ens.
   Findes som KLASSE og ikke som inline-styles fordi et pseudo-element ikke
   kan skrives inline: uden ::-webkit-details-marker viser WebKit stadig
   <details>-trekanten ved siden af ⋯. Præcis det manglede i de to
   hånd-rullede menuer (tilbuds-detaljen og tilbuds-listens rækker), og
   inline-mønstret kunne aldrig have rettet det. */
.fx-more { display:inline-block; position:relative; }
.fx-more > summary { list-style:none; cursor:pointer; user-select:none; }
.fx-more > summary::-webkit-details-marker { display:none; }

/* ═══ §33 MENUKOMPONENTEN — ÉN for hele CRM (menuloeft, 24-09-2026) ════════
   Andreas 24-09: «Tjek hele CRM igennem for grimme bokse som disse. De skal
   designoptimeres.» Skuddet var kundekortets «⋯ Mere»: ikonet paa sin EGEN
   linje over teksten, «Book tid» og «Bekraeft paa tablet» flydt sammen til
   én linje, ingen luft og ingen hover.

   🔴 AARSAGEN VAR IKKE KUNDEKORTET — DET VAR AT HUSET INGEN KOMPONENT HAVDE.
   `.qa-phone-menu`/`.qa-phone-item` havde NUL regler paa skrivebordet (kun i
   forta-mobil.css, under 899px). Hver menu skrev sit chrome som inline-style,
   og hvert punkt sit eget `display:flex; align-items:center; gap…`. Ordrens ⋯
   saa rigtig ud fordi dens punkter bar den inline-stil; kundekortets «Mere»
   blev bygget 24-09 uden den — og saa var et <a> med et SVG (`display:block`
   fra Tailwinds preflight) og en tekstnode praecis det Andreas saa. Samme
   aarsag i Udskriv ▾, Print labels ▾ og tablet-menuen i topbaren (maalt:
   3+3+7 punkter med ikonet over teksten).

   Derfor bor udseendet HER, én gang, og markup'en baerer kun klasser:
       <details class="fx-menu-greb">            (valgfri: kun luk/tastatur)
         <summary …>⋯</summary>
         <div class="fx-menu" role="menu">
           <a class="fx-menu-punkt" role="menuitem">{{ icon }} Tekst</a>
           <hr class="fx-menu-skel">                       gruppe-skel
           <button class="fx-menu-punkt" data-fare …>{{ icon }} Slet</button>
   `data-fare` = destruktivt: roedt og NEDERST, efter et skel (§8: Slet kun
   i ⋯). Positionering og tastatur (Esc, pile, Home/End, fokus tilbage til
   knappen, panelet holdes inden for skaermen) goer `static/js/skal-menu.js`.

   Tokens, ikke hex: --bg-panel, --bd-panel, --elev-float, --ink-NNN og --red-tx
   skifter selv i moerk (forta-dark.css), og --tbl-hover er husets hover-
   flade for raekker — et menupunkt ER en raekke. */
.fx-menu {
  position:absolute; right:0; top:100%; z-index:40; margin-top:6px;
  min-width:220px; max-width:min(340px, calc(100vw - 16px));
  display:flex; flex-direction:column; gap:1px;
  padding:6px; background:var(--bg-panel); color:var(--ink-900);
  border:1px solid var(--bd-panel); border-radius:var(--radius-sm);
  box-shadow:var(--elev-float); text-align:left; }
/* Et <form> om en knap maa ikke laegge sin egen boks ind i listen. */
.fx-menu > form { display:contents; margin:0; }
/* ... men en formular der SELV er en linje (felt + knap, fx kurv-vaelgerens
   «Ny kurv») skal beholde sin flex. `display:contents` lagde dens felter som
   raekker i panelets kolonne — maalt 24-09 (menuloeft2): navn, type og
   «Opret» paa hver sin linje i fuld bredde. (0,2,1) slaar (0,1,1). */
.fx-menu > form.fx-menu-linje { display:flex; }
.fx-menu-punkt {
  display:flex; align-items:center; gap:10px; width:100%; box-sizing:border-box;
  min-height:36px; padding:7px 10px; margin:0;
  background:transparent; border:0; border-radius:calc(var(--radius-sm) - 4px);
  color:var(--ink-900); font:inherit; font-size:13.5px; font-weight:500;
  line-height:1.3; text-align:left; text-decoration:none; white-space:normal;
  cursor:pointer; }
/* Ikonet er en fast 16px-soejle i ANDEN tone end teksten, saa oejet laeser
   teksterne som en spalte. `display:block` fra preflight er netop det der
   lagde det paa sin egen linje, naar punktet ikke var flex. */
.fx-menu-punkt > svg, .fx-menu-punkt > .lucide {
  flex:0 0 16px; width:16px; height:16px; color:var(--ink-500); }
.fx-menu-punkt:hover { background:var(--tbl-hover); color:var(--ink-900); text-decoration:none; }
.fx-menu-punkt:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.fx-menu-punkt:focus:not(:focus-visible) { outline:none; background:var(--tbl-hover); }
.fx-menu-punkt[disabled], .fx-menu-punkt[aria-disabled="true"] {
  opacity:.5; cursor:not-allowed; background:transparent; }
.fx-menu-punkt[data-fare], .fx-menu-punkt[data-fare] > svg { color:var(--red-tx); }
/* Det valgte punkt i en vaelger (aktiv virksomhed, aktiv kurv) — menuloeft2.
   Kun vaegten: fluebenet og en evt. flade er vaelgerens egne. */
/* `page` (adminmobil 24-09): et navigationspunkt der peger paa siden man
   staar paa — admin-telefonens «Menu». Samme vaegt som vaelgerens valgte. */
.fx-menu-punkt[aria-current="true"], .fx-menu-punkt[aria-current="page"] { font-weight:600; }
.fx-menu-skel { border:0; border-top:1px solid var(--bd-panel); margin:5px -6px; height:0; }
/* Skel tegnes kun MELLEM grupper: en gruppe der er slukket af en tilladelse
   efterlader ellers et skel oeverst, nederst eller to i traek. Saa kan
   skabelonen saette skel ubetinget og lade CSS'en rydde op. */
.fx-menu > .fx-menu-skel:first-child, .fx-menu > .fx-menu-skel:last-child,
.fx-menu > .fx-menu-skel + .fx-menu-skel { display:none; }
.fx-menu-gruppe { padding:6px 10px 2px; font-size:11px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--ink-500); }
/* En hjaelpelinje i menuen (fx «Andet antal» med felt) er ikke et punkt. */
.fx-menu-linje { display:flex; align-items:center; gap:8px; padding:6px 10px;
  font-size:13.5px; color:var(--ink-900); }
.fx-menu-linje > svg { flex:0 0 16px; width:16px; height:16px; color:var(--ink-500); }
/* Greb: <summary> uden browserens trekant. */
.fx-menu-greb { position:relative; }
.fx-menu-greb > summary { list-style:none; cursor:pointer; user-select:none; }
.fx-menu-greb > summary::-webkit-details-marker { display:none; }
/* skal-menu.js saetter data-fx-flyder naar panelet skal ud af en klippende
   forfader (tabel-wrapperens overflow) — saa ligger det over alt andet end
   modaler og sidebar. Koordinaterne skriver scriptet selv. */
.fx-menu[data-fx-flyder] { position:fixed; right:auto; margin-top:0; z-index:65; }
/* ADMIN-SKALLENS «Menu» PAA TELEFONEN (adminmobil, 24-09-2026).
   🔴 HVORFOR HER OG IKKE I forta-mobil.css (§31.2): admin indlaeser IKKE
   forta-mobil.css — og skal ikke. Filen goer moerk til standard paa telefon
   og omformer hele app-laget; admin har intet moerkt tema (maalt: lys og
   moerk giver samme md5 paa alle 13 admin-sider) og er et «ikke-maal» for
   §31. Reglerne herunder er derfor det mindste af §31 admin skal bruge:
   44px (§31.6) paa grebet og punkterne. De er (a) i et max-width:899px-lag,
   saa de ikke kan naa skrivebordet, og (b) skopet til `.admin-nav`, som kun
   findes i admin/templates/base.html — saa de ikke kan naa tech-skallen.
   Punkternes tal er mobil-lagets egne (forta-mobil.css, «§33
   MENUKOMPONENTEN PAA TELEFONEN»), ikke nye. */
@media (max-width:899px) {
  .admin-nav > summary { display:inline-flex; align-items:center; gap:6px;
    min-height:44px; min-width:44px; box-sizing:border-box; padding:0 12px 0 8px;
    margin-left:-8px; border-radius:var(--radius-sm); color:var(--ink-700);
    font-size:14px; font-weight:600; }
  .admin-nav > summary:hover, .admin-nav[open] > summary { background:var(--tbl-hover); }
  .admin-nav > summary:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
  .admin-nav .fx-menu-punkt { min-height:44px; font-size:15px; gap:12px; }
}
/* §8a responsivt fald-punkt (<1200px, Playwright-målt): de to split-knapper
   Udskriv/Print labels bliver ikon-piller. font-size:0 skjuler tekstnoden UDEN
   markup-ændring — Lucide-SVG'et har egne width/height-attributter og krymper
   derfor ikke med. Begge knapper har title+aria-label (§4: entydige ikoner). */
@media (max-width:1199px) {
  .tz-acts .print-order-main, .tz-acts .print-labels-main {
    font-size:0; padding-left:11px; padding-right:11px; gap:0; }
}
/* Under 900px (mobil) må rækken hellere ombryde end at klippe handlinger væk. */
@media (max-width:899px) { .tz-acts { flex-wrap:wrap; } }
/* ORDREFIX 4 (24-09-2026): grunden til en slukket knap staar som zonens
   SIDSTE barn, paa sin egen linje under knapperne. Raekken er `nowrap`
   (§8a's pixelregnskab), saa den ombryder KUN naar der er en grund. */
.tz-acts:has(> .tz-acts-grund) { flex-wrap:wrap; }
.tz-acts > .tz-acts-grund { flex:1 0 100%; margin:0; }

/* Fane-chips som indholds-kortets header (§8a: chips til venstre, bulk til
   højre). tabs_nav er en DELT komponent og røres ikke — vi styler wrapperen og
   syr den sammen med kortet nedenunder. */
.tz-linjekort > .tz-tabshead {
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-bottom:0; border-radius:var(--radius-panel) var(--radius-panel) 0 0;
  padding:11px 16px; }
.tz-tabshead .tz-tabshead-sp { flex:1 1 0; min-width:0; }
.tz-linjekort > #tab-content > .card:first-of-type,
.tz-linjekort > #tab-content > section > .card:first-of-type {
  border-top-left-radius:0; border-top-right-radius:0; }

/* §8a: "Reservér fast højre kolonne til op til FIRE ikon-knapper pr. varelinje
   (redigér · duplikér · slet · ombyt) — alle fire skal kunne stå samtidig ved
   1280 uden vandret scroll."  Regnestykket for de 150px:
     4 × 28px knap + 3 × 4px gap = 124px  +  2 × 8px td-padding (px-2) = 140px.
   De sidste 10px er luft, så en evt. fokus-ring ikke klipper.
   Knapperne er inline-flex-søskende uden wrapper i dag → HTML-whitespace giver
   ~4px ubestemmelige mellemrum og risiko for ombrydning; .linje-acts gør
   afstanden deterministisk (gap) og forbyder wrap eksplicit. */
.linje-acts-col { width:150px; }
.linje-acts { display:inline-flex; align-items:center; justify-content:flex-end;
  gap:4px; flex-wrap:nowrap; }
.linje-acts .list-action { width:28px; height:28px; flex:0 0 auto; }

/* ── CC.7 BATCH 4 — data-tabel + kort-header + celle-typografi porteret ORDRET
   fra prototypen (bruges af virksomhedsopslag Radar/Matrix + fremtidige batches).
   Tokens fra 0e (--ink/-2/-3/--border/--tbl-hover); .link = white-label
   --accent-link. .num/.search findes allerede i app.css. ─────────────────────── */
.tbl { width:100%; border-collapse:collapse; }
.tbl th { font-size:10.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2); text-align:left;
  padding:0 14px 12px; }
.tbl th.r, .tbl td.r { text-align:right; }
.tbl td { padding:13px 14px; border-top:1px solid var(--border); font-size:13.5px;
  color:var(--ink); vertical-align:middle; }
.tbl tr { transition:background .12s; }
.tbl tbody tr:hover { background:var(--tbl-hover); }
/* GATE 2.3 (2026-07-24): klikbare rækker mistede hånd-markøren i BATCH 6-porten.
   Den gamle regel .data-table .row-clickable (app.src.css) rammer IKKE .tbl-
   lister — de nye liste-templates (ordrer/kunder/fakturaer/varer/tilbud/
   abonnementer) bruger <table class="tbl"> med <tr class="row-clickable">. Denne
   .tbl-skopede regel genskaber cursor:pointer på alle klikbare rækker. */
.tbl tbody tr.row-clickable { cursor:pointer; }

/* ── LISTEBREDDE (27-09-2026): DEN KOLONNE DER GIVER SIG ─────────────────────
   Andreas 27-09, MacBook Pro med sidebaren aaben: «knapper … går ud over
   rammen» paa /ordrer. MAALT med husets typiske tekstlaengder ved 1280:
   /ordrer 1.140 px tabel i et kort paa 982 (med en overskrift paa raekken),
   /tilbud 1.155. «⋯» og status-pillen stod UDEN FOR kortet.
   🔴 AARSAGEN: `max-width:260px` paa en `truncate`-celle er et LOFT, ikke en
   bredde der kan give sig — `white-space:nowrap` goer cellens min-content lig
   hele teksten op til loftet, saa kolonnen var reelt FAST 260. Alle andre
   kolonner stod allerede paa deres min-content; der var intet tilbage at tage.
   `max-width:0` fjerner tekstens bidrag til min-content (kolonnen kan gaa
   helt ned), og den procentvise bredde paa <th> giver den sin andel naar der
   ER plads. Teksten klippes med ellipse; den fulde tekst staar i `title`.
   `.kol-klip-smal` er til en sekundaer kolonne (Ref.) der giver sig foer
   de faste. SKRIVEBORD-KUN: under 899px stables cellerne (§31.7), og en
   `max-width:0` dér ville slette cellen. Maalingen: leverance/LISTEBREDDE-27-09.md.
   Vaern: tests/test_listebredde_browser.py. */
@media (min-width: 900px) {
  .tbl td.kol-klip { max-width:0; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; }
  .tbl th.kol-klip { width:30%; max-width:0; overflow:hidden;
    text-overflow:ellipsis; white-space:nowrap; }
  .tbl th.kol-klip.kol-klip-smal { width:12%; }
}

/* ── FABLE ETAPE 3 (23-08-2026): `.tbl` ER KANON — DE DØDE NAVNE BLIVER ALIASER
   ────────────────────────────────────────────────────────────────────────────
   MÅLT i dette træ, ikke skønnet (se LEVERANCE-tabel.md §1.2):

       .table          27 tabeller.  Eneste `.table`-regel på maskinen er
                       Tailwinds display-utility i app.css: `.table{display:table}`
                       — et no-op på et element der ALLEREDE er display:table.
       .table-compact   3 tabeller.  NUL definition i static/css/ og i tech/.

   Begge familier renderede altså med browserens standard: ingen rammer, ingen
   polstring, ingen overskrift-typografi, ingen hover. De er ikke «et femte
   tabelsystem» — de er fravær af et.

   🔴 HVORFOR ALIAS OG IKKE BARE EN OMSKRIVNING AF SKABELONERNE.
   Skabelonerne ER skrevet om i samme runde (46 tabeller → `class="tbl …"`), så
   i dag rammer disse to selektorer ingenting i repoet. De står som VÆRN mod
   den skabelon optællingen ikke fandt — en Jinja-genereret tag, en gren der
   ikke er flettet endnu, en fil et andet hus tilføjer i morgen. Et alias
   koster to selektorer; en overset skabelon koster en naken tabel i produktion.

   🔴 HVORFOR `table.table` OG IKKE `.table`.
   `.table` er Tailwinds display-utility og kan lovligt stå på et <div> for at
   give det `display:table`. En bar `.table`-regel her ville give det <div>
   celle-polstring og en hover-farve. Målt 23-08: 27 af 27 forekomster af
   `.table` i tech/templates står på et <table>, og 0 på noget andet — men
   element-skopet gør det UMULIGT frem for usandsynligt.

   🔴 `.data-table` ER IKKE ALIASERET, OG DET ER ET VALG. Se LEVERANCE-tabel.md
   §3: 159 tabeller, egen besluttet ruleset (§23/10d/N19 for 11px-headeren,
   D.7 Del B for sticky), og en konvergering ville tage hver eneste liste i
   produktet fra ~30px til ~44px rækkehøjde. Det er en produkt-beslutning, ikke
   en oprydning. Kun hover-defekten er rettet, i app.src.css. ───────────────── */
table.table, table.table-compact { width:100%; border-collapse:collapse; }
table.table th, table.table-compact th {
  /* 🔴 --ink-2, IKKE --ink-3. Maalt 23-08: ink-3 (#7B95A3) gav 3,15:1 paa
     arvet flade — kontrast-gaten meldte det som et NYT brud da .table blev
     stylet i denne runde. Den kanoniske `.tbl th` har altid brugt --ink-2;
     kun den gamle form afveg. Ikke en beslutning — en manglende oprettelse. */
  font-size:10.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2); text-align:left;
  padding:0 14px 12px; }
table.table th.r, table.table td.r,
table.table-compact th.r, table.table-compact td.r { text-align:right; }
table.table td, table.table-compact td {
  padding:13px 14px; border-top:1px solid var(--border); font-size:13.5px;
  color:var(--ink); vertical-align:middle; }
table.table tr, table.table-compact tr { transition:background .12s; }
table.table tbody tr:hover,
table.table-compact tbody tr:hover { background:var(--tbl-hover); }
table.table tbody tr.row-clickable,
table.table-compact tbody tr.row-clickable { cursor:pointer; }
.card-h { display:flex; align-items:center; justify-content:space-between;
  margin-bottom:14px; }
.card-h .t { font-size:13px; font-weight:700; letter-spacing:.02em;
  color:var(--ink-2); text-transform:uppercase; }
.cell-main { font-weight:600; color:var(--ink); }
.cell-sub { font-size:11.5px; color:var(--ink-2); margin-top:2px; }
.link { color:var(--accent-link); font-size:13px; font-weight:600;
  cursor:pointer; text-decoration:none; }
.link:hover { text-decoration:underline; }

/* ── FOLDE-GREB I INDHOLDET: «Skift kunde», «Betal eksisterende …» ──────────
   Et <summary> arver brødtekstens farve, og på /kasse gav det en indre
   modstrid i ÉT kort: kortets link stod i --accent-link, mens HANDLINGEN stod
   i samme hvide som teksten omkring den. Kortet lærer altså øjet at accent =
   trykbart og lægger så grebet i brødtekst-farve.

   Målt 23-08-2026 ved 393px, mørkt tema: grebene rgb(222,233,241) — d.v.s.
   --ink-900, ikke en linkfarve. Andreas fotograferede dem og læste dem som
   overskrifter.

   🔴 FARVEN ER VALGT FOR AT MATCHE KORTETS EGET LINK, ikke som en fri accent.
   Ser du den som en tilfældig kulør og skifter den, genindfører du modstriden.
   Beslutning truffet af App-dirigenten 23-08-2026.

   🔴 OG DET ER FARVE, IKKE KNAPFORM — med vilje. En knapform ville give kortet
   TO primære handlinger og konkurrere med betalingsknappen; farven følger et
   mønster der allerede står i samme kort.

   🔴 TREKANTEN BLIVER. Den er husets sidst trufne afsløring (se noten ved
   `main summary` i forta-mobil.css), og to signaler er ikke ét for meget når
   det ene er farve og det andet form.

   Hvorfor ikke bare `.link`: den sætter også font-size 13px og weight 600, og
   det ville ændre grebets typografi ud over den ene ting der blev besluttet.
   Farven — og kun den — er det der var galt. */
.foldegreb { color:var(--accent-link); }
.foldegreb:hover { text-decoration:underline; }

/* CC.7 3.2/3.3: ordre-linje-tabellens BESKRIVELSE-kolonne skal have prioritet i
   kolonnefordelingen. Uden min-width kollapsede den til ~min-content (~12 tegn)
   når de øvrige kolonner (varenr + 4 beløbskolonner) tog pladsen → tårnhøje
   rækker. min-width sikrer den brugbar bredde; max-width matcher prototypens
   340px-loft; overflow-wrap bryder lange usammenhængende strenge (SN/varenr). */
.data-table td.linje-desc { min-width:240px; max-width:340px;
  overflow-wrap:anywhere; }

/* ── CC.7 BATCH 5 — kundekort-360-primitiver porteret ORDRET fra prototypen
   (crumbs, stak, kpi-tekst, feed-detaljer). Tokens fra 0e; .link-hover =
   white-label --accent-link. .feed-item findes fra BATCH 3. ────────────────── */
.crumbs { display:flex; align-items:center; gap:7px; font-size:12.5px;
  color:var(--ink-2); margin-bottom:14px; flex-wrap:wrap; }
.crumbs a { color:var(--ink-2); cursor:pointer; text-decoration:none; }
.crumbs a:hover { color:var(--accent-link); }
.crumbs b { color:var(--ink); }
.crumbs span.s { opacity:.5; }
.stack { display:flex; flex-direction:column; gap:18px; }
/* KPI-korttekst (prototypens .kpi .lab/.val/.meta — scopet, rører ikke app'ens
   .kpi-label/.kpi-value). Bruges på .card.glow.kpi i kundekortet. */
.kpi .lab { font-size:11px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-2); }
.kpi .val { font-family:var(--font-display); font-weight:600;
  font-size:clamp(24px,2.5vw,32px); letter-spacing:-.02em; margin-top:8px;
  color:var(--ink); font-variant-numeric:tabular-nums; line-height:1; }
.kpi .meta { display:flex; align-items:center; gap:8px; margin-top:12px;
  font-size:12px; color:var(--ink-2); }
/* BATCH 9d (GLOBAL-2): dæmpet enhed ("kr") efter et KPI-beløb — centralt sted
   for den gentagne inline `font-size:.5em;...`-styling. Skaleres relativt til
   beløbets font (em), så den passer i både store og små KPI-tal. */
.kpi-unit { font-size:.5em; font-weight:600; color:var(--ink-2); }
/* Aktivitets-feed-detaljer (feed-item porteret i BATCH 3). */
.feed-dot { width:8px; height:8px; border-radius:50%; background:var(--accent);
  margin-top:6px; flex:0 0 8px; }
.feed-txt { font-size:13px; color:var(--ink-2); line-height:1.5; }
.feed-txt b { color:var(--ink); font-weight:600; }
.feed-time { font-size:11px; color:var(--ink-2); white-space:nowrap;
  margin-left:auto; }

/* ── KUNDEKORT 2b (27-09-2026) — Oversigtens nye blokke ──────────────────
   Forslaget (rapporter/kundekortdesign/forslag.html på
   feature/kundekortdesign-27-09), tiltrådt af Andreas 27-09. Ikonfliserne er
   §31.7's `.app-row-ic` (36×36, tonet); her står kun det nye: listen med
   ikon · to linjer · beløb/pille («Det kræver handling», Kontaktpersoner),
   de tre spor og feedens ikon + fanenavn. */
.kd-liste { display:flex; flex-direction:column; }
.kd-li { display:flex; align-items:center; gap:12px; padding:10px 0;
  border-top:1px solid var(--border); color:inherit; text-decoration:none; }
.kd-liste > .kd-li:first-child { border-top:none; }
.kd-li-tekst { display:flex; flex-direction:column; gap:2px; min-width:0;
  flex:1 1 auto; }
.kd-li-main { font-size:13px; font-weight:600; color:var(--ink); }
.kd-li-sub { font-size:12px; color:var(--ink-2); }
.kd-li-end { display:flex; align-items:center; gap:10px; margin-left:auto;
  flex:0 0 auto; font-size:12.5px; color:var(--ink); }
a.kd-li:hover .kd-li-main { color:var(--accent-link); }
.kd-kraever { margin-top:14px; padding-top:12px; border-top:1px solid var(--border); }
.kd-kraever-h { font-size:11px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--ink-2); margin-bottom:2px; }
.kd-spor { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; }
.kd-spor-kort { display:flex; flex-direction:column; color:inherit;
  text-decoration:none; }
.kd-spor-h { display:flex; align-items:center; justify-content:space-between; gap:8px; }
.kpi .kd-spor-val { font-size:24px; }
.kd-spor-val .kd-enhed { font-size:.55em; font-weight:600; color:var(--ink-2); }
.kd-spor-krav { font-weight:600; }
.kd-spor-krav.wait { color:var(--amber-tx); }
.kd-spor-krav.due { color:var(--red-tx); }
.kd-spor-gaa { margin-top:auto; padding-top:12px; font-size:12.5px;
  font-weight:600; color:var(--accent-link); }
.kd-spor-kort:hover .kd-spor-gaa { text-decoration:underline; }
.kd-feed-ic { width:28px; height:28px; flex:0 0 28px; border-radius:9px; }
.kd-feed-slut { display:flex; flex-direction:column; align-items:flex-end;
  gap:2px; margin-left:auto; flex:0 0 auto; }
.kd-feed-fane { font-size:11px; color:var(--ink-2); white-space:nowrap; }

/* ── CC.7 BATCH 6 — liste-atomer porteret ORDRET fra prototypen (ordre-liste
   eksemplaret; genbruges af kundeliste-6b). Tokens fra 0e. .search/.tbl/.chip/
   .pill/.cell-* findes fra GATE 1. ─────────────────────────────────────────── */
.toolbar { display:flex; gap:12px; align-items:center; flex-wrap:wrap;
  margin-bottom:16px; }
.select { padding:11px 14px; border-radius:11px; background:var(--panel-solid);
  border:1px solid var(--border); color:var(--ink-2); font-size:13px;
  font-weight:500; cursor:pointer; display:flex; align-items:center; gap:8px; }
/* Række-handlinger (redigér/⋯) — skjult, vises ved row-hover (prototype). */
.rowact { opacity:0; display:flex; gap:4px; justify-content:flex-end;
  transition:.15s; }
.tbl tbody tr:hover .rowact, tr:hover > td > .rowact { opacity:1; }
/* §33 (menuloeft 24-09-2026): en AABEN raekkemenu holder sin celle synlig,
   og tastatur-fokus i cellen goer det samme. Panelet ligger med
   `position:fixed` over NABORAEKKERNE, og rammer musen 6px-luften mellem ⋯
   og panelet, er der et oejeblik hvor hverken raekken eller panelet er hovret
   — `opacity:0` paa cellen ville saa slukke panelet med den. Maalt: panelet
   havde flade (220x99) og var usynligt, fordi `.rowact` stod paa 0. */
.rowact:has(details[open]), .rowact:focus-within { opacity:1; }
.ico-btn { width:30px; height:30px; border-radius:8px; display:grid;
  place-items:center; color:var(--ink-2); cursor:pointer;
  border:1px solid transparent; background:transparent; }
.ico-btn:hover { background:var(--panel-2); border-color:var(--border);
  color:var(--ink); }

/* ── CC.7 BATCH 7 — Indkøb-facet-panel (venstre kolonne under kategoritræet).
   Porteret ORDRET fra prototypen (facetbox/facet/fopt/pricerange). §26-vagtpost:
   kun Producent · Kostpris · Lagerstatus bygges. ────────────────────────────── */
.facetbox { padding:14px 12px; margin-top:14px; }
.facet { border-top:1px solid var(--border); padding:12px 4px; }
.facet.first { border-top:none; padding-top:2px; }
.facet h5 { font-size:11px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2); margin:0 0 8px; }
.fopt { display:flex; align-items:center; gap:9px; font-size:12.7px;
  color:var(--ink-2); padding:3px 2px; text-decoration:none; cursor:pointer;
  border-radius:6px; }
.fopt:hover { background:var(--tbl-hover); color:var(--ink); }
.fopt.on { color:var(--ink); font-weight:600; }
.fopt input { accent-color:var(--accent); width:15px; height:15px; flex:0 0 auto;
  cursor:pointer; }
.fopt .c { margin-left:auto; font-family:var(--font-mono); font-size:10.5px;
  color:var(--ink-2); }
.fopt-scroll { max-height:220px; overflow-y:auto; margin:-2px -2px 0; padding:0 2px; }
.pricerange { display:flex; align-items:center; gap:6px; }
.pricerange input { width:100%; min-width:0; padding:7px 9px; border-radius:9px;
  background:var(--panel-solid); border:1px solid var(--border); color:var(--ink);
  font-size:12.5px; }
.pricerange span { color:var(--ink-2); }

/* ── Intern note-panel (§23/10g/M) — amber-flade der komposit'er KORREKT i
   dark. Inline `background:var(--amber-bg)` alene lagde dark'ens .14-alpha-amber
   over SIDE-baggrunden → "mudret oliven". Her lægges amber som gradient OVER en
   solid panel-flade: lys = opak #FDF4E3 (uændret look), dark = subtil amber-tint
   over #12263A. ────────────────────────────────────────────────────────────── */
.note-panel { background-color:var(--bg-panel);
  background-image:linear-gradient(var(--amber-bg), var(--amber-bg));
  border:1px solid var(--bd-panel); border-left:4px solid var(--amber-bd);
  border-radius:var(--radius-panel); padding:1rem; }
.note-panel h3 { color:var(--amber-tx); }

/* ── Tag-badge (§23/10c/M12) — neutralt TYPE-mærkat (fx ⌘K-palettens
   Kunde/Ordre/…). Ikke en status-pille: firkantet-blød (6px), ingen dot,
   ingen interaktion. ───────────────────────────────────────────────────── */
.tag-badge { display:inline-flex; align-items:center; border-radius:6px;
  background:var(--ink-100); color:var(--ink-600); font-size:10.5px;
  font-weight:600; letter-spacing:.02em; padding:2px 7px; white-space:nowrap; }

/* Beløbs-semantik (ind/ud) via tokens — fortegns-LOGIK ændres ikke (§8 i prompt). */
.amount-pos { color:var(--green-tx); }
.amount-neg { color:var(--red-tx); }
.amount-neutral { color:var(--ink-700); }

/* ── Statiske paneler: hvid, 1px kant, 16px radius, INGEN skygge (§7). ──── */
.panel-static {
  background:var(--bg-panel);
  border:1px solid var(--bd-panel);
  border-radius:var(--radius-panel);
  box-shadow:none;
}

/* ── Ikoner (§4): Lucide inline, currentColor, stroke 1.8. ───────────────── */
.lucide { stroke:currentColor; fill:none; stroke-width:1.8;
  stroke-linecap:round; stroke-linejoin:round; flex:0 0 auto;
  vertical-align:middle; }

/* ============================================================================
   D.2 — Mørk sidebar (236px) + slank topbar (§9). Ren layout/præsentation.
   Sidebar-gradient bruger nu brand-tokens (Del A): --b-deep → --b-mid.
   ========================================================================== */
.layout { display:flex; min-height:100vh; }

/* §31.3: bund-navet står i DOM'en for ALLE (ingen server-side viewport-gæt —
   se test_e11_tabel_stak), men er skjult som DEFAULT. Reglen hører hjemme her
   og ikke i forta-mobil.css: dén fil er ét max-width:899px-lag (§31.2), og en
   regel derinde kan pr. konstruktion ikke gøre noget ved en bred skærm. Uden
   denne linje ville navets links hænge som umarkeret tekst i bunden af hver
   desktop-side. Mobil-laget viser den igen med display:flex under 899px. */
.mnav { display:none; }

/* §31.2 + §31.4: blokke der KUN hører til telefon-fladen. Mobil-Hjem sammensætter
   prototypens skærm 1 af blokke der ikke har en plads i skrivebordets
   to-kolonne-workbench (morgenbrief-uddraget, "Seneste push"). De skal stå i
   DOM'en dér hvor de skal LÆSES på telefonen — §31.4 forbyder order:-hop, så
   visning må være lig DOM — og de skal være væk på skrivebordet.

   Løsningen er den samme som .mnav ovenfor, og af samme grund: default-skjult
   HER, vist igen af mobil-lagets ene media-blok. Reglen kan ikke bo i
   forta-mobil.css — dén fil er ét max-width:899px-lag (§31.2) og kan pr.
   konstruktion ikke gøre noget ved en bred skærm. Uden denne linje ville
   blokkene hænge midt i skrivebordets dashboard. */
.mobil-kun { display:none; }

/* ── ALARM-TALLET PAA «UAFSLUTTEDE»-DOEREN (19-09-2026, fund S7) ──────────
   Tallet efter knappens navn paa /kasse. Kasse-PC'en er dér arbejdet i
   butikken foregaar, og bag doeren ligger bl.a. bogfoeringer der fejlede
   EFTER at pengene var modtaget — skrivebordet saa den SAMME graa knap ved
   0 og ved 12.

   🔴 EGEN KLASSE, OG DET ER IKKE KOSMETIK. Mobil-udgaven hedder
   `.kasse-doer-tal`, og den klasse staar i `NYE_KLASSER`
   (tests/test_app_protohuller.py): §31.2 forbyder at et af app-lagets navne
   faar en regel i forta-core.css, *fordi en regel der kun kan eksistere
   inde i media-blokken ikke kan aendre en bred skaerm*. Foerste udgave af
   denne rettelse gav `.kasse-doer-tal` en topniveau-regel og blev roed paa
   netop det vaern — med rette. Skrivebordet faar derfor sit EGET navn, og
   app-klassen bliver hvor den hoerer hjemme.
   ⚠️ Mobil-udgaven beholder ogsaa `.mobil-kun`, og denne bliver skjult af
   `.mobil-skjul` under 899 px, saa praecis ÉN af dem tegnes ved enhver
   bredde — og kun én bliver laest op.

   Vaerdierne er mobil-lagets, ORDRET (forta-mobil.css `.kasse-doer-tal`).
   De to skal vise det SAMME; er de uenige, flytter tallet sig ved 899 px
   uden at nogen har bedt om det.
   `--ink-2` er maalt paa knappens egen flade (`--bg-panel`): lyst #4A6676
   paa #FFFFFF = 6,08, moerkt #9DB6C8 paa #12263A = 7,30. AA kraever 4,50,
   og dette er SMAA tegn, saa 3,00-undtagelsen for stor tekst gaelder ikke. */
.kasse-doer-alarm {
  margin-left: 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-2);
  white-space: nowrap;
}

/* §31 APP-TOPBAR: prototypens .app-top (mærke + skærmnavn + tenant-pille).
   Samme doktrin og samme grund som .mnav ovenfor: elementerne står i DOM'en
   for ALLE, er default-skjult HER, og vises igen af mobil-lagets ene
   media-blok under 899px. Reglen kan ikke bo i forta-mobil.css — dén fil er
   ét max-width:899px-lag (§31.2) og kan pr. konstruktion ikke gøre noget ved
   en bred skærm. Uden disse linjer ville et "F"-mærke og et dubleret
   skærmnavn stå midt i skrivebordets topbar ved siden af brødkrummen.

   .app-tenant-dot står med, selv om den ligger INDE i .app-tenant-pill og
   dermed allerede er usynlig af sin forælder: reglen skal kunne læses som
   "det her er app-topbarens elementer, og de er væk på skrivebordet" uden at
   læseren først skal regne forældre-kæden ud. Målt 15-08-2026 stod den som
   det eneste af de fire med display:inline i en computed-style-måling — nul
   px stor, men en unødig undtagelse i et svar der ellers var ensartet. */
.app-mark, .app-wm, .app-tenant-pill, .app-tenant-dot { display:none; }

/* §31 DETALJETYPEN (prototypens .det-top): tilbage-knap + titel + undertitel.
   Samme doktrin og samme grund som linjen ovenfor. Forskellen på de to sæt er
   HVORNÅR de står i DOM'en — app-top-elementerne står der altid, detaljetypens
   kun på de seks tegnede detaljeflader (base.html) — men på skrivebordet skal
   BEGGE være væk, og den regel kan ikke bo i forta-mobil.css: dén fil er ét
   max-width:899px-lag (§31.2) og kan pr. konstruktion ikke gøre noget ved en
   bred skærm.

   .app-tilbage står med SIN EGEN display:none selvom den også bærer .ico-btn:
   .ico-btn sætter display:grid, og uden denne linje ville en tilbage-pil stå
   midt i skrivebordets topbar ved siden af brødkrummen. Rækkefølgen afgør det
   ikke — .ico-btn står 100 linjer længere oppe — men at læse det ud af
   rækkefølgen er præcis den slags kaskade-argument der brød scan-knappen
   (test_kun_app_kaskade.py). Selektoren er derfor to klasser (0,2,0) og
   vinder på specificitet, ikke på placering. */
.app-tilbage.ico-btn, .app-det, .app-det-titel, .app-det-sub { display:none; }

.side {
  width:236px; flex:0 0 236px;
  /* §24.2: near-black sidebar i BEGGE modes (CC.7 0b — afkoblet fra
     --b-deep/--b-mid, se :root --sb-bg). 🔴 BULLETPROOF-KASKADE (fixer den
     observerede "hvid sidebar i lys mode på forta.dk"): FØRSTE deklaration er en
     SOLID mørk farve (#050D16) — den overlever selv hvis HELE tema-CSS'en/alle
     var()'er ikke resolver (stale edge-cache, load-timing). UDEN den faldt
     baggrunden til transparent → den hvide body.bg-white skinnede igennem = hvid
     sidebar. Derefter near-black-gradienten som statisk fallback og til sidst
     --sb-bg (samme near-black). */
  background:#050D16;
  background:linear-gradient(180deg,#050D16 0%,#07131F 100%);
  background:var(--sb-bg);
  display:flex; flex-direction:column; gap:2px;
  padding:18px 12px 14px; color:#fff;
  transition:width .18s ease, flex-basis .18s ease;
}
.side-logo { display:flex; align-items:center; justify-content:space-between;
  padding:0 6px 14px; }
.side-logo button { background:none; border:0; cursor:pointer; padding:0;
  display:flex; align-items:center; }
.side-logo-full { height:30px; width:auto; display:block; }
.side-logo-mark { height:32px; width:32px; display:none; }
/* D.2c: ADMIN-mærkat i admin-konsollens sidebar-logo (kun brugt i admin-appen). */
.admin-logo-link { display:flex; align-items:center; gap:9px; text-decoration:none; }
.admin-logo-tag { height:auto; width:auto; font-family:'JetBrains Mono',monospace;
  font-size:10px; font-weight:600; letter-spacing:.18em; color:rgba(255,255,255,.58);
  border:1px solid rgba(255,255,255,.22); border-radius:5px; padding:2px 6px;
  line-height:1; }
/* ADMIN: EN KNAPTEKST BRYDES ALDRIG (designens F5, 24-09-2026). Målt på 393
   over alle 51 admin-sider: 13 knapper stod på to-tre linjer og 48–66 px
   («Send SMS», «SMS-log», «Fjern adgang», «Nulstil kodeord» …). Mekanismen
   er den admindesign fandt for «Gem niveau»: en pill-knap i en flex-række
   presses ned til sin min-content, og uden nowrap er det ét ord pr. linje.
   Skopet til admin-skallen (`body.admin-konsol`, admin/templates/base.html):
   tech's knapper på telefonen ejes af app-designet (§31) og forta-mobil.css,
   og de er ikke rørt. Afprøvet før reglen blev skrevet: med nowrap er der
   0 brudte knapper og ingen vandret rulning på de ni sider med fund. */
.admin-konsol :is(.btn, .btn-primary, .btn-secondary, .btn-ghost, .btn-danger,
                  .btn-danger-outline) { white-space:nowrap; }
/* …og rækken de står i må bryde i stedet. Uden det gjorde nowrap siden
   BREDERE: målt på 393, /admin/sms-templates 402 → 425 px, fordi
   `.header-actions` (flex, ingen wrap) med tre knapper ikke længere kunne
   presses sammen, og Chrome zoomede hele siden ud. Under 899 får
   sidehovedet og dets handlinger lov at lægge sig på flere rækker. */
@media (max-width: 899px) {
  .admin-konsol .page-header,
  .admin-konsol .header-actions { flex-wrap:wrap; }
  /* F6 (designvalg 26-09, Andreas: «hver tabel får sin egen rulleboks»).
     Tabellerne ruller i `.table-scroll` i skabelonerne. Målt på 393 var
     der tre sider mere, hvor det brede ikke var en tabel:
       /admin/companies/<id>      fieldset 406: UA-standarden for fieldset
                                  er `min-inline-size:min-content`, så den
                                  kan ikke presses under sit indhold
       /admin/icecat-credentials  en URL i `.font-mono` uden brudpunkt, 460
       /admin/viderefakturering   `dd` i et `max-content 1fr`-grid med en
                                  sti uden mellemrum, 406
     `anywhere` og ikke `break-word`: kun `anywhere` sænker min-content, og
     det er min-content der bestemmer bredden i et grid og en flex-række. */
  .admin-konsol fieldset { min-width:0; }
  .admin-konsol :is(.font-mono, dd) { overflow-wrap:anywhere; }
}

/* ⚠️ Blokkene herunder stod først bagerst i filen og faldt dermed ind under
   `test_e4_scan_skaerm`, der læser alt fra `.scan-side` til filens ende som
   scan-skærmens CSS. De står her, ved admin-skallens egne regler. */
/* Admin F4 · farvevælger og filvælger (smaafix26 A10, 26-09-2026).
   Målt på /admin/companies/<id> (rapporter/smaafix26/RAPPORT.md §A10):
     farvevælger  56×40, grå UA-flade, hårdkodet kant #e5e7eb — ved siden af
                  knapper på 32 (393) / 38 (1400)
     filvælger    browserens «Choose File»: grå flade, 2px outset sort kant,
                  radius 0 — i et .form-input på 39,5 mod feltets 38
   Ingen husregel dækkede de to kontroller. Formen her LÅNES fra de regler
   der står ved siden af dem, ikke opfundet: højden fra knap-reglen
   (app.src.css `.btn`-familien: 32, fra 900px 38), kanten og tekstfarven fra
   `.btn-secondary` (--bd-control, --accent-link), radius fra `.form-input`.
   Afgrænset til `.admin-konsol`: admin har intet mørkt tema, mens tech's
   filfelter også tegnes i mørk og ikke er målt her. */
.admin-konsol .form-farve {
  width: 56px;
  height: 32px;
  padding: 3px;
  border: 1.5px solid var(--bd-control, #A9C3CB);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
}
@media (min-width: 900px) {
  .admin-konsol .form-farve { height: 38px; }
}
.admin-konsol .form-farve::-webkit-color-swatch-wrapper { padding: 0; }
.admin-konsol .form-farve::-webkit-color-swatch { border: none; border-radius: 5px; }
.admin-konsol .form-farve::-moz-color-swatch { border: none; border-radius: 5px; }
.admin-konsol .form-input[type="file"] {
  padding-top: 3px;
  padding-bottom: 3px;
  padding-left: 3px;
}
.admin-konsol .form-input[type="file"]::file-selector-button {
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  min-height: 30px;
  padding: 0 14px;
  margin-right: 10px;
  border: 1.5px solid var(--bd-control, #A9C3CB);
  border-radius: 9999px;
  /* Fladen er feltets egen (transparent), og teksten arver feltets ink.
     `--accent-link` som .btn-secondary var første udgave: kontrastgaten
     (test_dark_kontrast) regner tokens i begge tilstande og fandt
     #a4e2e4 på #fff = 1,44:1 i mørk. Admin har ingen mørk tilstand, men
     reglen skal ikke hvile på at det forbliver sådan. */
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.admin-konsol .form-input[type="file"]::file-selector-button:hover {
  border-color: currentColor;
}

/* «Mere»-prikken på kundekortet (smaafix26 A10, 26-09-2026).
   `[data-kunde-mere-prik]` fortæller at kunden vises på kunde-tabletten. Den
   var server-renderet på `tablet_showing_customer` og fulgte derfor ingen af
   de fire steder tilstanden skifter uden sideskift (start, stop, kundens svar,
   kundedisplay-autostop.js). Nu er tablet-knappens `data-mode` den ENE kilde:
   alle fire skriver den, og reglen her læser den. Ingen JS at holde i takt.
   Vagt: tests/test_kunde_mere_prik_live.py (393 og 1400, rigtige tryk). */
[data-kunde-mere-prik] {
  display: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-left: 6px;
}
[data-kunde-flere]:has([data-bekraeft-tablet][data-mode="stop"]) [data-kunde-mere-prik] {
  display: inline-block;
}
/* tabletknap 30-09-2026: på skrivebordet står «Bekræft på tablet» i rækken, og
   menuens punkt er `kun-app`. Uden «Book tid» var punktet menuens første, så
   skellet efter det ville stå ØVERST i menuen — `:first-child`-reglen i
   .fx-menu ser ikke at forgængeren er skjult. Prikken skjules af sin egen
   `kun-app` (reglen ovenfor har højere specificitet, men ikke !important). */
@media (min-width: 900px) {
  [data-kunde-flere] .fx-menu > .kun-app:first-child + .fx-menu-skel { display: none; }
}


/* D.4: .side-search er nu en <button> der åbner ⌘K-paletten (ikke længere
   en input/form). Reset button-chrome + fuld-bredde venstrestillet layout. */
.side-search { display:flex; align-items:center; gap:7px; margin:0 2px 12px;
  width:calc(100% - 4px); background:rgba(255,255,255,.07);
  border:1px solid rgba(255,255,255,.10); border-radius:9px; padding:7px 10px;
  cursor:pointer; text-align:left; font-family:inherit; }
.side-search:hover { background:rgba(255,255,255,.11);
  border-color:rgba(255,255,255,.18); }
.side-search .lucide { width:15px; height:15px; opacity:.6; flex:0 0 auto; }
.side-search .side-search-ph { flex:1; min-width:0; color:rgba(255,255,255,.4);
  font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.side-search kbd { font-size:10px; color:rgba(255,255,255,.4);
  border:1px solid rgba(255,255,255,.18); border-radius:5px; padding:1px 5px;
  flex:0 0 auto; font-family:'JetBrains Mono',monospace; }

.side-group { margin-top:13px; }
/* D.8: gruppe-label er nu en <button> (foldbar). Reset button-chrome og gør
   den til fuld-bredde flex-række med chevron yderst til højre. */
.side-group-label { display:flex; align-items:center; justify-content:space-between;
  gap:6px; width:100%; background:none; border:0; text-align:left;
  font-family:inherit; font-size:10px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:rgba(255,255,255,.38); padding:0 12px 5px;
  cursor:pointer; }
.side-group-label:hover { color:rgba(255,255,255,.62); }
.side-group-label .chev { display:inline-flex; opacity:.55;
  transition:transform .15s ease; }
.side-group-label .chev .lucide { width:13px; height:13px; }
.side-group.folded .side-group-label .chev { transform:rotate(-90deg); }
/* Foldet gruppe: skjul dens links (kun labelen/chevron står tilbage). */
.side-group.folded > a, .side-group.folded > details { display:none; }
/* Sammenklappet sidebar = ren ikon-skinne: fold ignoreres (alle ikoner vises). */
.side.collapsed .side-group.folded > a { display:flex; }

/* `:where(:not(.fx-menu-punkt))` (menuloeft2, 24-09-2026): bruger-menuen i
   foden er §33-komponenten, og dens punkter er <a> INDE i .side. Uden
   undtagelsen gav `.side a` dem sidebarens hvide tekst paa komponentens lyse
   flade. `:where` holder specificiteten paa (0,1,1) — med en bar `:not(...)`
   ville reglen stige til (0,2,1), blive lige med `.side-group.folded > a`
   ovenfor og vinde paa kilderaekkefoelgen: foldede grupper ville springe op. */
.side a:where(:not(.fx-menu-punkt)), .side summary.side-link {
  display:flex; align-items:center; gap:11px; position:relative;
  padding:8px 12px; border-radius:9px; font-weight:500; font-size:13.5px;
  color:rgba(255,255,255,.78); text-decoration:none; list-style:none;
  cursor:pointer; white-space:nowrap;
}
.side a:where(:not(.fx-menu-punkt)):hover, .side summary.side-link:hover {
  background:rgba(255,255,255,.07); color:#fff; }
.side a:where(:not(.fx-menu-punkt)) .lucide, .side summary.side-link .lucide {
  width:17px; height:17px; opacity:.85; flex:0 0 auto; }
/* §24.2: aktiv nav-tekst = accent-bright (prototypens --sb-active-tx). Fallback
   #fff FØR var() (motorer uden custom-props beholder hvid). */
.side a.on { background:rgba(255,255,255,.13); font-weight:600; color:#fff;
  color:var(--sb-active-tx); }
.side a.on::before { content:''; position:absolute; left:0; top:6px; bottom:6px;
  width:3px; background:var(--grad); border-radius:0 3px 3px 0; }
/* Nav-tællere bruger §5-pillen (ikke 'badge' — Pico-pattern). I sidebaren får
   de en kompakt, mørk-baggrunds-tunet stil; info = teal (aktiv/info),
   due = rød (forfaldne). Specificiteten her slår de globale pille-farver
   i sidebar-kontekst.

   🔴 BEGGE NAVNE STAAR HER (23-08-2026). base.html blev migreret fra
   `pill-info`/`pill-overdue` til `pill p-info`/`pill p-due`. En kontekst-regel
   som denne er den slags der IKKE bliver roed af en omdoebning: nav-taelleren
   ville stadig rendere som en almindelig pille, bare uden sidebarens kompakte
   maal og uden den moerke-flade-tunede farve — en flade-fejl uden en fejl.
   Aliasnavnene bliver staaende af samme grund som i app.src.css. */
.side a .pill-info, .side summary.side-link .pill-info,
.side a .pill.p-info, .side summary.side-link .pill.p-info,
.side a .pill-overdue, .side summary.side-link .pill-overdue,
.side a .pill.p-due, .side summary.side-link .pill.p-due {
  margin-left:auto; font-size:10.5px; font-weight:700; border-radius:99px;
  padding:1px 7px; }
.side a .pill-info, .side summary.side-link .pill-info,
.side a .pill.p-info, .side summary.side-link .pill.p-info {
  background:var(--teal-400); color:var(--on-info-fill,var(--ink-900));
  border-color:transparent; }
/* --on-info-fill er KUN defineret i de moerke lag (forta-dark/-mobil). I
   moerk inverterer --ink-900 til lys #EAF2F8, mens --teal-400 bliver lys
   turkis: 1,82:1 maalt paa malede pixels 24-09 (rapporter/pillefarver/).
   Lyst tema falder tilbage til --ink-900 og er uroert. */
.side a .pill-overdue, .side summary.side-link .pill-overdue,
.side a .pill.p-due, .side summary.side-link .pill.p-due {
  background:var(--red-tx); color:var(--on-status-fill,#fff); border-color:transparent; }
.side summary.side-link::-webkit-details-marker { display:none; }
/* `.side-submenu` og `.side-submenu-knap` er vaek (menuloeft2, 24-09-2026):
   bruger-menuen var deres eneste bruger og er nu §33 (`.fx-menu`). */

/* Scrollbart nav-område (mange punkter) — foot forbliver fast nederst. */
.side-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; display:flex;
  flex-direction:column; gap:2px; margin:0 -2px; padding:0 2px; scrollbar-width:thin; }
.side-scroll::-webkit-scrollbar { width:6px; }
.side-scroll::-webkit-scrollbar-thumb { background:rgba(255,255,255,.14);
  border-radius:6px; }

.side-foot { position:relative; margin-top:8px;
  border-top:1px solid rgba(255,255,255,.1); padding-top:12px; }
/* Bruger-menuens panel er §33 (`.fx-menu`, greb `.fx-menu-greb`);
   skal-menu.js vender det opad, fordi foden staar nederst. */
.side-user { display:flex; align-items:center; gap:9px; padding:7px 6px;
  border-radius:9px; cursor:pointer; }
.side-user:hover { background:rgba(255,255,255,.07); }
.side-avatar { width:32px; height:32px; border-radius:50%; background:var(--grad);
  color:#fff; display:flex; align-items:center; justify-content:center;
  font-family:'Sora',-apple-system,'Segoe UI',system-ui,sans-serif;
  font-weight:600; font-size:12.5px; flex:0 0 auto; }
.side-user-name { font-size:12.5px; font-weight:600; color:#fff; line-height:1.2; }
.side-user-role { font-size:11px; color:rgba(255,255,255,.45); }

/* §31 TEMA-SKIFTEREN I SIDEBARENS FOD — DEFAULT-SKJULT, PRÆCIS SOM
   DETALJETYPENS ØVRIGE ELEMENTER.
   Knappen renderes kun paa de seks detaljeflader (base.html, rute-betingelse
   via app_topbar_for) og hoerer KUN til under app-breakpointet: paa
   skrivebordet staar tema-skifteren i topbaren, hvor der er plads, og to
   skiftere i samme billede ville vaere to affordancer til én tilstand.
   Reglen kan ikke bo i forta-mobil.css — dén fil er ét max-width:899px-lag og
   kan pr. konstruktion ikke gøre noget ved en bred skærm. Samme doktrin og
   samme grund som .app-tilbage/.app-det ovenfor. */
.side-tema { display:none; }

/* Hovedkolonne + slank topbar */
.main { flex:1; min-width:0; display:flex; flex-direction:column; }
.topbar { display:flex; align-items:center; gap:12px; padding:0 18px;
  height:52px; flex:0 0 52px; background:var(--bg-panel);
  border-bottom:1px solid var(--bd-panel); }
.topbar-crumb { font-size:13px; color:var(--ink-600); font-weight:500; }
.topbar-spacer { flex:1; }
/* Neutral identitets-chip (fx admin-topbarens bruger-navn): IKKE status-
   semantik (§5 grøn = success) — rolige ink-toner. */
.chip-neutral { display:inline-flex; align-items:center; gap:6px; font-size:12px;
  color:var(--ink-700); background:var(--ink-100); border:1px solid var(--ink-200);
  border-radius:999px; padding:3px 10px; white-space:nowrap; }
.chip-neutral .lucide { opacity:.7; }
.topbar-bell { position:relative; background:none; border:0; cursor:pointer;
  color:var(--ink-600); display:flex; padding:4px; }
.topbar-bell:hover { color:var(--ink-800); }
.topbar-bell .bell-dot { position:absolute; top:2px; right:2px; width:7px;
  height:7px; border-radius:50%; background:var(--teal-400);
  border:1.5px solid var(--bg-panel); }
/* Invitations-linket i topbaren: ikon + antal. Antallet er et HJOERNE-MAERKE
   som klokkens .bell-dot, ikke et element paa raekke med ikonet.

   🔴 MAALT 20-08-2026 FOER RETTELSEN, paa baade 393px og 1280px: linket er
   `display:block`, og indholdet — et 16px ikon og en 27x21 `.p-pill` — er
   inline. De kan ikke staa ved siden af hinanden i linkets 44px, saa pillen
   BROED om paa linje to og lagde sig UNDER ikonet. Foelgen var ikke bare
   pillens egen placering: ikon+pille blev til en to-linjers stak, og hele
   stakken blev centreret i topbarens raekke — saa selve ikonet blev skubbet
   OP. Maalt paa 393px laa ikonets midte i 16 mens alle seks naboer i
   topbaren laa i 30. Paa 1280px: 15 mod 26. Det er dét man ser: ét ikon der
   sidder for hoejt, med et tal haengende under sig.

   Rettelsen er klokkens moenster, ikke et nyt: forael-elementet bliver
   `relative` og et centrerende flex, maerket bliver `absolute` i hjoernet og
   fylder derfor ikke i flowet. Kompakte maal (16px hoej, min-width 16px) saa
   et tocifret antal stadig kan staa uden at daekke ikonet. */
/* Grunden til at en knap er slukket — se _components/_slukket_grund.html.
   Dæmpet og lille, men IKKE dæmpet som knappen: teksten er dét man skal kunne
   læse, netop fordi knappen ikke kan trykkes. `align-items:flex-start` saa
   ikonet bliver staaende ved foerste linje naar teksten bryder om paa en
   telefon. */
.knap-grund { display:flex; align-items:flex-start; gap:6px; margin:6px 0 0;
  font-size:12px; line-height:1.4; color:var(--ink-600); max-width:46ch; }
.knap-grund .lucide { flex:0 0 auto; margin-top:1px; opacity:.75; }
/* I en wrappende handlingsraekke skal noten paa sin egen linje, ikke ind
   mellem knapperne. `flex-basis:100%` gaelder kun naar foraelderen ER en
   flex-raekke; ellers er den uden virkning. */
.detail-actionbar > .knap-grund { flex:1 0 100%; margin-top:0; }

.topbar-invitation { position:relative; display:inline-flex;
  align-items:center; justify-content:center; padding:4px; }
/* Baade chip-basen og §5-pillen: markuppen blev migreret 23-08-2026, og en
   kontekst-regel der kun kender det gamle navn bliver ikke roed — den
   efterlader bare maerket paa raekke med ikonet igen. Det var praecis den
   flade-fejl der blev maalt 20-08 og rettet med denne blok. */
.topbar-invitation .p-pill, .topbar-invitation .pill {
  position:absolute; top:0; right:0;
  min-width:16px; height:16px; padding:0 4px; border-radius:999px;
  font-size:10px; line-height:16px; justify-content:center; }
/* 🔴 DEN ENESTE UNDTAGELSE FRA §5's PILLE-PRIK, og den er maalt frem for
   skoennet. `.p-pill` fik 21-08-2026 prikken tilbage (app.src.css §13a —
   §5: «prik (5px dot) foer teksten i currentColor»). Reglen ovenfor er den
   ENESTE i de fire indlaeste stylesheets der giver en `.p-pill` sine egne
   maal, og grunden staar i noten fem linjer over den: dette er et
   HJOERNE-MAERKE som klokkens `.bell-dot`, ikke en statuspille. Feltet er
   16x16 og baerer et tal; en 5px prik plus 4px gap foran «1» ville skubbe
   cifret ud af sit eget maerke — og ved to cifre daekke det.

   Undtagelsen staar HER og ikke ved §13a, saa den flytter med elementet den
   beskytter. Vaernet er test_app_proto_pille_og_korthoved.
   ::before og ikke `content:none`: prikken er en ::before, og et element kan
   kun have én — `display:none` slukker den uden at roere pillens egen kasse. */
.topbar-invitation .p-pill::before { display:none; }
.topbar-burger { display:none; background:none; border:0; cursor:pointer;
  color:var(--ink-700); padding:4px; }
/* D.11: tema-toggle viser moon i lyst, sun i mørkt (ren CSS via body.dark). */
.theme-toggle .theme-ic-moon, .theme-toggle .theme-ic-sun { display:inline-flex; }
.theme-toggle .theme-ic-sun { display:none; }
body.dark .theme-toggle .theme-ic-moon { display:none; }
body.dark .theme-toggle .theme-ic-sun { display:inline-flex; }
.main > .page-shell, .main > #main { flex:1; }

/* Sammenfoldet ikon-rail (64px). Cookie-styret .collapsed sættes server-side. */
.side.collapsed { width:64px; flex:0 0 64px; padding:18px 8px 14px; }
.side.collapsed .side-logo { justify-content:center; }
.side.collapsed .side-logo-full { display:none; }
.side.collapsed .side-logo-mark { display:block; }
.side.collapsed .side-search,
.side.collapsed .side-group-label,
.side.collapsed a span.lbl,
.side.collapsed summary.side-link span.lbl,
.side.collapsed .side-user-meta { display:none; }
.side.collapsed a:where(:not(.fx-menu-punkt)), .side.collapsed summary.side-link { justify-content:center;
  padding:9px 0; gap:0; }
.side.collapsed .side-user { justify-content:center; padding:7px 0; }
.side.collapsed a .pill-info, .side.collapsed summary.side-link .pill-info,
.side.collapsed a .pill.p-info, .side.collapsed summary.side-link .pill.p-info,
.side.collapsed a .pill-overdue, .side.collapsed summary.side-link .pill-overdue,
.side.collapsed a .pill.p-due, .side.collapsed summary.side-link .pill.p-due {
  position:absolute; top:3px; right:9px; margin:0; padding:0;
  width:8px; height:8px; font-size:0; }

@media (prefers-reduced-motion: reduce) { .side { transition:none; } }

/* Mobil: sidebar off-canvas. BURGEREN ER VÆK — se A2 nedenfor.

   🔴 768 -> 899 (04-09-2026). Tallet var en RESTANCE, ikke et valg, og det
   kostede en telefon i landskab 236 af sine 844 px.

   §31.1 siger «≤ 899px = MOBIL» og begrunder det med at det er SAMME tal som
   sidebar-kollapset i §12 — «vælges et andet tal til bund-navet, opstår et
   bånd hvor brugeren hverken har sidebar eller bund-nav». Præmissen var
   forkert i koden: sidebar-kollapset stod på 768, bund-navet på 899. Båndet
   fandtes, bare med omvendt fortegn — brugeren fik BEGGE navigationssystemer
   i stedet for ingen af dem.

   MÅLT I EN BROWSER 04-09-2026, ikke læst i kaskaden (Chromium 151, 844×390,
   is_mobile, begge temaer, samme instans og samme data på begge sider):

       med 768   .side position:static · x 0 · synlig bredde 236 px
                 <main> begynder ved x=236 · .mnav fixed, 844 px bred, synlig
       med 899   .side position:fixed  · x −236 · synlig bredde 0 px
                 <main> begynder ved x=0 · .mnav uændret

   Tilstanden efter rettelsen er ikke ny. Målt på tre bredder i samme kørsel:
   760 og 844 er derefter identiske (off-canvas, burger display:none, .mnav
   flex), og 900 er uden for laget i BEGGE tilstande (sidebar 236, .mnav none)
   — skrivebordet kan pr. konstruktion ikke være rørt, fordi kun @media-
   grænsen ændrer sig.

   ⚠️ Burgeren er `display:none` i alle tre bredder (fjernet 25-08, A2), så
   sidebjælken er off-canvas OG uåbnelig ved 844 px. Det er præcis den
   tilstand der allerede gælder ved 760 px; navigationen sker gennem
   bund-navet og «Mere».

   ⚠️ §31.1 lister samtidig «768» blandt de komponent-lokale breakpoints der
   «forbliver hvor de er». Dokumentet er uenigt med sig selv: denne 768 er
   ikke komponent-lokal, den ER det layout-breakpoint §31.1 mener står på 899.

   `tests/test_breakpoint_parritet.py` låser PARITETEN, ikke tallet: flyttes
   brudpunktet en dag, skal begge lag flytte sammen.

   ⚠️ TO SPOR NAAEDE SAMME RETTELSE, OG DE MAALTE HVER SIN TING. Denne gren
   bar den fra app-linjen (21-08-2026); cc bar den ovenfor (04-09-2026).
   Fletningen 04-09 beholder BEGGE begrundelser, fordi ingen af dem
   indeholder den anden: cc's er GEOMETRI maalt i en browser, app-linjens er
   KASKADE maalt byte for byte plus historikken bag tallet.

   Maalt foer/efter i FIRE baelter: <=768 uaendret (12 af 12 byte-identiske),
   >=900 uaendret (15 af 15), og hele aendringen i 769-899 (0 af 24
   identiske). Paa de 106 app-flader: sidebjaelken paa skaermen i landskab
   106 -> 0, og trykflade-fund i landskab 737 -> 6 (de 731 var dens egne
   maal).

   Historikken siger restance, ikke beslutning:
     13-06-2026  37a815f0  sidebaren + denne 768-regel. Commit-beskeden siger
                           «Mobil: off-canvas + burger i topbaren» og INTET om
                           tallet. 768 er Tailwinds `md`, arvet fra Fase P.
     25-07-2026  fdbf81be  899 optraeder foerste gang i CSS overhovedet.
     28-07-2026  a4e7ccc6  forta-mobil.css — app-laget, bund-navet, §31.
     10-07-2026  ca5ac116  reglen FLYTTET hertil i en «pixel-identisk» split.
   768-reglen er seks uger AELDRE end 899 og blev aldrig valgt frem for den.
   Den var husets ENESTE haandskrevne 768-media-forespoergsel; de oevrige
   768-omtaler i CSS'en er kommentarer om Tailwinds md-praefiks. */
@media (max-width:899px) {
  .side { position:fixed; left:0; top:0; height:100vh; z-index:60;
    transform:translateX(-100%); transition:transform .2s ease; }
  .side.open { transform:none; box-shadow:0 0 40px rgba(0,0,0,.4); }

  /* ── A2 (25-08-2026): TELEFONEN HAR ÉT NAVIGATIONSSYSTEM ────────────────
     Her stod `.topbar-burger { display:flex; }`. Den er FJERNET, ikke
     overskrevet: basis-reglen (linje 1353) er allerede `display:none`, så
     ét slettet declaration slukker knappen i hele intervallet — og fordi
     den kun nogensinde blev tændt herinde, kan ændringen pr. konstruktion
     ikke nå ≥769px. Skrivebordet er urørt, målt ved 1280×900 før og efter.

     🔴 HVORFOR. Appen havde TO navigationssystemer, og de kolliderede
     fysisk. Målt 24/25-08 ved 393×852 med tenantadmin/19 moduler:
       · 15 destinationer havde to indgange; fire af dem bar FORSKELLIGE
         navne (Dashboard/Hjem, Lager/Lager & optælling, Ordrer/Ordrer &
         tilbud, Virksomhedsopslag/Virksomheder), og omvendt pegede ét navn
         to steder hen («Kundedisplay» → /opsaetning/tablet-fjernstyring
         mod «Kundedisplay-styring» → /kundedisplay).
       · Begge systemer er `fixed z-index:60`. `.mnav` står senere i DOM'en,
         så Scan-cirklen lå 58×15 px oven i skuffens bruger-række og VANDT
         hit-testen: et tryk på «Alice A · Tenantadmin» åbnede /scan.
       · Alle 25 rækker i skuffen målte 36,25 px mod §31.6's 44.
     Tegningen har ingen skuffe: 0 træffere på burger/drawer/sidebar, ingen
     menu-glyf blandt 48 ikondefinitioner, nul menu-knapper i fem
     app-topbarer (positiv kontrol: `i-grid` findes).

     🔴 MARKUPPEN BLIVER STÅENDE, OG DET ER MED VILJE. `<button
     class="topbar-burger" onclick="…classList.toggle('open')">` bliver i
     base.html: den er skjult, ikke slettet — samme doktrin som resten af
     app-laget («elementerne står i DOM'en for ALLE, CSS bestemmer
     synligheden»). Det holder også `.side.open` ovenfor i live som en
     BRUGT regel; en sletning ville gøre den til død CSS.

     ── OG ÉN LINJE MERE END BESTILT, MED ET TAL BAG ──────────────────────
     `visibility:hidden` er IKKE kosmetik og ikke en dublet af transformen.
     Målt 25-08 på /dashboard ved 393px: den lukkede skuffe står på x=-236
     og har **36 fokuserbare elementer — 34 % af sidens 105** — som ALLE
     ligger i tab-ordenen. I dag er det forsvarligt, fordi burgeren kan
     afsløre dem. Uden burgeren ville de være permanent uåbnelige og
     stadig tabbare: en tastatur- eller skærmlæser-bruger ville vandre
     gennem 36 mål der ikke kan nås. `transform` alene fjerner dem ikke;
     `visibility:hidden` gør, og den nedarves — derfor står den på `.side`
     og ikke på hvert barn.

     🔴 `.side.open` FÅR SIN SYNLIGHED TILBAGE. Reglen kan ikke fyre uden
     burgeren, men et værn — og en fremtidig genåbning — må ikke møde en
     skuffe der er åben og usynlig. Tilstanden skal betyde det den siger. */
  .side { visibility:hidden; }
  .side.open { visibility:visible; }
}

/* ── App-glue: logo + ikon-justering i topnav (D.1). ────────────────────── */
.topnav-logo { display:block; height:26px; width:auto; }
/* Inline Lucide-ikoner i nav/menu får lidt luft til teksten. */
.topnav-link .lucide, .topnav-more summary .lucide { margin-right:.2rem; }

/* ── Score-bånd (kondital 0-100, §5 sanktioneret rød-undtagelse). ───────── */
.score-low    { color:var(--red-tx); }
.score-mid    { color:var(--amber-tx); }
.score-high   { color:var(--green-tx); }
.score-band-low  { background:var(--red-bg);   border-color:var(--red-bd); }
.score-band-mid  { background:var(--amber-bg); border-color:var(--amber-bd); }
.score-band-high { background:var(--green-bg); border-color:var(--green-bd); }

/* ============================================================================
   D.7 Del C — TÆTHEDSTOGGLE (komfort/tæt). body.dense sættes SERVER-SIDE fra
   'dense'-cookie (context_processor). Komfort er default (ingen klasse).
   Tæt = mindre tabel-font, tættere celle-padding, skjulte celle-undertekster,
   kompakte piller. Rammer kun lister/tabeller — ikke KPI/kort/knapper. ======= */
body.dense .data-table { font-size:12.8px; }
body.dense .data-table thead th { padding-top:4px; padding-bottom:4px; }
body.dense .data-table tbody td { padding-top:3px; padding-bottom:3px; }
/* Celle-undertekster (navn + by/type/nr) skjules i tæt tilstand. */
body.dense .cell-sub { display:none; }
/* Kompakte piller (§5) i tæt tilstand. */
body.dense .pill, body.dense .p-pill,
body.dense [class^="pill-"], body.dense [class*=" pill-"] {
  font-size:10px; padding:2px 8px;
}
/* Række-handlinger må stadig kunne ses/klikkes i tæt tilstand. */
body.dense .data-table .qa-cell { padding-top:2px; padding-bottom:2px; }

/* ── 🔴 §31.7-CELLEN ER IKKE EN HOVER-AFSLØRET RÆKKEHANDLING ────────────────
   REGRESSION, fundet og målt af sporet `tabelhuller` 25-08-2026, afgjort af
   App-dirigenten samme dag. Rettelsen ligger i sin EGEN commit, så andre
   spor kan cherry-picke den med `git cherry-pick -x`.

   HVAD DER SKETE. `app.src.css` sætter
   `@media (hover: hover) { .data-table tbody .qa-cell { opacity: 0 } }` —
   skrivebordets egen konvention for rækkehandlinger, med `tr:hover` og
   `tr:focus-within` som afsløring. Den er rigtig, den ejes af skrivebordet,
   og den bruges af flader ingen af os har målt. **Den røres ikke.**

   Men §31.7 KRÆVER `.qa-cell` på handlings-cellen: uden klassen falder cellen
   i mobil-lagets `td:not(…):not(.qa-cell){display:none}` og forsvinder
   sporløst på telefonen. Da to `.data-table`-flader blev båret over i
   rækkeformen, meldte de sig derfor — uden at nogen valgte det — ind i en
   SKRIVEBORDS-konvention. Målt 1280×900 i hviletilstand:

       flade                 synlige endepunkter før -> efter porten
       lager/leverandoerer   4 -> 3   («Gem» væk)
       opsaetning/sms        2 -> 0   (Redigér OG Arkivér væk)
       webshop/status        4 -> 4   (`table.tbl`, ikke `.data-table`)

   🔴 OG DEN ER USYNLIG FOR ETHVERT GEOMETRISK VÆRN. «Gem» målte **48×26**,
   `checkVisibility()` svarede **true**, `innerText` gav «Gem» — og
   tekstens rect indeholdt **3 unikke farver** mod nabocellens **183**.
   Nul blæk. Opacity påvirker hverken rect eller `checkVisibility()`.
   Vagt: `rapporter/tabelhuller/vaerktoej/skrivebordsblaek.py` og
   `tests/test_app_qacell_skrivebordsblaek.py`, som måler blækket med en
   nabocelle som positiv kontrol i SAMME skud.

   🔴 HVORFOR RETTELSEN STÅR PÅ §31.7-CELLEN OG IKKE PÅ KONVENTIONEN.
   Det er TREDJE gang samme klasse: `.cell-main` (forta-core.css:941) og
   `.app-rl-main` (:526) bor også uden for mobil-laget, og nu bar `.qa-cell`
   en skrivebords-betydning. **En markering vi kræver af mobil-hensyn må ikke
   bære en betydning på skrivebordet som ingen har valgt.** Selektoren er
   derfor `table[data-app-raekke]` — altså præcis de tabeller §31.7 har
   gjort krav på, og ingen andre.

   SPECIFICITET, IKKE RÆKKEFØLGE: (0,2,2) mod konventionens (0,2,1), så
   reglen vinder uanset at forta-core.css indlæses FØR app.css.
   `.rowact` er urørt: ordrelisten (`table.tbl`) afslører sine egne knapper
   ved hover via `.rowact{opacity:0}`, og dét er dens eget valg — reglen her
   rører kun CELLENS opacity, ikke wrapperens. */
@media (hover: hover) {
  table[data-app-raekke] tbody td.qa-cell { opacity: 1; }
}

/* ============================================================================
   D.8 — Opsætnings-hub (kort-grid). Rolige ink-toner; ingen brand-gradient
   (§6: gradient kun til primær-handling, ikke pynt). ========================= */
.setting-section { margin-bottom:1.75rem; }
.setting-section-h { font-size:11px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-500); margin:0 0 .6rem; }
.setting-grid { display:grid; gap:14px;
  grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); }
.setting-card { display:flex; align-items:flex-start; gap:.7rem;
  padding:.85rem .9rem; background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-radius:var(--radius-panel); text-decoration:none; color:inherit;
  transition:border-color .12s ease, box-shadow .12s ease; }
.setting-card:hover { border-color:var(--accent);
  box-shadow:0 2px 10px rgba(11,27,43,.06); }
.setting-card-ic { flex:0 0 auto; width:34px; height:34px; border-radius:9px;
  background:var(--ink-100); color:var(--ink-700); display:flex;
  align-items:center; justify-content:center; }
.setting-card-body { display:flex; flex-direction:column; gap:2px; min-width:0; }
.setting-card-title { font-weight:600; font-size:13.5px; color:var(--ink-800); }
.setting-card-desc { font-size:12.5px; color:var(--ink-500); line-height:1.35; }

/* ============================================================================
   D.4 — ⌘K-KOMMANDOPALET (§18). Kerne-komponent (deles af alle Forta-
   produkter). §7b-overlay: backdrop rgba(11,27,43,.55), centreret 600px-boks,
   16px radius, flydende skygge. En instans i base.html; controlleren i
   base.html styrer åbn/luk + tastatur. =====================================*/
.pal-overlay { position:fixed; inset:0; z-index:1100;
  background:rgba(11,27,43,.55); display:flex; align-items:flex-start;
  justify-content:center; padding:12vh 16px 16px; }
.pal-overlay[hidden] { display:none; }
.pal-box { width:100%; max-width:600px; max-height:70vh; display:flex;
  flex-direction:column; background:var(--bg-panel);
  border:1px solid var(--bd-panel); border-radius:var(--radius-panel);
  box-shadow:0 24px 60px rgba(11,27,43,.34); overflow:hidden; }

/* Søgefelt øverst (Lucide search + input + esc-hint). */
.pal-input-wrap { display:flex; align-items:center; gap:11px;
  padding:15px 18px; border-bottom:1px solid var(--ink-100); }
.pal-input-wrap .lucide { color:var(--ink-500); flex:0 0 auto; }
.pal-input { flex:1; min-width:0; border:0; outline:none; background:transparent;
  font-family:inherit; font-size:16px; color:var(--ink-900); }
.pal-input::placeholder { color:var(--ink-500); }
/* §31.6 (17-09-2026, spor trykmaal): feltet er paletten eneste maal og
   maalte 227x40 ved 393px — skrivefeltets egen hoejde, ikke wrapperens. Kun
   under 899px, saa skrivebordets palette er uroert (§31.2). Feltet VOKSER;
   wrapperens 15px polstring bliver staaende, saa ikon og esc-hint flugter. */
@media (max-width: 899px) {
  .pal-input { min-height:44px; }
}
.pal-esc { flex:0 0 auto; font-size:10px; color:var(--ink-500);
  border:1px solid var(--ink-200); border-radius:5px; padding:2px 6px;
  font-family:'JetBrains Mono',monospace; }

/* Scroll-område: resultater + handlinger. */
.pal-results, .pal-actions { overflow-y:auto; }
.pal-results { flex:0 1 auto; }
.pal-sec { padding:8px 8px 10px; }
.pal-sec + .pal-sec { border-top:1px solid var(--ink-100); }
.pal-sec-h { font-size:10px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-500); padding:4px 10px 6px; }

/* Række: ikon-chip + titel/metadata + type-mærkat + kbd-hint. */
.pal-row { display:flex; align-items:center; gap:11px; padding:8px 10px;
  border-radius:10px; text-decoration:none; color:inherit; cursor:pointer; }
.pal-row-ic { flex:0 0 auto; width:30px; height:30px; border-radius:8px;
  background:var(--ink-100); color:var(--ink-600); display:flex;
  align-items:center; justify-content:center; }
.pal-row-main { flex:1 1 auto; min-width:0; display:flex; flex-direction:column;
  gap:1px; }
.pal-row-title { font-size:13.5px; font-weight:600; color:var(--ink-800);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.pal-row-meta { font-size:12px; color:var(--ink-500);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* §23/10c/M12: type-mærkatet er nu en .tag-badge (6px, kantløs, ingen dot) —
   .pal-row-badge bærer kun palette-rækkens layout (flex-shrink-guard). */
.pal-row-badge { flex:0 0 auto; }
.pal-row-kbd { flex:0 0 auto; opacity:0; }
.pal-row-kbd kbd { font-size:10px; color:var(--ink-500);
  border:1px solid var(--ink-200); border-radius:5px; padding:1px 6px;
  font-family:'JetBrains Mono',monospace; }
/* Valgt/hover: accent-soft flade + accent-tonet ikon-chip + synlig kbd-hint. */
.pal-row.is-sel, .pal-row:hover { background:var(--accent-soft); }
.pal-row.is-sel .pal-row-ic, .pal-row:hover .pal-row-ic {
  background:var(--bg-panel); color:var(--accent-link); }
.pal-row.is-sel .pal-row-kbd { opacity:1; }
/* 🔴 SEKUNDAERTEKSTEN FOELGER FLADEN, IKKE RAEKKEN (17-09-2026, spor trykmaal).
   `--ink-500` er et PANEL-token: moerkt har det kun +0,40 over AA paa
   --bg-panel (forta-mobil.css skriver det selv). Paa den tonede valgte raekke
   dumper det. MAALT paa pixels, 393x852, Chromium 153, moerkt tema:
       .pal-row-meta «#100»  #7d94a9 paa #173f51   3,58   (AA 4,50)
       kbd «↵»               #7d94a9 paa #173f51   3,58
   Parret der er bygget til netop den flade er --accent-soft-tx paa
   --accent-soft, og det er en white-label-kontrakt der ALLEREDE er maalt over
   899 accenter (tests/test_accent_soft_tx_formel.py, laveste 4,99). Et lysere
   ink-token eller en hex ville kun vaere maalt for VORES turkis — fladen
   bevaeger sig med tenanten, saa teksten skal ogsaa goere det. */
.pal-row.is-sel .pal-row-meta, .pal-row:hover .pal-row-meta,
.pal-row.is-sel .pal-row-kbd kbd { color:var(--accent-soft-tx); }

/* Tom-tilstand i paletten (§17.7). */
.pal-empty { display:flex; flex-direction:column; align-items:center;
  text-align:center; padding:30px 16px; color:var(--ink-500); font-size:13px; }
.pal-empty p { margin:0; }

/* Footer-linje med tastatur-hints. */
.pal-foot { flex:0 0 auto; display:flex; flex-wrap:wrap; gap:14px;
  padding:9px 16px; border-top:1px solid var(--ink-100);
  background:var(--ink-50); }
.pal-hint { display:inline-flex; align-items:center; gap:4px; font-size:11px;
  color:var(--ink-500); }
.pal-hint kbd { font-size:10px; color:var(--ink-600); background:var(--bg-panel);
  border:1px solid var(--ink-200); border-radius:4px; padding:0 4px;
  font-family:'JetBrains Mono',monospace; }

/* ============================================================================
   B5 — GENVEJS-OVERLAY («?»). Samme §7b-flade som kommandopaletten ovenfor
   (backdrop rgba(11,27,43,.55), centreret boks, 16px radius, flydende
   skygge), men EGNE klasser: paletten er en handlings-flade med markering
   og hover, overlayet er en ren læse-flade. Fælles klasser ville binde de
   to sammen, og næste gang nogen ændrede palettens rækkehøjde, ville
   genvejslisten flytte sig med.
   ========================================================================= */
.gv-overlay { position:fixed; inset:0; z-index:1100;
  background:rgba(11,27,43,.55); display:flex; align-items:flex-start;
  justify-content:center; padding:9vh 16px 16px; }
.gv-overlay[hidden] { display:none; }
.gv-box { width:100%; max-width:620px; max-height:78vh; display:flex;
  flex-direction:column; background:var(--bg-panel);
  border:1px solid var(--bd-panel); border-radius:var(--radius-panel);
  box-shadow:0 24px 60px rgba(11,27,43,.34); overflow:hidden; }
.gv-box:focus { outline:none; }

.gv-head { flex:0 0 auto; display:flex; align-items:center; gap:12px;
  padding:14px 18px; border-bottom:1px solid var(--ink-100); }
.gv-title { flex:1 1 auto; margin:0; font-size:15px; font-weight:700;
  color:var(--ink-900); }
/* §31.6: ethvert interaktivt element skal kunne rammes med en tommel.
   44×44 gælder under breakpointet, men knappen er den samme flade — den
   får målet på alle bredder frem for at skifte størrelse ved 899px. */
.gv-luk { flex:0 0 auto; min-width:44px; min-height:44px; display:flex;
  align-items:center; justify-content:center; background:transparent;
  border:0; padding:0; cursor:pointer; }
.gv-luk kbd { font-size:10px; color:var(--ink-500);
  border:1px solid var(--ink-200); border-radius:5px; padding:2px 6px;
  font-family:'JetBrains Mono',monospace; }
.gv-luk:hover kbd { color:var(--ink-800); border-color:var(--ink-400); }

.gv-body { flex:1 1 auto; overflow-y:auto; padding:4px 0 8px; }
.gv-sec { padding:10px 18px 4px; }
.gv-sec + .gv-sec { border-top:1px solid var(--ink-100); margin-top:6px; }
.gv-sec-h { font-size:10px; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-500); padding-bottom:2px; }
.gv-sec-hvornaar { margin:0 0 8px; font-size:12px; color:var(--ink-500); }

.gv-liste { margin:0; }
/* Tasterne i egen kolonne: en genvejsliste læses ved at scanne NED ad
   tasterne, ikke ved at læse sætningerne. Kolonnen er fast bred, så
   kbd-blokkene står under hinanden i stedet for at danne en takket kant. */
.gv-raekke { display:flex; align-items:baseline; gap:14px;
  padding:5px 0; }
.gv-taster { flex:0 0 128px; display:flex; flex-wrap:wrap; align-items:center;
  gap:3px; margin:0; }
.gv-taster kbd { font-size:10.5px; color:var(--ink-700); background:var(--ink-50);
  border:1px solid var(--ink-200); border-radius:4px; padding:1px 5px;
  font-family:'JetBrains Mono',monospace; }
.gv-eller { font-size:10.5px; color:var(--ink-500); padding:0 1px; }
/* SLAAET FRA (18-09-2026): en genvej tenanten har slukket UDELADES IKKE af
   oversigten — en bruger der ikke kan se at «+» er slaaet fra, tror den er i
   stykker. Tasten staar derfor stadig, men gennemstreget, og raekken baerer
   et ord. To signaler frem for ét: gennemstregning alene er farve-/formsvag
   paa smaa kbd'er, og ordet alene lader tasten se aktiv ud.
   Kun `opacity` + `text-decoration` — ingen ny farve, saa §23-kontrasten er
   den samme som raekkens. */
.gv-taster.gv-fra kbd { text-decoration:line-through; opacity:.55; }
.gv-fra-maerke { font-size:10px; text-transform:uppercase;
  letter-spacing:.4px; color:var(--ink-500); }
.gv-hvad { flex:1 1 auto; min-width:0; margin:0; font-size:13px;
  color:var(--ink-800); }

.gv-foot { flex:0 0 auto; padding:9px 18px; border-top:1px solid var(--ink-100);
  background:var(--ink-50); }
.gv-hint { font-size:11px; color:var(--ink-500); }
.gv-hint kbd { font-size:10px; color:var(--ink-600); background:var(--bg-panel);
  border:1px solid var(--ink-200); border-radius:4px; padding:0 4px;
  font-family:'JetBrains Mono',monospace; }

/* Under breakpointet er 128px til tastekolonnen for meget af en 393px-skærm:
   beskrivelsen ville brække til tre linjer. Der stables de to i stedet. */
@media (max-width: 899px) {
  .gv-overlay { padding:6vh 12px 12px; }
  .gv-raekke { flex-direction:column; gap:3px; }
  .gv-taster { flex:0 0 auto; }
}

/* ============================================================================
   D.5 — FORTA CALL-OPKALDSKORT (§10). Kerne-komponent: indgående opkald vises
   som et flydende kort nederst-til-højre (afløser den gamle emoji-popup). §7-
   flade (16px, flydende skygge); pulserende gradient-ikon (Lucide phone) der
   respekterer prefers-reduced-motion. Kontekst-piller (forfalden faktura/åben
   ordre/aktiv sag) slås op på nummeret og injiceres i .call-card-context.
   ========================================================================= */
#call-pops-container { position:fixed; bottom:16px; right:16px; z-index:1000;
  display:flex; flex-direction:column; gap:10px; max-width:360px; }
.call-card { background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-radius:var(--radius-panel); padding:14px 16px;
  box-shadow:0 16px 44px rgba(11,27,43,.22); color:var(--ink-800);
  animation:callCardIn .24s ease-out; }
.call-card-top { display:flex; align-items:flex-start; gap:11px; }
.call-card-ic { flex:0 0 auto; width:38px; height:38px; border-radius:11px;
  background:var(--grad); color:#fff; display:flex; align-items:center;
  justify-content:center; position:relative;
  animation:callPulse 1.7s ease-in-out infinite; }
.call-card-ic .lucide { width:19px; height:19px; }
.call-card-body { flex:1 1 auto; min-width:0; }
.call-card-dir { font-size:10.5px; font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; color:var(--ink-500); }
.call-card-name { font-size:14px; font-weight:600; color:var(--ink-900);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.call-card-name small { font-weight:400; color:var(--ink-500); }
.call-card-num { font-family:'JetBrains Mono',monospace; font-size:12.5px;
  color:var(--ink-600); margin-top:1px; letter-spacing:-.01em; }
.call-card-close { flex:0 0 auto; background:none; border:0; cursor:pointer;
  color:var(--ink-500); padding:2px; display:flex; }
.call-card-close:hover { color:var(--ink-800); }
.call-card-close .lucide { width:16px; height:16px; }
/* C-4 (21-08): tegningens `.call-src` — linjen der forklarer hvorfor pillerne
   under den står der. Dæmpet og småt: den skal kunne LÆSES, ikke ses. Samme
   token og samme størrelse som `.call-card-dir`, så kortet har to
   sekundær-linjer i samme stemme og ikke tre forskellige. */
.call-card-src { font-size:10.5px; letter-spacing:.03em; color:var(--ink-500);
  margin-top:9px; }
/* Kontekst-piller (injiceres async fra fragment; tom → skjult). */
.call-card-context { display:flex; flex-wrap:wrap; gap:5px; margin-top:10px; }
.call-card-context:empty { display:none; }
.call-card-actions { display:flex; gap:6px; margin-top:12px; }
.call-card-actions .btn-primary, .call-card-actions .btn-secondary {
  flex:1 1 0; justify-content:center; text-decoration:none; font-size:12.5px;
  padding:6px 10px; white-space:nowrap; }
@keyframes callCardIn {
  from { transform:translateX(18px); opacity:0; }
  to   { transform:none; opacity:1; }
}
/* Pulserende halo på ikonet (accent-glow-ring der ånder). */
@keyframes callPulse {
  0%,100% { box-shadow:0 0 0 0 var(--accent-glow); }
  50%     { box-shadow:0 0 0 7px rgba(43,179,184,0); }
}
@media (prefers-reduced-motion: reduce) {
  .call-card { animation:none; }
  .call-card-ic { animation:none; }
}
/* Opgave-påmindelse (Fase G) genbruger kortet: amber STATISK ikon (ingen puls,
   det er ikke et live-opkald). */
.call-card--task .call-card-ic { background:var(--amber-bg); color:var(--amber-tx);
  animation:none; }

/* ============================================================================
   §23/10d — KOMPONENT-HULLER (H7/M13-M16/Del 5). Kerne-klasser der manglede
   ét sted: toast · tooltip · skeleton · disabled-tilstand · celle-trunkering,
   plus motion-standard (Del 5). select/pagination/tabs bor i app-laget hvor
   .form-* og D.7b-partial allerede definerer dem (samme cascade → undgår
   override).
   ========================================================================= */

/* M16: ny radius-token (store input-flader, fx POS-beløbsfelt). */
:root { --radius-input-lg:12px; }

/* H7 — Toast (§7b-panelsprog). BRUGES KUN VED FEJL — succes vises inline i
   selve fladen (swappet fragment/flash), aldrig som toast. Flydende nederst-
   højre; rød venstrekant markerer fejl-semantik. aria-live sættes i markup. */
.toast-stack { position:fixed; right:16px; bottom:16px; z-index:1200;
  display:flex; flex-direction:column; gap:8px; max-width:360px; }
.toast { display:flex; align-items:flex-start; gap:10px; padding:12px 14px;
  background:var(--bg-panel); border:1px solid var(--bd-panel);
  border-left:3px solid var(--red-tx); border-radius:var(--radius-panel);
  box-shadow:0 16px 44px rgba(11,27,43,.22); color:var(--ink-800);
  font-size:13px; animation:toastIn .18s ease-out; }
.toast-ic { flex:0 0 auto; color:var(--red-tx); display:flex; }
.toast-body { flex:1 1 auto; min-width:0; }
.toast-title { font-weight:600; color:var(--ink-900); }
.toast-close { flex:0 0 auto; background:none; border:0; cursor:pointer;
  color:var(--ink-500); padding:2px; display:flex; }
.toast-close:hover { color:var(--ink-800); }
@keyframes toastIn { from { transform:translateX(16px); opacity:0; }
  to { transform:none; opacity:1; } }

/* H7 — Tooltip (rent CSS, hover/fokus). Sæt .tt på en trigger med data-tt="…". */
.tt { position:relative; }
.tt::after { content:attr(data-tt); position:absolute; left:50%; bottom:calc(100% + 6px);
  transform:translateX(-50%) translateY(2px); white-space:nowrap;
  /* MØRKT TEMA (§20): --ink-800 INVERTERER (#1A2D40 -> #DEE9F1). En rå
     `color:#fff` gav derfor hvid tekst på næsten-hvid chip i mørk = 1,23:1
     — hver eneste tooltip i app'en var ulæselig. --bg-panel er modens flade
     og inverterer MED ink-skalaen: 14,06:1 i lys, 12,49:1 i mørk. */
  background:var(--ink-800); color:var(--bg-panel); font-size:11px; font-weight:500;
  padding:4px 8px; border-radius:6px; opacity:0; pointer-events:none;
  transition:opacity .12s ease, transform .12s ease; z-index:60; }
.tt:hover::after, .tt:focus-visible::after { opacity:1;
  transform:translateX(-50%) translateY(0); }

/* Kompakt «Markér som abonnement» (abovindue 30-09-2026). Forklaringer der
   stod under felterne, står bag et «i» ved etiketten.
   .abo-lab  etiketrækken: etiket · chips · «i». position:relative er
             ANKERET for tooltippen, så den får feltkolonnens bredde og
             ombryder — .tt ovenfor er nowrap og ville løbe ud af vinduet.
   .abo-i    en ÆGTE knap (fokusérbar; aria-label bærer hele teksten).
             Tooltippen vises ved hover, tastaturfokus og tryk (:focus —
             på touch får knappen fokus ved tryk). Knappen selv er ikke
             positioneret, så ::after placeres efter .abo-lab.
   .abo-chip «auto-fundet»/«auto»/«fra linjen» ved etiketten. */
.abo-lab { position:relative; display:flex; align-items:center; gap:6px;
  flex-wrap:wrap; margin-bottom:4px; min-height:20px; }
.abo-lab > .form-label { margin:0; }
.abo-chip { font-size:10.5px; font-weight:600; line-height:1.5;
  letter-spacing:0; text-transform:none; white-space:nowrap;
  background:var(--accent-soft); color:var(--accent-soft-tx);
  border-radius:999px; padding:0 7px; }
.abo-i { display:inline-grid; place-items:center; flex:0 0 auto;
  width:18px; height:18px; padding:0; margin:0; background:none; border:0;
  cursor:help; color:var(--ink-500); }
.abo-i > span { display:grid; place-items:center; width:16px; height:16px;
  border-radius:50%; border:1px solid var(--bd-panel); font-size:10px;
  font-weight:700; font-style:normal; line-height:1; }
.abo-i:hover > span, .abo-i:focus-visible > span { color:var(--accent-link);
  border-color:currentColor; }
.abo-i::after { content:attr(data-tip); position:absolute; left:0; right:0;
  top:calc(100% + 4px); white-space:normal; text-transform:none;
  letter-spacing:0; text-align:left; background:var(--ink-800);
  color:var(--bg-panel); font-size:12px; font-weight:500; line-height:1.4;
  padding:6px 9px; border-radius:6px; opacity:0; pointer-events:none;
  transition:opacity .12s ease; z-index:70; }
.abo-i:hover::after, .abo-i:focus::after { opacity:1; }
.abo-kommentar > summary { cursor:pointer; font-size:13.5px; font-weight:600;
  color:var(--accent-link); list-style:none; }
.abo-kommentar > summary::-webkit-details-marker { display:none; }
/* §31.6: under breakpointet er trykfladen 44×44, men den tegnede cirkel og
   etiketrækkens højde er de samme — den negative margin tager luften ud. */
@media (max-width: 899px) {
  .abo-i { width:44px; height:44px; margin:-13px; }
  .abo-kommentar > summary { min-height:44px; display:flex; align-items:center; }
}

/* H7 — Skeleton-loader (indlæsnings-pladsholder). Respekterer reduced-motion. */
.skeleton { display:block; border-radius:6px;
  background:linear-gradient(90deg, var(--ink-100) 25%, var(--ink-200) 37%,
  var(--ink-100) 63%); background-size:400% 100%;
  animation:skeletonSweep 1.4s ease-in-out infinite; }
.skeleton-text { height:.72em; margin:.28em 0; }
.skeleton-line { height:12px; }
@keyframes skeletonSweep { 0% { background-position:100% 50%; }
  100% { background-position:0 50%; } }

/* H7/M-input — Ensartet disabled-tilstand for ALLE kontroller: 45% opacity +
   not-allowed. Knapper med Tailwinds disabled:opacity-50 (0,2,0) beholder deres
   værdi; øvrige element-kontroller (0,1,0) rammes her. */
button:disabled, select:disabled, textarea:disabled, input:disabled,
.is-disabled, [aria-disabled="true"] {
  opacity:.45; cursor:not-allowed;
}

/* M13 — Celle-trunkering (opt-in): navn/tekst-celler får max-bredde + ellipsis.
   Sæt title="…" i markup for fuld værdi ved hover. Nr./dato/beløb bruger IKKE
   denne (de har egen nowrap-garanti). */
.cell-truncate { max-width:22ch; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }

/* Del 5 — Motion-standard. 150ms ease-out på hover/fokus for de almindelige
   interaktive flader (knapper/links/kort/kontroller). Menu/modal-scale-in
   (200ms .98→1 + fade) via keyframe nedenfor. prefers-reduced-motion nuller. */
.motion-pop { animation:motionPop .2s ease-out; }
@keyframes motionPop { from { transform:scale(.98); opacity:0; }
  to { transform:scale(1); opacity:1; } }
@media (prefers-reduced-motion: reduce) {
  .toast, .skeleton, .motion-pop { animation:none; }
  .tt::after { transition:none; }
}

/* §32 — Søg-og-vælg-felter: markeringen. Én klasse for ALLE resultatlister
   (ul>li, table>tr, div>button), sat af static/js/soegefelt.js. Hover og
   tastatur sætter den SAMME klasse — derfor kan de to aldrig divergere, og
   der kan ikke opstå to markerede eller nul markerede med listen åben.
   currentColor-kanten sikrer at markeringen også ses i tvungen-kontrast-tilstand,
   hvor baggrundsfarver bliver kasseret. */
.soeg-aktiv, .soeg-aktiv > td {
  background: var(--tbl-hover, #e0edff) !important;
}
.soeg-aktiv {
  box-shadow: inset 3px 0 0 0 var(--accent, #1E4A7A);
  border-radius: .25rem;
}
@media (forced-colors: active) {
  .soeg-aktiv { outline: 2px solid currentColor; outline-offset: -2px; }
}
/* §32.4 — advarslen BÆRER fokus efter et swap, så ↵ ikke kan bære brugeren
   forbi den. Fokus sættes PROGRAMMATISK af static/js/fokus.js, og browsere
   tegner ikke :focus-visible for programmatisk fokus på et tabindex="-1"-
   element. Uden denne regel ville brugeren stå et sted uden at kunne se hvor —
   og en advarsel man ikke kan se man står på, er stadig ikke en advarsel.
   Derfor :focus, ikke :focus-visible.

   🔴 outline-offset er NEGATIV, og det er ikke kosmetik. Målt 07-08-2026:
   advarsels-boksene har hårdkodede lyse baggrunde (#FEE2E2 / #FEF3C7) der
   IKKE følger temaet, mens panelet bagved gør. Med en POSITIV offset ligger
   ringen uden for boksen — i lys mode på #EBF4F6 (7,44:1, fint), men i dark
   mode på #192d40, hvor currentColor (#991B1B) kun giver 1,70:1. Den ville
   være usynlig præcis dér hvor den betyder mest. Med -2px ligger ringen på
   boksens EGEN lyse flade og måler 6,80:1 (rød) og 6,37:1 (gul) i BEGGE
   modes, fordi boksens farver er tema-uafhængige. Samme greb som .soeg-aktiv
   bruger ovenfor. currentColor holder desuden i tvungen-kontrast-tilstand.

   Den rigtige langsigtede rettelse er at tokenisere de to advarsels-bokse så
   de følger temaet — det er en CC.7-opgave, ikke en §32-opgave. */
[data-advarsel]:focus {
  outline: 2px solid currentColor;
  outline-offset: -2px;
  border-radius: .25rem;
}
/* Tom liste og indlæsende liste — samme boks-geometri som en fyldt liste, så
   feltet ikke hopper når svaret lander. */
.soeg-tom, .soeg-indlaeser {
  padding: .5rem .6rem; font-size: .82rem; font-style: italic;
  color: var(--ink-3, #64748b);
}
.soeg-indlaeser::after {
  content: ""; display: inline-block; width: .5rem; height: .5rem;
  margin-left: .4rem; border-radius: 50%;
  background: currentColor; animation: soegPuls 1s ease-in-out infinite;
}
@keyframes soegPuls { 0%, 100% { opacity: .25; } 50% { opacity: .9; } }
@media (prefers-reduced-motion: reduce) {
  .soeg-indlaeser::after { animation: none; opacity: .6; }
}

/* ── E2.3: foto-optagelsens to veje (kerne-komponent, begge bredder) ─────────
   Knapperne på service-fanen er <label>-elementer med et sr-only
   <input type="file"> indeni — se rationalet i _tab_service.html. To ting
   følger IKKE af .btn-klasserne, fordi de er skrevet til <button>:

   1) cursor. En <button> får pointer af browseren; en <label> får det ikke,
      og en knap der ikke ser klikbar ud bliver ikke trykket på.

   2) fokusringen. .btn-secondary/.btn-ghost tegner deres ring på :focus —
      men fokus lander på det skjulte input, ikke på labelen. Uden denne regel
      ville tastaturbrugeren stå på kontrollen uden at kunne se hvor, præcis
      som §32.4-advarslen beskriver. Samme greb som [data-advarsel]:focus:
      currentColor (holder i tvungen kontrast) og NEGATIV offset, så ringen
      ligger på knappens egen flade frem for på panelet bagved — knapperne
      er runde (.btn er rounded-full), og en positiv ring ville skære hjørner. */
[data-foto-knap] { cursor: pointer; }
[data-foto-knap]:focus-within {
  outline: 2px solid currentColor;
  outline-offset: -2px;
}

/* ═══ E4 fase 2: SCAN-SKÆRMEN (/scan) ═══════════════════════════════════════
   Prototypens skærm 3. Reglerne står i KERNEN og ikke i mobil-laget, og det
   er et bevidst valg med en grund: /scan er en RUTE, ikke en mobil-variant af
   en skrivebordsside. Den kan åbnes på en pc med webcam, og en flade der kun
   havde stil under 899px ville dér stå som en stak nøgne divs.

   §31.2's garanti ("desktop bit-identisk") holdes stadig: hver eneste selektor
   herunder er NY. Ingen eksisterende side har et .cam, et .reticle eller et
   .scan-traf, så ingen eksisterende side kan ændre udseende af dette.

   🔴 FARVER: PROTOTYPEN ER FACIT, IKKE TOKENERNE (rettet 15-08-2026).
   Første udgave portede med husets tokens (--ink-900, --border) og med ren
   hvid på hint-teksten, begrundet med at "et token ville følge temaet og gøre
   teksten ulæselig". Det var en RATIONALISERING af et gæt: prototypen bruger
   #B9D3DE, en dæmpet blågrå, og en flerstops-gradient hvor jeg havde en flad
   farve. Kamera-viewporten er ikke en tema-flade — den er et fast mørkt
   kamerabillede i BEGGE temaer, og prototypen sætter dens værdier direkte.
   Hver rå værdi herunder står ORDRET i prototypen; det er låst af
   test_scan_skaermen_bruger_kun_prototypens_egne_vaerdier. */

/* 🔴 SIDEN SKAL FYLDE, ELLERS FYLDER VIEWPORTEN IKKE.
   Prototypen scoper containeren til skærmen — `#scr-scan .app-scroll{display:
   flex;flex-direction:column;…}` — og `.cam{flex:1}` strækker sig i DEN. Første
   udgave portede kun reglen på `.cam` og glemte containeren den hænger på;
   resultatet var et 330px viewfinder med ~380px tomt under kortet. Målt på et
   skærmbillede, ikke i en test.
   Porteret som en container-regel og ikke som en ny højde på `.cam`: prototypen
   har allerede en løsning, og en `min-height` med et gættet tal ville være min. */
main.page-shell--scan { display: flex; flex-direction: column; }
/* ══ DRIFTSBJÆLKEN (18-08-2026) ════════════════════════════════════════════
   En kritisk driftsalarm skal ikke kunne overses. Bjælken ligger FØRST i
   .main (over topbaren), fuld bredde, og den er den eneste flade i huset der
   har lov at være mættet rød.

   🔴 HVORFOR IKKE .p-due/--red-bg-parret. Semantik-pillerne er BLEGE med rød
   tekst — rigtigt for en status i en tabel, forkert for det her: bjælken skal
   vinde over alt andet på skærmen, og en bleg rosa flade taber til en topbar.
   Den mættede farve er derfor et valg, ikke en forglemmelse.

   To niveauer, to udseender, med vilje:
     .driftsalarm-kritisk  mættet rød   — vi VED der er noget galt
     .driftsalarm-ukendt   bleg ravgul  — vi ved at vi ikke kan se det
   De to må ikke kunne forveksles på afstand; "ukendt" er hverken rød eller
   grøn, og et fælles udseende ville gøre den ene til den anden.

   Mørk tilstand: 'ukendt' bruger --amber-*-tokens, som body.dark selv
   overskriver. Den røde er skrevet direkte (ikke som afledt token), netop
   fordi et token defineret i :root ikke ville se body.dark's override. */
.driftsalarm {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid transparent;
  font-size: 14px; line-height: 1.4;
}
.driftsalarm-kritisk {
  background: #B3261E; color: #fff; border-bottom-color: #8C1D18;
}
body.dark .driftsalarm-kritisk { background: #A32019; border-bottom-color: #7A170F; }
.driftsalarm-ukendt {
  background: var(--amber-bg); color: var(--amber-tx);
  border-bottom-color: var(--amber-bd);
}
.driftsalarm-ic { flex: 0 0 auto; padding-top: 1px; }
.driftsalarm-tekst { flex: 1 1 auto; min-width: 0; }
.driftsalarm-titel { display: block; font-weight: 700; letter-spacing: .01em; }
.driftsalarm-liste { margin: 4px 0 0; padding-left: 18px; }
.driftsalarm-liste li { margin: 1px 0; }
/* Ingen ellipsis: en afkortet fejltekst er en fejltekst man ikke kan handle
   på, og bjælken må hellere blive høj end uforståelig. */
.driftsalarm-liste li b { font-weight: 700; }
.driftsalarm-alder { display: block; margin-top: 4px; opacity: .85; font-size: 13px; }
.driftsalarm-link {
  flex: 0 0 auto; align-self: center; white-space: nowrap;
  color: inherit; text-decoration: underline; font-weight: 600;
}
.driftsalarm-luk {
  flex: 0 0 auto; align-self: flex-start;
  background: none; border: 0; cursor: pointer; color: inherit;
  opacity: .8; padding: 2px; line-height: 0; border-radius: 6px;
  /* 🔴 Tommelmål. Knappen er lille NOK til ikke at invitere til et
     reflekstryk, men stor nok til at kunne rammes bevidst. */
  min-width: 28px; min-height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
}
.driftsalarm-luk:hover { opacity: 1; }
.driftsalarm-luk:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
@media (max-width: 899px) {
  .driftsalarm { flex-wrap: wrap; padding: 10px 12px; }
  /* §31.6 (17-09-2026, spor trykmaal): linket maalte 157x20 ved 393px i
     begge temaer — en understreget tekstlinje, ikke et maal. Det VOKSER til
     44 px; teksten klippes ikke og ombryder stadig ikke (`white-space:
     nowrap` ovenfor). Den foldede forms eget link har en mere specifik regel
     laengere nede, som ogsaa baerer maalet. */
  .driftsalarm-link { align-self: flex-start; min-height: 44px; }
  /* D2 (11-09-2026, Fables anmeldelse): den foldede form paa telefonen
     (base.html). Summary er HELE den trykbare raekke og mindst 44 px (§31.6);
     den er stadig roed, fuld bredde og foerst i .main — ikke et badge.
     Reglerne staar HER og ikke i forta-mobil.css, fordi bjaelkens egne
     klasser bor i denne fil (tests/test_driftsalarm_bjaelke.py maaler dem her),
     og fordi de alle ligger i dette @media-lag, saa skrivebordet ikke ser dem. */
  .driftsalarm-fold > .driftsalarm-sammen {
    display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px;
    min-height: 44px; cursor: pointer; list-style: none;
  }
  .driftsalarm-fold > .driftsalarm-sammen::-webkit-details-marker { display: none; }
  .driftsalarm-antal { font-weight: 700; white-space: nowrap; }
  .driftsalarm-fold > .driftsalarm-sammen > .lucide {
    margin-left: auto; flex: 0 0 auto; transition: transform .15s;
  }
  .driftsalarm-fold[open] > .driftsalarm-sammen > .lucide { transform: rotate(180deg); }
  /* inline-flex og ikke inline-block: denne regel er (0,2,0) og slaar
     `.driftsalarm-link`s egen ovenfor, saa det er HER tommelmaalet skal staa
     for det link telefonen faktisk viser. margin-top 6 -> 0: de 44 px giver
     selv ~12 px luft over teksten, saa den visuelle afstand til listen er
     ikke mindre end foer. */
  .driftsalarm-fold > .driftsalarm-link {
    display: inline-flex; align-items: center; min-height: 44px; margin-top: 0;
  }
  /* Maalt 11-09 paa 7b845344a ved 393x852: den foldede bjaelke var 138 px,
     fordi <details> tog hele bredden og skubbede luk-knappen ned paa sin EGEN
     raekke (summary y=43, luk y=99). `flex: 1 1 0` lader den give plads, saa
     ikon · summary · luk staar paa én raekke. Og luk-knappen var 28x28 — under
     §31.6's 44 paa en telefon. Dens FUNKTION og titel er uaendrede («Skjul i
     denne session»); kun trykfladen er vokset. */
  .driftsalarm-fold { flex: 1 1 0; }
  .driftsalarm-luk { min-width: 44px; min-height: 44px; }
  /* LIGGENDE TELEFON (28-09-2026, spor smaafejl): KOMPAKT BJAELKE.
     Maalt 28-09 paa 9c2ca6688 ved 852x393 som tina (tenantadmin, «KRITISK
     ALARM: Konkurs registreret»): bjaelken var 0-65 px, og kassens
     betalingsfliser stod ved ankomst 316-379 mod navets top 341 — halvt
     under folden (rapporter/liggende/, J6-resten).
     Summary og luk-knappen ER allerede 44 px (§31.6); de 2x10 px polstring
     omkring dem er luft, og luft er det en 393 px hoej skaerm ikke har.
     Bjaelken bliver 44 px + kanten. Den er stadig roed, fuld bredde, foerst
     i .main og kan ikke overses — kun luften er vaek. Ikonet flyttes ned, saa
     det staar midt for summary-raekken (20 px ikon i 44 px: 12 px).
     `html.liggende` saettes af static/js/liggende.js; reglerne staar i DETTE
     eksisterende lag og ikke som en ny @media (§31.2 i forta-mobil.css, og
     bjaelkens klasser bor i denne fil). Vagt: tests/test_app_smaafejl_browser.py. */
  html.liggende .driftsalarm { padding-top: 0; padding-bottom: 0; }
  html.liggende .driftsalarm-ic { padding-top: 12px; }
  /* 🔴 KOMPAKT BJAELKE ALENE RAEKKER IKKE. Maalt efter de to regler ovenfor:
     bjaelken 65 -> 45 px, fliserne 296-359 mod navets top 341 — stadig
     18 px under folden, og Scan-ringen staar 7 px over navet (334).
     Resten tages af den TOMME luft der ligger mellem topbaren og fladen,
     og KUN naar bjaelken staar der (`.driftsalarm ~` — den er soeskende til
     <main> i .main), saa en side uden alarm er bit-identisk med i dag:
       · <main>s top-polstring 24 -> 8 (app.src.css `py-6`)
       · sidehovedets 12 px raekke-gap under den TOMME titel-<div>
         (h1 og undertitel er skjult af `data-app-titel-dublet`, se
         forta-mobil.css); `="kun-titel"` har en synlig undertitel og er
         undtaget, saa den ikke klistres til handlingerne. */
  html.liggende .driftsalarm ~ main.page-shell { padding-top: 8px; }
  html.liggende .driftsalarm ~ main.page-shell .page-header[data-app-titel-dublet]:not([data-app-titel-dublet="kun-titel"]) { gap: 0; }
}

/* appgennemgang3 J4 (28-09-2026): lagermodtagelsens «Manuel linje»-felt.
   Stod som `style="min-width:22rem"` i modtag_session.html og stak 27-60 px
   ud over en telefon; som klasse kan mobil-laget loefte den
   (forta-mobil.css, samme navn). Skrivebordet er uaendret. */
.modtag-manuel-felt { min-width: 22rem; }


/* ── «Vis som» (28-09-2026, tech/vis_som.py) ─────────────────────────────
   Banneret staar oeverst paa HVER side mens en tenantadmin ser Forta som en
   bruger. Farven er bevidst husets eneste STRIBEDE flade og ens i lyst og
   moerkt tema: den maa ikke kunne forveksles med en statusbesked (gul
   `.alert-warning`) eller med temaets accent. Kontrast maalt med WCAG-formlen:
   #1A1200 paa det lyseste stribe-stop #F5B400 = 10,09:1, paa #E8A600 = 8,74:1;
   hvid paa knappens #1A1200 = 18,58:1.
   `position: sticky` i dokumentets top — ikke fixed — saa den skubber
   skallen ned i stedet for at ligge hen over topbaren. */
.vis-som-banner { position: sticky; top: 0; z-index: 1000; display: flex;
  align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 6px 16px;
  background: repeating-linear-gradient(135deg, #F5B400 0 14px, #E8A600 14px 28px);
  color: #1A1200; border-bottom: 2px solid #1A1200; font-size: 14px;
  line-height: 1.3; }
.vis-som-banner-ikon { display: inline-flex; }
.vis-som-banner-tekst { flex: 1 1 auto; min-width: 0; }
.vis-som-banner-tekst strong { font-weight: 700; }
.vis-som-banner-kun { font-weight: 500; }
.vis-som-banner-besked { font-weight: 700; }
.vis-som-banner-form { margin: 0; }
.vis-som-afslut { min-height: 44px; padding: 0 16px; border: 0;
  border-radius: 10px; background: #1A1200; color: #FFFFFF; font-weight: 700;
  font-size: 14px; cursor: pointer; }
.vis-som-afslut:focus-visible { outline: 3px solid #FFFFFF;
  outline-offset: 2px; }
/* Bekræftelses-siden (users/vis_som_start.html). */
.vis-som-start { display: flex; justify-content: center; padding: 3rem 1rem; }
.vis-som-start > .card { width: 100%; max-width: 440px; }
.vis-som-start-hoved { text-align: center; }
.vis-som-start-hoved h2 { margin: 0 0 .25rem; }
.vis-som-start-ikon { display: inline-flex; color: var(--ink-500);
  margin-bottom: .5rem; }
.vis-som-start-regler { margin: 0 0 1rem; padding-left: 1.2rem; font-size: 14px;
  color: var(--ink-700); }
.vis-som-start-regler li { margin: .25rem 0; }
.vis-som-start-kode { font-size: 1.6rem; letter-spacing: .4rem;
  text-align: center; }
.vis-som-start-knapper { display: flex; gap: 8px; justify-content: flex-end; }
.vis-som-knap { display: inline-flex; align-items: center; }
.vis-som-start-bekraeft { display: flex; gap: 10px; align-items: flex-start;
  font-size: 14px; font-weight: 600; }
.vis-som-start-bekraeft input { margin-top: 3px; }
/* «udført af Tina som Alice» i historikken (aendringer + audit-log). */
.vis-som-som { color: var(--ink-600); font-style: italic; }
/* Brugerlistens handlingscelle: med oejet som tredje handling broed
   «Rettigheder · Moduler» over to linjer ved 1280 (maalt 28-09 i skud).
   Scopet til cellen der BAERER oejet, saa ingen anden tabel roeres. */
td.qa-cell:has(> .vis-som-knap) { white-space: nowrap; }


/* 🔴 SKRIV IKKE NYE REGLER EFTER SCAN-AFSNITTET HERUNDER.
   `test_e4_scan_skaerm.test_scan_skaermen_bruger_kun_prototypens_egne_vaerdier`
   slicer `core[core.index('.scan-side'):]` — altså fra scan-afsnittet og
   HELE VEJEN TIL FILENS SLUTNING — og kræver at hver rå farve i det udsnit
   står ordret i scan-prototypen. Alt man føjer til i bunden af filen
   havner derfor inde i scan-skærmens vindue og bliver rødt, uanset hvilken
   flade reglen hører til. Målt 18-08-2026: driftsbjælkens fire røde
   nuancer blev meldt som «farver på scan-skærmen».
   Nye afsnit hører derfor OVER denne linje. */

main.page-shell--scan > .scan-side { flex: 1 1 auto; }

.scan-side { display: flex; flex-direction: column; gap: 13px; }

/* Viewporten. flex:1 + min-height er prototypens egne tal: den skal FYLDE,
   for et kamerabillede man skal sigte med kan ikke være en miniature.
   Radius er 20px og IKKE --radius-panel (16px): prototypen sætter den
   eksplicit blødere end husets paneler. Kanten er .14 og ikke tokenets .16 —
   også et bevidst valg i tegningen. */
.cam {
  flex: 1 1 auto;
  min-height: 330px;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 20px;
  border: 1px solid rgba(120, 190, 210, .14);
  background: linear-gradient(180deg, #0b141d 0%, #101c27 45%, #0a1118 100%);
}

/* Den radiale teal-glød bag sigtekornet. Den var UDELADT i første udgave, og
   det er den der løfter midten af viewporten ud af det flade mørke. Ligger som
   ::after, altså over videoen og under sigtekornet — 10 % teal er for svagt til
   at forstyrre en stregkode, og kontinuiteten mellem hvile og live er værd
   mere end de sidste procent kontrast. */
.cam::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(300px 200px at 50% 45%,
              rgba(43, 179, 184, .10), transparent 70%);
}

/* Videoen fylder rammen og beskæres frem for at strækkes — et forvrænget
   kamerabillede gør stregkoden sværere at ramme, ikke lettere. Skjult indtil
   kameraet faktisk kører, så en tom sort <video> ikke ligner et frosset
   billede. */
.cam-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .2s ease;
}
.cam.cam-on .cam-video { opacity: 1; }

/* Sigtekornet: fire hjørner, ingen ramme hele vejen rundt. Prototypens greb —
   en lukket firkant lægger sig som en maske over etiketten, fire hjørner
   peger på hvor den skal ligge uden at dække den. */
.reticle { width: 230px; height: 230px; position: relative; z-index: 2; }
.reticle i {
  position: absolute; width: 36px; height: 36px;
  border: 3px solid var(--accent-bright);
  opacity: .95;
}
.reticle i:nth-child(1) { top: 0; left: 0;  border-right: none; border-bottom: none; border-radius: 12px 0 0 0; }
.reticle i:nth-child(2) { top: 0; right: 0; border-left: none;  border-bottom: none; border-radius: 0 12px 0 0; }
.reticle i:nth-child(3) { bottom: 0; left: 0;  border-right: none; border-top: none; border-radius: 0 0 0 12px; }
.reticle i:nth-child(4) { bottom: 0; right: 0; border-left: none;  border-top: none; border-radius: 0 0 12px 0; }

.scanline {
  position: absolute; left: 10px; right: 10px; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--accent-bright), transparent);
  /* 🔴 Gløden ER det der gør linjen til en laser. Uden den er den en streg —
     den var udeladt i første udgave, og det var den enkeltrettelse der
     betyder mest for om fladen ligner tegningen. */
  box-shadow: 0 0 14px rgba(67, 228, 228, .8);
  animation: scanmove 2.4s ease-in-out infinite;
}
@keyframes scanmove {
  0%, 100% { top: 14px; }
  50%      { top: calc(100% - 16px); }
}
/* §32: en linje der kører frem og tilbage i det uendelige er præcis den slags
   bevægelse reduced-motion findes for. Sigtekornet bliver stående — det er
   bærende information, animationen er ikke. */
@media (prefers-reduced-motion: reduce) {
  .scanline { animation: none; top: 50%; }
}

.cam-hint {
  position: absolute; bottom: 16px; left: 0; right: 0;
  text-align: center; z-index: 3;
  font-size: 12.5px; font-weight: 600; color: #B9D3DE;
  text-shadow: 0 2px 8px rgba(0, 0, 0, .7);
}

/* "Tænd kameraet" står UNDER sigtekornet, ikke i det.
   🔴 To forsøg før dette. Først midt i viewporten — så viste hvileskærmen en
   knap oven på sigtekornet som tegningen ikke har. Så flyttet til bottom:46px,
   hvor den landede PRÆCIS på sigtekornets nederste hjørner, fordi viewporten
   dengang kun var 330px høj. Begge fejl var usynlige i en test og tydelige på
   et billede.
   Nu: sigtekornet er 230px centreret, så halvdelen af den frie plads under det
   er `calc(50% - 115px)`; knappen sidder midt i den luft, og afstanden holder
   uanset hvor høj viewporten bliver. Mindre knap (btn-sm) så den heller ikke
   dominerer på en lav skærm. */
.cam-start {
  position: absolute;
  bottom: calc((50% - 115px) / 2);
  z-index: 4;
  white-space: nowrap;
}

.scan-manuel { display: flex; gap: 8px; }
.scan-manuel .form-input { flex: 1 1 auto; min-width: 0; }
/* "Slå op" brød over to linjer ("Slå" / "op") — knappen krympede fordi feltet
   tog al pladsen. Set på et billede. `flex:0 0 auto` + nowrap giver den dens
   egen bredde tilbage. */
.scan-manuel .btn-secondary { flex: 0 0 auto; white-space: nowrap; }

/* ── SCANNINGENS KONTEKST OG DENS SPOR (23-08-2026) ────────────────────────
   To smaa flader, begge PROVISORISKE i formen. Andreas godkendte formen paa
   ordene «goer som du anbefaler saa ser vi om det ikke er fint naar vi tester»
   — teksten og udseendet er altsaa MENT at kunne aendre sig efter en
   afproevning paa telefonen, og en senere aendring er ikke en regression.

   🔴 Ingen af dem har et modstykke i prototypen. Tegningens eneste banner er
   `.push`, en svaevende push-notifikation, og den form er BEVIDST ikke laant:
   et automatisk spring er ikke noget der kom udefra, og laante vi `.push`
   ville en navigation brugeren selv udloeste ligne en notifikation.

   Begge bruger husets tokens (ingen nye farver), saa lys/moerk foelger med
   uden en anden regel. */

/* Konteksten paa /scan: «hvad kommer der til at ske naar jeg scanner».
   En kontekst man ikke kan se, er en man ikke kan fortryde. */
.scan-kontekst {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; border-radius: 12px;
  background: var(--bg-panel); border: 1px solid var(--bd-panel);
  font-size: 12.5px; color: var(--ink);
}
.scan-kontekst > span { flex: 1 1 auto; min-width: 0; }
/* 🔴 `--accent-link`, OG BEGGE TILSTANDE ER MAALT (23-08-2026).
   Foerste udgave brugte `--accent`: #1E96B0 giver **3,47:1** paa den lyse
   flade — AA-tekst kraever 4,50. Praecis det tal er allerede betalt for i
   CLAUDE.md paa primaerknappens gradient; samme farve, samme fejl, ny flade.
   Anden udgave brugte `--accent-strong` og var VAERRE: den er #15495D i lys
   (9,80:1 ✅) men opløses ogsaa til #15495D i MOERK, hvor den giver 1,91:1.
   En rettelse der kun maales i den ene tilstand flytter bruddet.
   `--accent-link` er per-tilstand og bestaar begge:
       lys   #1B567E  ->  7,84:1 (paa #FFFFFF) · 7,00:1 (paa #EDF3F6)
       moerk #b2e7e8  -> 11,35:1 (paa #12263A) · 13,78:1 (paa #081320)
   Instrumentet blev kalibreret mod `test_dark_kontrast`s egne 3,47 FOER de
   nye tal blev maalt. */
.scan-kontekst svg { flex: 0 0 auto; color: var(--accent-link); }
/* §31.6: ethvert interaktivt element under breakpointet er >= 44px. Krydset
   er fladens ene vej ud af konteksten og skal kunne rammes med en tommel. */
.scan-kontekst-luk {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  margin: -9px -12px -9px 0;   /* tommelmaalet maa ikke goere raekken hoejere */
  color: var(--ink-2);
}

/* Sporet paa DESTINATIONEN: «hvordan kom jeg hertil, og hvordan kommer jeg
   tilbage». Diskret med vilje — den skal kunne laeses, ikke laegge beslag paa
   toppen af en side brugeren er kommet for at se. */
.scan-spor {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 12px; padding: 7px 11px; border-radius: 10px;
  background: var(--bg-panel); border: 1px solid var(--bd-panel);
  font-size: 12px; color: var(--ink-2);
}
.scan-spor svg { flex: 0 0 auto; }
.scan-spor a {
  margin-left: auto;
  display: inline-flex; align-items: center; min-height: 44px;
  margin-top: -7px; margin-bottom: -7px;
  /* Samme maaling som `.scan-kontekst svg` ovenfor — se noten dér. */
  color: var(--accent-link); font-weight: 600; text-decoration: none;
}
.scan-spor a:hover, .scan-spor a:focus-visible { text-decoration: underline; }

/* Prototypens `.mcard.scan-res` — kortets egen afstand. `.scan-side { gap }`
   dækker afstanden opad; margin-bottom:0 hindrer at husets kort-margin lægger
   luft under det sidste element på skærmen. */
.scan-res { margin-bottom: 0; }

.scan-traf + .scan-traf {
  border-top: 1px solid var(--bd-panel);
  margin-top: 12px; padding-top: 12px;
}
/* Rækken: prototypens `.scan-res .rr` og `.scan-res .thumb`, tal for tal.
   Thumb'en var 38px med et gråt ikon i første udgave; tegningen har 44px og et
   TEAL ikon, og de to ting er det man ser først på kortet. */
.scan-traf-top { display: flex; align-items: center; gap: 12px; }
/* 🔴 PROTOTYPENS SELEKTOR ER `.scan-res .thumb` — gentaget HER og ikke kun i
   blok-overskriften ovenfor, fordi den der springer ind på `.scan-thumb` ikke
   ser overskriften. Navnet er husets (samme oversættelse som dashboard.html
   bruger `.kpi` for prototypens `.stat`); VÆRDIERNE er tegningens.
   Korrespondancen bæres to andre steder og skal blive ved med at passe:
     · `tests/test_dark_kontrast.py`s ALLOW-post for `.scan-thumb` begrunder
       sig med at prototypen sætter `--accent` på `.scan-res .thumb`
     · `tech/templates/scan.html`s hoved forklarer hvorfor navnene er husets */
.scan-thumb {
  flex: 0 0 44px;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 12px;
  background: var(--bg-panel-2);
  border: 1px solid var(--border);
  color: var(--accent);
}
.scan-traf-tekst { min-width: 0; flex: 1 1 auto; }
/* .rl-main */
.scan-titel { font-size: 13px; font-weight: 600; color: var(--ink); line-height: 1.3; }
/* Prototypen sætter TO klasser på serienummeret (rl-sub og mono-klassen), og
   sidstnævntes 11.5px vinder over rl-sub's 11px fordi den står senere i filen.

   🔴 Klassenavnene er skrevet UDEN punktum med vilje. `test_doede_css_klasser`
   læser denne fil RÅT — den stripper ikke kommentarer — så et `.navn` i en
   kommentar tæller som en DEFINITION. Min første formulering skrev punktummet
   og "betalte" dermed en gæld i registret som ikke er betalt: klassen bruges
   stadig i indkoeb/ og abonnementer/ uden nogen regel. Meldt som fund. */
.scan-under {
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: -.02em;
  color: var(--ink-2); margin-top: 2px;
  overflow-wrap: anywhere;
}
.scan-traf-tal {
  flex: 0 0 auto;
  display: flex; flex-direction: column; align-items: flex-end; gap: 3px;
}
.scan-pris {
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: -.02em;
  font-weight: 600; color: var(--ink);
  white-space: nowrap;
}
/* Prototypen sætter lager-pillen ned til 9.5px inline — mindre end den
   almindelige pille, så den ikke konkurrerer med prisen over sig. */
.scan-traf-tal .pill { font-size: 9.5px; }

/* To knapper på række, lige brede — prototypens .scan-btns. Formen om
   "Læg i kurv" er kun indpakning og må ikke klemme knappen sammen. */
.scan-btns {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 10px; margin-top: 12px;
}
/* 🔴 :not([hidden]) er IKKE pynt. `display:contents` her ville slå UA-reglen
   `[hidden]{display:none}` ud på specificitet, og en skjult "Læg i kurv"-form
   ville tegne sin knap alligevel — altså præcis den knap vi har besluttet at
   en bruger uden POS-adgang ikke må se. Et skjul der afhænger af en
   display-regel skal beskytte sig mod display-regler. */
.scan-btns > form:not([hidden]) { display: contents; }
.scan-btns .btn-primary,
.scan-btns .btn-secondary {
  width: 100%;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  /* §31.6: tommelmål. Knapperne er fladens to udgange, og de rammes med en
     tommel mens den anden hånd holder varen. */
  min-height: 44px;
}
/* Står "Læg i kurv" ikke der (ingen POS-adgang, eller intet entydigt
   varenummer), skal "Åbn vare" ikke efterlade et hul hvor knappen var. */
.scan-btns > form[hidden] + .btn-secondary { grid-column: 1 / -1; }

.scan-tom { color: var(--ink-2); text-align: center; padding: 8px 0; }

/* 🔴 MOBIL-OPKALDSLINKET ER SKJULT SOM DEFAULT (2026-08-15).
   `.phone-tel-link` er telefonens EGEN dialer og hører kun til under
   breakpointet; mobil-laget viser den igen. Konstruktionen er vendt samme vej
   som resten af §31: skjult her, vist dér — den omvendte (synlig som default,
   skjult i mobil-laget) ville pr. definition ændre skrivebordet, og §31.2
   kræver at det er bit-identisk. */
/* 🔴 DENNE REGEL GÆLDER OGSÅ ADMIN — den er bare uden virkning DER I DAG.
   Målt i den kørende app 15-08: /admin/ laster forta-core.css (men hverken
   forta-mobil.css eller forta-dark.css). At linket er SKJULT i admin er
   derfor ikke en afgrænsning — det er den samme globale regel, og admin får
   aldrig mobil-lagets `display:inline-flex` der viser det igen.

   I praksis er den uden virkning fordi `_phone_with_call.html` forekommer 0
   gange i admin/templates/. Renderer en admin-flade en dag komponenten, får
   den et permanent skjult opkalds-ikon — ikke et synligt, og ikke en fejl der
   bliver rød. Så ved du hvad du arver. */
.phone-tel-link { display: none; }

/* ══════════════════════════════════════════════════════════════════════════
   KUNDEDISPLAY-PULS — knappen der VISER noget paa kundedisplayet lige nu.
   Andreas 25-08-2026: «saa skal denne knap man har trykket paa … pulsere med
   en behagelig farve men en man laegger maerke til, saa man husker at trykke
   Stop visning.»

   KROGEN ER DEN SAMME SOM AUTO-STOPPETS (static/js/kundedisplay-autostop.js):
   `[data-kundedisplay-knap][data-mode="stop"]`. Knapperne skifter selv
   `data-mode` fra deres egne lyttere, saa pulsen taender og slukker uden en
   linje JavaScript her — og en fjerde flade arver den ved at saette de samme
   attributter.

   ── FARVEVALGET ─────────────────────────────────────────────────────────
   Amber (--amber-bg / --amber-tx), IKKE roed. Roed betyder FEJL i huset, og
   en aktiv kundevisning er en NORMALTILSTAND man skal huske at afslutte.
   Tokens frem for literals: `forta-dark.css` redefinerer begge, saa mørkt
   tema kommer gratis og white-label roerer dem ikke.

   ── 🔴 KONTRAST: PULSEN ROERER INGEN KONTRASTBAERENDE FLADE ──────────────
   En puls der animerer BAGGRUND kan bestaa i sit ene yderpunkt og dumpe i
   det andet. Derfor animerer denne kun en `box-shadow` UDEN FOR border-box.
   Tekstfarve, fyld, kant og den indre 2px-ring er ORDRET ENS i alle
   keyframes — saa de to yderpunkter er samme maaling, ikke to maalinger.
   Maalt 25-08-2026 (WCAG 2.x relativ luminans):

       --amber-tx paa --amber-bg     LYS  #815C00 / #FDF4E3          5,55
                                     MRK  #E0A93E / .14 over #081320 6,85
                                     MRK  #E0A93E / .14 over #12263A 5,52
       indre ring (fuld --amber-tx) mod fladen bagved
                                     LYS  / --bg-app  #EDF3F6        5,41
                                     LYS  / panel     #FFFFFF        6,06
                                     MRK  / --bg-app  #081320        8,82
                                     MRK  / --bg-panel #12263A       7,27

   AA-tekst kraever 4,50; et grafisk objekt (WCAG 1.4.11) 3,00. Begge holder
   i begge temaer. Vaernet er tests/test_kundedisplay_puls.py, som REGNER
   tallene ud af tokens — saa en fremtidig token-aendring bliver roed her
   frem for at blive opdaget paa en skaerm.

   🔴 KANTEN ROERES IKKE. `.btn-secondary` baerer `--bd-control` fordi §24.3
   forbyder kantloese sekundaerknapper paa hvid. `--amber-bd` maaler kun
   1,24:1 mod --bg-app, saa at farve kanten amber ville SVAEKKE den graense
   der identificerer kontrollen. Fyld + tekstfarve + ring er markeringen.
   ══════════════════════════════════════════════════════════════════════ */
[data-kundedisplay-knap][data-mode="stop"],
[data-kundedisplay-knap][data-mode="stop"]:hover {
  /* :hover staar med fordi `.btn-secondary:hover` (0,2,0) ellers vinder paa
     kildeorden — app.css indlaeses EFTER denne fil. */
  --kd-ring: var(--amber-tx);
  background: var(--amber-bg);
  color: var(--amber-tx);
  box-shadow: 0 0 0 2px var(--kd-ring);
  animation: kd-puls 1.9s ease-in-out infinite;
}
/* Den indre 2px-ring staar i BEGGE keyframes med samme farve og samme bredde;
   det eneste der bevaeger sig er den ydre, gennemsigtige gloed. */
@keyframes kd-puls {
  0%, 100% {
    box-shadow: 0 0 0 2px var(--kd-ring),
                0 0 0 2px color-mix(in srgb, var(--amber-tx) 30%, transparent);
  }
  50% {
    box-shadow: 0 0 0 2px var(--kd-ring),
                0 0 0 9px color-mix(in srgb, var(--amber-tx) 0%, transparent);
  }
}

/* 🔴 EN ANIMATION SLAAR ENHVER NORMAL DEKLARATION — ogsaa en med hoejere
   specificitet: keyframes bor i «animation origin», et hoejere kaskadeniveau.
   Uden `animation: none` her ville husets fokusring (`:focus-visible`, som
   OGSAA er en box-shadow) blive spist af pulsen, og knappen ville miste sin
   tastaturmarkering praecis mens den er vigtigst. Ringene stables: husets tre
   lag indenfor, kundedisplay-ringen yderst. */
[data-kundedisplay-knap][data-mode="stop"]:focus-visible {
  animation: none;
  box-shadow: 0 0 0 1.5px var(--accent),
              0 0 0 3px var(--accent-glow),
              0 0 0 4.5px var(--ink),
              0 0 0 6.5px var(--kd-ring);
}

/* 🔴 EN KNAP DER KUN ER MARKERET VED BEVAEGELSE ER USYNLIG FOR NOGEN — og for
   andre er bevaegelsen direkte ubehagelig. Reduced-motion faar derfor ikke
   «ingenting»; den faar den SAMME markering staaende stille, og den er
   maalt (5,41–8,82 ovenfor). `!important` fordi vi slaar en animation fra,
   og animationer vinder over normale deklarationer. */
@media (prefers-reduced-motion: reduce) {
  [data-kundedisplay-knap][data-mode="stop"],
  [data-kundedisplay-knap][data-mode="stop"]:hover {
    animation: none !important;
    box-shadow: 0 0 0 3px var(--kd-ring) !important;
  }
}


/* ── UNDERSKRIFT-KORTETS ANNULLÉR-KRYDS (§31.6) ───────────────────────────
   Andreas 27-08-2026: «lav en kryds oppe højre hjørne af denne Underskriv
   boks hvis man ønsker at annullere.»

   🔴 44×44 UBETINGET, IKKE KUN UNDER BREAKPOINTET. §31.6 kræver ≥44px for
   ethvert interaktivt element under 899px; kortet vises begge steder, og en
   regel der KUN gælder i mobil-laget ville skulle vedligeholdes to steder
   for at holde ét mål. Ikonet er 18px — et 24px felt om et 18px kryds falder
   for tommelmålet, og det er præcis den fejl kravet findes for at fange.

   Feltet er kvadratisk og glyffen centreret med `place-items`, så
   klikfladen er hele kvadratet og ikke kun stregerne i krydset.

   🔴 HOVER-FARVEN VAR RØD OG ER DET IKKE MERE — MÅLT, IKKE VALGT.
   Første udgave brugte `--red-tx` på `--ink-100`, fordi krydset ANNULLERER
   en anmodning og ikke bare lukker en boks. `test_dark_kontrast` fældede
   den: **#E65F58 på #24374a = 3,57:1** i mørkt tema, hvor AA kræver 4,50.

   ⚠️ OG DEN NÆRLIGGENDE RETTELSE VIRKER HELLER IKKE. Huset har et designet
   danger-par (`--red-tx` på `--red-bg`), og det er det man griber efter.
   Målt med værnets egen contrast()-funktion: **3,99:1 i mørkt** — også
   under AA. Rød tekst på en dæmpet flade bærer ikke i mørkt tema her,
   uanset hvilken af husets to flader man vælger. (Meldt til crmdirigent som
   et selvstændigt fund om `--red-bg`/`--red-tx`-parret; det er ikke denne
   knaps sag at rette.)

   Derfor `--ink-900`: **15,89:1 lyst · 10,79:1 mørkt**. Affordancen bæres af
   den tonede flade — nøjagtig som husets øvrige ghost-ikonknapper
   (`.tz-kunde-chev:hover` gør det samme) — og det destruktive ligger hvor
   det hører hjemme: i `aria-label`, i `title` og i `hx-confirm`. Et rødt
   kryds i et hjørne trækker i øvrigt øjet mod netop den uoprettelige
   handling, som er den modsatte af den vi vil invitere til. */
.sig-kryds {
  width: 44px; height: 44px; flex: 0 0 44px;
  display: grid; place-items: center;
  padding: 0; border: 0; border-radius: 12px;
  background: transparent; color: var(--ink-3);
  cursor: pointer;
}
.sig-kryds:hover, .sig-kryds:focus-visible {
  background: var(--ink-100); color: var(--ink-900);
}

/* ── BILLEDET PAA EN TILBUDSLINJE (2026-08-28, sporet `tilbudsrydning`) ──────
   🔴 CELLEN SKAL OGSAA TEGNE NOGET NAAR DER IKKE ER ET BILLEDE. Billedvalget
   og den lokale billed-cache har vaeret bygget faerdig siden 22-08, og Andreas
   spurgte 28-08 hvor man saetter billeder paa varerne. Et miniaturebillede der
   kun findes naar valget allerede er truffet, kan ikke laere nogen at valget
   findes — derfor `.linje-billede-tom`, som er en INVITATION og ikke en
   tilstand.
   Begge former er 44px hoeje: §31.6 kraever det under breakpointet, og en celle
   der skifter hoejde alt efter om linjen har et billede, ville faa tabellen til
   at hoppe naar et billede vaelges. */
.linje-billede-knap, .linje-billede-tom {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 2px 8px 2px 4px;
  border: 1px solid transparent; border-radius: var(--radius-control, 8px);
  background: transparent; color: var(--ink-3);
  font-size: 12px; line-height: 1; cursor: pointer;
}
.linje-billede-tom { border-color: var(--border); border-style: dashed; }
.linje-billede-knap:hover, .linje-billede-tom:hover,
.linje-billede-knap:focus-visible, .linje-billede-tom:focus-visible {
  background: var(--tbl-hover); color: var(--ink); border-color: var(--border);
}
.linje-billede-knap[disabled] { cursor: default; }
.linje-billede-mini {
  width: 40px; height: 40px; object-fit: contain;
  border: 1px solid var(--border); border-radius: var(--radius-control, 8px);
  background: var(--bg-panel-2, transparent);
}
/* Mobil-kortets udgave staar paa sin egen raekke og skal ikke se ud som en
   knap; kortet er i forvejen ét klikmaal via blyanten. */
.mlinje-kort-billede { margin-top: 6px; }
.mlinje-kort-billede a {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; color: var(--ink-2); font-size: 12px;
  text-decoration: none;
}
/* --ink-2, ikke --ink-3: linjen er 12px BRoedTEKST i et link, saa §23 kraever
   4,50:1. Maalt 31-08-2026 (samme regnestykke som vagtens egne 3,15):
       --ink-3  lys #7B95A3 3,15:1 · moerk #63809A 3,73:1   BEGGE under AA
       --ink-2  lys #4A6676 6,08:1 · moerk #9DB6C8 7,30:1   begge bestaar
   Fundet af test_dark_kontrast::test_ingen_kontrastbrud_paa_arvet_flade, som
   var roed ALLEREDE paa runde 3's base e90057c08 — bruddet kom ind med
   fletningen, ikke med denne gren. */
.mlinje-billede-tom { display: inline-flex; align-items: center; gap: 6px; }

/* ── «SAADAN SER KUNDEN DET» PAA TILBUDDET (2026-08-28) ─────────────────────
   🔴 `display:block` PAA <summary> ER BEVIDST UDELADT. En tidligere runde
   maalte at `display:flex` paa en <summary> giver den sin trykhoejde OG
   sletter dens ::marker — trekanten der er hele signalet om at der er noget
   at folde ud. Hoejden kommer derfor af padding, ikke af en display-skifter.
   44px jf. §31.6: summaryen ER klikmaalet. */
.tz-forhaandsvisning {
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-panel, 12px);
  background: var(--bg-panel, transparent);
}
.tz-forhaandsvisning > summary {
  padding: 12px 16px; min-height: 44px;
  font-weight: 600; color: var(--ink); cursor: pointer;
  border-radius: var(--radius-panel, 12px);
}
.tz-forhaandsvisning > summary:hover { background: var(--tbl-hover); }
.tz-forhaandsvisning > .form-help { padding: 0 16px; }
.tz-forhaandsvisning > iframe {
  display: block; width: calc(100% - 32px); height: 72vh; margin: 8px 16px 16px;
  border: 1px solid var(--border); border-radius: var(--radius-panel, 12px);
  background: var(--bg-panel-2, #fff);
}
/* Titel-linjen i forhaandsvisningens summary. Se skabelonen for hvorfor den
   ligger i et indre span frem for paa summaryen selv. */
.tz-forhaandsvisning > summary .tz-fv-titel {
  display: inline-flex; align-items: center; gap: 8px; vertical-align: middle;
}
/* ── ② «paa telefonen» + «Åbn i fuld bredde ↗» (04-09-2026) ──────────────
   🔴 MAERKET ER SKJULT SOM UDGANGSPUNKT OG TAENDES FOERST VED 1600px.
   Under graensen staar panelet UNDER komposeren i fuld bredde (maalt: 1.122
   px ved 1440), og dér rendrer det kundens SKRIVEBORDS-dokument — samme
   dokumenthoejde som kundens rigtige side, 1.975 = 1.975. En tekst der sagde
   «paa telefonen» dér ville vaere forkert praecis hvor panelet er mest
   retvisende. Det er derfor `display:none` i grundlaget og ikke omvendt:
   paastanden skal taendes af den betingelse der goer den sand. */
.tz-fv-tlf { display: none; color: var(--ink-2); font-weight: 400; }
/* Linket til fuld bredde staar til hoejre i summary-raekken. `margin-left:
   auto` kraever at summaryen selv er flex — men den maa IKKE faa
   `display:flex`, for det sletter dens ::marker (husets egen maaling ved
   `.tz-forhaandsvisning`). `float` loeser det uden at roere display-typen. */
.tz-fv-fuld {
  float: right; display: inline-flex; align-items: center;
  min-height: 44px; padding: 0 10px; margin: -12px -6px -12px 0;
  /* 🔴 `--accent-link` OG IKKE `--accent`. MAALT af
     `test_dark_kontrast.py::test_ingen_kontrastbrud_paa_arvet_flade` i
     foerste udgave: `--accent` er `#1E96B0` i LYST tema og giver **3,47:1**
     som tekst — AA kraever 4,50. Det er PRAECIS det tal husets egen note om
     hvid paa `--grad-btn` baerer, og det er ikke et tilfaelde: begge
     kommer af at bruge selve accenten som blaek.
     `--accent-link` er husets token for netop den rolle — `#1B567E` i lys,
     `color-mix(accent 45%, white)` i moerk — altsaa lys nok i moerkt tema
     og moerk nok i lyst. */
  color: var(--accent-link); font-size: 12.5px; font-weight: 600;
  text-decoration: none;
}
.tz-fv-fuld:hover { text-decoration: underline; }
.tz-fv-fuld:focus-visible { outline: 2px solid var(--accent);
  outline-offset: 2px; border-radius: 8px; }
@media (min-width: 1600px) {
  .tz-fv-tlf { display: inline; }
}

/* ══ «KLADDEN FOERST» — CHIP-RAEKKEN I INFO-PANELET (04-09-2026) ═══════════
   ② De tomme felter foldes til «+»-chips med taeller. MAALT foer: 9 af 12
   felter i panelet viste «—» paa en frisk kladde, og panelet var 1.115 px
   hoejt uanset indhold.

   🔴 CHIPPEN ER SELV KLIKMAALET (en <summary>), saa 44px er §31.6's krav og
   ikke en pynt. Den er MINIMUM — chippen vokser med sin tekst.
   🔴 STIPLET KANT NAAR DER INTET ER, HEL NAAR DER ER NOGET. Det er samme
   konvention prototypen bruger for «ikke endeligt» (.fbadge), og den giver
   raekken en aflaeselig forskel uden at bruge farve alene. Foldens `open`
   saettes af skabelonen naar gruppen har en vaerdi. */
.tz-kladdelinje { min-width: 0; }
/* 🔴 «Flere» SKRIVES UD NAAR ⋯ STAAR ALENE. Husets grundregel skjuler
   etiketten over 899px, fordi handlingsraekken dér er ÉN linje uden plads
   til et ord mere (§8a's pixelregnskab). Paa en kladde er raekken TOM
   bortset fra ⋯ — pladsen findes, og §4's egen begrundelse fra telefonen
   gaelder saa ogsaa her: tre prikker alene er ikke et entydigt ikon.
   Markoeren er et data-attribut paa beholderen og ikke en klasse: klassen
   `tz-acts-more` taelles som SUBSTRENG af `test_ordre_knapraekke.py`, og et
   nyt klassenavn i den familie ville faa den til at melde to ⋯-menuer. */
.detail-actionbar[data-tz-kladde] .tz-mere-etiket { display: inline; }
.tz-kchips { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; }
.tz-kchip {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 14px;
  border: 1px dashed var(--bd-control); border-radius: 999px;
  background: var(--panel-solid); color: var(--ink-2);
  font-size: 13px; cursor: pointer; list-style: none;
}
/* `::-webkit-details-marker` og `list-style` — trekanten hoerer ikke paa en
   chip; den ville bryde pilleformen. Chippen har sit eget «+»-tegn som
   signal, og det staar KUN naar gruppen er tom. */
.tz-kchip::-webkit-details-marker { display: none; }
.tz-kchip:hover { border-color: var(--accent); color: var(--ink); }
.tz-kchip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tz-kchip-fast { border-style: solid; color: var(--ink); cursor: default; }
.tz-kchip-fast .tz-flabel { margin: 0; }
.tz-kchip-plus { color: var(--accent-link); font-weight: 700; font-size: 15px;
  line-height: 1; }  /* --accent-link, ikke --accent: se noten ved .tz-fv-fuld */
.tz-kchip-tael { font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11.5px; color: var(--ink-2); }
.tz-kfold { min-width: 0; }
.tz-kfold[open] > .tz-kchip { border-style: solid; color: var(--ink); }
/* Felterne foldes ud UNDER chip-raekken i fuld bredde. `position: static` og
   ikke en popover: et felt i en popover ville lukke sig selv ved det foerste
   klik uden for, og inline-editens popovere (kunde, medarbejder, sag) aabner
   netop uden for. To lag popover oven paa hinanden er den slags der virker
   indtil nogen bruger det. */
/* 🔴 EN AABEN FOLD TAGER **IKKE** HELE RAEKKEN. Foerste udgave gjorde
   (`flex: 1 1 100%`), og MAALT paa 1920 med tilbud 40002 (som HAR en
   overskrift) blev resultatet at «Overskrift 1 af 1» stod som en 1.150 px
   bred bjaelke om ét tekstfelt, og «Referencer»/«Tekster» blev skubbet ned
   paa en anden raekke. Chip-raekken holdt op med at vaere en raekke praecis
   naar der var noget i den — altsaa i det almindelige tilfaelde.
   `260px` som basis: bredt nok til et inline-felt med en label, smalt nok
   til at tre folde kan staa ved siden af hinanden paa et skrivebord.
   Paa telefonen er raekken smallere end 260 px, saa `flex-wrap` giver den
   fulde bredde af sig selv — uden en egen regel i mobil-laget. */
.tz-kfold[open] {
  flex: 1 1 260px; max-width: 420px;
  display: flex; flex-direction: column; gap: 8px;
}
.tz-kfelter {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px; border-radius: var(--radius-panel, 12px);
  border: 1px solid var(--border); background: var(--bg-panel-2, transparent);
}
/* C5 (26-09): tilbuddets TEKSTFELTER er flerlinjede — en aaben tekstfold
   tager hele raekken, modsat topzonens enkeltfelter ovenfor (260/420 px).
   Kun `.lyn-tekstfold`; topzonens regel roeres ikke. */
.tz-kfold.lyn-tekstfold[open] { flex: 1 1 100%; max-width: none; }
/* F10 (27-09): «Afvist af kunden»-kortet paa tilbudsdetaljen. Begrundelsen
   er kundens egne ord — citeret, med linjeskift bevaret. */
.tilbud-afvist { border-left: 4px solid var(--red-bd); }
.tilbud-afvist-grund {
  margin: 8px 0 0; padding: 6px 12px; border-left: 3px solid var(--border);
  white-space: pre-line; color: var(--ink);
}

/* ════════════════════════════════════════════════════════════════════════════
   DATOFELT — dansk format uden at miste den native kalender. 27-08-2026.
   Markup og hele begrundelsen: tech/templates/_components/_datofelt.html.

   Konstruktionen i tre lag, nedefra:
     1. .datofelt-tekst   det synlige felt (.form-input), dansk dd-mm-åååå
     2. .datofelt-ikon    kalender-glyf, ren dekoration (pointer-events:none)
     3. .datofelt-native  det ÆGTE <input type="date">, gennemsigtigt, øverst

   🔴 `opacity: 0`, ALDRIG `display: none` eller `visibility: hidden`. Et felt
   der ikke renderes, kan ikke vise en kalender — og på telefonen ER det
   feltet der bærer kalenderen. Gennemsigtigt og på plads er derfor ikke en
   stiløvelse; det er hele mekanismen.
   ══════════════════════════════════════════════════════════════════════════ */
.datofelt {
  position: relative;
  display: inline-flex;
  align-items: stretch;
}

/* Plads til ikonet, så en lang dato ikke løber ind under det. */
.datofelt-tekst {
  padding-right: 38px;
  width: 100%;
}

.datofelt-ikon {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--ink-500);
}

.datofelt-native {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  /* §31.6: kalender-åbneren er et interaktivt element og skal kunne rammes.
     44px også på musen — det koster intet, og under 899px er det et krav. */
  width: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  opacity: 0;
  cursor: pointer;
  z-index: 2;
}

/* 🔴 CHROME ÅBNER KUN KALENDEREN FRA SIN EGEN INDIKATOR, ikke fra et klik hvor
   som helst i feltet. Uden denne regel ville vores 44px-flade være et klikmål
   der ikke gør noget. Indikatoren strækkes ud over hele feltet, så «klik på
   kalender-ikonet» og «klik på knappen» er den samme handling. */
.datofelt-native::-webkit-calendar-picker-indicator {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}

/* 🔴 INGEN `min-height` PAA GRUNDREGLEN. `top:0; bottom:0` giver allerede
   feltets egen hoejde; et gulv oveni ville faa overlejringen til at STIKKE UD
   under kontrollen paa skrivebordet, hvor raekken er lavere end 44 px — en
   usynlig 10 px stribe der stjaeler klik fra det der ligger under. Maalt
   27-08: kontrollen var 33,5 px hoej ved 1280 px, overlejringen 44.
   Under 899 px er §31.6's gulv allerede opfyldt af `.form-input`s egne
   `min-height: 44px` (forta-mobil.css), som kontrollen arver — saa kravet
   holdes af den regel der ejer det, ikke af en kopi her. */

/* ── TELEFONEN: HELE KONTROLLEN ER KALENDEREN ────────────────────────────────
   `pointer: coarse` og ikke en bredde: kriteriet er om der PEGES MED EN FINGER,
   ikke hvor bredt vinduet er. Et smalt browservindue på skrivebordet skal
   stadig kunne tastes i; en telefon skal åbne kalenderen ved ét tryk, præcis
   som et rå `<input type="date">` gør i dag. Ingen JavaScript involveret. */
@media (pointer: coarse) {
  .datofelt-native {
    left: 0;
    width: auto;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   VERIFIKATIONSFLADEN — udfaldet skal kunne skelnes UDEN farve (29-08-2026)

   🔴 TO AF DE FEM UDFALD ER NEUTRALE, og de betyder vidt forskellige ting:
   `intet_bevis` er en underskrift fra foer seglet fandtes — gyldig, bare
   uden noget at regne efter. `ukendt` er «vi har ingen saadan underskrift».
   Baerer de samme farve OG samme kant, er de kun adskilt af overskriften.

   Kanten baerer derfor udfaldet: STIPLET for «uden bevis», PRIKKET for
   «findes ikke». Det er tegningens greb (docs-udkast/FORTA_SIGN_ADMIN.html,
   skaerm 4), og det er en tilgaengelighedsforbedring frem for en pynt —
   en laeser der ikke skelner farverne har stadig et signal.

   ⚠️ REGLEN BOR HER OG IKKE I app.src.css. Tailwinds `border-dashed` /
   `border-dotted` findes maalt NUL gange i den BYGGEDE static/css/app.css,
   saa en utility-klasse ville vaere en doed klasse indtil nogen koerte et
   build — praecis den «kontakt uden ledning» test_doede_css_klasser vaerner
   mod. forta-core.css er haandskrevet og indlaeses direkte af base.html.

   Selektoren er attributtet og ikke en klasse: `data-udfald` staar der i
   forvejen som instrumentets krog, og en klasse ville skulle baere baade
   navnet og udseendet. Samme form som `table[data-stack]`.
   Vagt: tests/test_sign_verifikationsflade.py
   ══════════════════════════════════════════════════════════════════════ */
.card[data-udfald="intet_bevis"] { border-style: dashed; border-width: 2px; }
.card[data-udfald="ukendt"]      { border-style: dotted; border-width: 2px; }

/* Afvigelses-tabellens frosne vaerdi. `<s>` faar sin streg af browseren;
   her daempes den kun, saa den levende vaerdi er den oejet lander paa. */
.verifikation-afvigelser s { color: var(--ink-500); text-decoration-thickness: 1px; }
.verifikation-afvigelser .pil { color: var(--ink-500); padding-right: 4px; }

/* ══════════════════════════════════════════════════════════════════════════
   VERIFIKATIONENS SEGL-HERO, TJEKLISTE OG TIDSSTEMPLER (01-09-2026)
   F1/F3/F4/F5 fra RAPPORT-sign-designsyn-30-08.md — facit er
   docs-udkast/FORTA_SIGN_ADMIN.html, skaerm 4 (.vhero/.vseal/.vchecks).

   🔴 EMBLEMET ER IKKE PYNT. Fladen aabnede med husets generiske `alert-*`-
   kasse paa den ene skaerm i produktet hvis emne ER et segl — og facit
   tegner FEM emblemer der ikke kan forveksles, netop fordi de fem udfald
   ikke maa smelte sammen til «ok» og «fejl».

   🔴 FARVERNE ER HUSETS TOKENS, IKKE FACITS. Facit har sit eget saet
   (--ok-tx/--warn-tx/…) fra en selvstaendig adminportal; her staar husets
   green/amber/red/info-par, saa emblemet skifter tema sammen med resten.
   Maalt 01-09 med instrumentet i rapporter/sign-designsyn/kontrast.py
   (kalibreret paa CLAUDE.md's egne tal, 3,47/2,55/1,56 og 5,38/7,34/11,98
   reproduceret ordret FOER nye tal blev taget):

       tekst-par (AA-krav 4,50)        LYS    MOERK
       .vhero-under/.vcheck ink-600    6,27    8,41
       .vmeta-k/.vstempel ink-500      6,03    4,90

       emblem-ikon paa tonet flade (WCAG 1.4.11 non-text, krav 3,00)
       groen · amber · roed · info     5,42 · 5,55 · 5,88 · 7,03  (lys)
                                       3,83 · 5,42 · 3,78 · 7,00  (moerk)

   ⚠️ DE TO MOERKE PAA 3,8 ER IKKE TEKST. Ikonet er en stregtegning med
   `aria-hidden`, og dommen staar som ORD i pillen ved siden af — ingen
   oplysning haenger paa at kunne skelne kuloeren. Non-text-kravet er 3,00,
   og begge bestaar. Havde de baaret tekst, ville de vaere roede.
   ⚠️ Og de 3,8 er husets kendte H1-fund (rapportens afsnit H, meldt til
   CRM 30-08 som et forta-core-anliggende): grundfarven paa sin egen tonede
   flade i moerkt tema. Der er BEVIDST ikke lagt et Sign-lokalt loeft ind —
   verdikt-pillen ville da vaere en anden groen end statuspillen 40 px
   laengere nede paa samme side, og en flade der modsiger sig selv er
   vaerre end et kendt hus-fund.
   ══════════════════════════════════════════════════════════════════════ */
.vhero { display:flex; gap:20px; align-items:center; flex-wrap:wrap; }
.vhero-tekst { flex:1 1 260px; min-width:0; }
.vhero-titel { font-family:var(--font-display); font-size:19px; font-weight:700;
  letter-spacing:-.01em; line-height:1.3; margin:9px 0 0; color:var(--ink-900); }
.vhero-under { font-size:12.5px; color:var(--ink-600); line-height:1.6;
  margin:5px 0 0; max-width:560px; }  /* facits maal; 60ch braekkede
     'nu.' ned paa en linje for sig i et skud ved 1280px. */
/* Verdiktet i STORE BOGSTAVER. Transformationen bor i CSS'en, saa strengen i
   DOM'en stadig er den ENE tekst der bor i tech/routes/signatures.py — en
   proeve og en skabelon maa ikke kunne skrive hver sin. */
.vverdikt { text-transform:uppercase; letter-spacing:.06em; }

/* Seglet: en drejende stiplet ring om en tonet ikon-firkant. */
.vseal { width:88px; height:88px; flex:0 0 88px; position:relative;
  display:grid; place-items:center; }
.vseal-ring { width:88px; height:88px; position:absolute; inset:0; }
.vseal-ring circle { fill:none; stroke-width:2.5; stroke-dasharray:4 6;
  stroke-linecap:round; stroke:var(--ink-300);
  transform-origin:50% 50%; animation:vseal-drej 26s linear infinite; }
.vseal-ikon { position:relative; z-index:2; width:52px; height:52px;
  border-radius:16px; display:grid; place-items:center;
  border:1px solid transparent; background:var(--ink-100); color:var(--ink-600); }
@keyframes vseal-drej { to { transform:rotate(360deg); } }
/* 🔴 KUN 'ok' DREJER. En flade der efterproever et brud maa ikke se levende
   ud — bevaegelsen er en bekraeftelse, og den hoerer kun til det udfald der
   bekraefter noget. */
.vseal--stille .vseal-ring circle { animation:none; }
@media (prefers-reduced-motion: reduce) {
  .vseal-ring circle { animation:none; }
}

/* Udfaldets farve baeres af `data-segl` paa heroen — samme greb som
   `[data-udfald]` paa kortet: attributtet staar der i forvejen som
   instrumentets krog, og en klasse skulle baere baade navn og udseende. */
.vhero[data-segl="ok"] .vseal-ikon { background:var(--green-bg);
  color:var(--green-tx); border-color:var(--green-bd); }
.vhero[data-segl="ok"] .vseal-ring circle { stroke:var(--green-bd); }
.vhero[data-segl="aendret"] .vseal-ikon { background:var(--amber-bg);
  color:var(--amber-tx); border-color:var(--amber-bd); }
.vhero[data-segl="aendret"] .vseal-ring circle { stroke:var(--amber-bd); }
.vhero[data-segl="brudt_segl"] .vseal-ikon { background:var(--red-bg);
  color:var(--red-tx); border-color:var(--red-bd); }
.vhero[data-segl="brudt_segl"] .vseal-ring circle { stroke:var(--red-bd); }
/* De to NEUTRALE skal kunne skelnes UDEN farve — samme greb som kortets kant
   ovenfor: STIPLET for «uden bevis», PRIKKET for «findes ikke». Ringen
   gentager skelnen, saa den ogsaa staar naar man kun ser emblemet. */
.vhero[data-segl="intet_bevis"] .vseal-ikon { background:var(--info-bg);
  color:var(--info-tx); border-color:var(--info-tx); border-style:dashed; }
.vhero[data-segl="intet_bevis"] .vseal-ring circle { stroke:var(--info-tx);
  stroke-dasharray:2 8; }
.vhero[data-segl="ukendt"] .vseal-ikon { border-color:var(--ink-400);
  border-style:dotted; }
.vhero[data-segl="ukendt"] .vseal-ring circle { stroke:var(--ink-400);
  stroke-dasharray:1 10; }

/* Tjeklisten: hvad blev der efterproevet. */
.vchecks { list-style:none; display:grid; gap:9px; margin:16px 0 0; padding:0; }
.vcheck { display:flex; gap:10px; align-items:flex-start; font-size:12.5px;
  color:var(--ink-600); line-height:1.55; }
.vcheck b { color:var(--ink-900); font-weight:600; }
.vcheck-ikon { flex:0 0 16px; width:16px; height:16px; margin-top:2px;
  color:var(--ink-500); }
.vcheck--ok .vcheck-ikon { color:var(--green-tx); }
.vcheck--advarsel .vcheck-ikon { color:var(--amber-tx); }
.vcheck--fejl .vcheck-ikon { color:var(--red-tx); }
.vcheck-tekst { min-width:0; }
.vcheck-link { display:inline-block; margin-left:6px; color:var(--accent-link);
  text-decoration:underline; text-underline-offset:2px; }

/* Hvornaar skete det, og hvornaar blev der maalt. */
.vmeta { display:flex; flex-wrap:wrap; gap:4px 22px; margin-top:16px;
  padding-top:12px; border-top:1px solid var(--bd-panel); }
.vmeta-post { display:flex; align-items:baseline; gap:7px; }
.vmeta-k { font-size:10px; font-weight:800; letter-spacing:.07em;
  text-transform:uppercase; color:var(--ink-500); white-space:nowrap; }
.vmeta-v { font-size:12.5px; color:var(--ink-700); }

/* Tredjeparts-tidsstemplet. Tre tilstande, og ingen af dem er en fejl:
   et manglende stempel er et manglende uafhaengigt VIDNE — beviset selv er
   uberoert. Derfor ingen fejlfarve paa nogen af de tre. */
.vstempel { margin:10px 0 0; font-size:12px; color:var(--ink-500);
  line-height:1.55; }
.vstempel-k { font-weight:700; color:var(--ink-700); margin-right:6px; }
.vstempel[data-stempel="stemplet"] .vstempel-k { color:var(--green-tx); }
.vstempel-tsa { display:block; margin-top:3px; font-family:var(--font-mono);
  font-size:11px; color:var(--ink-600); word-break:break-all; }

@media (max-width: 899px) {
  /* §31.6: ethvert interaktivt element er ≥44px under breakpointet. Linket
     til audit-loggen staar inde i en tjek-linje og ville ellers vaere en
     tekst-hoej trykflade paa telefonen. */
  .vcheck-link { display:flex; align-items:center; min-height:44px; }
  .vhero { gap:14px; }
  .vseal { width:64px; height:64px; flex:0 0 64px; }
  .vseal-ring { width:64px; height:64px; }
  .vseal-ikon { width:40px; height:40px; border-radius:12px; }
  .vseal-ikon svg { width:20px; height:20px; }
}
/* ── Opsætnings-hub v2 (beslutning 3, 29-08-2026) — tilstand paa kortene ── */
.setting-card-st { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:4px;
  font-size:11.5px; color:var(--ink-500); }
.setting-card-meta { font-size:11.5px; color:var(--ink-500); }
.setting-hub-sidst { display:block; margin-top:2px; color:var(--ink-500); font-size:12.5px; }
.setting-hub-vaerktoej { display:flex; flex-wrap:wrap; gap:10px; align-items:center; margin-bottom:1.25rem; }
.setting-hub-vaerktoej .search-input { max-width:420px; flex:1 1 260px; }
.setting-hub-kom-i-gang { margin-bottom:1.75rem; }
.setting-hub-tjek { list-style:none; margin:.75rem 0 0; padding:0; }
.setting-hub-tjek li { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:8px 0; border-top:1px solid var(--bd-panel); }
.setting-hub-tjek li > span:nth-child(2) { flex:1 1 240px; font-size:13.5px; }
.setting-hub-kom-i-gang > summary { cursor:pointer; list-style:none; }
.setting-hub-kom-i-gang > summary::-webkit-details-marker { display:none; }
.setting-hub-kom-i-gang > summary h3::before { content:"▸ "; color:var(--ink-500); }
.setting-hub-kom-i-gang[open] > summary h3::before { content:"▾ "; }
/* §24.5 hub -> detalje: «‹ Opsætning» over titlen paa opsaetningssiderne. */
.setting-back { display:inline-block; font-size:12.5px; color:var(--accent-soft-tx); text-decoration:none; margin-bottom:4px; }
.setting-back:hover { text-decoration:underline; }
/* 30-08 (rydroede): ink-500 gav 3,88:1 i moerk paa ink-100 — ink-600 bestaar AA i begge. */
.empty-state-ic { width:44px; height:44px; border-radius:10px; background:var(--ink-100); display:inline-flex; align-items:center; justify-content:center; margin-bottom:8px; color:var(--ink-600); }
/* Foldede sektioner paa opsaetningssider (printer v2, beslutning 5). */
details.card > summary.setting-fold-h { cursor:pointer; list-style:none; font-weight:600; font-size:15px; display:flex; gap:8px; align-items:baseline; flex-wrap:wrap; }
details.card > summary.setting-fold-h::-webkit-details-marker { display:none; }
details.card > summary.setting-fold-h::before { content:"▸"; color:var(--ink-500); }
details.card[open] > summary.setting-fold-h::before { content:"▾"; }
details.card[open] > summary.setting-fold-h { margin-bottom:12px; }
details.card > section.card { box-shadow:none; }
/* Noegle/vaerdi-liste (min Microsoft-konto m.fl.): to kolonner paa skrivebord, stak under 900px. */
dl.noegle-vaerdi { display:grid; grid-template-columns:max-content 1fr; gap:6px 16px; margin:0; font-size:13.5px; }
dl.noegle-vaerdi dt { font-size:11px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--ink-500); align-self:baseline; }
dl.noegle-vaerdi dd { margin:0; }
@media (max-width:899px) { dl.noegle-vaerdi { grid-template-columns:1fr; gap:2px; } dl.noegle-vaerdi dd { margin-bottom:8px; } }
/* Noegle/vaerdi-TABEL (th pr. raekke, ingen thead): stak under 900px, saa vaerdien faar hele bredden. */
@media (max-width:899px) {
  table[data-noegle-vaerdi] tr { display:block; padding:6px 0; border-bottom:1px solid var(--bd-panel); }
  table[data-noegle-vaerdi] th, table[data-noegle-vaerdi] td { display:block; width:100%; padding:2px 0; border:0; }
  table[data-noegle-vaerdi] th { font-size:11px; letter-spacing:.07em; text-transform:uppercase; color:var(--ink-500); }
}
/* ============================================================================
   CVR-BERIGELSE — beviset side om side (2026-08-30)
   ----------------------------------------------------------------------------
   Fladen har ét krav der styrer resten: Andreas skal kunne dømme et forslag
   PÅ ÉT BLIK, uden at klikke. Derfor to spalter — kunden til venstre, CVR-
   registrets træf til højre — og de felter der ER forskellige markeret.

   🔴 `.cvr-afvig` sættes fra en MÅLING i tech/services/cvr_berigelse.py, med
   match-motorens egen normalisering. Ikke fra streng-lighed i skabelonen:
   «Torp IT ApS» og «Torp IT» ser forskellige ud som strenge og er samme navn
   for motoren, og en markering dér ville få Andreas til at dømme på en anden
   sammenligning end den der gav rækken dens spand.

   Markeringen er BÅDE farve og en venstrekant. Farve alene ville være den
   eneste bærer af informationen (§23), og en afvigelse er præcis det man ikke
   må overse.
   ========================================================================= */
.cvr-bevis {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
}
.cvr-bevis-side { min-width: 0; }          /* uden den sprænger lange navne gitteret */
.cvr-bevis-hoved {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-500);
    margin-bottom: 4px;
}
.cvr-bevis-navn { font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.cvr-bevis-nr {
    margin-top: 6px;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.cvr-afvig {
    color: var(--c-danger);
    border-left: 3px solid var(--c-danger);
    padding-left: 7px;                     /* 3px kant + 4px luft = teksten står stille */
    margin-left: -10px;
}

/* Afkrydsningen i SANDSYNLIG-spanden. Etiketten er en del af trykmålet, så
   man rammer den med tommelen og ikke kun den 13px brede boks. */
.cvr-vaelg {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    cursor: pointer;
}
.cvr-vaelg-tekst { font-size: 13px; font-weight: 500; }

/* USIKKER-spandens kandidater. `auto-fit` frem for et fast kolonnetal: antallet
   af træf er 2, 3 eller 10, og et fast tal ville enten spilde plads eller
   klemme dem. minmax'ens 220px er gulvet hvor et firmanavn + adresse stadig
   kan læses uden at brække midt i et ord. */
.cvr-kandidater {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
}
/* Kandidat-kortet blev 31-08 en <label> om en radioknap i stedet for en egen
   <form>: per-raekke-knapperne ligger nu i den faelles form og overstyrer maalet
   med `formaction`, og indlejrede <form> er ugyldig HTML. */
.cvr-kandidat {
    display: block;
    border: 1px solid var(--bd-panel);
    border-radius: 10px;
    padding: 12px;
    min-width: 0;
    cursor: pointer;
}
.cvr-kandidat input[type="radio"] { width: 20px; height: 20px; margin: 0 0 6px; }
/* 🔴 DET VALGTE SELSKAB SKAL KUNNE SES UDEN AT KIGGE PAA PRIKKEN. Et
   kandidat-kort uden synlig valgt-tilstand er praecis der hvor man tror man har
   valgt ét selskab og godkender et andet — og et forkert CVR er vaerre end et
   tomt. Kanten baerer det, ikke kun farven (§23), saa den ogsaa ses uden
   farvesyn. `:has()` mangler i aeldre browsere; da staar radioknappen selv
   tilbage som markoer, hvilket er den tilstand vi havde i forvejen. */
.cvr-kandidat:has(input[type="radio"]:checked) {
    border-color: var(--accent-strong);
    box-shadow: inset 0 0 0 1px var(--accent-strong);
}
.cvr-raekke kbd {
    font-size: 11px;
    padding: 1px 5px;
    border: 1px solid currentColor;
    border-radius: 4px;
    opacity: .75;
}

/* ════════════════════════════════════════════════════════════════════════════
   LYNKLADDEN — tilbuddets arbejdsflade (03-09-2026)
   Forslag 1 i RAPPORT-tilbudsdesign-03-09.md.

   Tokens er husets egne (--panel, --accent, --ink …), saa fladen foelger
   temaskifteren uden en egen mørk kopi. 🔴 Ingen farve defineres KUN her:
   en hardkodet vaerdi ville se rigtig ud i lyst tema og forsvinde i moerkt.

   ⚠️ HVID TEKST PAA TEAL-GRADIENT ER FORBUDT (CLAUDE.md, maalt 3,47:1 mod
   AA's 4,50). Primaerknappen bruger derfor --tekst-paa-lys-accent (#08131F),
   som maaler 5,38 / 7,34 / 11,98 paa de tre gradient-stop. Ret den ikke
   tilbage til hvid.

   🔴 OG SEKUNDAER TEKST ER --ink-2, ALDRIG --ink-3. RETTET 04-09-2026
   EFTER AT `test_dark_kontrast` BLEV ROED.
   Foerste udgave brugte --ink-3 til alt daempet: hjaelpetekst, meta,
   gruppe-overskrifter, «↵ tilfoej»-hintet, den tomme forslagsliste og
   «Intet billede»-knappen. Maalt paa vores egne panelfarver:

       --ink-3   lys  #7B95A3   3,15 paa #FFFFFF · 2,82 paa #EBF4F6
                 moerk #63809A  3,93 paa #0E2233 · 3,41 paa #192d40
       --ink-2   lys  #4A6676   6,08 paa #FFFFFF · 5,45 paa #EBF4F6
                 moerk #9DB6C8  7,69 paa #0E2233 · 6,68 paa #192d40

   AA kraever 4,50. --ink-3 falder i BEGGE temaer paa ALLE vores flader;
   --ink-2 bestaar med margen og er stadig visuelt daempet, saa hensigten
   overlever.

   🔴 VAGTEN KUNNE KUN SE TRE AF NITTEN, og det er hele grunden til at
   rettelsen er en GENNEMGAAENDE udskiftning og ikke tre linjer.
   `test_ingen_kontrastbrud_i_komponent_css` kan kun parre en farve med en
   baggrund naar BEGGE staar i SAMME regel — den navngav derfor
   `.lyn-cmd-kbd`, `.lyn-forslag-tom` og `.lyn-bv-valg`. De oevrige seksten
   arver deres baggrund og var usynlige for maalingen, men stod paa
   NOEJAGTIG de samme paneler med noejagtig samme tal. At rette de tre ville
   have gjort vagten groen og efterladt klassen — og naeste laeser ville have
   haft en groen vagt som bevis paa at fladen var i orden.

   ⚠️ TEKSTEN ER IKKE GJORT STOERRE ELLER FED for at naa en loempeligere
   graense. Kun farven er skiftet, og kun til et token huset allerede har,
   saa temaskifteren foelger med af sig selv.

   ⚠️ Huset har selv TRE --ink-3-tekster tilbage (linje 885, 2573, 2594).
   De maaler det samme og er ikke roert her — de er ikke lynkladdens, og en
   rettelse af dem hoerer i en runde der kan maale deres egne flader.
   ════════════════════════════════════════════════════════════════════════════ */

.lyn { display: block; }

.lyn-fejl {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 14px; padding: 10px 12px;
  border: 1px solid var(--red-bd); background: var(--red-bg);
  color: var(--red-tx); border-radius: var(--radius-control);
  font-size: 13px; line-height: 1.5;
}

/* ── KOMMANDOFELTET ──────────────────────────────────────────────────── */
.lyn-cmd-form { position: relative; margin: 0 0 16px; }
.lyn-cmd {
  display: flex; align-items: center; gap: 10px;
  padding: 0 12px; min-height: 52px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-control);
  background: var(--panel-solid);
  transition: border-color .12s, box-shadow .12s;
}
.lyn-cmd:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.lyn-cmd-prompt {
  font-family: var(--font-mono); font-size: 18px; line-height: 1;
  /* 🔴 --accent-soft-tx OG IKKE --accent. Maalt 04-09: `--accent` er
     #1E96B0 i lyst tema og giver 3,47:1 paa hvid — under AA's 4,50, og
     praecis samme tal som primaerknappens forbudte hvid-paa-teal.
     `--accent-soft-tx` er husets token for ACCENT-FARVET TEKST og vender
     med temaet: 7,84 / 7,02 i lyst (#1B567E), 11,96 / 10,39 i moerkt
     (#b2e7e8). Turkisen overlever dermed dér hvor den kan baeres — paa
     den moerke flade — og bliver til husets dybe teal paa den lyse.
     ⚠️ --accent-strong duer IKKE: den er defineret som en MOERKNET accent
     til fyldte elementer og ville vaere naesten usynlig paa et moerkt
     panel. Et token der kun er maalt i ét tema er ikke et tekst-token. */
  color: var(--accent-soft-tx); flex: none;
}
.lyn-cmd-input {
  flex: 1 1 auto; min-width: 0; border: 0; background: transparent;
  font-size: 15px; color: var(--ink); padding: 12px 0;
}
.lyn-cmd-input:focus { outline: none; }
.lyn-cmd-kbd {
  flex: none; font-size: 11px; padding: 3px 7px;
  border: 1px solid var(--border); border-radius: 6px;
  color: var(--ink-2); background: var(--bg-panel-2);
  font-family: var(--font-mono);
}
.lyn-hjaelp { margin: 6px 2px 0; font-size: 12px; color: var(--ink-2); }

/* 🔴 TELEFONENS TOTAL ER SKJULT PAA SKRIVEBORDET — og reglen SKAL staa i
   kerne-laget, ikke i mobil-laget. Totalen findes to steder i markup'en
   (§31.4 forbyder at mobil-laget flytter DOM-knuder), og hvis KUN
   mobil-laget kendte til dubletten, ville skrivebordet vise BEGGE.
   Maalt paa et skud ved 1440px 03-09: praecis det skete — «6 linjer ·
   ekskl. moms 107.192,50» stod under kommandofeltet OG «Total ekskl.
   moms» i bunden. To beloeb paa samme skaerm er ikke en kosmetisk fejl;
   det er to paastande om det samme.
   Mobil-laget taender den igen og slukker `.lyn-total`. */
.lyn-cmd-total { display: none; }

.lyn-spinner { flex: none; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-top-color: var(--accent); animation: lyn-snurre .7s linear infinite; }
@keyframes lyn-snurre { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .lyn-spinner { animation: none; } }

/* Forslagslisten svaever OVER linjerne — den maa ikke skubbe fladen ned
   hver gang man taster et bogstav. */
.lyn-forslag-holder { position: relative; }
.lyn-forslag {
  position: absolute; left: 0; right: 0; top: 4px; z-index: 30;
  margin: 0; padding: 4px; list-style: none;
  max-height: 320px; overflow-y: auto;
  background: var(--panel-solid); border: 1px solid var(--border-strong);
  border-radius: var(--radius-control); box-shadow: var(--elev-float);
}
.lyn-forslag-tom {
  position: absolute; left: 0; right: 0; top: 4px; z-index: 30;
  padding: 10px 12px; font-size: 13px; color: var(--ink-2);
  background: var(--panel-solid); border: 1px solid var(--border);
  border-radius: var(--radius-control); box-shadow: var(--elev-float);
}
.lyn-forslag-rad { margin: 0; padding: 0; }
.lyn-forslag-knap {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: 0; background: transparent; cursor: pointer;
  text-align: left; border-radius: 8px; color: var(--ink);
}
.lyn-forslag-knap:hover,
.lyn-forslag-knap.markeret { background: var(--accent-soft); }
.lyn-forslag-knap.markeret { outline: 2px solid var(--accent); outline-offset: -2px; }
.lyn-forslag-navn { flex: 1 1 auto; min-width: 0; display: block; }
.lyn-forslag-navn b { display: block; font-size: 13.5px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lyn-forslag-navn span { display: block; font-size: 11.5px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lyn-forslag-sum { flex: none; font-size: 13px; }
/* D3 (26-09): «2 pakker hedder …». --amber-tx er tema-tokenet (lyst og
   moerkt har hver sin vaerdi), saa advarslen ikke skal bære egen hex. */
.lyn-forslag-navn .lyn-forslag-advarsel { color: var(--amber-tx); font-weight: 600; }
.lyn-forslag-tast { flex: none; font-size: 11px; color: var(--ink-2); }

.lyn-ic {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 9px;
  background: var(--accent-soft); color: var(--accent-soft-tx);
  font-size: 11.5px; font-weight: 700; font-family: var(--font-mono);
}
.lyn-ic-amber { background: var(--amber-bg); color: var(--amber-tx); }

/* ── LINJEKORTENE ────────────────────────────────────────────────────── */
.lyn-grp {
  display: flex; align-items: baseline; gap: 10px;
  margin: 14px 2px 6px; font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2); font-weight: 700;
}
.lyn-grp-top { margin-top: 22px; }
.lyn-grp-note { margin-left: auto; text-transform: none; letter-spacing: 0;
  font-weight: 400; font-size: 11.5px; }

.lyn-linjer { display: flex; flex-direction: column; gap: 6px; }
/* C4 (26-09): softphone-knappen (fixed, 56x56, 16 px fra hjoernet — se
   softphone/widget.html) daekkede linjens «⋯» naar linjen stod nederst.
   MAALT: «⋯» sidder ved vw−45 i HELE intervallet 900–1599 px, knappen
   starter ved vw−72. Fra 1600 staar forhaandsvisningen ved siden af
   linjerne (reglen laengere nede), og under 900 skjuler mobil-laget
   knappen paa detaljesider — derfor kun dette interval, og kun naar
   widgetten findes. 36 px = 27 px overlap + 9 px luft. */
@media (min-width: 900px) and (max-width: 1599px) {
  body:has(#softphone-root) .lyn-linjer { padding-right: 36px; }
}
.lyn-linje {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 22px minmax(0, 1fr) auto 92px 116px 104px 44px;
  padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius-control); background: var(--panel-solid);
}
.lyn-linje:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* 🔴 PLACERING PR. KLASSE, IKKE PR. SOESKENDE-RAEKKEFOELGE (05-09-2026).
   Gitteret ovenfor har SEKS spor UBETINGET, men TO af boernene renderes kun
   naar linjen kan redigeres: `.lyn-greb` (spor 1) og `.lyn-mere` (spor 6) staar
   bag `{% if kan %}` i `_lyn_komposer.html`. Paa et SENDT tilbud er der derfor
   FIRE boern i seks spor, og auto-placeringen skubbede hvert af dem ét spor til
   venstre — beskrivelsen landede i grebets 22px-spor.

   MAALT 05-09 paa `133542aaa`, sendt tilbud, rendret flade:
       1440px   .lyn-desc 22px · .lyn-stepper 599px · .lyn-pris 199px
       1920px   .lyn-desc 22px · .lyn-stepper 434px · .lyn-pris 199px
   🔴 BREDDEN LOESER DET IKKE: kun spor 2 vokser, og spor 2 var antalsfeltet.
   Beskrivelsen var 22px ved ALLE maalte bredder.

   ⚠️ HVORFOR IKKE EN GITTERDEFINITION PR. TILSTAND, og hvorfor ikke et
   altid-rendret, skjult greb: begge goer LAYOUTET afhaengigt af TILSTANDEN.
   Her er det kun PLACERINGEN der bindes, og den bindes til hvad elementet ER.
   Foelgen er maalt, ikke haabet — den redigerbare tilstand er BIT-IDENTISK
   foer/efter (1440px: greb 28 · desc 686 · stepper 112 · pris 116 · tot 104 ·
   mere 34, samme x paa alle seks), og paa det sendte tilbud staar `.lyn-pris`
   og `.lyn-tot` i PRAECIS samme x som paa kladden. Et tilbud der gaar fra
   kladde til sendt flytter altsaa ikke et eneste tal.
   (Den maalte tredje form — `auto` i spor 1 og 6, saa de tomme spor falder
   sammen — gav 816px i stedet for 750px til beskrivelsen, men flyttede
   ⋯-sporet 44px -> 34px og dermed HELE talblokken 10px paa den REDIGERBARE
   flade. Det er en aendring af den flade Andreas ser, for 66px.)

   ⚠️ MOBIL-LAGET RAMMES IKKE: `forta-mobil.css` indlaeses EFTER denne fil
   (base.html:75 mod :86) og placerer med `grid-area`, som er en shorthand der
   ogsaa saetter kolonnen. Maalt ved 393px: bit-identisk foer/efter i begge
   tilstande. */
/* ENHEDEN (tilbudenhed 27-09-2026) fik sit eget, FASTE spor 4 (92px) — ikke
   `auto`. Et auto-spor ville falde sammen paa et sendt tilbud (valget
   renderes kun paa en kladde) og saa give de to tilstande forskellige
   sporlister; med et fast spor staar `.lyn-pris` og `.lyn-tot` paa samme x
   i begge, som reglen ovenfor kraever. Prisen er 102px (spor + gap) fra
   beskrivelsen. Vaern: tests/test_tilbud_lynlinje_gitter.py. */
.lyn-greb    { grid-column: 1; }
.lyn-desc    { grid-column: 2; }
.lyn-stepper { grid-column: 3; }
.lyn-enhed   { grid-column: 4; }
.lyn-pris    { grid-column: 5; }
.lyn-tot     { grid-column: 6; }
.lyn-mere    { grid-column: 7; }
.lyn-linje-spoegelse { opacity: .45; border-style: dashed; }
/* F08 · TEKSTLINJEN (27-09-2026): en linje uden beloeb. Samme kort, samme
   greb og ⋯ som varelinjen — beskrivelsen spaender over de fem spor hvor
   antal, enhed, pris og total ellers staar (2 / 7). Tomme talfelter med
   «0,00» ville sige noget der ikke er sandt. Teksten er fed som
   tekstblokkenes overskrift (`.lyn-blok-titel`), saa de to laeses som
   samme slags ting; de er stadig adskilte (se skabelonen). */
.lyn-linje-tekst > .lyn-desc { grid-column: 2 / 7; }
.lyn-tekstlinje-input, .lyn-tekstlinje-vis { font-weight: 600; }

.lyn-greb {
  cursor: grab; color: var(--ink-2); font-size: 15px; line-height: 1;
  text-align: center; user-select: none;
  /* 28×56 px (rapportens §4.1) — det er greb-maalet, ikke §31.6's 44×44:
     grebet findes KUN paa skrivebordet, hvor pegeredskabet er en mus. */
  width: 28px; height: 56px; display: flex; align-items: center;
  justify-content: center; margin: -8px 0 -8px -6px;
}
.lyn-greb:active { cursor: grabbing; }

.lyn-desc { min-width: 0; }
.lyn-desc-input {
  /* <textarea rows="1"> — se skabelonens note. Den ligner et enkeltlinjes
     felt indtil teksten ikke kan vaere der, og vokser saa (JS: `voksFelt`). */
  display: block; width: 100%; border: 0; background: transparent;
  padding: 2px 0; margin: 0; resize: none; overflow: hidden;
  font-family: inherit; font-size: 13.5px; font-weight: 600;
  line-height: 1.35; color: var(--ink);
  border-bottom: 1px solid transparent;
}
.lyn-desc-input:hover { border-bottom-color: var(--border); }
.lyn-desc-input:focus { outline: none; border-bottom-color: var(--accent); }
.lyn-desc-meta { display: block; font-size: 11.5px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lyn-mini-pill {
  display: inline-block; padding: 0 6px; border-radius: var(--radius-pill);
  background: var(--bg-panel-2); font-size: 10.5px;
}

.lyn-stepper {
  display: inline-flex; align-items: center;
  border: 1px solid var(--border); border-radius: var(--radius-control);
  overflow: hidden; background: var(--panel-solid);
}
.lyn-step {
  width: 32px; height: 32px; border: 0; background: transparent;
  color: var(--ink-2); font-size: 16px; line-height: 1; cursor: pointer;
}
.lyn-step:hover { background: var(--accent-soft); color: var(--accent-soft-tx); }
.lyn-step:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lyn-antal {
  width: 46px; border: 0; background: transparent; text-align: center;
  font-size: 13.5px; color: var(--ink); font-family: var(--font-mono);
  padding: 6px 0;
}
.lyn-antal:focus { outline: none; background: var(--accent-soft); }

/* Enhedsvalget ER husets `.form-select` (samme klasse som ordrens
   linjemodal, med husets egen pil og §22's 38px). Her staar kun det
   linjekortet selv kraever: sporet er 92px, saa teksten maa kunne klippes. */
.lyn-enhed { min-width: 0; text-overflow: ellipsis; }

.lyn-pris { display: flex; flex-direction: column; align-items: flex-end; }
.lyn-pris-input {
  width: 100%; border: 1px solid transparent; background: transparent;
  text-align: right; font-size: 13.5px; color: var(--ink); padding: 5px 6px;
  border-radius: 7px;
}
.lyn-pris-input:hover { border-color: var(--border); }
.lyn-pris-input:focus { outline: none; border-color: var(--accent);
  background: var(--panel-solid); }
.lyn-rabat { font-size: 11px; color: var(--amber-tx); }

.lyn-tot { text-align: right; font-size: 13.5px; font-weight: 600;
  color: var(--ink); }

.lyn-mere {
  width: 34px; height: 34px; border: 1px solid transparent;
  border-radius: 9px; background: transparent; color: var(--ink-2);
  font-size: 16px; line-height: 1; cursor: pointer;
}
.lyn-mere:hover { border-color: var(--border); color: var(--ink); }
.lyn-mere:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lyn-mere[aria-expanded="true"] { background: var(--accent-soft);
  color: var(--accent-soft-tx); }

/* ── ⋯-PANELET (ikke en modal — det folder ud UNDER sin egen linje) ──── */
.lyn-merepanel {
  margin: -2px 0 6px; padding: 12px 14px;
  border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 var(--radius-control) var(--radius-control);
  background: var(--bg-panel-2);
  display: flex; flex-direction: column; gap: 12px;
}
.lyn-merepanel-felt label { display: block; font-size: 11.5px;
  color: var(--ink-2); margin-bottom: 4px; }
.lyn-merepanel-felt textarea {
  width: 100%; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel-solid); color: var(--ink); padding: 8px 10px;
  font-size: 13px; font-family: inherit; resize: vertical;
}
.lyn-merepanel-raekke { display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap; }
.lyn-merepanel-label { font-size: 11.5px; color: var(--ink-2); min-width: 130px; }
.lyn-rabat-felt { display: inline-flex; align-items: center; gap: 4px; }
.lyn-rabat-felt input { width: 74px; text-align: right; padding: 6px 8px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel-solid); color: var(--ink); font-size: 13px; }
.lyn-rabat-felt span { font-size: 12px; color: var(--ink-2); }
.lyn-merepanel-handlinger { display: flex; gap: 8px; flex-wrap: wrap; }
.lyn-hnd {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 34px; padding: 0 12px; cursor: pointer;
  border: 1px solid var(--bd-control); border-radius: var(--radius-control);
  background: var(--panel-solid); color: var(--ink-2);
  font-size: 12.5px; text-decoration: none;
}
.lyn-hnd:hover { border-color: var(--accent); color: var(--ink); }
.lyn-hnd-fare { color: var(--red-tx); border-color: var(--red-bd); }
.lyn-hnd-fare:hover { background: var(--red-bg); border-color: var(--red-tx); }
.lyn-billedvalg:empty { display: none; }

.lyn-tom { padding: 26px 0; text-align: center; color: var(--ink-2); }
.lyn-tom p { margin: 0 0 4px; }

/* ── TEKSTBLOKKENE SOM SEKTION (tekstblokredigering 27-09-2026) ─────────
   Tilbuddets KOPI af hver valgt blok, i samme kort-form som linjerne:
   greb · indhold · ⋯. Tre spor frem for linjernes seks — en blok har intet
   antal, ingen pris og ingen total, og en tom kolonne til dem ville sige
   noget der ikke er sandt. Samme ramme, radius og flade som `.lyn-linje`,
   saa de laeses som «samme slags ting» (Andreas: «på samme måde som de
   andre»). Egen klasse og IKKE `.lyn-linje`: linjegitteret og dets vagt
   (test_tilbud_lynlinje_gitter) handler om talkolonner. */
.lyn-blok-plac { margin: 10px 2px 4px; font-size: 11.5px; color: var(--ink-2); }
.lyn-blokliste { display: flex; flex-direction: column; gap: 6px; }
@media (min-width: 900px) and (max-width: 1599px) {
  body:has(#softphone-root) .lyn-blokliste { padding-right: 36px; }
}
.lyn-blok {
  display: grid; align-items: start; gap: 10px;
  grid-template-columns: 22px minmax(0, 1fr) 44px;
  padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius-control); background: var(--panel-solid);
}
.lyn-blok:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Placering pr. klasse (samme grund som linjerne): `.lyn-greb` og `.lyn-mere`
   har globale `grid-column: 1 / 6` fra linjegitteret. */
.lyn-blok > .lyn-greb { grid-column: 1; margin-top: -8px; }
.lyn-blok > .lyn-blok-krop { grid-column: 2; min-width: 0; }
.lyn-blok > .lyn-mere { grid-column: 3; }
.lyn-blok-titel, .lyn-blok-tekst {
  display: block; width: 100%; border: 0; background: transparent;
  padding: 2px 0; margin: 0; font-family: inherit; color: var(--ink);
  border-bottom: 1px solid transparent;
}
.lyn-blok-titel { font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.lyn-blok-titel::placeholder { color: var(--ink-2); font-weight: 400; }
.lyn-blok-tekst { font-size: 13px; line-height: 1.45; resize: none;
  overflow: hidden; margin-top: 2px; }
.lyn-blok-titel:hover, .lyn-blok-tekst:hover { border-bottom-color: var(--border); }
.lyn-blok-titel:focus, .lyn-blok-tekst:focus { outline: none;
  border-bottom-color: var(--accent); }
.lyn-blok-titel-vis { display: block; font-size: 13.5px; color: var(--ink); }
.lyn-blok-resume { margin: 2px 0 0; font-size: 13px; color: var(--ink-2);
  white-space: pre-line; }
.lyn-blok-meta { display: flex; flex-wrap: wrap; align-items: center;
  gap: 6px; margin-top: 4px; font-size: 11.5px; color: var(--ink-2); }
.lyn-blok-meta [data-afviger] { color: var(--amber-tx); }
.lyn-linkknap { border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; color: var(--accent-link); text-decoration: underline; }
.lyn-linkknap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── TEKSTBLOK-CHIPS ─────────────────────────────────────────────────── */
.lyn-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.lyn-chip {
  display: inline-flex; align-items: center; min-height: 32px;
  padding: 0 13px; cursor: pointer; text-decoration: none;
  border: 1px solid var(--chip-bd); border-radius: var(--radius-pill);
  background: var(--chip); color: var(--ink-2); font-size: 12.5px;
}
.lyn-chip:hover { border-color: var(--accent); color: var(--ink); }
.lyn-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.lyn-chip.on {
  background: var(--accent-soft); border-color: var(--accent);
  color: var(--accent-soft-tx); font-weight: 600;
}
.lyn-chip.on::before { content: '✓'; margin-right: 6px; font-size: 11px; }
.lyn-chip[disabled] { opacity: .55; cursor: default; }
.lyn-chip-ny { border-style: dashed; color: var(--ink-2); }

/* ── BUNDEN: UNDERSKRIFT · GYLDIGHED · TOTAL ─────────────────────────── */
/* 🔴 `flex-start`, IKKE `flex-end` (tekstblokredigering 27-09-2026).
   Andreas: «Står skævt overfor hinanden». MAALT i Chromium ved 1400/1280:
   Underskrift-etiketten stod 24 px OVER Gyldig til-etiketten. Grunden var
   bund-justeringen: Underskrift-gruppen baerer en hjaelpetekst UNDER
   kontrollen («MitID er ikke bygget endnu.»), saa dens bund laa lavere, og
   `flex-end` skubbede hele gruppen op. Top-justeret flugter etiketterne og
   kontrollerne, og hjaelpeteksten haenger under sin egen gruppe uden at
   roere naboen. Vagt: tests/test_lyn_bund_flugter_browser.py. */
.lyn-foot {
  display: flex; align-items: flex-start; gap: 26px; flex-wrap: wrap;
  margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--border);
}
.lyn-foot-felt { min-width: 0; }
.lyn-foot-label { font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-2); font-weight: 700;
  margin-bottom: 6px; }
.lyn-foot-hint { text-transform: none; letter-spacing: 0; font-weight: 400;
  margin-left: 6px; }
.lyn-foot-laast { display: block; margin-top: 5px; font-size: 11.5px;
  color: var(--amber-tx); max-width: 42ch; }

.lyn-seg {
  display: inline-flex; border: 1px solid var(--bd-control);
  border-radius: var(--radius-control); overflow: hidden;
  background: var(--panel-solid);
}
.lyn-seg-knap {
  min-height: 34px; padding: 0 14px; border: 0; cursor: pointer;
  background: transparent; color: var(--ink-2); font-size: 12.5px;
  border-right: 1px solid var(--border);
}
.lyn-seg-knap:last-child { border-right: 0; }
.lyn-seg-knap:hover:not([disabled]) { background: var(--accent-soft); }
.lyn-seg-knap:focus-visible { outline: 2px solid var(--accent);
  outline-offset: -2px; }
.lyn-seg-knap.on {
  background: var(--accent-strong); color: #fff; font-weight: 600;
}
.lyn-seg-knap[disabled] { opacity: .55; cursor: default; }

/* `.lyn-dato` er INDPAKNINGEN (husets `.datofelt`, 23-09-2026) — rammen
   sidder paa tekstfeltet inden i, ellers tegnes to kanter. Hoejre-padding
   giver plads til kalender-ikonet (.datofelt-tekst's 38px). */
.lyn-dato .datofelt-tekst {
  min-height: 34px; padding: 0 38px 0 10px; font-size: 13px;
  border: 1px solid var(--bd-control); border-radius: var(--radius-control);
  background: var(--panel-solid); color: var(--ink);
}
/* ⑥ HURTIGVALG TIL «GYLDIG TIL». De to knapper og datofeltet er ÉN
   kontrol-gruppe: samme hoejde, samme kant, samme radius, saa de laeses som
   tre valg af samme slags og ikke som «to knapper og et felt».
   `flex-wrap` fordi 393px ikke rummer «+30 dage · +14 dage · dd-mm-åååå»
   paa én linje — det maalte alternativ er at klippe datofeltet. */
.lyn-datovalg { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* 36 px = segmentets YDRE hoejde (34 px knap + 1 px kant over og under i
   `.lyn-seg`). Uden det stod gyldighedens tre kontroller 2 px lavere end
   underskriftens segment ved siden af — maalt, samme vagt som ovenfor.
   Kun paa skrivebordet: under 899px stables grupperne, og §31.6's 44 px
   (forta-mobil.css) maa ikke kunne tabe til en regel med flere klasser. */
.lyn-datoknap {
  border: 1px solid var(--bd-control); border-radius: var(--radius-control);
  background: var(--panel-solid);
}
@media (min-width: 900px) {
  .lyn-datoknap,
  .lyn-datovalg .lyn-dato .datofelt-tekst { min-height: 36px; }
}
.lyn-datoknap:last-child { border-right: 1px solid var(--bd-control); }
.lyn-datoknap.on { border-color: var(--accent-strong); }
/* ① «Beløbet kommer med den første linje» — teksten der staar hvor nullet
   stod. Samme daempning som `.lyn-total small`, saa den ikke konkurrerer med
   kommandofeltet om opmaerksomheden. */
.lyn-total-tom { font-size: 12px; color: var(--ink-2); }
.lyn-total { margin-left: auto; text-align: right; }
.lyn-total small { display: block; font-size: 11px; color: var(--ink-2); }
/* Maanedsbeloebet under engangstotalen (tilbudopus B5/F05, 26-09-2026):
   samme daempning som etiketten, saa «At betale nu» stadig er tallet. */
.lyn-total-md { display: block; font-size: 11px; color: var(--ink-2); }
.lyn-total-md b { font-size: 12.5px; color: var(--ink); }

/* ── Kundekortets Abonnementer: den grå beskrivelseslinje på ÉN linje
   (kunder/_tab_abonnementer.html, `data-abonnement-graa`). Stod inline indtil
   app4fix K2 (02-10-2026) og slog dermed mobil-lagets `.kun-skrivebord
   { display:none }`, så linjen renderede på telefonen. `:where()` giver
   reglen specificitet 0: `.kun-skrivebord` vinder altid, uanset hvilket ark
   der indlæses sidst. */
:where(.abo-graa-linje) {
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── «Linje slettet · Fortryd» (tilbudopus 26-09-2026, static/js/fortryd.js).
   Nederst i midten; paa telefon OVER bundnavigationen (se mobil-laget).
   Knappen er 44 px hoej (§31.6) og har accentens tekstfarve paa panelet. */
.fortryd-toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 1200; display: flex; align-items: center; gap: 12px;
  max-width: min(560px, calc(100vw - 32px));
  padding: 6px 6px 6px 16px; border-radius: 12px;
  background: var(--bg-panel); color: var(--ink);
  border: 1px solid var(--bd-panel);
  box-shadow: var(--shadow-float);
  font-size: 14px;
}
/* Hed indtil 26-09 (fortrydfelt) `white-space: nowrap` med ellipse. Det
   holdt til «Linje slettet «navn»», men en RETTELSE siger hvad der skete
   («antal 3 → 5 · Support»), og på 393 px klippede ellipsen netop tallene.
   Nu højst to linjer; knappen bliver 44 px uanset. */
.fortryd-tekst {
  min-width: 0; overflow: hidden; line-height: 1.3;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  line-clamp: 2; overflow-wrap: anywhere;
}
.fortryd-knap {
  flex: none; min-height: 44px; min-width: 44px; padding: 0 16px;
  border: 1px solid var(--accent); border-radius: var(--radius-control);
  background: transparent; color: var(--accent-link); font-weight: 700; cursor: pointer;
}
.fortryd-knap:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.fortryd-knap[disabled] { opacity: .6; cursor: default; }
.lyn-total b { font-size: 22px; color: var(--ink); }

/* ── SEND ────────────────────────────────────────────────────────────── */
.lyn-send { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap;
  align-items: center; }
.lyn-send-primaer {
  flex: 1 1 260px; min-height: 46px; padding: 0 20px; cursor: pointer;
  border: 0; border-radius: var(--radius-control);
  background: var(--grad-btn);
  /* 🔴 HVID I LYST TEMA, MOERK I MOERKT — fordi --grad-btn skifter side.
     Lyst tema: --grad-btn er MOERK (#104D5E -> #15697E); hvid 9,35 / 6,26.
     Moerkt tema: den LYSE turkis; dér er hvid 3,47:1 og #08131F rigtig
     (regel i forta-dark.css og forta-mobil.css).
     Hed indtil 26-09-2026 «IKKE HVID» uden tema — det var sandt om den
     lyse turkis og gav 2,00 / 2,99:1 i lyst tema (tilbudopus A3).
     Vagt: tests/test_lyn_sendknap_kontrast.py. */
  color: #fff;
  font-size: 14.5px; font-weight: 700;
}
.lyn-send-primaer[disabled] { opacity: .5; cursor: default; }
.lyn-send-primaer:focus-visible { outline: 3px solid var(--accent);
  outline-offset: 2px; }
.lyn-send-sekundaer {
  min-height: 46px; padding: 0 18px; cursor: pointer;
  border: 1px solid var(--bd-control); border-radius: var(--radius-control);
  background: var(--panel-solid); color: var(--ink-2); font-size: 13.5px;
}
.lyn-send-sekundaer:hover { border-color: var(--accent); color: var(--ink); }
.lyn-send-grund { font-size: 11.5px; color: var(--ink-2); max-width: 44ch; }

/* ── ARBEJDSFLADEN: KOMPOSER + KUNDENS SIDE SIDE OM SIDE ─────────────── */
/* «Hoejre side viser kundens side live» (rapportens §4.1, punkt 6).
   🔴 FOERST VED 1600px — OG TALLET ER MAALT, IKKE VALGT.
   Foerste udgave sagde 1280. Et skud ved 1440×1000 (03-09, tilbud 40002 i
   dev-seeden) viste hvad det kostede: sidebaren tager 220px, forhaands-
   visningen 400px, og linjekortets tal-kolonner ~264px — saa
   beskrivelsen fik ~250px og blev klippet midt i ordet:
       «Overvågningskameraopsætning inkl. kab|»
       «Adgangskontrolsystem — montering, prog|»
   Et <input> klipper uden ellipse, saa der er ikke engang et «…» der
   siger at der staar mere. En saelger der ikke kan laese hvad han saelger,
   er en daarligere byttehandel end en forhaandsvisning der maa foldes ud.
   Ved 1600px er indholdsbredden ~1300, komposeren ~880 og beskrivelsen
   ~410px — nok til de laengste varenavne i seeden.
   Under graensen staar panelet under komposeren; det er stadig AABENT paa
   linjer-fanen, saa det er en rulning vaek, ikke et klik. */
/* 🔴 425px OG IKKE 400 — TALLET ER MAALT MOD KUNDENS TELEFON (04-09-2026).
   MAALT foer: kolonnen 400px gav en iframe paa 366px, og BAADE kundesidens
   mobil-blok OG dens <=480-blok var aktive derinde. 366px er en bredde intet
   kundeapparat har; sælgeren saa hverken kundens telefon eller kundens
   skrivebord, men en tredje ombrydning der ikke findes i verden.
   🔴 TALLET ER MAALT FREM, IKKE REGNET FREM — OG FOERSTE REGNESTYKKE VAR
   FORKERT. Rapportens forslag var 425px «saa iframen bliver 393». MAALT ved
   1920 og 1600 med 425: iframens ydre kasse 391 px og dokumentets viewport
   inde i den **389** px. Kaeden aeder 36 px, ikke 32: `calc(100% - 32px)`
   plus <details>' egen 1px kant i hver side plus iframens egen 1px kant i
   hver side. 429 giver de fire tilbage.
   MAALT EFTER (429, dokumentets EGEN `documentElement.clientWidth` inde i
   rammen, ikke elementets rect): 393 px ved baade 1920 og 1600.
   ⚠️ MAAL INDEFRA, IKKE UDEFRA. `getBoundingClientRect().width` paa
   <iframe> er kassen INKLUSIVE dens kant; det er ikke den bredde kundens
   dokument ombryder efter. Forskellen er praecis de 2 px der gjorde at
   «391» saa ud som «taet nok paa 393». */
@media (min-width: 1600px) {
  .lyn-arbejde[data-lyn-tab="linjer"] {
    display: grid; grid-template-columns: minmax(0, 1fr) 429px;
    gap: 20px; align-items: start;
  }
  .lyn-arbejde[data-lyn-tab="linjer"] > .tz-forhaandsvisning {
    position: sticky; top: 16px; margin: 0;
  }
  .lyn-arbejde[data-lyn-tab="linjer"] > .tz-forhaandsvisning iframe {
    height: 62vh;
  }
}

/* ── LISTENS KOMMANDOFELT (/tilbud) ──────────────────────────────────── */
.lyn-opret { margin: 0 0 18px; max-width: 640px; }
/* Etiket + raekke (27-09-2026, Andreas: «mere tydeligt»). Feltet har SAMME
   hoejde som listens soegefelt lige under (38 px, app.src.css §22; 44 under
   899px i forta-mobil.css) — to tekstfelter over hinanden i hver sin hoejde
   ser ud som to slags ting. Knappen er husets .btn-primary; kun dens plads i
   raekken saettes her. */
.lyn-opret-etiket {
  display: block; margin: 0 0 6px;
  font-size: 13px; font-weight: 600; color: var(--ink);
}
.lyn-opret-raekke { display: flex; align-items: stretch; gap: 8px; }
.lyn-opret-raekke .lyn-cmd {
  flex: 1 1 auto; min-width: 0; min-height: 38px;
  /* Kanten skal kunne SES (WCAG 1.4.11: 3:1 mod fladen). `--border-strong`
     er #BDD5DB paa hvid = 1,4:1. En blanding af temaets egen tekstfarve
     vender med temaet og kraever ingen hex pr. tema. Maalt i Chromium,
     se leverancen. */
  border-color: color-mix(in srgb, var(--ink) 55%, transparent);
}
/* 🔴 FOKUS SKAL GENTAGES PAA SAMME SPECIFICITET. Reglen ovenfor (0,2,0)
   slaar `.lyn-cmd:focus-within` (0,2,0, TIDLIGERE i filen) — maalt 27-09:
   kanten blev ikke turkis ved fokus. */
.lyn-opret-raekke .lyn-cmd:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.lyn-opret .lyn-cmd-input { padding: 6px 0; }
.lyn-opret-knap { flex: none; white-space: nowrap; }

/* ── BILLEDVALGET I ⋯-PANELET ────────────────────────────────────────── */
.lyn-bv { display: flex; flex-direction: column; gap: 10px;
  padding-top: 4px; border-top: 1px dashed var(--border); }
.lyn-bv-soeg { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.lyn-bv-soeg label { font-size: 11.5px; color: var(--ink-2); }
.lyn-bv-soeg input { flex: 1 1 160px; min-width: 0; padding: 6px 9px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel-solid); color: var(--ink); font-size: 13px; }
.lyn-bv-galleri {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
}
.lyn-bv-valg {
  display: flex; align-items: center; justify-content: center;
  min-height: 76px; padding: 4px; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-control);
  background: var(--panel-solid); color: var(--ink-2); font-size: 11.5px;
}
.lyn-bv-valg img { max-width: 100%; height: 66px; object-fit: contain; }
.lyn-bv-valg:hover { border-color: var(--accent); }
.lyn-bv-valg:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 🔴 DET VALGTE SKAL KUNNE SES. Et galleri hvor intet er markeret, kan ikke
   fortaelle om linjen allerede HAR et billede — og saa vaelger man det igen
   for en sikkerheds skyld. */
.lyn-bv-valg.on { border-color: var(--accent); border-width: 2px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }

/* Kvitteringen for et gem der ikke har en knap. Se skabelonens note. */
.lyn-gemt {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 0 12px; padding: 4px 10px;
  border: 1px solid var(--green-bd); background: var(--green-bg);
  color: var(--green-tx); border-radius: var(--radius-pill);
  font-size: 12px;
}

/* §32.4 — advarslen paa kundeforslaget. Se skabelonens note. */
.lyn-advarsel { display: block; font-size: 11px; font-weight: 600; margin-top: 2px; }
.lyn-advarsel-roed { color: var(--red-tx); }
.lyn-advarsel-amber { color: var(--amber-tx); }
.lyn-ic-roed { background: var(--red-bg); color: var(--red-tx); }
.lyn-forslag-spaerret { opacity: .72; cursor: not-allowed; }

/* ══ .mailkrop — BEHOLDEREN OM EN FREMMED MAILS HTML ══════════════════════
   🔴 DET HER ER ET SIKKERHEDSKRAV, IKKE STYLING, og kravet er skrevet ned et
   andet sted end her. `core/mail_sanering.py`s eget hoved forklarer hvorfor
   mail-profilen tillader `div` og `span` — indgaaende forretningsmail ER
   tabel-layout, og signeringssidens snaevre liste maser
   «Fakturanr4711» sammen uden separator, hvilket er vaerre end tabt
   formatering fordi det LIGNER indhold. Og saa skriver modulet:

       «resten af den halvdel er et KRAV TIL FLADEN, ikke til dette modul:
        mailkroppen skal males i en beholder med egen stacking-kontekst og
        overflow:hidden. Det bygges i UI-runden.»

   Det er denne runde. Beholderen er den anden halvdel af en begrundelse der
   ellers kun var halvt indfriet: renseren slipper `div`/`span` ind, og en
   generisk beholder er praecis det man bygger et fuldskaerms-overlay af.
   Stil-listen slipper kun `text-align` igennem, saa `position:fixed` kan
   ikke naa hertil ad den vej — men `!important` herunder er billigt og
   goer det UMULIGT frem for usandsynligt.

   Vagt: tests/test_mailind_ui.py::test_mailkroppen_kan_ikke_daekke_fladen.

   ⚠️ REGLEN LEVER I forta-core.css OG IKKE I MOBIL-LAGET. §31.2's lag er for
   layout under 899px; en fremmed mails HTML er lige farlig paa en 27-tommer.
   En regel der kun findes i et media-lag, findes ikke paa skrivebordet. */
.mailkrop {
  /* Egen stacking-kontekst: `isolation` uden bivirkninger paa layoutet.
     Et `z-index` inde i mailen kan derefter ikke naa OVER husets egen
     chrome — det hoejeste den kan naa, er toppen af denne kasse. */
  isolation: isolate;
  /* Intet maa stikke ud af kassen — hverken en bred tabel eller et element
     med negative margener. `auto` og ikke `hidden` paa X-aksen: en
     prisliste er bredere end en telefon, og §31.4 forbyder vandret rulning
     paa `<body>`, ikke i en beholder der ejer sin egen. */
  overflow-x: auto;
  overflow-y: hidden;
  position: relative;
  max-width: 100%;
  /* Afsenderens tekst arver ikke husets typografi-skala ukritisk; mailen
     skal se ud som en mail og ikke som en Forta-flade. */
  font-size: 14px;
  line-height: 1.5;
  word-break: break-word;
}
/* 🔴 INTET INDE I MAILEN MAA FORLADE KASSEN. `position:fixed` ville tage
   hele viewporten uanset forfaedrenes `overflow`; `sticky` ville klaebe til
   rullebeholderen. Begge er neutraliseret ved ROD — én regel paa `*` frem
   for en attribut-selektor paa `[style*="fixed"]`, fordi en strengsoegning i
   et attribut kan omgaas (mellemrum, versaler, en `<style>`-blok) mens
   `position` som egenskab ikke kan.

   ⚠️ OG DER STAAR IKKE `max-width` HER. Foerste udgave havde
   `* { max-width: 100% !important }`, og den ville have TAGET DEN BREDE
   TABEL TILBAGE: en prisliste bredere end kassen ville blive presset sammen
   i stedet for at rulle — altsaa praecis den sammenmasning mail-profilen
   findes for at undgaa, blot udfoert af CSS i stedet for af saneringen.
   Loftet hoerer paa `img`, hvor det ikke koster noget. */
.mailkrop * { position: static !important; }
/* Tabellen er hele grunden til at mail-profilen er bredere end
   signeringssidens. Den skal kunne LAESES — celler uden luft er den
   sammenmasning saneringen netop undgik. */
.mailkrop table { border-collapse: collapse; }
.mailkrop td, .mailkrop th { padding: 2px 8px; vertical-align: top; }
.mailkrop img { max-width: 100%; height: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   M365-VARSLET PAA SEND-FLADERNE — spor `mailbanner` (2026-09-12)
   ══════════════════════════════════════════════════════════════════════════
   Tegnes af `_components/_m365_varsel.html`, som `tech/services/m365_varsel`
   fylder. Staar HER og ikke inline i de to skabeloner, fordi begge viser
   samme varsel: to inline-kopier ville betyde at den ene bliver rettet.

   ── FARVEVALGET ─────────────────────────────────────────────────────────
   Amber (--amber-bg / --amber-tx / --amber-bd), IKKE roed. Roed betyder FEJL
   i huset, og her er der endnu ikke sket noget galt — det er hele pointen at
   varslet kommer FOER fejlen. Samme begrundelse som kundedisplay-pulsen
   (~l. 2570), og samme grund til at det er TOKENS og ikke literaler:
   forta-dark.css redefinerer alle tre, saa moerkt tema kommer gratis og
   white-label roerer dem ikke.

   ── 🔴 §31.6: HANDLINGEN ER 44px VED ENHVER BREDDE, IKKE KUN UNDER 899 ────
   `min-height` paa et INLINE element goer ingenting; derfor `inline-flex`.
   Og maalet staar i BASISLAGET frem for i forta-mobil.css' §31.6-blok: den
   blok naas kun under 899px, og en regel der kun gaelder ét sted kan kun
   maales ét sted. 44 ved alle bredder er en STAERKERE paastand end 44 under
   breakpointet, og den kan ikke tabes af at nogen aendrer en media query.

   ── 🔴 :hover ROERER INGEN KONTRASTBAERENDE FLADE ────────────────────────
   Foerste udkast lagde en tonet baggrund paa hover. Den ville aendre fladen
   under teksten, saa det maalte forhold kun gjaldt den ene af to tilstande —
   samme faelde som en puls der animerer `background`. Understregning
   aendrer ingen farve, og kontrasten er derfor ÉT tal og ikke to.

   ── KONTRAST (regnet af tokens i tests/test_m365_varsel_flade.py) ────────
   Tallene skrives IKKE af her. `--amber-tx` er allerede moerknet to gange i
   huset (#946B00 -> #8A6300 -> #815C00), og en kommentar falder ikke med.
   Vaernet laeser tokens ud af forta-core.css (lys) og forta-dark.css (moerk)
   og regner WCAG forfra, i begge temaer, mod BEGGE de flader varslet staar
   paa (--bg-panel i modalen). Kravet er AA-tekst 4,50.
   ══════════════════════════════════════════════════════════════════════ */
.m365-varsel {
  background: var(--amber-bg);
  border: 1px solid var(--amber-bd);
  border-radius: 0.5rem;
  padding: 0.75rem 0.9rem;
  color: var(--amber-tx);
}
.m365-varsel-h {
  margin: 0 0 0.25rem 0;
  font-weight: 700;
  font-size: 0.875rem;
  color: var(--amber-tx);
}
.m365-varsel-t {
  margin: 0 0 0.7rem 0;
  font-size: 0.8125rem;
  color: var(--amber-tx);
}
.m365-varsel-knap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1.5px solid var(--amber-tx);
  background: transparent;
  color: var(--amber-tx);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
}
.m365-varsel-knap:hover,
.m365-varsel-knap:focus-visible {
  text-decoration: underline;
}

/* =====================================================================
   VIDEREFAKTURERING — designløft 18-09-2026 (Andreas: «de kan godt blive
   noget pænere og mere brugervenlige»). Modulets flader havde ~60 inline
   `style=`-attributter og ingen egen regel; det der gentages står nu her.

   Forløbslinjen (.vf-forloeb): månedens tre skridt — Godkend → Fakturér →
   Bogfør — som §17.3-KPI-kort der ER links til deres sektion. Et trin med
   noget at gøre bærer accent-kanten; et tomt trin er dæmpet, så øjet
   lander på det der venter. Kortene genbruger .kpi/.kpi-label/.kpi-value
   (app.src.css) og .trin-tal (ovenfor) — ingen ny typografi.
   Gridet ombryder af sig selv under ~15rem pr. kort, så §31.4's én-kolonne
   kommer uden en regel i mobil-laget (§31.2: desktop er urørt). ========== */
.vf-forloeb { display:grid; gap:12px; margin-bottom:22px;
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
a.vf-trin { display:block; color:inherit; text-decoration:none; min-height:44px;
  transition:border-color .15s ease, box-shadow .15s ease; }
a.vf-trin:hover, a.vf-trin:focus-visible { border-color:var(--accent); text-decoration:none; }
.vf-trin[data-tilstand="aktiv"] { border-color:var(--accent); }
/* Tomt trin: `--ink-2`, ikke `--ink-500`. Maalt 23-09-2026: `--ink-500` paa
   den tonede `--ink-100`-chip giver i moerkt tema #7d94a9 paa #24374a =
   3,88:1 (under AA 4,50); `--ink-2` #9DB6C8 bestaar i begge temaer. Chippen
   er stadig daempet mod det aktive trins accent. */
.vf-trin[data-tilstand="tom"] .trin-tal { background:var(--ink-100); color:var(--ink-2); }
.vf-trin[data-tilstand="tom"] .kpi-value { color:var(--ink-500); }
.vf-trin-h { display:flex; align-items:center; gap:8px; }
.vf-trin-h .trin-tal { width:1.5rem; height:1.5rem; font-size:.78rem; }
.vf-trin-pil { margin-left:auto; display:inline-flex; color:var(--ink-500); }

/* Sektionshoved: trin-tal ELLER ikon-chip til venstre, tekst i midten,
   valgfri højreblok (filterchips) der ombryder under teksten på smal skærm. */
.vf-sektion { display:flex; flex-wrap:wrap; align-items:flex-start; gap:10px 12px;
  margin-bottom:12px; }
.vf-sektion-trin { width:36px; height:36px; font-size:1rem; }
.vf-sektion-ic { flex:none; width:36px; height:36px; border-radius:10px; margin:0; }
.vf-sektion-tekst { flex:1 1 16rem; min-width:0; }
.vf-sektion-hoejre { flex:0 1 auto; margin-left:auto; }

/* Sumlinje under en tabel (kunder · avance | beløb) og handlingsrækken med
   knappen. Sumlinjen er en div og ikke en <tfoot>, fordi §31.7's rækkeform
   (table[data-app-raekke]) gør tbody til block og ville lade en tfoot stå
   uden for griddet på telefonen. */
.vf-sum { display:flex; flex-wrap:wrap; justify-content:space-between; align-items:baseline;
  gap:6px 16px; margin-top:10px; padding-top:10px; border-top:2px solid var(--border);
  font-size:13px; }
.vf-sum-tal { font-family:var(--font-display); font-weight:700; font-size:17px;
  font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--ink); }
.vf-handling { display:flex; flex-wrap:wrap; justify-content:flex-end; align-items:center;
  gap:8px 14px; margin-top:14px; }

/* Foldede lister inde i en række (linjer bag en kunde, fravalgte, ventende). */
.vf-fold > summary { cursor:pointer; }
.vf-linjer { list-style:none; padding:0; margin:8px 0 0; }
.vf-linjer > li { display:flex; justify-content:space-between; align-items:flex-start; gap:12px;
  padding:4px 0; border-top:1px solid var(--bd-panel); font-size:13px; }
.vf-linje-hoejre { display:flex; gap:8px; align-items:center; white-space:nowrap; }
/* Bilagene bag Fakturér-listen (23-09-2026): ÉN post pr. bilag i stedet for en
   knap under hver kunde for hvert bilag. Summary er en hel række med 44 px
   trykmål (§31.6); pilen vender når folden er åben. */
.vf-bagliste > summary { display:flex; align-items:center; gap:10px; min-height:44px; list-style:none; }
.vf-bagliste > summary::-webkit-details-marker { display:none; }
.vf-bagliste-ic { display:inline-flex; color:var(--accent-link, var(--accent)); }
.vf-bagliste-tekst { flex:1 1 auto; min-width:0; display:flex; flex-wrap:wrap; column-gap:8px; align-items:baseline; }
.vf-bagliste-pil { display:inline-flex; color:var(--ink-500); transition:transform .15s; }
.vf-bagliste[open] .vf-bagliste-pil { transform:rotate(180deg); }
.vf-bagliste .vf-linjer > li { align-items:center; flex-wrap:wrap; }
.vf-bagliste .vf-linje-hoejre { margin-left:auto; }
.vf-bagliste-post { flex:1 1 12rem; min-width:0; display:flex; flex-direction:column; }
.vf-bagliste-knap { min-height:44px; display:inline-flex; align-items:center; gap:6px; }
/* ══ GUIDER — hjælpe-fladen /guider (19-09-2026) ══════════════════════════
   Læse-flade: oversigtens rækker + guidens trin. Farverne er TOKENS, ikke
   hexe, så white-label og mørkt tema følger med uden egen mørk-blok — de to
   eneste tema-afhængige regler er skud-skiftet nederst, som vælger det
   skærmbillede der matcher brugerens tema (lyst/mørkt) uden JS. */
.guide-raekke {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  min-height: 44px;              /* §31.6 — interaktiv række */
  color: var(--ink);
  text-decoration: none;
}
.guide-raekke:hover { background: var(--accent-soft); }
.guide-raekke-nr {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-soft-tx);
  font-size: 12.5px;
  font-weight: 700;
}
.guide-raekke-tekst { flex: 1 1 auto; min-width: 0; display: block; }
.guide-raekke-titel { display: block; font-weight: 600; font-size: 14px; }
.guide-raekke-resume {
  display: block;
  font-size: 12.5px;
  color: var(--ink-500);
}
.guide-trin-hoved {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}
.guide-trin-nr {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-soft-tx);
  font-weight: 700;
  font-size: 14px;
}
.guide-trin-tekst { margin: 3px 0 0; font-size: 14.5px; color: var(--ink); }
.guide-knap {
  /* Ordret knaptekst — tegnes som en «knap» så den kan genkendes 1:1. */
  display: inline-block;
  padding: 1px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius-control);
  background: var(--ink-100);
  font-weight: 600;
  white-space: nowrap;
}
.guide-skud {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-panel);
  margin: 4px 0 10px;
}
.guide-skud-note {
  font-size: 12px;
  color: var(--ink-500);
  margin: -4px 0 10px;
}
.guide-du-skal-se {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--green-tx);
  background: var(--green-bg);
  border-radius: var(--radius-control);
  padding: 8px 12px;
  margin: 0;
}
.guide-galt-liste {
  margin: 0;
  padding-left: 20px;
  font-size: 13.5px;
  color: var(--ink);
}
.guide-galt-liste li { margin-bottom: 6px; }
/* Tema-skiftet: brugeren ser skuddet i sit EGET tema. Default (lyst) viser
   -lyst; body.dark bytter. Trin med kun ét tema bruger .guide-skud alene. */
.guide-skud-lyst { display: block; }
.guide-skud-moerk { display: none; }
body.dark .guide-skud-lyst { display: none; }
body.dark .guide-skud-moerk { display: block; }

/* ── GUIDE-PANELET (indgang A) — skuffen topbarens «?» fylder ────────────
   Ingen backdrop: fladen bagved SKAL forblive brugbar mens panelet står
   åbent (beslutning 19-09-2026). z-index under paletten (1100), over alt
   indhold. Under 899px bliver skuffen et bundark, så telefonen beholder
   sin arbejdsflade øverst. */
.guide-panel {
  position: fixed;
  top: 64px;
  right: 12px;
  bottom: 12px;
  width: 420px;
  max-width: calc(100vw - 24px);
  overflow-y: auto;
  background: var(--panel-solid);
  border: 1px solid var(--bd-panel);
  border-radius: var(--radius-panel);
  box-shadow: var(--elev-float);  /* husets svæve-elevation — scan-vagten skanner alt efter .scan-side, så halen skal være literal-fri */
  z-index: 1000;
}
.guide-panel[hidden] { display: none; }
.guide-panel-hoved {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  background: var(--panel-solid);
  border-bottom: 1px solid var(--border);
}
.guide-panel-titel {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 700;
  font-size: 14.5px;
  color: var(--ink);
}
.guide-panel-krop { padding: 14px; }
.guide-panel-resume {
  font-size: 13px;
  color: var(--ink-500);
  margin: 0 0 12px;
}
.guide-panel-trin { margin-bottom: 16px; }
.guide-panel-galt {
  border-top: 1px solid var(--border);
  padding-top: 12px;
  font-size: 13px;
  color: var(--ink);
}
.guide-panel-galt strong { display: block; margin-bottom: 6px; }
@media (max-width: 899px) {
  .guide-panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-width: none;
    max-height: 70vh;
    border-radius: var(--radius-panel) var(--radius-panel) 0 0;
    border-bottom: none;
  }
}

/* ── PRINT: en guide skal kunne hænges op bag disken ─────────────────────
   Kravet (19-09-2026): hver guide kan printes som én side. Kromet væk,
   skuddene skrumpes, mørke skud udelades (papir er lyst), og trinnene må
   ikke knækkes over et sideskifte. */
@media print {
  .topbar, aside.side, .mnav, .guide-panel, .pal-overlay,
  .guide-print-knap, nav { display: none !important; }
  body { background: #fff !important; }
  .main { margin: 0 !important; padding: 0 !important; }
  .guide-skud { max-width: 62%; }
  .guide-skud-moerk { display: none !important; }
  body.dark .guide-skud-lyst { display: block !important; }
  .guide-trin-tekst, .guide-du-skal-se, .guide-galt-liste {
    color: CanvasText !important;   /* systemets tekstfarve paa papir — ingen ny hex i skallen */
  }
  section { break-inside: avoid; }
}

/* ── «Kom i gang»-kortet på forsiden (indgang C) ─────────────────────────
   Tjeklisten for nye brugere. Rækkerne er links til guiderne; fluebenet
   viser «åbnet», og hele kortet forsvinder når alt er læst eller lukket. */
.guide-kort-hoved {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.guide-kort-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}
.guide-kort-raekke {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;              /* §31.6 */
  padding: 4px 6px;
  border-radius: var(--radius-control);
  color: var(--ink);
  text-decoration: none;
  font-size: 14px;
}
.guide-kort-raekke:hover { background: var(--accent-soft); }
.guide-kort-raekke.laest {
  color: var(--ink-500);
  text-decoration: line-through;
}
.guide-kort-flueben { display: inline-flex; color: var(--accent-soft-tx); }

/* Ord-trin (uden_skud): billedet slipper her MED VILJE — betaling er en
   ægte kladdeordre, terminalen lever uden for browseren (Andreas 19-09).
   Tegnes som en tydelig overgang, ikke som en fejl. */
.guide-uden-skud {
  font-size: 13.5px;
  font-style: italic;
  color: var(--ink-500);
  border-left: 3px solid var(--border);
  padding: 8px 12px;
  margin: 4px 0 10px;
}

/* Styrepulten · bånd 1 · Kassen (regnskab/_styrepult_kassen.html, 23-09-2026).
   .sp-gaet: et tal der hviler på et gæt står i kursiv og bærer «~».
   .sp-link / .sp-traek: ≥ 44 px trykmål (§31.6). */
.sp-gaet { font-style: italic; }
.sp-link { display: inline-flex; align-items: center; min-height: 44px; }
.sp-traek { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
            min-height: 44px; padding: 6px 0; border-top: 1px solid var(--ink-100); }
.sp-traek:first-child { border-top: none; }
/* Bånd 4 · MRR-broen: fire led side om side, to og to på en smal skærm.
   Ingen af leddene er interaktive, så §31.6 gælder ikke her. */
.sp-bro { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
          gap: .5rem; margin: 0; }
.sp-bro > div { padding: 6px 8px; border-radius: 8px; background: var(--ink-50, var(--ink-100)); }
.sp-bro dd { margin: 0; font-weight: 600; }
@media (max-width: 899px) { .sp-bro { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sp-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden;
          background: var(--ink-100); }
.sp-bar > i { display: block; height: 100%; }
.sp-frem { stroke-dasharray: 6 5; }

/* ══ Udsendelser: liste, detalje, skabeloner (udsendelser-fuld, 23-09-2026) ══
   Astras forslag 2 i husets sprog: kort, ikon i tonet firkant, piller. Kun
   tokens, ingen hex, så begge temaer og white-label følger med. */
.uds-kpi { display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:12px; }
.uds-kpi > .kpi { background:var(--bg-panel); border:1px solid var(--border);
  border-radius:var(--radius-panel,14px); padding:14px 16px; }
.uds-kpi .uds-fremdrift { grid-column:1 / -1; }
.uds-fremdrift-bar { height:6px; border-radius:3px; background:var(--accent);
  transition:width .4s ease; min-width:4px; }
.uds-fremdrift { background:var(--ink-100); border-radius:3px; padding:0; }
.uds-fremdrift p { padding-top:6px; background:var(--bg-app); }
.uds-ikon { display:inline-flex; align-items:center; justify-content:center;
  flex:0 0 auto; width:40px; height:40px; border-radius:11px;
  background:var(--info-bg); color:var(--info-tx); }
.uds-tom, .uds-planlagt { display:flex; align-items:flex-start; gap:14px; }
.uds-skabeloner { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:12px; }
.uds-skabelon h3 { overflow-wrap:anywhere; }
.uds-emne { font-weight:600; color:inherit; text-decoration:none; overflow-wrap:anywhere; }
.uds-emne:hover { text-decoration:underline; }
.uds-titel { overflow-wrap:anywhere; margin:.35rem 0 .25rem; }
.uds-overlinje { display:flex; flex-wrap:wrap; gap:6px; }
.uds-handlinger { flex-wrap:wrap; align-items:center; }
.uds-mere { position:relative; }
.uds-mere > summary { list-style:none; cursor:pointer; }
.uds-mere > summary::-webkit-details-marker { display:none; }
.uds-mere-panel { position:absolute; right:0; top:calc(100% + 6px); z-index:20;
  width:min(300px, calc(100vw - 32px)); box-shadow:var(--shadow-float); }
.uds-preview-ramme { position:relative; overflow:hidden; border:1px solid var(--border);
  border-radius:10px; background:var(--ink-50); }
.uds-preview { display:block; border:0; transform-origin:0 0; width:640px; height:720px;
  background:var(--ink-50); }
.uds-fejltekst { overflow-wrap:anywhere; }
.uds-gensend-liste { max-height:260px; overflow:auto; padding-left:1.1rem; margin-bottom:0; }
.uds-gensend-liste li { margin:.2rem 0; overflow-wrap:anywhere; }
@media (max-width: 899px) {
  .uds-kpi { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .uds-handlinger > * { flex:1 1 auto; }
}
.uds-gem { display:flex; flex-wrap:wrap; align-items:flex-start; gap:8px;
  padding-top:12px; border-top:1px solid var(--border); }
.uds-gem-valg { position:relative; }
.uds-gem-valg > summary { list-style:none; cursor:pointer; }
.uds-gem-valg > summary::-webkit-details-marker { display:none; }
.uds-gem-panel { position:absolute; left:0; top:calc(100% + 6px); z-index:20;
  width:min(300px, calc(100vw - 32px)); padding:14px; background:var(--bg-panel);
  border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-float); }
@media (max-width: 899px) {
  .uds-gem-panel { position:static; width:100%; margin-top:8px; box-shadow:none; }
  .uds-gem-valg[open] { flex:1 1 100%; }
}
.uds-modtagerform { border:0; padding:0; margin-left:0; margin-right:0; }
.uds-valg-raekke { display:flex; flex-wrap:wrap; gap:6px; }
.uds-valg { display:inline-flex; align-items:center; gap:8px; min-height:44px;
  padding:0 12px; border:1px solid var(--border); border-radius:var(--radius-pill,999px);
  background:var(--bg-panel); cursor:pointer; font-size:.9rem; }
.uds-valg:has(input:checked) { border-color:var(--accent); background:var(--info-bg); color:var(--info-tx); }
.uds-valg input { accent-color:var(--accent); width:18px; height:18px; margin:0; }
/* Søgbart modtagervalg (27-09-2026) — static/js/soegevaelger.js.
   .sv = select'en gjort til søgefelt; .uds-soegliste = afkrydsningslisten
   med filter. Typemærket (Varegruppe/Abonnement) er samme lille pille i
   begge, så de to sider læses ens. Rækkerne er 44 px under 899 px (§31.6). */
.sv { position:relative; }
.sv-felt-raekke { display:flex; gap:6px; align-items:stretch; }
.sv-felt { flex:1 1 auto; min-width:0; }
.sv-ryd { flex:0 0 auto; }
.sv-liste { max-height:min(320px, 50vh); overflow-y:auto; margin-top:4px; padding:4px;
  background:var(--bg-panel); border:1px solid var(--border); border-radius:10px;
  box-shadow:var(--shadow-float); }
.sv-opt { display:flex; align-items:center; gap:8px; width:100%; min-height:36px;
  padding:6px 10px; border:0; border-radius:.25rem; background:transparent; color:inherit;
  font:inherit; font-size:.9rem; text-align:left; cursor:pointer; }
.sv-opt.sv-er-valgt .sv-navn { font-weight:600; }
.sv-navn { min-width:0; overflow-wrap:anywhere; }
.sv-tom { margin:0; padding:8px 10px; font-size:.85rem; color:var(--ink-2); }
.sv-valgt { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:6px 0 0; font-size:.85rem; }
.sv-valgt:empty { display:none; }
.sv-type, .uds-type { flex:0 0 auto; display:inline-block; padding:1px 7px; border-radius:var(--radius-pill,999px);
  font-size:.7rem; font-weight:700; letter-spacing:.02em; text-transform:uppercase;
  background:var(--bg-app); color:var(--ink-2); border:1px solid var(--border); }
.sv-type-varegruppe, .uds-type-varegruppe { background:var(--info-bg); color:var(--info-tx); border-color:transparent; }
.sv-type-abonnement, .uds-type-abonnement, .sv-type-flere { background:var(--bg-app); color:var(--ink-2); }
.uds-soegliste-top { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.uds-soegliste-top .form-input { flex:1 1 220px; min-width:0; }
.uds-soegliste-antal { font-size:.85rem; color:var(--ink-2); white-space:nowrap; }
.uds-soegliste [data-soegeliste-raekker] { max-height:min(360px, 55vh); overflow-y:auto; }
@media (max-width: 899px) {
  .sv-opt { min-height:44px; }
  .sv-ryd { min-width:44px; min-height:44px; }
}
.kp-roller { display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:6px; }
.kp-rolle { min-height:36px; padding:0 12px; border:1px solid var(--border);
  border-radius:var(--radius-pill,999px); background:var(--bg-panel); color:inherit;
  font-size:.8rem; cursor:pointer; }
.kp-rolle[aria-pressed="true"] { border-color:var(--accent); background:var(--info-bg); color:var(--info-tx); font-weight:600; }
@media (max-width: 899px) { .kp-rolle { min-height:44px; } }
/* Kundekort etape 3 (27-09-2026): Kontakter som kortgitter på skrivebordet —
   tre spalter ved 1280 (forslaget). Under 899px er det én spalte, og 2c's
   rækker bærer listen; kortet vises kun ved :target (forta-mobil.css). */
.kp-gitter { display:grid; grid-template-columns:repeat(auto-fill, minmax(300px, 1fr)); gap:16px; align-items:start; }
@media (max-width: 899px) { .kp-gitter { display:block; } }
.kp-kort { margin:0; }
.kp-primaer { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-bottom:8px; }
.kp-modtager { border-top:1px solid var(--border); padding-top:10px; margin-top:4px; }
.kp-detaljer { border-top:1px solid var(--border); margin-top:10px; padding-top:8px; }
.kp-detaljer > summary { cursor:pointer; min-height:28px; display:flex; align-items:center; }
.kp-detaljer[open] > summary { margin-bottom:8px; }
/* Kundekort etape 3: Kommunikation i to spalter — tidslinjen til venstre,
   note, mailvalg og markedsføring til højre. Én spalte under 899px. */
.kom-spalter { display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:16px; align-items:start; }
.kom-hoved, .kom-side { min-width:0; }
@media (max-width: 899px) { .kom-spalter { display:block; } .kom-side { margin-top:16px; } }
/* Kundekort etape 3: Aftaler — listen og kortet «Næste aftale» side om side. */
.aft-spalter { display:grid; grid-template-columns:minmax(0,1fr) 280px; gap:16px; align-items:start; }
@media (max-width: 899px) { .aft-spalter { display:block; } }
/* CVR-fanens afsnitsknapper er ankre; afsnittet må ikke lande under den
   klæbende topbjælke. */
.cvr-afsnit { scroll-margin-top:80px; }
/* Snapshots-fanens «Vis» (etape 3): felterne kun til læsning. */
.snap-vis > summary { list-style:none; cursor:pointer; }
.snap-vis > summary::-webkit-details-marker { display:none; }
.snap-vis-panel { margin-top:8px; padding:10px 12px; border:1px solid var(--border);
  border-radius:10px; background:var(--bg-panel-2, var(--bg-panel)); min-width:260px; }
.snap-felter { display:grid; grid-template-columns:auto 1fr; gap:4px 12px; margin:0; font-size:12.5px; }
/* --ink-2, ikke --ink-3: målt 3,15:1 i lyst tema (test_dark_kontrast). */
.snap-felter dt { color:var(--ink-2); } .snap-felter dd { margin:0; word-break:break-word; }
/* «Sammenlign med nu» (SNAPSHOTS-30-09): felt · snapshot · nu, og dagens
   værdi markeret med husets gule tone (--amber-tx på --amber-bg består
   AA i begge temaer — se «Statusfarverne» i CLAUDE.md). */
.snap-diff { display:grid; grid-template-columns:auto 1fr 1fr; gap:4px 12px; font-size:12.5px; }
.snap-diff-h { color:var(--ink-2); font-weight:600; }
.snap-diff-felt { color:var(--ink-2); }
.snap-diff-foer, .snap-diff-nu { word-break:break-word; }
.snap-diff-mark { background:var(--amber-bg); color:var(--amber-tx); border-radius:4px; padding:0 3px; }
.snap-gendan { margin:4px 0 0; }
.snap-handlinger { display:flex; gap:14px; justify-content:flex-end; align-items:flex-start; flex-wrap:nowrap; white-space:nowrap; }
.snap-handlinger .snap-vis-panel { white-space:normal; }
/* 🔴 2c's to telefon-knapper stod OGSÅ på skrivebordet (målt 27-09 i
   FØR-skuddene ved 1280): `.mobil-kun{display:none}` taber til knappens
   egen `display` (`.btn-primary`/`.btn-ghost`, samme specificitet, senere
   i kaskaden). Skrivebordet har feltet og søgeformularen fremme, så
   knapperne er rene dubletter dér. Reglen står i et min-width-lag, så den
   ikke kan ramme telefonen. */
@media (min-width: 900px) { .kd-note-knap.mobil-kun, .kd-soeg-knap.mobil-kun { display:none; } }
/* Kundekort etape 3: «Mere»-menuens ikon i en tonet firkant (prototypens
   rækker, skærm 18). Pilen kun i telefonens bundark (forta-mobil.css). */
.kd-mere-ic { display:inline-flex; align-items:center; justify-content:center;
  flex:0 0 28px; width:28px; height:28px; border-radius:8px;
  background:var(--accent-soft); color:var(--accent-soft-tx); }
.kd-mere-pil { display:none; color:var(--ink-2); }
/* Driftshændelser (udsendelser-fuld C) */
.uds-sektion { font-size:.78rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-2); margin:1.5rem 0 .6rem; }
.uds-ikon--ok { background:var(--green-bg); color:var(--green-tx); }
.uds-ikon--drift { background:var(--red-bg); color:var(--red-tx); }
.drift-kort-liste { display:grid; gap:12px; }
.drift-kort { display:flex; align-items:flex-start; gap:14px; color:inherit; text-decoration:none; }
.drift-kort:hover { border-color:var(--accent); }
.drift-titel { overflow-wrap:anywhere; }
.drift-loefte, .drift-loefte-bar { background:var(--amber-bg); color:var(--amber-tx);
  border-left:3px solid var(--amber-bd, var(--amber-tx)); border-radius:8px; padding:8px 12px; }
.drift-loefte-bar { display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.drift-loefte-bar--brudt { background:var(--red-bg); color:var(--red-tx); border-left-color:var(--red-tx); }
.drift-form { display:grid; gap:16px; max-width:760px; }
.drift-beroerte-boks { background:var(--info-bg); color:var(--info-tx); border-radius:10px; padding:12px 14px; }
.drift-beroerte-boks .text-neutral { color:inherit; opacity:.9; }
.drift-tal { font-size:1.4rem; font-variant-numeric:tabular-nums; }
.drift-send-bjaelke { position:sticky; bottom:0; padding:12px 0; background:var(--bg-app); z-index:5; }
.drift-tidslinje { list-style:none; margin:0; padding:0 0 0 6px; border-left:2px solid var(--border); }
.drift-trin { position:relative; display:flex; gap:12px; padding:0 0 16px 14px; }
.drift-prik { position:absolute; left:-12px; top:6px; width:12px; height:12px; border-radius:50%;
  background:var(--ink-300); border:2px solid var(--bg-panel); }
.drift-prik--undersoeger { background:var(--red-tx); }
.drift-prik--aarsag_fundet { background:var(--amber-tx); }
.drift-prik--overvaager { background:var(--info-tx); }
.drift-prik--loest { background:var(--green-tx); }
.uds-drift-banner { display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
@media (max-width: 899px) {
  .drift-send-bjaelke .btn-primary { width:100%; justify-content:center; }
}
/* Indsigt (udsendelser-fuld D): én serie, husets accent, tynde søjler med
   afrundet top forankret til bundlinjen. */
.uds-indsigt { display:grid; grid-template-columns:minmax(0,3fr) minmax(0,2fr); gap:16px; }
.uds-soejler { display:flex; align-items:stretch; gap:10px; height:220px;
  border-bottom:1px solid var(--border); padding-top:4px; }
.uds-soejle { flex:1 1 0; min-width:44px; display:flex; flex-direction:column; justify-content:flex-end;
  align-items:center; gap:4px; color:inherit; text-decoration:none; position:relative; }
.uds-soejle-bar { width:min(48px, 70%); min-height:2px; background:var(--accent);
  border-radius:4px 4px 0 0; transition:filter .15s; }
.uds-soejle:hover .uds-soejle-bar, .uds-soejle:focus-visible .uds-soejle-bar { filter:brightness(1.12); }
.uds-soejle-tal { font-size:.8rem; font-weight:700; font-variant-numeric:tabular-nums; }
.uds-soejle-akse { position:absolute; bottom:-22px; font-size:.75rem; color:var(--ink-2); }
.uds-soejler + details { margin-top:34px; }
.uds-sundhed { margin:0; display:grid; gap:0; }
.uds-sundhed > div { display:flex; justify-content:space-between; gap:12px; padding:10px 0;
  border-bottom:1px solid var(--border); }
.uds-sundhed > div:last-child { border-bottom:0; }
.uds-sundhed dt { font-size:.9rem; }
.uds-sundhed dd { margin:0; text-align:right; }
@media (max-width: 899px) { .uds-indsigt { grid-template-columns:1fr; } .uds-soejler { gap:6px; } }
.kp-kategorier { list-style:none; margin:0; padding:0; }
.kp-kategorier > li { display:flex; justify-content:space-between; align-items:center; gap:12px;
  padding:8px 0; border-bottom:1px solid var(--border); min-height:44px; }
.kp-kategorier > li:last-child { border-bottom:0; }
/* Tidslinjens link til en udsendelse: et helt trykmål på telefon (§31.6). */
@media (max-width: 899px) { .kom-link { display:inline-flex; align-items:center; min-height:44px; } }
/* `.kpi` (forta-core §3) sætter Sora 26–32 px og −0,02em på HELE kortet;
   målt 23-09: nøgletallenes undertekst arvede det og så ud som ét langt ord.
   Kortet nulstilles, og kun tallet (.kpi-value) bærer displayskriften. */
.uds-kpi > .kpi { font-family:inherit; font-size:inherit; font-weight:inherit;
  letter-spacing:normal; line-height:1.4; }
.uds-kpi .kpi-value { font-family:'Sora',-apple-system,'Segoe UI',system-ui,sans-serif;
  font-weight:600; font-size:clamp(24px,3vw,30px); letter-spacing:-0.02em; line-height:1.1;
  font-variant-numeric:tabular-nums; }
.uds-tabel td.num { white-space:nowrap; }
@media (max-width: 899px) {
  /* Specificitet over husets table[data-stack] (0,1,2): table.cls[data-stack] (0,2,2). */
  table.uds-modtager-tabel[data-stack] thead { display:none; }
  table.uds-modtager-tabel[data-stack], table.uds-modtager-tabel[data-stack] tbody { display:block; }
  table.uds-modtager-tabel[data-stack] tr { display:grid; grid-template-columns:minmax(0,1fr) auto;
    gap:2px 10px; padding:10px 2px; margin:0; border:0; border-bottom:1px solid var(--border);
    border-radius:0; background:transparent; }
  table.uds-modtager-tabel[data-stack] td { display:block; padding:0; border:0; width:auto; }
  table.uds-modtager-tabel[data-stack] td::before { content:none; display:none; }
  table.uds-modtager-tabel[data-stack] td:nth-child(1) { grid-column:1; font-weight:600; overflow-wrap:anywhere; }
  table.uds-modtager-tabel[data-stack] td:nth-child(3) { grid-column:2; grid-row:1 / span 2; text-align:right !important; }
  table.uds-modtager-tabel[data-stack] td:nth-child(2) { grid-column:1; color:var(--ink-2); font-size:.85rem; overflow-wrap:anywhere; }
  table.uds-modtager-tabel[data-stack] td:nth-child(4) { display:none; }
  table.uds-modtager-tabel[data-stack] td:nth-child(1) a { display:inline-flex; align-items:center; min-height:44px; }
}
@media (max-width: 899px) { .uds-modtager-tabel .uds-fejltekst { max-width:46vw; margin-left:auto; } }
/* Driftshændelsens kriterie-blok og editorens rolle-række (klasserne bruges
   som krog for hx og [hidden]; reglerne her giver dem luft). */
.drift-kriterier { display:grid; gap:6px; }
.uds-roller { padding-left:2px; }

/* Styrepulten · leverance 2 (23-09-2026): hver post er ÉN række — navn og
   beløb til venstre, handlingen til højre. Andreas: «knapperne står i en
   ujævn søjle, og teksten over dem bryder og overlapper». */
.sp-blok { border-left: 3px solid var(--ink-200); padding: 6px 0 6px 12px; }
.sp-blok-advarsel { border-left-color: var(--amber-tx); }
.sp-blok-bank { border-left-color: var(--green-tx); }
.sp-blok-tekst { font-size: .875rem; line-height: 1.45; margin: 0 0 6px; }
.sp-raekke { padding: 6px 0; border-top: 1px solid var(--ink-100); }
.sp-raekke:first-child { border-top: none; }
.sp-raekke-hoved { display: flex; align-items: center; gap: .75rem;
                   flex-wrap: wrap; min-height: 44px; }
.sp-raekke-navn { flex: 1 1 12rem; min-width: 0; }
.sp-raekke-beloeb { margin-left: auto; font-weight: 600; white-space: nowrap; }
.sp-kandidater { padding: 2px 0 2px 12px; }
.sp-marker { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
             justify-content: flex-end; }
.sp-marker-grund { width: auto; min-height: 44px; }
.sp-marker-note { flex: 1 1 14rem; min-height: 44px; }

/* Styrepulten · leverance 3 (23-09-2026): designløft af Kassen-kortet.
   Følger app-prototypens regnskabsskærm (#scr-regnskab): KPI-række med to
   tal side om side (.kpi-strip), og rækker med etiket til venstre og beløb
   til højre (.tot-row). Rækkefølgen er læsningens: tal → kurve → træk →
   afstemning. */
.sp-kassen { display: flex; flex-direction: column; gap: 12px; }
.sp-hoved { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.sp-kpi-raekke { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.sp-kpi { border: 1px solid var(--ink-100); border-radius: 12px; padding: 10px 12px; min-width: 0; }
.sp-kpi .kpi-value { font-size: clamp(1.35rem, 5vw, 2rem); line-height: 1.1; }
.sp-enhed { font-size: .5em; font-weight: 600; color: var(--ink-500); }
.sp-saetning { margin: 0; font-size: .95rem; line-height: 1.45; }
.sp-kurve { margin: 0; }
.sp-kurve svg { width: 100%; height: auto; display: block; }
.sp-akse { display: flex; justify-content: space-between; font-size: .75rem; color: var(--ink-500); margin-top: 2px; }
.sp-afsnit { font-size: .8rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
             color: var(--ink-500); margin: 6px 0 0; }
.sp-meta { display: block; font-size: .75rem; color: var(--ink-500); margin-top: 2px; }
.sp-meta .pill { margin-left: 4px; }
.sp-poster { padding-left: 12px; }
.sp-marker-fold > summary { list-style: none; display: inline-flex; align-items: center; cursor: pointer; }
.sp-marker-fold > summary::-webkit-details-marker { display: none; }
.sp-marker-fold[open] > summary { margin-bottom: 6px; }
.sp-advarsler { font-size: .75rem; color: var(--ink-600); padding-left: 1.1rem; margin: 0; }
.sp-herkomst { border-top: 1px solid var(--ink-100); padding-top: 10px; }
@media (max-width: 899px) {
  .sp-kpi { padding: 8px 10px; }
  .sp-raekke-navn { flex-basis: 60%; }
}
/* Handlingerne står mod HØJRE kant, også når rækken brydes på telefonen —
   samme kant som beløbene (målt i browseren 23-09: ved 390 px faldt de ned
   på egen linje, venstrestillet). */
.sp-raekke-hoved > button { margin-left: auto; }
/* 🔴 IKKE display:flex på <details>: målt 23-09 i Chromium gav det de
   lukkede fold-ud-blokkes felter en boks (26×44) — indholdet var ikke længere
   skjult. text-align flytter knappen uden at røre skjulningen. */
.sp-marker-fold { text-align: right; }
.sp-marker-fold > .sp-marker { text-align: left; }

/* Styrepulten · afstemningen som KORT (Andreas 23-09 kl. 21: «det hele er
   rodet sammen, så man ikke kan se hvad der hænger sammen med hvad»).
   Én kreditor = ét kort: hovedet (navn · beløb · én handling) og det banken
   fandt indrykket under, INDE i kortet. */
.sp-kort-liste { display: flex; flex-direction: column; gap: 8px; }
.sp-kort { border: 1px solid var(--ink-100); border-left: 4px solid var(--ink-200);
           border-radius: 10px; padding: 6px 12px; background: var(--bg-panel, transparent); }
.sp-kort-advarsel { border-left-color: var(--amber-tx); }
.sp-kort-bank { border-left-color: var(--green-tx); }
.sp-under { margin: 2px 0 4px 12px; padding: 4px 0 4px 10px; border-left: 2px solid var(--ink-100);
            font-size: .8rem; }
.sp-under-bank { border-left-color: var(--green-tx); }
.sp-handling { flex: 0 0 auto; }
/* «Markér betalt» folder formularen ud i kortet: skjult afkrydsning + label. */
.sp-kort .sp-marker { display: none; padding: 6px 0 2px; }
.sp-toggle:checked ~ .sp-marker { display: flex; }
.sp-toggle:focus-visible ~ .sp-raekke-hoved .sp-handling { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Handlingen (knap ELLER label) står mod højre, også når hovedet brydes. */
.sp-raekke-hoved > .sp-handling { margin-left: auto; }

/* ═══ OPSLAG-FORSIDEN (/virksomheder) — opslag-opus etape 1, 24-09-2026 ═════
   Andreas 24-09: «Det ligner noget rod lige nu.» Hvad der var rodet er maalt i
   rapporter/opslag-opus/ANALYSE.md; her staar kun formen:
     · fanerne paa SAMME plads som paa Radar og Matrix (under sidehovedet)
     · soegefeltet foerst, uden «N af N vurderet» (stod der to gange)
     · opmaerksomhed: hoejst tre raekker pr. sektion, saa kortene i gitteret
       faar samme hoejde af sig selv — foer fik 3 og 10 raekker samme kasse
       og den femte sektion stod alene med et hul ved siden af
     · beloebet paa spil i sektionens hoved, i huset format (kr foran)
   Raekkerne er husets app-raekke (§31.7) — skrivebordet en tabel med
   flugtende tal, telefonen prototypens hovedlinje/underlinje. */
.opslag-nav { margin-bottom:16px; }
.opslag-soeg { margin-bottom:24px; }
.opslag-soeg-raekke { display:flex; gap:12px; align-items:center; flex-wrap:wrap; }
.opslag-soeg-raekke > .form-input { flex:1; min-width:220px; }
.opm { margin-bottom:24px; }
.opm-top { display:flex; align-items:baseline; justify-content:space-between;
  gap:4px 12px; flex-wrap:wrap; margin-bottom:10px; }
.opm-titel { margin:0; font-size:11px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2); }
.opm-daekning { font-size:12px; color:var(--ink-2); }
.opm-gitter { display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:12px; }
.opm-kort { display:flex; flex-direction:column; margin:0; padding:16px 18px; }
.opm-kort--bred { grid-column:1 / -1; }
.opm-hoved { display:grid; grid-template-columns:auto minmax(0, 1fr) auto;
  gap:12px; align-items:start; padding-bottom:10px; border-bottom:1px solid var(--border); }
.opm-hoved > .pill { min-width:34px; justify-content:center; font-size:13px; }
.opm-label { grid-column:2; grid-row:1; margin:0; font-size:15px; font-weight:650;
  line-height:1.3; letter-spacing:normal; text-transform:none; color:var(--ink); }
.opm-sum { grid-column:3; grid-row:1 / span 2; }
.opm-why { grid-column:2; grid-row:2; margin:0; font-size:12px; color:var(--ink-2); }
.opm-sum { text-align:right; white-space:nowrap; }
.opm-sum-tal { display:block; font-size:15px; font-weight:650; color:var(--ink); }
.opm-sum-lbl { font-size:11px; color:var(--ink-2); }
/* Tabellen i kortet har intet hoved; cellerne tager kortets indrykning. */
.opm-tabel td { padding:9px 0; vertical-align:middle; }
.opm-tabel td + td { padding-left:12px; }
.opm-tabel tr:first-child td { border-top:none; }
/* Ophoert-panelets kolonnehoved (navngivne kolonner) flugter med cellerne. */
.opm-doede th { padding:10px 0 6px; white-space:nowrap; }
.opm-doede th + th { padding-left:12px; }
.opm-doede td[data-opm-abon] { width:1%; white-space:nowrap; }
.opm-tabel .app-rl-sub { font-size:12px; color:var(--ink-2); }
.opm-tabel td.td-amount { text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
/* Fakta-linjen («Score 60 · 43 dg DSO») er ÉN oplysning og maa ikke brydes
   midt i; navnet giver efter i stedet (maalt: brudt paa 3 af 3 raekker i
   Reel risiko i foerste forslagsrunde). Samme for resultatets CVR · by. */
.opm-tabel td[data-app-sub], .opslag-tabel td[data-app-sub],
.opslag-tabel .pill { white-space:nowrap; }
/* Lange juridiske navne («… A/S · Afd. Nord/Vest · Att. Bogholderi, Løn»)
   brød til fire linjer i en halv spalte; to er nok til at genkende firmaet. */
.opm-tabel td[data-stack-title] > a { display:-webkit-box; -webkit-line-clamp:2;
  -webkit-box-orient:vertical; overflow:hidden; }
.opm-menu > summary { padding:4px 8px; }
.opm-alle { margin-top:auto; padding-top:10px; align-self:flex-start;
  display:inline-flex; align-items:center; gap:4px; font-size:13px; font-weight:600; }
.opslag-vaerktoej { display:flex; flex-wrap:wrap; gap:12px; margin-bottom:24px; }
.opslag-vaerktoej-link { flex:1 1 260px; display:flex; gap:12px; align-items:flex-start;
  padding:12px 16px; border:1px solid var(--border); border-radius:var(--radius-sm);
  background:var(--bg-panel); color:var(--ink); text-decoration:none; }
.opslag-vaerktoej-link:hover { background:var(--tbl-hover); }
.opslag-vaerktoej-link strong { display:block; font-size:14px; font-weight:600; }
.opslag-vaerktoej-link small { display:block; margin-top:2px; font-size:12px; color:var(--ink-2); }
.opslag-resultat .opm-top { margin-bottom:4px; }
.opslag-resultat td.td-amount { text-align:right; }
/* Radars henvisning til Opslag (opslag-opus fase 3): samme link-form som
   Opslags vaerktoejer, i fuld bredde, med pilen yderst til hoejre. */
.radar-henvisning { margin-top:18px; align-items:center; }
.radar-henvisning > svg:last-child { margin-left:auto; color:var(--ink-2); }

@media (max-width: 899px) {
  /* ── ⑥b ÉN FAELLES REGEL FOR ALLE TEKSTFELTER (feltzoom 26-09-2026) ───────
     🔴 HVORFOR I CORE OG IKKE I forta-mobil.css: login-familien henter core,
     ikke mobil-laget — og /login stod paa 13px (maalt 26-09, 393x852).
     Under 899px er dette ark og mobil-arket samme lag; reglen er
     `!important`, saa raekkefoelgen mellem de to ark er uden betydning.
     Navnelisten i forta-mobil.css («⑥ FORMFELTERNE») holdt ikke: MAALT 26-09 (rapporter/feltzoom/, 250
     crawlede sider, 393x852, begge temaer, felter i DOM'en ogsaa naar de er
     skjulte i modal/bundark/merepanel) stod der stadig 62 SYNLIGE felter
     under 16px paa 9 sider og 35 skjulte, fra otte kilder navnelisten aldrig
     havde kendt: `.pricerange input` 12,5 · `.lyn-merepanel-felt textarea`/
     `.lyn-rabat-felt input` 13 · `table[data-stack] td.num …` 13,5 ·
     `.bon-field-row input`/`textarea.bon-lines` 0,85rem · `.pd-qty` 0,9rem ·
     og lyn-editorens egne tre i forta-mobil.css (14/15/15). Og skabelonerne bærer
     INLINE-stoerrelser crawleren ikke naar: sms/_modal 0,875rem ×3,
     send_til_kunde/_modal 0,9375rem, pin_admin 0,9rem. Hver ny flade kan
     finde en ny kilde; derfor en regel der ikke kan overstemmes.

     🔴 `!important` ER MED VILJE. Uden den vinder enhver klasse med stoerre
     specificitet — og inline-stile — og 16px er ufravigeligt (iOS/Android-
     WebView zoomer ind paa et felt under 16px og zoomer ikke ud selv).
     🔴 OG DEN KRYMPER IKKE DE STORE. `max(16px, var(--felt-fs, 16px))`:
     et felt der med vilje er STOERRE, melder sig ind med `--felt-fs`
     (maalt 26-09: tre — kassebeloebet 1,875rem, PIN 1,8rem, 2FA-kode
     1,25rem — plus 17px/1,05rem/1,1rem i skabeloner uden for crawlen).
     Et felt der glemmer det, bliver 16px: grimt, aldrig zoom.
     IKKE `maximum-scale=1`/`user-scalable=no` i viewport-meta'en — det ville
     tage brugerens knib (WCAG 1.4.4). Kun under 899px; skrivebordet er
     uroert (§31.2). Vaern: tests/test_felt_zoom_telefon_browser.py. */
  input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=range]):not([type=color]):not([type=file]):not([type=submit]):not([type=button]):not([type=reset]):not([type=image]),
  select, textarea, [contenteditable]:not([contenteditable=false]) {
    font-size: max(16px, var(--felt-fs, 16px)) !important;
  }
  .pos-amount-input { --felt-fs: 1.875rem; }   /* app.src.css: text-3xl */
}

/* Kvitteringens nummerfelt (27-09-2026, `pos/_receipt_choice.html`): vises
   kun naar kunden intet mobilnummer har. `.form-input` er `w-full`; paa
   skrivebordet ville feltet ellers strække sig over hele kortet over tre
   smaa knapper. Mobil-laget ophaever loftet (knapperne fylder dér bredden). */
.kvit-tlf { max-width: 16rem; }
/* Kvitteringsvalget efter et kassesalg (02-10-2026): alle knapper og felter
   har tommelmaalet 44 px — OGSAA paa skrivebordet, hvor `.btn-*` ellers er
   38 px. Kassen staar ofte paa en touch-skaerm ved disken; §31.6's 44 px
   gaelder dér, selvom vinduet er bredt. Vagt:
   tests/test_kvittering_email_primaer_browser.py. */
[data-receipt-group] [data-receipt],
[data-receipt-group] .kvit-tlf { min-height: 44px; }

/* ── Real-time-sync-toasten (`_refresh_toast.html`) — UDEN FOR FLOWET ─────────
   forta-d6 05-10-2026: toasten byttes ind efter load og skubbede detaljesiden
   (34 px). Fast placering: skrivebord øverst til højre under topbjælken,
   telefon over bundnavet. «Synkroniseret» toner ud efter 4 s; fejl står og kan
   lukkes. z-index under modaller (husets dialoger ligger højere). */
/* Skrivebord: NEDERST til højre over Forta Calls svævende knap (designkritik
   §31 T3) — øverst til højre lå den oven på sidernes «Guide» og handlinger. */
.refresh-toast {
  position: fixed; bottom: 96px; right: 16px; z-index: 55;
  display: inline-flex; align-items: center; gap: 8px; max-width: min(28rem, calc(100vw - 32px));
  padding: 8px 14px; border-radius: 999px; border: 1px solid var(--bd-panel);
  background: var(--bg-panel); box-shadow: var(--shadow-float);  /* husets token (begge temaer), ikke en opfundet nuance */
}
/* 🔴 EN SVÆVENDE BOKS MÅ ALDRIG LIGGE OVER NOGET MAN SKAL TRYKKE PÅ (forta-d6
   05-10-2026, fuld suite af pakke 124: fejl-toasten dækkede «Slet tilbud» i
   den åbne ⋯-menu ved 852×393). Husets lag har ingen fælles z-index-skala
   (1–75), og menupanelet lever i en stacking context, så et lavere z-index
   flytter kun problemet. Reglen er derfor: er et LAG åbent — en menu
   (details[open] med role=menu), en dialog eller en modal (aria-modal),
   regnskabshubben — træder toasten til side. Den er tilbage, når laget lukkes. */
/* `[aria-modal]` kun når det er ÅBENT: kommandopaletten, genvejsoverlayet og
   underskriftsarket står altid i DOM'en og skjules med `hidden` (på sig selv
   eller forælderen). Målt 05-10: uden afgrænsningen var toasten skjult på
   hver side. */
body:has(details[open] [role="menu"], dialog[open],
         [aria-modal="true"]:not([hidden]):not([hidden] *),
         [data-regnskab-hub][open]) .refresh-toast {
  visibility: hidden; }
.refresh-toast--ok { animation: refresh-toast-ud .4s ease 4s forwards; }
.refresh-toast--fejl { border-color: var(--amber-tx); }
.refresh-toast-ikon { background: none; border: 0; padding: 0; display: inline-flex; align-items: center; color: inherit; cursor: default; }
.refresh-toast--lille { padding: 0; width: 40px; height: 40px; justify-content: center; }
.refresh-toast--lille .refresh-toast-tekst, .refresh-toast--lille .refresh-toast-luk { display: none; }
.refresh-toast--lille .refresh-toast-ikon { cursor: pointer; width: 100%; height: 100%; justify-content: center; }
@keyframes refresh-toast-ud { to { opacity: 0; visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { .refresh-toast--ok { animation-duration: .01s; } }
.refresh-toast-luk { background: none; border: 0; padding: 0 2px; min-width: 24px; min-height: 24px;
  font-size: 16px; line-height: 1; color: var(--ink-2); cursor: pointer; }
@media (max-width: 899px) {
  /* +28 px: den hævede Scan-knap rager op over navet (målt 05-10: toastens bund 743 mod knappens top ~740). */
  .refresh-toast { bottom: calc(var(--mnav-h, 76px) + 28px); left: 16px; right: 16px; justify-content: center; }
  /* 46 = 44 + 2×1 px kant: det er KNAPPEN indeni der skal være 44 (§31.6),
     ikke boksen udenom — med 44 målte ⚠-knappen 42×42 (app-fund F3 09-10-2026). */
  .refresh-toast--lille { left: auto; width: 46px; height: 46px; }
  .refresh-toast-luk { min-width: 44px; min-height: 44px; }
}
