/* GENERERET AF hubspot/theme/scripts/synk-kilder.sh — RET IKKE HER.
   Kilde: packages/ui/src/tokens/designtokens.css
   Filen er gitignoreret. Skal en værdi ændres, ændres den i kilden.
   Kildevalget og dets rækkefølge står i hubspot/theme/src/kilder.ts. */
/* =============================================================================
   12-designtokens.css — Viborg Museums booking- og kundeplatform

   PRODUKT OG STANDARDTEMA (kuratorvindue 21, 2026-09-29, MT-0; Martins
   beslutning 28/9 nr. 4 og 5; ADR-103)
   Platformen er et produkt for flere museer. Tokenlaget (navne, roller,
   kontrastkrav, tonemodel, skala) er PRODUKTETS og gælder alle museer.
   Farve-, skrift- og billedværdierne nedenfor er VIBORG MUSEUMS
   STANDARDTEMA: de er temafelternes værdier i Viborgs egen HubSpot-portal
   (portalprofilen hubspot/theme/profiler/147795778.json, der injiceres som
   standard i temaets fields.json af udrul.sh --portal=147795778; spike
   MT-P0: der findes intet API til temaindstillinger) og er de værdier,
   organisation nr. 1 ser. Et andet museum får sine egne værdier i sin egen
   portalprofil eller temaeditor; sætter det intet, får det produktets
   neutrale standard (13-design-korrektionsnotat.md afsnit 1a).
   Tokennavnene (--dk-* m.fl.) er tekniske navne og omdøbes ikke.

   TEMAFELTERNE — fem grupper i temaets fields.json
     logoer     logo til lys flade, logo til mørk flade, faneikon
     farver     8 farvefelter (nedenfor) og valget «flader»
     skrifter   overskrift og brødtekst (valg over en lukket liste)
     fotos      faldback-fotos til kort og sidehoveder
     identitet  museumsnavn (fald, når motorens profil ikke svarer; et
                «choice» med ét valg — «text» afvises af 2025.2),
                profil (profilens øjebliksbillede til de serverrenderede
                moduler, en overgang), entra_staff_tenant_id og
                entra_staff_client_id (medarbejdernes Entra til øerne;
                «ingen» = ingen Entra) — kuratorvindue 22, 2026-09-29
   De 8 farvefelter og det token, hvert felt bærer. Værdierne står ved
   tokenet i afsnit 1 og 2 og er Viborgs; de ændres ikke her.
     primaer          bærer  --dk-bordeaux        (afsnit 1)
     primaer_dyb      bærer  --dk-bordeaux-dyb    (afsnit 1)
     accent           bærer  --dk-roed            (afsnit 1)
     accent_tekst     bærer  --dk-roed-dyb        (afsnit 1)
     accent_blegt     bærer  --dk-roed-blegt      (afsnit 1)
     rolig_flade      bærer  --dk-sand            (afsnit 1)
     sekundaer_tekst  bærer  --dk-graa-600        (afsnit 2)
     sidebaggrund     bærer  --dk-graa-25         (afsnit 2)
   Valget «flader»: «afledt» (--flade-* afledt af farverne med color-mix())
   eller «tokenlag» (afsnit 3's målte værdier). Viborg står på «tokenlag».
   «afledt» afleder OGSÅ de tekst-, kant-, overlay- og skyggetoner, der
   ellers ville bære kunde nr. 1's kulør uden et felt (AFLEDTE_TONER i
   hubspot/theme/scripts/verificer-tema.mjs); de semantiske farver
   (--tone-*, --status-*, --tekst-fejl, --tekst-destruktiv m.fl.) afledes
   aldrig — de er produktets (kuratorvindue 22, 2026-09-29; MT-T3 fund 2).
   Kontrastkravet nedenfor gælder HVERT museums farver og måles pr. portal
   på den levende side af hubspot/theme/scripts/verificer-tema.sh.
   Rettet tokenlag til packages/ui. Genereret 3. august 2026.
   Kanonisk grundlag: KANONISKE-RETTELSER.md R12.
   =============================================================================

   HVAD DENNE FIL ER
   Den er en RETTELSE af designleverancens :root-blok
   (Design/unpacked/"Viborg Museum bookingplatform.dc.html"), ikke et redesign.
   Brandidentiteten står fast: bordeaux #450019, Domkirkekvarterets røde,
   sandfarverne, Big Shoulders Display + Figtree. Alle 75 tokens fra
   designleverancen er gennemgået; de korrekte er bevaret uændret, de
   utilstrækkelige er rettet, og hver rettelse er dokumenteret med et MÅLT
   kontrastforhold.

   FACIT-REGLEN (bindende, se 13-design-korrektionsnotat.md afsnit 1)
   08-skaermspecs-kundeflader.md og 09-skaermspecs-intern-app.md er facit for
   felter, funktioner, valideringer og tilstande.
   04-motor-database-ddl.md er facit for statusværdier (enum).
   Designleverancen er kilde til tokens, komponentudtryk og visuel retning —
   intet andet.

   KONTRASTKRAV (WCAG 2.1 AA, KR-D-030, KR-SY-026, S8 §2.4)
   1.4.3  brødtekst og små ikoner      ≥ 4,5:1
   1.4.3  stor tekst (≥ 24px, eller ≥ 18,66px fed)  ≥ 3,0:1
   1.4.11 UI-komponentgrænser og grafik der bærer betydning  ≥ 3,0:1
   Alle tal i denne fil er beregnet med WCAG 2.1's relative luminans-formel
   (sRGB-linearisering + 0,2126R/0,7152G/0,0722B, (L1+0,05)/(L2+0,05)) og
   afrundet til nærmeste med to decimaler (kuratorvindue 22: her stod
   «afrundet nedad»; 11 af 18 par passer kun med nærmeste — E12-S02 fund 2,
   MT-T2 fund 3 — og afrundingen afgør aldrig, om et krav er opfyldt).
   Referenceflader:
     hvid  = #FFFFFF   grå-25 = #F6F2F4   linje = #F0EAED   sand = #ECE5E8
   ============================================================================= */

:root {

  /* ---------------------------------------------------------------------------
     1. BRAND — UÆNDRET fra designleverancen (KR-D-015, KR-SY-018)
     Aflæst i screendumps fra domkirkekvarteret.dk. Må ikke justeres.
     Værdierne er VIBORGS STANDARDTEMA (kuratorvindue 21, 2026-09-29, MT-0):
     de står som temafelter i gruppen «farver» i Viborgs portal, og «må ikke
     justeres» gælder Viborgs værdier. Et andet museums værdier kommer fra
     dets egen portal og skal opfylde de samme kontrastkrav som filens
     hoved (målt på den levende side af hubspot/theme/scripts/
     verificer-tema.sh).
     --------------------------------------------------------------------------- */
  --dk-bordeaux:        #450019;  /* Primær brandfarve. Flade til mørke sektioner, tekst, fokusring.
                             ↳ hvid tekst på fladen 16,57:1 */
  --dk-bordeaux-dyb:    #2E0011;  /* Dybeste bordeaux. Kodeflader, sidefod, overlejringsbund.
                             ↳ hvid tekst på fladen 18,68:1 */
  --dk-roed:            #E4003C;  /* Hjemmesidens signaturrøde. KUN flade + hvid tekst, aldrig lille tekst.
                             ↳ hvid tekst på fladen 4,81:1; som tekst: hvid 4,81 · grå-25 4,34 · linje 4,06 · sand 3,88 */
  --dk-roed-dyb:        #B80031;  /* Rød TEKST, rød ikonografi og røde fokusrammer. Erstatter --dk-roed i tekstrolle.
                             ↳ hvid tekst på fladen 6,81:1; som tekst: hvid 6,81 · grå-25 6,14 · linje 5,74 · sand 5,50 */
  --dk-roed-blegt:      #F7BDCC;  /* Deaktiveret primærknap (flade). Bærer aldrig information alene.
                             ↳ knaptekst --knap-deaktiveret-tekst på den: 5,85:1 */
  --dk-sand:            #ECE5E8;  /* Rolig sektionsflade. */

  /* ---------------------------------------------------------------------------
     2. NEUTRALE FLADER — UÆNDRET
     --------------------------------------------------------------------------- */
  --dk-hvid:            #FFFFFF;  /* Kortflade, feltbaggrund, indholdsflade. */
  --dk-graa-25:         #F6F2F4;  /* Sidebaggrund bag kort. */
  --dk-graa-100:        #E4DCE0;  /* Dekorativ skillelinje. RETTET ROLLE: må ikke længere afgrænse komponenter.
                             ↳ mod hvid kun 1,35:1 — utilstrækkelig som komponentgrænse (1.4.11) */
  --dk-graa-300:        #C9BEC5;  /* Dekorativ tone. RETTET ROLLE: er ikke længere feltramme.
                             ↳ mod hvid kun 1,80:1 — utilstrækkelig som komponentgrænse (1.4.11) */
  --dk-graa-600:        #7A5265;  /* Sekundær tekst.
                             ↳ som tekst: hvid 6,52 · grå-25 5,87 · linje 5,49 · sand 5,26 — mindst 5,26:1, består 4,5:1 */
  --dk-graa-800:        #5C2A40;  /* Kraftig sekundær tekst, tabeloverskrifter.
                             ↳ som tekst: hvid 11,29 · grå-25 10,17 · linje 9,51 · sand 9,11 — mindst 9,11:1, består 4,5:1 */

  /* ---------------------------------------------------------------------------
     3. FLADER DER MANGLEDE ET NAVN (nye tokens)
     Designet brugte disse hex-værdier uden token. Nu navngivet.
     --------------------------------------------------------------------------- */
  --flade-hvid-varm:      #FDF9FB;  /* Varm hvid. 5 forekomster i designet.
                               ↳ som flade under primær tekst --dk-bordeaux: 15,88:1 */
  --flade-svag:           #FBF8F9;  /* Svagt tonet kortflade. 12 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 15,70:1 */
  --flade-rolig:          #F4EFF2;  /* Rolig indholdsflade. 3 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 14,58:1 */
  --flade-rolig-2:        #F2EDF0;  /* Rolig indholdsflade, et trin dybere. 13 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 14,32:1 */
  --flade-daempet:        #E0D7DC;  /* Dæmpet flade, fx tabelhoved. 18 af 42 forekomster var flade.
                               ↳ som flade under primær tekst --dk-bordeaux: 11,78:1 */
  --flade-daempet-2:      #D8CDD3;  /* Dæmpet flade, dybere. 6 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 10,73:1 */
  --flade-skravering:     #E2DDE0;  /* Stribe i skraveringsmønster for blokeret/utilgængelig tid. 22 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 12,35:1 */
  --flade-roed-svag:      #FDF0F4;  /* Rosa antydning. Valgt sprog, valgt kort, blød fremhævning. 14 forekomster.
                               ↳ som flade under primær tekst --dk-bordeaux: 14,95:1 */

  /* ---------------------------------------------------------------------------
     4. TEKSTFARVER — RETTET
     Tre niveauer, alle testet mod de fire lyse flader. Ingen af dem falder
     under 4,5:1 på nogen flade de er godkendt til.
     --------------------------------------------------------------------------- */
  --tekst-primaer:      #450019;  /* = --dk-bordeaux. hvid 16,57 · grå-25 14,94 · linje 13,97 · sand 13,37 */
  --tekst-sekundaer:    #7A5265;  /* = --dk-graa-600. hvid 6,52 · grå-25 5,87 · linje 5,49 · sand 5,26 */
  --tekst-daempet:      #845C6D;  /* RETTET. Erstatter designets #8C6274 (49 forekomster,
                                    faldt til 4,12:1 på sand). hvid 5,63 · grå-25 5,07 · linje 4,74 · sand 4,54 */
  --tekst-deaktiveret:  #845C6D;  /* RETTET. Erstatter #C0B2B9 (2,04:1 mod hvid) og
                                    #9C8A93 (2,93:1 mod grå-25) i kalenderceller.
                                    Samme værdi som --tekst-daempet: deaktiveret tilstand bæres af
                                    stiplet kant + aria-disabled + ikon, ALDRIG af farve alene (KR-D-022).
                                    hvid 5,63 · grå-25 5,07 · linje 4,74 · sand 4,54 */
  --tekst-fejl:         #B80031;  /* = --dk-roed-dyb. hvid 6,81 · grå-25 6,14 · linje 5,74 · sand 5,50 */
  --tekst-destruktiv:   #98202F;  /* Aflys/slet. Adskilt fra brandrødt så «køb» og «slet»
                                    aldrig ligner hinanden. hvid 8,13 · grå-25 7,33 · linje 6,85 · sand 6,56 */

  /* ---------------------------------------------------------------------------
     5. KANTER — RETTET, OG NAVNGIVET EFTER ROLLE
     Den vigtigste rettelse i filen. Designet brugte én hårkant (#E4DCE0) og
     én feltramme (#C9BEC5) til både dekoration og komponentgrænser. En
     komponentgrænse skal bestå 1.4.11 (≥ 3,0:1); en ren dekorativ streg skal
     ikke. Derfor er de nu adskilt ved navn, så det er umuligt at bruge
     forkert.
     --------------------------------------------------------------------------- */
  --kant-ui:            #947E8C;  /* RETTET. ENESTE tilladte farve på en komponentgrænse:
                                    tekstfelt, vælger, afkrydsning, radioknap, konturknap,
                                    kalendercelle, tabelramme, kortkant der kan klikkes.
                                    Afledt af #C9BEC5 med bevaret kulør (H≈322°), sænket lyshed.
                                    hvid 3,74 · grå-25 3,37 · linje 3,15 · sand 3,01 — mindst 3,01:1, består 1.4.11 på ALLE fire flader.
                                    Var #C9BEC5 = 1,80:1 mod hvid og 1,62:1 mod grå-25. */
  --kant-felt:          #947E8C;  /* = --kant-ui. Eget navn, så en feltramme kan revideres
                                    uafhængigt af øvrige komponentgrænser. */
  --kant-felt-fejl:     #98202F;  /* Fejltilstand på felt. hvid 8,13 · grå-25 7,33 · linje 6,85 · sand 6,56 */
  --kant-markant:       #450019;  /* Valgt/aktiv kant. hvid 16,57 · grå-25 14,94 · linje 13,97 · sand 13,37 */
  --kant-dekorativ:     #E4DCE0;  /* = --dk-graa-100. KUN rene skillelinjer uden betydning.
                                    1,35:1 mod hvid — bevidst under 3:1, tilladt fordi
                                    stregen ikke bærer information (1.4.11 gælder ikke).
                                    Må ALDRIG omkranse et interaktivt element. */
  --kant-dekorativ-svag:#F0EAED;  /* Rækkeskillelinje i tabeller og lister. 85 forekomster i
                                    designet uden token. 1,19:1 mod hvid — samme forbehold. */
  --kant-skravering:    #E2DDE0;  /* Stribe i skraveringsmønster (blokeret/utilgængelig).
                                    Mønstret — ikke farven — er informationsbæreren (KR-D-022). */

  /* ---------------------------------------------------------------------------
     6. PÅ MØRKE FLADER — NYT
     Aktørportalens sidebjælke, e-mailskabeloner, kodeflader og sidefoden
     ligger på bordeaux. Designet brugte fem unavngivne lyse nuancer her og
     rgba-hvid til kanter, der ikke består 1.4.11. Nu navngivet og rettet.
     Godkendte bundflader: #450019, #2E0011, #5C2A40.
     --------------------------------------------------------------------------- */
  --paa-moerk-tekst:            #FFFFFF;  /* Primær tekst på mørk flade.
                                     ↳ bordeaux 16,57 · bordeaux-dyb 18,68 · grå-800 11,29 — mindst 11,29:1 */
  --paa-moerk-tekst-sekundaer:  #F0DCE3;  /* Brødtekst på mørk flade. 2 forekomster uden token.
                                     ↳ bordeaux 12,67 · bordeaux-dyb 14,28 · grå-800 8,63 — mindst 8,63:1 */
  --paa-moerk-tekst-daempet:    #E0C4CF;  /* Inaktivt navigationspunkt. 14 forekomster uden token.
                                     ↳ bordeaux 10,23 · bordeaux-dyb 11,53 · grå-800 6,97 — mindst 6,97:1 */
  --paa-moerk-tekst-svag:       #E8CFD8;  /* Understøttende tekst. 2 forekomster uden token.
                                     ↳ bordeaux 11,32 · bordeaux-dyb 12,76 · grå-800 7,71 — mindst 7,71:1 */
  --paa-moerk-label:            #C79AAA;  /* Versal-label i sidebjælken. 10 forekomster uden token.
                                     ↳ bordeaux 6,81 · bordeaux-dyb 7,68 · grå-800 4,64 — mindst 4,64:1 */
  --paa-moerk-kode:             #F3E2E8;  /* Kodeblok på --dk-bordeaux-dyb. 1 forekomst uden token.
                                     ↳ bordeaux 13,30 · bordeaux-dyb 14,99 · grå-800 9,06 — mindst 9,06:1 */
  --paa-moerk-succes:           #8FE0B4;  /* Grønt flueben-ikon på bordeaux. 2 forekomster uden token.
                                     ↳ bordeaux 10,65 · bordeaux-dyb 12,00 · grå-800 7,25 — mindst 7,25:1 */
  --kant-ui-paa-moerk:         rgba(255,255,255,.39);
                                  /* RETTET. Komponentgrænse på mørk flade.
                                     Designet brugte .12/.14/.18/.22 — alle under 1,9:1 og dermed
                                     i strid med 1.4.11. Ved 39 % opacitet:
                                     på #450019 → #8E6373 = 3,30:1
                                     på #2E0011 → #80636E = 3,49:1
                                     på #5C2A40 → #9C7D8A = 3,07:1 */
  --kant-dekorativ-paa-moerk:  rgba(255,255,255,.14);
                                  /* Ren dekorativ streg på mørk flade. Ingen betydning. */

  /* ---------------------------------------------------------------------------
     7. FOKUS — RETTET OG FAKTISK ANVENDT
     Designet definerede --fokus-moerk, men brugte den 0 gange og demonstrerede
     ingen fokustilstand på mørke flader. Her er begge ringe defineret, opdelt i
     farve + bredde, og bundet til en :focus-visible-regel nederst i filen.
     KR-D-030, KR-SY-026, WCAG 2.4.7 + 1.4.11.
     --------------------------------------------------------------------------- */
  --fokus-farve-lys:    #450019;  /* Fokusring på LYSE flader.
                                    hvid 16,57 · grå-25 14,94 · linje 13,97 · sand 13,37 — mindst 13,37:1 */
  --fokus-farve-moerk:  #FFFFFF;  /* Fokusring på MØRKE flader.
                                    bordeaux 16,57 · bordeaux-dyb 18,68 · grå-800 11,29 · #98202F 8,13 · #B80031 6,81 · #E4003C 4,81 · #7A5265 6,52 */
  --fokus-bredde:       3px;
  --fokus-offset:       2px;
  --fokus-lys:          var(--fokus-bredde) solid var(--fokus-farve-lys);
  --fokus-moerk:        var(--fokus-bredde) solid var(--fokus-farve-moerk);

  /* ---------------------------------------------------------------------------
     8. TONEMODELLEN — BÆRENDE LAG (S9 §2.8, KR-D-021, KR-D-016, KR-D-025)
     Syv toner. Hver tone har tekst, flade og kant. Et statusbadge bygges
     ALTID af de tre tokens og aldrig af en løs nuance.
     Tone er semantisk, ikke dekorativ: en ny statusværdi vælger en tone,
     ikke en farve. Det er den eneste måde at holde statusvisninger ensartede
     på tværs af bookingflow, webshop, kundeportal, aktørportal og cockpit.
     Farverne er designleverancens egne otte statusfamilier, gennuanceret så
     kanterne består 1.4.11.
     KR-D-022 / KR-SY-021: farve er ALDRIG eneste informationsbærer. Hvert
     badge skal have ikon og tekst. Tokens her leverer kun farven.
     --------------------------------------------------------------------------- */

  /* NEUTRAL — Blågrå. Startpunkt, informationsstatus, intet krav om handling.
     tekst på egen flade 6,75:1 (krav 4,5) · tekst på hvid 7,90:1
     kant mod hvid 3,52:1 · mod grå-25 3,18:1 · mod egen flade 3,01:1 (krav 3,0)
     flade mod hvid 1,17:1 — fladen alene bærer ingen information */
  --tone-neutral-tekst:    #3E5464;
  --tone-neutral-flade:    #E8EEF1;
  --tone-neutral-kant:     #658EA4;

  /* WAITING — Rav. Systemet eller en anden part skylder et svar; en frist løber.
     tekst på egen flade 6,01:1 (krav 4,5) · tekst på hvid 6,87:1
     kant mod hvid 3,46:1 · mod grå-25 3,12:1 · mod egen flade 3,03:1 (krav 3,0)
     flade mod hvid 1,14:1 — fladen alene bærer ingen information */
  --tone-waiting-tekst:    #7D5113;
  --tone-waiting-flade:    #F8EFDE;
  --tone-waiting-kant:     #AD8335;

  /* PROGRESS — Indigo. Arbejdet er i gang eller delvist gennemført.
     tekst på egen flade 7,35:1 (krav 4,5) · tekst på hvid 8,67:1
     kant mod hvid 3,55:1 · mod grå-25 3,20:1 · mod egen flade 3,01:1 (krav 3,0)
     flade mod hvid 1,18:1 — fladen alene bærer ingen information */
  --tone-progress-tekst:   #3B4A75;
  --tone-progress-flade:   #E9ECF6;
  --tone-progress-kant:    #7187BF;

  /* SUCCESS — Grøn. Positiv slutstatus.
     tekst på egen flade 7,36:1 (krav 4,5) · tekst på hvid 8,66:1
     kant mod hvid 3,53:1 · mod grå-25 3,18:1 · mod egen flade 3,00:1 (krav 3,0)
     flade mod hvid 1,18:1 — fladen alene bærer ingen information */
  --tone-success-tekst:    #265440;
  --tone-success-flade:    #E5EFE9;
  --tone-success-kant:     #5B9477;

  /* ATTENTION — Blomme. Afvigelse, ændring eller udløbet frist — kræver et menneskes blik.
     tekst på egen flade 8,18:1 (krav 4,5) · tekst på hvid 9,68:1
     kant mod hvid 3,55:1 · mod grå-25 3,20:1 · mod egen flade 3,00:1 (krav 3,0)
     flade mod hvid 1,18:1 — fladen alene bærer ingen information */
  --tone-attention-tekst:  #6B2C64;
  --tone-attention-flade:  #F3E9F2;
  --tone-attention-kant:   #AF75A5;

  /* CRITICAL — Rød. Afvisning, aflysning eller fejl.
     tekst på egen flade 6,83:1 (krav 4,5) · tekst på hvid 8,13:1
     kant mod hvid 3,59:1 · mod grå-25 3,23:1 · mod egen flade 3,01:1 (krav 3,0)
     flade mod hvid 1,19:1 — fladen alene bærer ingen information */
  --tone-critical-tekst:   #98202F;
  --tone-critical-flade:   #F9E7EA;
  --tone-critical-kant:    #CA6A7A;

  /* MUTED — Grå. Lukket, arkiveret, forbrugt, tilbagetrukket eller irrelevant.
     tekst på egen flade 8,56:1 (krav 4,5) · tekst på hvid 10,22:1
     kant mod hvid 3,61:1 · mod grå-25 3,26:1 · mod egen flade 3,02:1 (krav 3,0)
     flade mod hvid 1,19:1 — fladen alene bærer ingen information */
  --tone-muted-tekst:      #463F44;
  --tone-muted-flade:      #EDEAEC;
  --tone-muted-kant:       #93828C;

  /* ---------------------------------------------------------------------------
     9. HVAD DER BLEV RETTET I STATUSPALETTEN
     Designets otte kantfarver lå på 1,49–1,70:1 mod hvid og bestod dermed
     ikke 1.4.11. Hver kant er sænket i lyshed med bevaret kulør og mætning,
     indtil den består 3,0:1 mod hvid, mod grå-25 OG mod sin egen flade.
     Tekstfarver og fladefarver er UÆNDREDE — de bestod allerede.

       tone        design-kant  før (hvid)  rettet    efter (hvid/grå-25/flade)
       neutral     #C7D6DE      1,49      #658EA4   3,52 / 3,18 / 3,01
       waiting     #E3CDA4      1,55      #AD8335   3,46 / 3,12 / 3,03
       progress    #C3CCE4      1,61      #7187BF   3,55 / 3,20 / 3,01
       success     #B9D4C6      1,58      #5B9477   3,53 / 3,18 / 3,00
       attention   #DCC3D8      1,64      #AF75A5   3,55 / 3,20 / 3,00
       critical    #E7BCC3      1,70      #CA6A7A   3,59 / 3,23 / 3,01
       muted       #D2CBCF      1,59      #93828C   3,61 / 3,26 / 3,02

     Den ottende designfamilie, oliven (--status-afsluttet #4F5530 / #EFF0E4 /
     #CFD2B6), er UDGÅET. S9 §2.8 giver `completed` tonen tone-muted, og
     tone-muted skal også bære `refunded`, `busy`, `withdrawn`, `expired`,
     `skipped` og `handed_over`. Grå læses entydigt som «lukket/arkiveret»;
     oliven ville læses som en selvstændig betydning og bryde KR-D-021.
     Se afsnit 16 for aliaset, der holder gamle referencer i live.
     --------------------------------------------------------------------------- */

  /* ---------------------------------------------------------------------------
     10. BETALINGSPALETTEN — RETTET (R12)
     Designet havde fem betalingstokens, heriblandt --pay-restance. «Restance»
     er IKKE en status i systemet: economy.payment_status (S4) har syv værdier
     og ingen af dem hedder restance. Tokenet er SLETTET.
     Paletten er nu economy.payment_status' syv faktiske værdier med de danske
     labels fra S8 §16.2, hver bundet til sin tone fra S9 §2.8.
     --------------------------------------------------------------------------- */
  --pay-pending:              var(--tone-waiting-tekst);   /* Afventende           tone-waiting, tekst på flade 6,01:1 */
  --pay-sent:                 var(--tone-progress-tekst);   /* Udsendt              tone-progress, tekst på flade 7,35:1 */
  --pay-completed:            var(--tone-success-tekst);   /* Gennemført           tone-success, tekst på flade 7,36:1 */
  --pay-partially_refunded:   var(--tone-attention-tekst);   /* Delvist refunderet   tone-attention, tekst på flade 8,18:1 */
  --pay-refunded:             var(--tone-muted-tekst);   /* Refunderet           tone-muted, tekst på flade 8,56:1 */
  --pay-declined:             var(--tone-critical-tekst);   /* Afvist               tone-critical, tekst på flade 6,83:1 */
  --pay-cancelled:            var(--tone-critical-tekst);   /* Annulleret           tone-critical, tekst på flade 6,83:1 */

  --pay-pending-flade:        var(--tone-waiting-flade);
  --pay-sent-flade:           var(--tone-progress-flade);
  --pay-completed-flade:      var(--tone-success-flade);
  --pay-partially_refunded-flade:  var(--tone-attention-flade);
  --pay-refunded-flade:       var(--tone-muted-flade);
  --pay-declined-flade:       var(--tone-critical-flade);
  --pay-cancelled-flade:      var(--tone-critical-flade);

  --pay-pending-kant:         var(--tone-waiting-kant);
  --pay-sent-kant:            var(--tone-progress-kant);
  --pay-completed-kant:       var(--tone-success-kant);
  --pay-partially_refunded-kant:  var(--tone-attention-kant);
  --pay-refunded-kant:        var(--tone-muted-kant);
  --pay-declined-kant:        var(--tone-critical-kant);
  --pay-cancelled-kant:       var(--tone-critical-kant);

  /* ---------------------------------------------------------------------------
     11. AKTØRSVAR (KR-D-026) — RETTET
     Designets --svar-manglende var #8A2B1E, en rustrød uden for enhver
     tonefamilie. Manglende svar er ikke en fejl, men et opfølgningspunkt:
     tone-attention. Synligheden kommer fra `attention_badge` (S9 §2.4) og
     ikonet, ikke fra farven (KR-D-006, KR-D-022).
     --------------------------------------------------------------------------- */
  --svar-yes:           var(--tone-success-tekst);   /* Ja               tone-success */
  --svar-no:            var(--tone-critical-tekst);   /* Nej              tone-critical */
  --svar-pending:       var(--tone-waiting-tekst);   /* Afventer         tone-waiting */
  --svar-missing:       var(--tone-attention-tekst);   /* Manglende svar   tone-attention */

  /* ---------------------------------------------------------------------------
     12. TYPOGRAFI — UÆNDRET fra designleverancen
     Big Shoulders Display + Figtree er STAND-IN, indtil museets licensfiler
     foreligger. Udskiftning må kun ske i --font-display og --font-broed;
     skalaen står fast, så ombrydning ikke skal gennemgås to gange.
     Skrifterne er temafelter i gruppen «skrifter» (kuratorvindue 21,
     2026-09-29, MT-0) — valgfelter over en lukket liste, fordi et temas
     fields.json intet egentligt skriftfelt har (spike MT-P0): Big Shoulders
     Display + Figtree er VIBORGS valg, sat i Viborgs portal. Produktets
     neutrale standard er systemskriften (system-ui, sans-serif) i begge
     roller. Skalaen er produktets og står fast for alle museer.
     Bemærk: --type-* sætter kun font-shorthand. text-transform: uppercase på
     display-niveauerne sættes i komponenten, ikke i tokenet, fordi versal-tekst
     på engelsk bliver bredere (design-brief afsnit 2.10).
     --------------------------------------------------------------------------- */
  --font-display:       'Big Shoulders Display', sans-serif;
  --font-broed:         'Figtree', system-ui, sans-serif;
  --type-display-xl:    600 56px/1 var(--font-display);      /* stor tekst — kontrastkrav 3,0:1 */
  --type-display-l:     600 40px/1.05 var(--font-display);   /* stor tekst */
  --type-display-m:     600 28px/1.1 var(--font-display);    /* stor tekst */
  --type-display-s:     600 20px/1.15 var(--font-display);   /* IKKE stor tekst: 20px < 24px → 4,5:1 */
  --type-broed-l:       400 18px/1.6 var(--font-broed);      /* 4,5:1 */
  --type-broed-m:       400 16px/1.6 var(--font-broed);      /* 4,5:1 */
  --type-broed-s:       400 14px/1.5 var(--font-broed);      /* 4,5:1 */
  --type-label:         700 12px/1.33 var(--font-broed);     /* 4,5:1 */
  --label-spacing:      .12em;
  --tabular:            tabular-nums;   /* NYT. Klokkeslæt, beløb, antal og nedtælling
                                           skal stå i tabulære tal, ellers hopper
                                           30-minutters-timeren. */

  /* ---------------------------------------------------------------------------
     13. SPACING, FORM OG SKYGGE — UÆNDRET
     --------------------------------------------------------------------------- */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px;
  --radius-0: 0;    /* Domkirkekvarterets udtryk er retkantet. */
  --radius-1: 2px;  /* Kun badges og chips. */
  --skygge-overlay:     0 10px 34px rgba(69,0,25,.20);
  --skygge-loeftet:     0 2px 10px rgba(69,0,25,.10);   /* NYT: navngiver designets anden skyggeværdi. */
  --overlay-baggrund:   rgba(46,0,17,.55);              /* NYT: modal-bagtæppe, var unavngivet. */
  --kant-haar:          1px solid var(--kant-dekorativ);      /* BEVARET NAVN, ny værdi-rolle: dekorativ. */
  --kant-komponent:     1px solid var(--kant-ui);             /* NYT: brug denne omkring alt interaktivt. */

  /* ---------------------------------------------------------------------------
     14. BRYDEPUNKTER — NYT (KR-D-029)
     Designleverancen indeholder 0 @media-forespørgsler og kun 3 mobilrammer i
     alt. Brydepunkterne er derfor fastlagt her og er bindende.

     VIGTIGT: en CSS-variabel kan IKKE bruges i en @media-forespørgsel.
     Tokenene nedenfor er den kanoniske KILDE til værdierne og skal
     eksporteres til SCSS/TS ved build (packages/ui/src/tokens.ts), så
     @media-reglerne skrives med de literale pixelværdier og aldrig
     divergerer. Skriv @media (min-width: 600px), ikke var(--bp-tablet).

       mobil    0    –  599px   base, ingen forespørgsel
       tablet   600  – 1023px   @media (min-width: 600px)
       desktop  1024 – 1439px   @media (min-width: 1024px)
       bred     1440px og op    @media (min-width: 1440px)

     Regel (KR-D-029, design-brief afsnit 2.8):
       Bookingflow, webshop og aktørportal er MOBILE-FIRST — basislaget er
       mobil, og hvert af bookingflowets otte trin skal have en fuldt
       specificeret mobilvisning.
       DP-cockpittet er DESKTOP-FIRST, men skal være brugbart på tablet:
       ingen central funktion må falde bort under 1024px; tabeller får
       vandret rul med fastfrosset første kolonne, ikke skjulte kolonner.
     --------------------------------------------------------------------------- */
  --bp-mobil:           0;
  --bp-mobil-max:       599px;
  --bp-tablet:          600px;
  --bp-tablet-max:      1023px;
  --bp-desktop:         1024px;
  --bp-desktop-bred:    1440px;

  /* Indholdsbredder, aflæst i designleverancen og nu navngivet */
  --bredde-side:        1180px;  /* Ydre indholdsbredde i cockpit og kundeflader. */
  --bredde-flow:        700px;   /* Bookingflowets kolonne. */
  --bredde-smal:        620px;   /* Login, L1/L2, fejlsider. */
  --bredde-tekst:       70ch;    /* Brødtekstmål. Designet varierede 62–88ch; 70ch er normalen. */
  --bredde-mobil-ramme: 340px;   /* Mobilmockup-bredde i designleverancen. */
  --min-maalflade:      44px;    /* NYT. Mindste berøringsmål (WCAG 2.5.5 AAA / 2.5.8 AA i 2.2).
                                    Designet specificerer ingen — kalendercellerne og
                                    tælleknapperne i trin 4 er under dette på mobil. */

  /* ---------------------------------------------------------------------------
     15. FORRETNINGSREGLER MED VISUEL KONSEKVENS — UÆNDRET
     Tallene er visningskonstanter. Den autoritative kilde er motorens
     regelkonfiguration (S5); fladen må aldrig regne på dem selv (S8 §2.7).
     --------------------------------------------------------------------------- */
  --reservation-minutter:           30;
  --reservation-advarsel-minutter:  5;
  --slot-granularitet-minutter:     15;
  --kort-varsel-dage:               14;   /* NYT: KR-K-026, vises i trin 3, kurv, trin 8, kvittering. */
  --afvigelse-tolerance-procent:    20;   /* NYT: S9 §3.7 A7. UI-konstant i fase 1 (AFGJORT). */

  /* ---------------------------------------------------------------------------
     16. TREDJEPARTSMÆRKER — NYT
     Kortordningernes egne farver. WCAG 1.4.3's logotype-undtagelse gælder:
     de må ikke justeres. De skal derfor ALTID ledsages af tekstnavnet, så
     betalingsmetoden kan læses uden farve (KR-D-022).
     --------------------------------------------------------------------------- */
  --brand-visa:         #1A1F71;
  --brand-mastercard:   #EB001B;
  --brand-mobilepay:    #5A78FF;

  /* ---------------------------------------------------------------------------
     17. KNAPPER — navngivning af designets hardkodede knapfarver
     --------------------------------------------------------------------------- */
  --knap-primaer-flade:        #E4003C;  /* hvid tekst 4,81:1 — består 4,5:1 */
  --knap-primaer-flade-hover:  #B80031;  /* hvid tekst 6,81:1 */
  --knap-sekundaer-flade:      #450019;  /* hvid tekst 16,57:1 */
  --knap-destruktiv-flade:     #98202F;  /* hvid tekst 8,13:1 */
  --knap-destruktiv-hover:     #7C1926;  /* hvid tekst 10,38:1 — 1 forekomst uden token */
  --knap-deaktiveret-flade:    #F7BDCC;
  --knap-deaktiveret-tekst:    #7A2B3D;  /* 5,85:1 på den blege flade — 4 forekomster uden token.
                                            Deaktiveret tilstand SKAL desuden bære aria-disabled og en
                                            forklarende tekst ved siden af knappen (KR-D-017–020). */
  --knap-tekst-farve:          #B80031;  /* Tekstknap på lys flade. 6,14:1 mod grå-25 */
}

/* =============================================================================
   18. ENUM → TONE: DEN KOMPLETTE MAPPINGTABEL
   =============================================================================
   Facit for VÆRDIERNE er 04-motor-database-ddl.md (`CREATE TYPE ... AS ENUM`)
   sammenholdt med R1 i KANONISKE-RETTELSER.md.
   Facit for TONERNE er 09-skaermspecs-intern-app.md §2.8.
   Facit for de danske LABELS er 08-skaermspecs-kundeflader.md §16 og S9 §2.8.

   BROEN MELLEM DANSK OG ENGELSK — læs dette, før du navngiver noget.
   Designleverancen brugte danske tokennavne (--status-modtaget), mens
   enum-værdien i databasen, API'et og alle kontrakter er engelsk (`received`).
   Det er en fejlkilde: en frontend-agent skal ellers oversætte i hovedet
   mellem det, API'et sender, og det, tokenet hedder.
   Reglen her er derfor:
     1. TOKENNAVNE og KLASSENAVNE er ENGELSKE og staves nøjagtigt som
        enum-værdien fra S4. `received`, ikke `modtaget`.
     2. DANSKE LABELS er DATA, ikke design. S8 §16 er utvetydig: «Koden er
        den stabile nøgle; teksten er visningsklar og leveres af API'et.»
        Fladen viser det, API'et sender (fx `status_label`, `state_label`) —
        den må ikke slå labels op i CSS.
     3. Tabellen nedenfor er den bindende oversættelsesnøgle. Den bruges til
        at verificere API'ets tekster og til at oversætte til `en`, ikke som
        runtime-kilde.
     4. De gamle danske tokennavne findes som alias i afsnit 21, så
        designleverancens eksempler stadig kan læses. De er UDFASEDE.

   ---------------------------------------------------------------------------

   core.booking_status   [S9 §2.8 + S8 §16.1 (facit)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   received                    Modtaget                      tone-neutral
   awaiting                    Afventer                      tone-waiting
   assigned                    Tildelt                       tone-progress
   confirmed                   Bekræftet                     tone-success
   changed                     Ændret                        tone-attention
   rejected                    Afvist                        tone-critical
   cancelled                   Aflyst                        tone-critical
   completed                   Afsluttet                     tone-muted

   core.session_status   [S9 §2.8 + S8 §16.3 (facit)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   planned                     Planlagt                      tone-neutral
   awaiting_assignment         Afventer tildeling            tone-waiting
   assigned                    Tildelt                       tone-progress
   confirmed                   Bekræftet                     tone-success
   changed                     Ændret                        tone-attention
   cancelled                   Aflyst                        tone-critical
   completed                   Afsluttet                     tone-muted

   economy.payment_status   [S9 §2.8 + S8 §16.2 (facit)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   pending                     Afventende                    tone-waiting
   sent                        Udsendt                       tone-progress
   completed                   Gennemført                    tone-success
   partially_refunded          Delvist refunderet            tone-attention
   refunded                    Refunderet                    tone-muted
   declined                    Afvist                        tone-critical
   cancelled                   Annulleret                    tone-critical

   economy.order_status   [S4 + R1 (facit); S8 §16.3 mangler draft/failed og nævner expired]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   draft                       Kladde                        tone-neutral
   awaiting_payment            Afventer betaling             tone-waiting
   paid                        Betalt                        tone-success
   partially_refunded          Delvist refunderet            tone-attention
   refunded                    Refunderet                    tone-muted
   cancelled                   Annulleret                    tone-critical
   failed                      Fejlet                        tone-critical

   ticketing.ticket_status   [S4 + R1 (facit); labels fra S8 §16.3]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   issued                      Udstedt                       tone-neutral
   valid                       Gyldig                        tone-success
   used                        Brugt                         tone-muted
   cancelled                   Annulleret                    tone-critical
   refunded                    Refunderet                    tone-muted
   expired                     Udløbet                       tone-muted

   ticketing.qr_status   [S4 + R1 (deactivated → revoked)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   active                      Aktiv                         tone-success
   redeemed                    Indløst                       tone-muted
   expired                     Udløbet                       tone-muted
   revoked                     Spærret                       tone-critical

   economy.gift_card_status   [S4 + R1]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   active                      Aktivt                        tone-success
   depleted                    Opbrugt                       tone-muted
   expired                     Udløbet                       tone-muted
   cancelled                   Annulleret                    tone-critical

   core.activity_status   [S4]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   draft                       Kladde                        tone-neutral
   published                   Offentliggjort                tone-success
   sold_out                    Udsolgt                       tone-attention
   cancelled                   Aflyst                        tone-critical
   completed                   Afsluttet                     tone-muted

   core.flow_status   [S9 §2.8 (facit)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   active                      Aktiv                         tone-progress
   awaiting_response           Afventer svar                 tone-waiting
   stopped                     Stoppet                       tone-attention
   failed                      Fejlet                        tone-critical
   completed                   Afsluttet                     tone-muted

   core.assignment_status   [S4 + R1 (10 værdier) — S9 §2.8 nævner 6 andre; S4 vinder; cancelled/handed_over-labels = S5 §7.1 + S9 §2.8, BUG-841, kuratorvindue 11]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   proposed                    Foreslået                     tone-neutral
   requested                   Forespurgt                    tone-waiting
   accepted                    Accepteret                    tone-success
   declined                    Afvist                        tone-attention
   assigned                    Tildelt                       tone-progress
   confirmed                   Bekræftet                     tone-success
   cancelled                   Annulleret                    tone-critical
   handed_over                 Overdraget                    tone-muted
   completed                   Gennemført                    tone-muted
   no_show                     Udeblevet                     tone-critical

   core.assignment_request_status   [S4 + R1; toner fra S9 §2.8]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   sent                        Afventer svar                 tone-waiting
   reminded                    Påmindelse sendt              tone-waiting
   accepted                    Accepteret                    tone-success
   declined                    Afvist                        tone-attention
   expired                     Frist udløbet                 tone-attention
   withdrawn                   Trukket tilbage               tone-muted
   superseded                  Sendt videre                  tone-muted

   core.handover_status   [S4 + R1; S9 §2.8: tone som forespørgselsstatus]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   open                        Afventer                      tone-waiting
   accepted                    Accepteret                    tone-success
   declined                    Afvist                        tone-attention
   expired                     Frist udløbet                 tone-attention
   cancelled                   Annulleret                    tone-muted
   resolved_by_dp              Løst af DP                    tone-progress
   resulted_in_cancellation    Førte til aflysning           tone-critical

   core.change_request_status   [S4 + R1 (8 værdier)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   submitted                   Indsendt                      tone-neutral
   under_evaluation            Under vurdering               tone-progress
   awaiting_actor_acceptance   Afventer aktørens accept      tone-waiting
   awaiting_customer_confirm   Afventer kundens bekræftelse  tone-waiting
   approved                    Godkendt                      tone-success
   applied                     Gennemført                    tone-success
   rejected                    Afvist                        tone-critical
   withdrawn                   Trukket tilbage               tone-muted

   core.waitlist_status   [S4 + S8 §16.3 (facit for labels)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   waiting                     På venteliste                 tone-waiting
   offered                     Plads tilbudt                 tone-attention
   converted                   Plads købt                    tone-success
   withdrawn                   Afmeldt                       tone-muted

   core.waitlist_offer_status   [S4]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   sent                        Tilbud sendt                  tone-waiting
   accepted                    Accepteret                    tone-success
   declined                    Afvist                        tone-muted
   expired                     Tilbud udløbet                tone-attention

   realtime.availability_state   [S4 + R1; toner fra S9 §2.8 (tentative = "eventuel ledig")]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   available                   Ledig                         tone-success
   tentative                   Eventuel ledig                tone-attention
   busy                        Optaget                       tone-muted

   realtime.cart_status   [S4 + S8 §16.3 (facit for labels)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   open                        Åben                          tone-progress
   expired                     Udløbet                       tone-attention
   converted                   Gennemført                    tone-success
   released                    Frigivet                      tone-muted

   realtime.reservation_status   [S4 + R1 + S8 §16.3]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   active                      Aktiv                         tone-progress
   released                    Frigivet                      tone-muted
   converted                   Gennemført                    tone-success
   expired                     Udløbet                       tone-attention

   comm.delivery_status   [S4 + R1 (7 værdier)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   queued                      I kø                          tone-neutral
   sent                        Sendt                         tone-progress
   delivered                   Leveret                       tone-progress
   opened                      Åbnet                         tone-success
   read                        Læst                          tone-success
   failed                      Fejlet                        tone-critical
   bounced                     Afvist af modtager            tone-critical

   comm.alert_severity   [S4]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   info                        Information                   tone-neutral
   warning                     Advarsel                      tone-attention
   critical                    Kritisk                       tone-critical

   sync.outbox_status   [S4 (S6 §8.6, regelscope sync jf. R3)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   pending                     Afventer                      tone-waiting
   in_flight                   Undervejs                     tone-progress
   delivered                   Leveret                       tone-success
   failed                      Fejlet                        tone-critical
   dead_letter                 Død besked                    tone-critical
   skipped                     Sprunget over                 tone-muted

   sync.inbound_status   [S4]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   received                    Modtaget                      tone-neutral
   processed                   Behandlet                     tone-success
   ignored                     Ignoreret                     tone-muted
   failed                      Fejlet                        tone-critical

   core.actor_status   [S4]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   active                      Aktiv                         tone-success
   temporarily_unavailable     Midlertidigt utilgængelig     tone-attention
   deactivated                 Deaktiveret                   tone-muted

   ticketing.qr_result   [S4 — resultat af scanning (A23)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   valid                       Gyldig                        tone-success
   already_redeemed            Allerede indløst              tone-attention
   expired                     Udløbet                       tone-attention
   unknown                     Ukendt kode                   tone-critical
   not_permitted               Ikke tilladt                  tone-critical

   core.unavailability_reason   [S4 + R1 — vises altid med skraveret mønster (S9 §2.8)]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   vacation                    Ferie                         tone-muted
   sick_leave                  Sygdom                        tone-muted
   closed_period               Lukkeperiode                  tone-muted
   other                       Andet                         tone-muted

   (ingen enum — KR-D-026, S9 §2.8/§5.2)   [Aggregeret aktørsvar i DP-visninger]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   yes                         Ja                            tone-success
   no                          Nej                           tone-critical
   pending                     Afventer                      tone-waiting
   missing                     Manglende svar                tone-attention

   (ingen enum — S8 §16.3 "Ledighed")   [Ledighed på kunde- og webshopflader]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   available                   Ledige pladser                tone-success
   few_left                    Få tilbage                    tone-attention
   sold_out                    Udsolgt                       tone-critical
   closed                      Lukket                        tone-muted

   (ingen enum — S8 §16.4, KR-SY-020/KR-D-011)   [Trinvis brugerrejse; state_label fra API er autoritativ]
   værdi (kanonisk)            dansk label                   tone
   --------------------------------------------------------------------------
   done                        Gennemført                    tone-success
   current                     I gang                        tone-progress
   pending                     Afventer                      tone-waiting
   failed                      Mislykkedes                   tone-critical
   skipped                     Sprunget over                 tone-muted

   AFVIGELSER MELLEM S9 §2.8 OG S4 — noteret, S4 vinder (facit-princippet)
   · assignment_status: S9 §2.8 lister assigned/confirmed/handover_pending/
     cancelled_by_actor/cancelled/completed. S4 + R1 har ti værdier
     (proposed, requested, accepted, declined, assigned, confirmed, cancelled,
     handed_over, completed, no_show). S4's værdier bruges. S9's tonehensigt
     er ført over: «afventer overdragelse» → waiting, «aflyst af aktør» →
     attention.
   · assignment_request_status: S9's `pending` er S4's `sent`; S9's `escalated`
     er S4's `superseded`. Tonerne følger med.
   · availability: S9 skriver `possibly_available`; S4's enum hedder
     `tentative`. Samme tilstand, samme tone.
   · order_status: S8 §16.3 lister `expired`, som ikke findes i
     economy.order_status. S4 + R1 er facit; `expired` mappes ikke.
     ÅBENT PUNKT til spec-kurator — se korrektionsnotatets afsnit 9.
   ============================================================================= */

/* =============================================================================
   19. ENUM → TONE SOM BRUGBARE SELEKTORER
   =============================================================================
   Tre måder at bruge tonen på, alle sætter de samme tre variable:
     --tone-tekst, --tone-flade, --tone-kant

   a) Direkte:        <span class="badge tone-success">
   b) Via statusværdi: <span class="badge" data-booking-status="confirmed">
        — så kan fladen skrive API'ets råværdi direkte ind uden en oversættelse
          i JSX, og en ukendt værdi falder tilbage til tone-neutral.
   c) Via egen tone:   <span class="badge" data-tone="waiting">

   Attributnavnet er enum'ets navn i kebab-case uden skemapræfiks:
     core.booking_status            → data-booking-status
     economy.payment_status         → data-payment-status
     core.assignment_request_status → data-assignment-request-status
   ============================================================================= */

.tone-neutral,
[data-tone="neutral"],
[data-booking-status="received"],
[data-session-status="planned"],
[data-order-status="draft"],
[data-ticket-status="issued"],
[data-activity-status="draft"],
[data-assignment-status="proposed"],
[data-change-request-status="submitted"],
[data-delivery-status="queued"],
[data-alert-severity="info"],
[data-inbound-status="received"] {
  --tone-tekst: var(--tone-neutral-tekst);
  --tone-flade: var(--tone-neutral-flade);
  --tone-kant:  var(--tone-neutral-kant);
}

.tone-waiting,
[data-tone="waiting"],
[data-booking-status="awaiting"],
[data-session-status="awaiting_assignment"],
[data-payment-status="pending"],
[data-order-status="awaiting_payment"],
[data-flow-status="awaiting_response"],
[data-assignment-status="requested"],
[data-assignment-request-status="sent"],
[data-assignment-request-status="reminded"],
[data-handover-status="open"],
[data-change-request-status="awaiting_actor_acceptance"],
[data-change-request-status="awaiting_customer_confirm"],
[data-waitlist-status="waiting"],
[data-waitlist-offer-status="sent"],
[data-outbox-status="pending"],
[data-actor-response="pending"],
[data-journey-state="pending"] {
  --tone-tekst: var(--tone-waiting-tekst);
  --tone-flade: var(--tone-waiting-flade);
  --tone-kant:  var(--tone-waiting-kant);
}

.tone-progress,
[data-tone="progress"],
[data-booking-status="assigned"],
[data-session-status="assigned"],
[data-payment-status="sent"],
[data-flow-status="active"],
[data-assignment-status="assigned"],
[data-handover-status="resolved_by_dp"],
[data-change-request-status="under_evaluation"],
[data-cart-status="open"],
[data-reservation-status="active"],
[data-delivery-status="sent"],
[data-delivery-status="delivered"],
[data-outbox-status="in_flight"],
[data-journey-state="current"] {
  --tone-tekst: var(--tone-progress-tekst);
  --tone-flade: var(--tone-progress-flade);
  --tone-kant:  var(--tone-progress-kant);
}

.tone-success,
[data-tone="success"],
[data-booking-status="confirmed"],
[data-session-status="confirmed"],
[data-payment-status="completed"],
[data-order-status="paid"],
[data-ticket-status="valid"],
[data-qr-status="active"],
[data-gift-card-status="active"],
[data-activity-status="published"],
[data-assignment-status="accepted"],
[data-assignment-status="confirmed"],
[data-assignment-request-status="accepted"],
[data-handover-status="accepted"],
[data-change-request-status="approved"],
[data-change-request-status="applied"],
[data-waitlist-status="converted"],
[data-waitlist-offer-status="accepted"],
[data-availability-state="available"],
[data-cart-status="converted"],
[data-reservation-status="converted"],
[data-delivery-status="opened"],
[data-delivery-status="read"],
[data-outbox-status="delivered"],
[data-inbound-status="processed"],
[data-actor-status="active"],
[data-qr-result="valid"],
[data-actor-response="yes"],
[data-availability-offer="available"],
[data-journey-state="done"] {
  --tone-tekst: var(--tone-success-tekst);
  --tone-flade: var(--tone-success-flade);
  --tone-kant:  var(--tone-success-kant);
}

.tone-attention,
[data-tone="attention"],
[data-booking-status="changed"],
[data-session-status="changed"],
[data-payment-status="partially_refunded"],
[data-order-status="partially_refunded"],
[data-activity-status="sold_out"],
[data-flow-status="stopped"],
[data-assignment-status="declined"],
[data-assignment-request-status="declined"],
[data-assignment-request-status="expired"],
[data-handover-status="declined"],
[data-handover-status="expired"],
[data-waitlist-status="offered"],
[data-waitlist-offer-status="expired"],
[data-availability-state="tentative"],
[data-cart-status="expired"],
[data-reservation-status="expired"],
[data-alert-severity="warning"],
[data-actor-status="temporarily_unavailable"],
[data-qr-result="already_redeemed"],
[data-qr-result="expired"],
[data-actor-response="missing"],
[data-availability-offer="few_left"] {
  --tone-tekst: var(--tone-attention-tekst);
  --tone-flade: var(--tone-attention-flade);
  --tone-kant:  var(--tone-attention-kant);
}

.tone-critical,
[data-tone="critical"],
[data-booking-status="rejected"],
[data-booking-status="cancelled"],
[data-session-status="cancelled"],
[data-payment-status="declined"],
[data-payment-status="cancelled"],
[data-order-status="cancelled"],
[data-order-status="failed"],
[data-ticket-status="cancelled"],
[data-qr-status="revoked"],
[data-gift-card-status="cancelled"],
[data-activity-status="cancelled"],
[data-flow-status="failed"],
[data-assignment-status="cancelled"],
[data-assignment-status="no_show"],
[data-handover-status="resulted_in_cancellation"],
[data-change-request-status="rejected"],
[data-delivery-status="failed"],
[data-delivery-status="bounced"],
[data-alert-severity="critical"],
[data-outbox-status="failed"],
[data-outbox-status="dead_letter"],
[data-inbound-status="failed"],
[data-qr-result="unknown"],
[data-qr-result="not_permitted"],
[data-actor-response="no"],
[data-availability-offer="sold_out"],
[data-journey-state="failed"] {
  --tone-tekst: var(--tone-critical-tekst);
  --tone-flade: var(--tone-critical-flade);
  --tone-kant:  var(--tone-critical-kant);
}

.tone-muted,
[data-tone="muted"],
[data-booking-status="completed"],
[data-session-status="completed"],
[data-payment-status="refunded"],
[data-order-status="refunded"],
[data-ticket-status="used"],
[data-ticket-status="refunded"],
[data-ticket-status="expired"],
[data-qr-status="redeemed"],
[data-qr-status="expired"],
[data-gift-card-status="depleted"],
[data-gift-card-status="expired"],
[data-activity-status="completed"],
[data-flow-status="completed"],
[data-assignment-status="handed_over"],
[data-assignment-status="completed"],
[data-assignment-request-status="withdrawn"],
[data-assignment-request-status="superseded"],
[data-handover-status="cancelled"],
[data-change-request-status="withdrawn"],
[data-waitlist-status="withdrawn"],
[data-waitlist-offer-status="declined"],
[data-availability-state="busy"],
[data-cart-status="released"],
[data-reservation-status="released"],
[data-outbox-status="skipped"],
[data-inbound-status="ignored"],
[data-actor-status="deactivated"],
[data-unavailability-reason="vacation"],
[data-unavailability-reason="sick_leave"],
[data-unavailability-reason="closed_period"],
[data-unavailability-reason="other"],
[data-availability-offer="closed"],
[data-journey-state="skipped"] {
  --tone-tekst: var(--tone-muted-tekst);
  --tone-flade: var(--tone-muted-flade);
  --tone-kant:  var(--tone-muted-kant);
}

/* =============================================================================
   20. DANSKE LABELS SOM TOKENS — designtidsreference, IKKE runtime-kilde
   =============================================================================
   Kun de to kataloger designleverancen selv leverede, så et komponentgalleri
   kan rendere uden API. Runtime-kilden er ALTID API'ets label-felt (S8 §16).
   Hardkodes de i fladen, går den engelske version i stykker (KR-K-005,
   design-brief afsnit 2.10) og DP mister muligheden for at rette teksten
   uden ny udrulning (KR-SY-134).
   Resten af katalogerne står i tabellen i afsnit 18.
   ============================================================================= */
:root {
  --label-booking-received:              "Modtaget";
  --label-booking-awaiting:              "Afventer";
  --label-booking-assigned:              "Tildelt";
  --label-booking-confirmed:             "Bekræftet";
  --label-booking-changed:               "Ændret";
  --label-booking-rejected:              "Afvist";
  --label-booking-cancelled:             "Aflyst";
  --label-booking-completed:             "Afsluttet";

  --label-payment-pending:               "Afventende";
  --label-payment-sent:                  "Udsendt";
  --label-payment-completed:             "Gennemført";
  --label-payment-partially_refunded:    "Delvist refunderet";
  --label-payment-refunded:              "Refunderet";
  --label-payment-declined:              "Afvist";
  --label-payment-cancelled:             "Annulleret";
}

/* =============================================================================
   21. UDGÅEDE TOKENS OG NAVNGIVNING AF DE SIDSTE HEX-VÆRDIER
   =============================================================================
   Designleverancen indeholder 69 unikke hex-værdier i 2.546 forekomster.
   Efter denne fil har hver eneste af dem et navn eller en efterfølger.
   Ingen farve står tilbage uden.

   A. SLETTET UDEN ERSTATNING
   --------------------------------------------------------------------------
   --pay-restance  #8A2B1E     «Restance» er ikke en status. economy.payment_status
                               har syv værdier og ingen af dem er restance.
                               Findes 0 gange i S4, S8 og S9. SLETTET (R12).
                               #8A2B1E, #F7E9E5, #E5C4BB og #C98E80 var kun i
                               brug til dette badge og til --svar-manglende;
                               de er alle erstattet af tone-attention.

   B. OMDØBT — samme farve, nyt navn (ingen visuel ændring)
   --------------------------------------------------------------------------
   #F0EAED   → --kant-dekorativ-svag        85 forekomster, alle border-bottom/-top
   #E0D7DC   → --flade-daempet              42 forekomster: 18 flade, 24 kant (kant → --kant-dekorativ)
   #E2DDE0   → --flade-skravering           22 forekomster, stribe i blokeret-mønster
   #FDF0F4   → --flade-roed-svag            14 forekomster, valgt sprog / valgt kort
   #F2EDF0   → --flade-rolig-2              13 forekomster
   #FBF8F9   → --flade-svag                 12 forekomster
   #E0C4CF   → --paa-moerk-tekst-daempet    14 forekomster, inaktiv navigation
   #C79AAA   → --paa-moerk-label            10 forekomster, versal-label i sidebjælken
   #F7E9E5   → (udgået, se A)               8 forekomster
   #D8CDD3   → --flade-daempet-2            6 forekomster
   #6B4356   → --tekst-sekundaer            5 forekomster; 8,20:1 mod hvid, samme familie som --dk-graa-600
   #C98E80   → (udgået, se A)               5 forekomster
   #FDF9FB   → --flade-hvid-varm            5 forekomster
   #EFE9EC   → --kant-dekorativ-svag        5 forekomster, border-bottom
   #7A2B3D   → --knap-deaktiveret-tekst     4 forekomster
   #F4EFF2   → --flade-rolig                3 forekomster
   #F0DCE3   → --paa-moerk-tekst-sekundaer  2 forekomster
   #E8CFD8   → --paa-moerk-tekst-svag       2 forekomster
   #8FE0B4   → --paa-moerk-succes           2 forekomster
   #295C60   → --tone-muted-tekst           2 forekomster; var --pay-refunderet, nu tone-muted (S9 §2.8)
   #E4EFF0   → --tone-muted-flade           1 forekomst, flade under --pay-refunderet
   #B7D3D6   → --tone-muted-kant            1 forekomst, kant under --pay-refunderet
   #7C1926   → --knap-destruktiv-hover      1 forekomst
   #E5C4BB   → (udgået, se A)               1 forekomst
   #F3E2E8   → --paa-moerk-kode             1 forekomst
   #1A1F71   → --brand-visa                 1 forekomst, kortordningens eget mærke
   #EB001B   → --brand-mastercard           1 forekomst, kortordningens eget mærke
   #5A78FF   → --brand-mobilepay            1 forekomst, kortordningens eget mærke
   #FFF      → --dk-hvid                    373 forekomster i kort form; normaliseres til #FFFFFF

   C. RETTET — ny værdi, fordi den gamle ikke bestod
   --------------------------------------------------------------------------
   #C9BEC5  → --kant-ui #947E8C          feltramme: 1,80:1 → 3,74:1 mod hvid
   #E4DCE0  → --kant-ui #947E8C          hårkant om interaktivt: 1,35:1 → 3,74:1
              --kant-dekorativ #E4DCE0   bevaret som ren skillelinje, 1,35:1, uden information
   #E4003C  → --dk-roed-dyb #B80031      som LINK og lille tekst: 4,34:1 → 6,14:1 mod grå-25
              --dk-roed #E4003C          bevaret som KNAPFLADE med hvid tekst, 4,81:1
   #9C8A93  → --tekst-deaktiveret #845C6D  kalender «lukkedag»: 2,93:1 → 5,07:1 mod grå-25
   #C0B2B9  → --tekst-deaktiveret #845C6D  kalender deaktiveret dag: 2,04:1 → 5,63:1 mod hvid
   #8C6274  → --tekst-daempet #845C6D    dæmpet tekst: 4,12:1 → 4,54:1 mod sand
   #C7D6DE, #E3CDA4, #C3CCE4, #B9D4C6, #DCC3D8, #E7BCC3, #D2CBCF
            → tone-*-kant                de otte badgekanter, se afsnit 9
   rgba(255,255,255,.12/.14/.18/.22)
            → --kant-ui-paa-moerk .39    komponentgrænse på mørk flade, 1,34–1,87:1 → 3,30:1

   D. UDFASEDE ALIAS — holder designleverancens danske navne i live
   --------------------------------------------------------------------------
   Brug dem ikke i ny kode. De fjernes, når alle tre frontends er migreret.
   ============================================================================= */
:root {
  --status-modtaget:         var(--tone-neutral-tekst);   /* UDFASET → data-booking-status="received" */
  --status-modtaget-flade:   var(--tone-neutral-flade);
  --status-modtaget-kant:    var(--tone-neutral-kant);
  --status-afventer:         var(--tone-waiting-tekst);   /* UDFASET → data-booking-status="awaiting" */
  --status-afventer-flade:   var(--tone-waiting-flade);
  --status-afventer-kant:    var(--tone-waiting-kant);
  --status-tildelt:          var(--tone-progress-tekst);   /* UDFASET → data-booking-status="assigned" */
  --status-tildelt-flade:    var(--tone-progress-flade);
  --status-tildelt-kant:     var(--tone-progress-kant);
  --status-bekraeftet:       var(--tone-success-tekst);   /* UDFASET → data-booking-status="confirmed" */
  --status-bekraeftet-flade: var(--tone-success-flade);
  --status-bekraeftet-kant:  var(--tone-success-kant);
  --status-aendret:          var(--tone-attention-tekst);   /* UDFASET → data-booking-status="changed" */
  --status-aendret-flade:    var(--tone-attention-flade);
  --status-aendret-kant:     var(--tone-attention-kant);
  --status-afvist:           var(--tone-critical-tekst);   /* UDFASET → data-booking-status="rejected" */
  --status-afvist-flade:     var(--tone-critical-flade);
  --status-afvist-kant:      var(--tone-critical-kant);
  --status-aflyst:           var(--tone-critical-tekst);   /* UDFASET → data-booking-status="cancelled" */
  --status-aflyst-flade:     var(--tone-critical-flade);
  --status-aflyst-kant:      var(--tone-critical-kant);
  --status-afsluttet:        var(--tone-muted-tekst);   /* UDFASET → data-booking-status="completed" */
  --status-afsluttet-flade:  var(--tone-muted-flade);
  --status-afsluttet-kant:   var(--tone-muted-kant);

  /* UDFASET: designets betalings- og aktørsvarsnavne */
  --pay-afventer:    var(--pay-pending);      /* → data-payment-status="pending"   */
  --pay-betalt:      var(--pay-completed);    /* → data-payment-status="completed" */
  --pay-annulleret:  var(--pay-cancelled);    /* → data-payment-status="cancelled" */
  --pay-refunderet:  var(--pay-refunded);     /* → data-payment-status="refunded"  */
  --svar-ja:         var(--svar-yes);
  --svar-nej:        var(--svar-no);
  --svar-afventer:   var(--svar-pending);
  --svar-manglende:  var(--svar-missing);
}

/* =============================================================================
   22. KOMPONENTKLASSER — det minimum, tokenlaget skal levere for at være brugbart
   =============================================================================
   Ikke et komponentbibliotek. Kun de regler, hvor en frontend-agent ellers
   ville vælge en farve eller en kant på egen hånd og bryde kontrastkravet.
   ============================================================================= */

/* --- 22.1 Statusbadge (KR-D-021, KR-D-022, KR-SY-021) ---------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) 10px;
  border-radius: var(--radius-1);
  font: var(--type-broed-s);
  font-weight: 600;
  color: var(--tone-tekst, var(--tone-neutral-tekst));
  background: var(--tone-flade, var(--tone-neutral-flade));
  border: 1px solid var(--tone-kant, var(--tone-neutral-kant));
}
/* Ikonet er obligatorisk. Farve må aldrig stå alene (KR-D-022, KR-SY-021).
   Ikonet arver tekstfarven og har derfor samme målte kontrast som teksten. */
.badge > .badge__ikon { flex: none; width: 1em; height: 1em; fill: currentColor; }
/* Skærmlæsere skal have hele betydningen, ikke kun labelen. */
.badge > .badge__tekst { white-space: nowrap; }

/* --- 22.2 Formularfelt (KR-D-017–020, S8 §2.5) ----------------------------- */
.felt {
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
  background: var(--dk-hvid);
  border: 1px solid var(--kant-felt);      /* 3,74:1 mod hvid — består 1.4.11 */
  border-radius: var(--radius-0);
  padding: var(--sp-3) var(--sp-4);
  min-height: var(--min-maalflade);
  width: 100%;
}
.felt::placeholder { color: var(--tekst-daempet); }   /* 5,63:1 mod hvid */
.felt[aria-invalid="true"] { border-color: var(--kant-felt-fejl); border-width: 2px; }
.felt[disabled], .felt[aria-disabled="true"] {
  color: var(--tekst-deaktiveret);
  background: var(--dk-graa-25);
  border-style: dashed;                    /* tilstanden bæres af mønster, ikke farve */
}
.felt-fejltekst { font: var(--type-broed-s); color: var(--tekst-fejl); }  /* 6,81:1 mod hvid */
/* Bindende markup — se korrektionsnotatets afsnit 6:
   <label for="ID">…<span aria-hidden="true">*</span><span class="kun-skaermlaeser"> (skal udfyldes)</span></label>
   <input id="ID" aria-invalid="true" aria-describedby="ID-fejl">
   <p id="ID-fejl" class="felt-fejltekst">…</p>                                   */

/* --- 22.3 Fokus — gælder ALLE fokuserbare elementer ------------------------ */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--fokus-lys);
  outline-offset: var(--fokus-offset);
}
/* Mørke flader. Designleverancen definerede --fokus-moerk, men anvendte den
   0 gange og viste ingen fokustilstand på bordeaux. Her er den bundet.
   Sæt .paa-moerk på enhver container med bordeaux-baggrund. */
.paa-moerk :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--fokus-moerk);
  outline-offset: var(--fokus-offset);
}
.paa-moerk { color: var(--paa-moerk-tekst); }
.paa-moerk .felt { border-color: var(--kant-ui-paa-moerk); }

/* --- 22.4 Trinindikator (KR-D-011, KR-SY-020, S8 §3.2) --------------------- */
/* aria-current="step" på det aktive trin er OBLIGATORISK — designleverancen
   har 0 forekomster af aria-current. Tilstanden skal desuden bæres af tekst
   og ikon, ikke af farve alene. */
.trin[aria-current="step"] { color: var(--tekst-primaer); font-weight: 700; border-bottom: 2px solid var(--kant-markant); }
.trin[data-trin-tilstand="done"]    { color: var(--tone-success-tekst); }
.trin[data-trin-tilstand="pending"] { color: var(--tekst-daempet); }   /* 5,63:1 — ikke #C0B2B9 */
.trin[data-trin-tilstand="failed"]  { color: var(--tone-critical-tekst); }

/* --- 22.5 Kalendercelle (S8 §6.4, KR-D-023) -------------------------------- */
.kalendercelle {
  min-width: var(--min-maalflade);
  min-height: var(--min-maalflade);
  font: var(--type-broed-m);
  font-variant-numeric: var(--tabular);
  color: var(--tekst-primaer);
  background: var(--dk-hvid);
  border: 1px solid var(--kant-ui);
}
.kalendercelle[aria-disabled="true"],
.kalendercelle[data-tilstand="closed"] {
  color: var(--tekst-deaktiveret);         /* RETTET fra #C0B2B9 (2,04:1) og #9C8A93 (2,93:1) */
  background: var(--dk-graa-25);
  border-style: dashed;
  border-color: var(--kant-dekorativ);
}
.kalendercelle[data-tilstand="blocked"] {
  background: repeating-linear-gradient(135deg,
    var(--tone-muted-flade), var(--tone-muted-flade) 5px,
    var(--kant-skravering) 5px, var(--kant-skravering) 10px);
  border-color: var(--tone-muted-kant);
}

/* --- 22.6 Timer til 30-minutters reservationen (KR-K-018, S8 §9.5) --------- */
/* aria-live er OBLIGATORISK. Designleverancen har 0 forekomster.
   role="timer" alene annoncerer ikke; brug aria-live="polite" og skift til
   "assertive", når --reservation-advarsel-minutter er nået. */
.reservationstimer { font-variant-numeric: var(--tabular); color: var(--tekst-primaer); }
.reservationstimer[data-advarsel="true"] { color: var(--tone-critical-tekst); font-weight: 700; }

/* --- 22.7 Kun for skærmlæsere --------------------------------------------- */
.kun-skaermlaeser {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- 22.8 Reduceret bevægelse --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* =============================================================================
   23. BRYDEPUNKTERNE SOM FAKTISKE @MEDIA-REGLER
   =============================================================================
   Skabelonen frontend-agenter skal kopiere. Pixelværdierne er literale, fordi
   var() ikke virker i en @media-forespørgsel; de skal holdes synkrone med
   --bp-* i afsnit 14 gennem tokens.ts-eksporten.
   ============================================================================= */
/* mobil = base, ingen forespørgsel */
@media (min-width: 600px)  { :root { --brydepunkt: tablet;  } }
@media (min-width: 1024px) { :root { --brydepunkt: desktop; } }
@media (min-width: 1440px) { :root { --brydepunkt: bred;    } }

/* =============================================================================
   24. AFVIGELSE TIL MUSEETS GODKENDELSE — MED KORREKTE TAL
   =============================================================================
   Designleverancens afvigelsesnote angav to forkerte tal. De rettede tal
   nedenfor er beregnet med WCAG 2.1's formel og er dem, museet skal godkende
   på.

     Farvepar                          designets påstand   faktisk målt
     ---------------------------------------------------------------------
     #E4003C på #FFFFFF                6,4:1               4,81:1
     #B80031 på #FFFFFF                7,3:1               6,81:1

   Hvad afvigelsen faktisk er:
   Domkirkekvarterets #E4003C måler 4,81:1 mod hvid. Den består altså 4,5:1
   som knapflade med hvid tekst og som brødtekst direkte på hvid — men kun
   dér. På sidebaggrunden #F6F2F4 falder den til 4,34:1 og på sandfladen
   #ECE5E8 til 3,88:1; begge er under 4,5:1 og dur derfor ikke til link,
   lille tekst eller ikon. Derfor er #B80031 indført til rød tekst, røde
   ikoner og røde fokusrammer: 6,81:1 mod hvid, 6,14:1 mod #F6F2F4 og
   5,50:1 mod #ECE5E8.
   Rød som FLADE er uændret. Ingen brandfarve er udskiftet; der er tilføjet
   én mørkere nuance af den samme røde til tekstrollen, præcis som design-
   briefens punkt 2.9 foreskriver.
   ============================================================================= */

/* =============================================================================
   LAG 2 — KOMPONENTLAGET (E12-S02, «Designsystemet i kode»)
   =============================================================================
   ALT OVENFOR denne linje er `spec/12-designtokens.css`, ORDRET og uændret.
   Prøven `test/tokenlaget.test.ts` sammenligner byte for byte og bliver rød,
   hvis ét tegn i lag 1 flyttes. Skal en VÆRDI ændres, ændres den i spec/12 — og
   først efter at kontrastforholdet er genberegnet og det målte tal skrevet i
   kommentaren (spec/13 afsnit 7).

   ALT HERUNDER er ADDITIVT og indfører:
     · ingen ny farve                    — hver farve er en var() fra lag 1
     · ingen hex-værdi                   — håndhævet af `test/tokenlaget.test.ts`
     · ingen ny kontrastpåstand          — de målte tal står i lag 1 og
                                           efterprøves af `test/a11y/kontrast.test.ts`,
                                           der REGNER dem ud af WCAG 2.1's
                                           formel i stedet for at tro på dem

   Hvorfor lag 2 ligger i SAMME fil som lag 1: E12-S01's kildeliste
   (`hubspot/theme/src/kilder.ts`) kopierer ÉN fil ind i temaet. Lå komponent-
   laget ved siden af, ville temaet få tokens uden komponenter, og de tre
   frontends ville ikke længere dele det samme udtryk (accept 1).
   ============================================================================= */

/* =============================================================================
   25. TO TÆTHEDER (KR-D-002, E12-S02 accept 4)
   =============================================================================
   Ikke to komponentsæt — ÉN mekanisme. Hver komponent læser de samme otte
   variabler, og tætheden sættes af en forfader:

     <div data-taethed="enkel">   kunde- og aktørvendt: handlingsorienteret
     <div data-taethed="taet">    administrativt: flere detaljer pr. skærm

   Tallene er designleverancens egne, aflæst i komponentbiblioteket:
   «Højde 48 px kundevendt · 36 px i cockpittet · aldrig under 44 px på mobil».

   DEN SIDSTE HALVSÆTNING ER REGLEN, IKKE EN NOTE. Basislaget er mobil
   (KR-D-029), og dér er BEGGE tætheder mindst --min-maalflade (44px). Først
   fra tablet og op må den tætte variant gå ned på 36px — dér er der en mus.
   Derfor findes 36-tallet kun inde i @media-blokken i afsnit 34.

   `--taethed-navn` er ikke dekoration: den lader en prøve og en udvikler læse
   den beregnede tæthed ud af DOM'en i stedet for at gætte på klassenavne.

   `--kontrol-hoejde` ER DEN ENE HØJDE, ALLE KONTROLFORMER LÆSER (QA-fund 21,
   30/8). Målt live på 1388px stod fem sideordnede kontroller i fem højder —
   vælger 44,0px, tekstfelt 51,6, datofelt 53,6, antalfelt 52,8, knap 48 —
   med SAMME polstring og SAMME skriftstørrelse. Forskellen kom hverken fra
   tokens eller fra skærmene, men fra hver kontrolforms egen indre højde:
   `<select>` klampes af browseren, `<input type=date>` bærer en højere
   skyggekontrol end `type=text`, og antalfeltets 18px-tal er 3,2px højere end
   tekstfeltets 16px. Sat op ad hinanden — katalogets filterrække, checkoutens
   leveringsvælger — springer underkanterne 9,6px.

   HØJDEN KAN DERFOR IKKE OVERLADES TIL POLSTRINGEN. Hver kontrolform får en
   EKSPLICIT `height` fra dette ene token, og den lodrette polstring skrives
   til 0: browseren centrerer selv en enkeltlinjekontrols indhold i sin
   højde, og så er indholdets egen linjehøjde ikke længere med til at bestemme
   den ydre. Vandret polstring og alt andet er uændret.

   TALLET ER TÆTHEDENS EGET og ikke et nyt: `--taethed-hoejde` bærer allerede
   designleverancens «48 px kundevendt · 36 px i cockpittet · aldrig under
   44 px på mobil», og knappen har stået på det hele tiden — det er de fire
   ANDRE former, der aldrig spurgte. Tokenet er derfor et ALIAS med et navn,
   der siger, hvad det er til: det kan ikke skride fra knappens højde, og en
   kontrolform, der senere vil have sin egen, skal ændre navnet og dermed
   forklare sig.
   --------------------------------------------------------------------------- */
:root,
[data-taethed="enkel"] {
  --taethed-navn:        enkel;
  --taethed-hoejde:      48px;              /* designleverancens kundevendte knaphøjde */
  --taethed-hoejde-min:  var(--min-maalflade);
  --kontrol-hoejde:      var(--taethed-hoejde);
  --kontrol-hoejde-min:  var(--taethed-hoejde-min);
  --taethed-pad-y:       var(--sp-3);       /* 12px */
  --taethed-pad-x:       var(--sp-5);       /* 24px */
  --taethed-gab:         var(--sp-3);
  --taethed-raekke:      var(--min-maalflade);
  --taethed-tekst:       var(--type-broed-m);
  --taethed-tekst-lille: var(--type-broed-s);
}

[data-taethed="taet"] {
  --taethed-navn:        taet;
  /* MOBIL (basislaget): den tætte variant er lige så stor som den enkle.
     En administrator med en telefon i hånden har samme fingre som en kunde. */
  --taethed-hoejde:      var(--min-maalflade);
  --taethed-hoejde-min:  var(--min-maalflade);
  --kontrol-hoejde:      var(--taethed-hoejde);
  --kontrol-hoejde-min:  var(--taethed-hoejde-min);
  --taethed-pad-y:       var(--sp-2);       /* 8px */
  --taethed-pad-x:       var(--sp-4);       /* 16px */
  --taethed-gab:         var(--sp-2);
  --taethed-raekke:      var(--min-maalflade);
  --taethed-tekst:       var(--type-broed-s);
  --taethed-tekst-lille: var(--type-label);
}

/* =============================================================================
   26. KNAPPER — seks roller, fem tilstande (KR-D-003, KR-D-009, KR-D-012)
   =============================================================================
   Rollerne er designleverancens egne fire plus konturvarianten af den
   destruktive. Tilstandene er de fem, komponentbiblioteket viser: standard,
   hover, fokus, deaktiveret og «i gang».

   MÅLTE FORHOLD (alle fra lag 1, ingen nye):
     primær standard    hvid på --knap-primaer-flade        4,81:1
     primær hover       hvid på --knap-primaer-flade-hover  6,81:1
     sekundær           hvid på --knap-sekundaer-flade     16,57:1
     sekundær hover     hvid på --dk-bordeaux-dyb          18,68:1
     kontur             --tekst-primaer på hvid            16,57:1 · kant 16,57:1
     tekstknap          --knap-tekst-farve på hvid          6,81:1
     destruktiv         hvid på --knap-destruktiv-flade      8,13:1
     destruktiv hover   hvid på --knap-destruktiv-hover     10,38:1
     destruktiv kontur  --tekst-destruktiv på hvid           8,13:1 · kant 8,13:1
     deaktiveret        --knap-deaktiveret-tekst på flade    5,85:1
   --------------------------------------------------------------------------- */
/* `text-decoration: none` HØRER TIL I BASEN OG IKKE HOS DEN ENKELTE SKÆRM
   (K2's aflevering fund 1). En knap kan være et `<button>` ELLER et
   `<a class="knap">` — det sidste, når handlingen er en navigation, der skal
   kunne åbnes i en ny fane. Linket arver da BROWSERENS standard­understregning:
   afsnit 22's `:where(a):not(.knap)` undtager netop knappen fra HUSETS farve-
   og understregningsregel, men en undtagelse fra husets regel er ikke en
   erklæring, og browserens egen står tilbage. Live viste kundeportalens «Skriv
   til os» derfor understreget hvid tekst inde i den røde primærknap, mens
   tomtilstandens `<button>` med samme klasse stod rent — samme klasse, to
   udtryk. Basen sætter den nu for ALLE apps, og skærmenes lokale plastre kan
   fjernes. */
.knap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  box-sizing: border-box;
  /* Fælles kontrolhøjde (afsnit 25, QA-fund 21). Tallet er uændret —
     `--kontrol-hoejde` ER `--taethed-hoejde` — men knappen læser det nu ad
     det navn, de fire andre kontrolformer også læser, så de ikke kan skride
     fra hinanden igen. */
  min-height: var(--kontrol-hoejde-min);
  height: var(--kontrol-hoejde);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  border: 1px solid transparent;
  border-radius: var(--radius-0);
  font: var(--taethed-tekst);
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.knap[data-rolle="primaer"] {
  background: var(--knap-primaer-flade);
  color: var(--dk-hvid);
}
.knap[data-rolle="primaer"]:hover {
  background: var(--knap-primaer-flade-hover);
}

.knap[data-rolle="sekundaer"] {
  background: var(--knap-sekundaer-flade);
  color: var(--dk-hvid);
}
.knap[data-rolle="sekundaer"]:hover {
  background: var(--dk-bordeaux-dyb);
}

/* Konturknappens kant ER komponentgrænsen og skal derfor bestå 1.4.11.
   --kant-markant måler 16,57:1 mod hvid; designets kontur i --dk-roed ville
   have været 4,81:1 — som også består, men kun mod hvid. --kant-markant består
   mod alle fire lyse flader (13,37:1 er den laveste). */
.knap[data-rolle="kontur"] {
  background: var(--dk-hvid);
  color: var(--tekst-primaer);
  border-color: var(--kant-markant);
}
.knap[data-rolle="kontur"]:hover {
  background: var(--flade-roed-svag);
}

.knap[data-rolle="tekst"] {
  background: none;
  color: var(--knap-tekst-farve);
  height: auto;
  min-height: var(--min-maalflade);
  padding: var(--taethed-pad-y) var(--sp-2);
  text-decoration: underline;
  text-underline-offset: 4px;
}

.knap[data-rolle="destruktiv"] {
  background: var(--knap-destruktiv-flade);
  color: var(--dk-hvid);
}
.knap[data-rolle="destruktiv"]:hover {
  background: var(--knap-destruktiv-hover);
}

.knap[data-rolle="destruktiv-kontur"] {
  background: var(--dk-hvid);
  color: var(--tekst-destruktiv);
  border-color: var(--kant-felt-fejl);
}
.knap[data-rolle="destruktiv-kontur"]:hover {
  background: var(--tone-critical-flade);
}

/* DEAKTIVERET vinder over rollen — derfor står den efter alle roller.
   Tilstanden bæres af flade, markør OG af `aria-disabled`, og årsagen står som
   tekst ved siden af knappen (spec/13 afsnit 8 punkt 5). Farve alene bærer den
   aldrig (KR-D-022).

   `:hover` STÅR MED I SELEKTOREN, og det er ikke en dublet. Rækkefølgen alene
   var ikke nok: rollernes hover-regler (`.knap[data-rolle="primaer"]:hover`)
   vejer klasse + attribut + pseudoklasse, mens tilstanden her kun vejede klasse
   + attribut — hover VANDT altså over deaktiveret, selv om tilstanden står
   sidst i filen. Live gav det den slukkede knap sin STÆRKE rolleflade, mens
   teksten blev stående i `--knap-deaktiveret-tekst`: mørkerødt på mørkerødt —
   #7A2B3D på #B80031 måler 1,38:1 — og på en telefon blev farven hængende
   efter tryk, til man rørte noget andet (uitest gruppe 46, «Log ind med Viborg
   Museum»). Med pseudoklassen med vejer de to lige, og den, der står sidst,
   vinder — altså tilstanden. Alle seks roller dækkes af de samme selektorer. */
/* DEN STIPLEDE KANT MANGLEDE (VQA-523). spec/12's egen `--tekst-deaktiveret`
   siger reglen ordret: «deaktiveret tilstand bæres af stiplet kant +
   aria-disabled + ikon, ALDRIG af farve alene (KR-D-022)» — og VQA målte
   `border-top-style: solid` med `border-top-color: rgba(0,0,0,0)` på hver
   eneste slukkede knap i cockpittet. Tilstanden hvilede altså på den blege
   rosa flade og på markøren; for en bruger, der ikke ser den forskel, stod
   knappen som en almindelig knap.
   Fladen er RIGTIG og bliver (spec/12 l. 422). Det er kanten, der kom til.
   `currentColor` og ikke et eget navn: kanten skal følge tekstens farve, så
   den er synlig BÅDE på den blege flade og på tekstknappen, der ingen flade
   har — og så den ikke kan drive fra teksten, hvis tokenet flyttes. */
.knap[aria-disabled="true"],
.knap[aria-disabled="true"]:hover,
.knap[disabled],
.knap[disabled]:hover {
  background: var(--knap-deaktiveret-flade);
  color: var(--knap-deaktiveret-tekst);
  border-style: dashed;
  border-color: currentColor;
  cursor: not-allowed;
}
/* TEKSTKNAPPEN BEHOLDER SIN FORM, OGSÅ NÅR DEN ER SLUKKET (VQA-105c).
   Reglen ovenfor giver ALLE seks roller den blege rosa flade, og for de fem
   er det rigtigt: de HAR en flade at slukke. Tekstknappen har ingen — den er
   en understreget linje — så den blege flade gav den en kasse, den ikke har
   tændt. Live blev «Send ny kode · aktiv om 43 sek.» derfor en 259 px bred
   rosa boks-knap midt på A0's trin 2, hvor designet har en diskret
   tekstlinje, og den konkurrerede med «Log ind» lige over.
   Slukket bæres her af FARVEN (--knap-deaktiveret-tekst, 9,37:1 mod hvid),
   af markøren og af `aria-disabled` + årsagsteksten — som for alle andre
   roller er farve aldrig eneste bærer (KR-D-022). Vægten (0,3,0) er én
   attribut højere end tilstandsreglen ovenfor, så rækkefølgen i filen ikke
   er det, der afgør det.

   DEN STIPLEDE KANT ARVES OG BLIVER (VQA-523). Reglen herunder rører kun
   flade og farve; `border-style: dashed` fra tilstandsreglen ovenfor står
   ved magt, og `currentColor` gør den til den samme mørkerøde som teksten.
   Det er en hårstreg og ikke den rosa kasse, VQA-105c handlede om — og den
   giver tekstknappen den formbårne markør, spec/12's `--tekst-deaktiveret`
   kræver af ALLE seks roller. */
.knap[data-rolle="tekst"][aria-disabled="true"],
.knap[data-rolle="tekst"][aria-disabled="true"]:hover,
.knap[data-rolle="tekst"][disabled],
.knap[data-rolle="tekst"][disabled]:hover {
  background: none;
  color: var(--knap-deaktiveret-tekst);
}

/* ÅRSAGEN ER EN OPLYSNING OG IKKE EN FEJL (BUG-585).
   Her stod `--tekst-destruktiv` i vægt 600, og ENHVER slukket knaps årsag blev
   derfor tegnet i fejlfarve: «Skriv en besked, før du sender.» i rødt lige
   efter en vellykket afsendelse (D5), «Ret et felt ovenfor …» ved en urørt
   profil (A16/A3a/A18c), «Der er ingen ulæste notifikationer at markere.»
   (A21) og profilmenuens henvisning. Brugeren havde ikke gjort noget forkert.
   Ti ark havde hver sin lokale nedtoning (fx `cockpit-faelles.css` afsnit 11,
   `faelles.css`' ventetekst, `bookinger.css`' sortering), så samme slags
   oplysning stod i TO farver alt efter skærmen (dækningsrunden Y1).
   Tonen er nu husets rolige — den samme `--tekst-sekundaer`, lokalarkene
   allerede bruger — ét sted for alle tre frontends. Rødt hører til en
   FELTFEJL efter et faktisk forsøg (S8 §2.2), og dén står ved feltet med
   `aria-invalid` og ikke her. Slukket bæres stadig af stiplet kant,
   markør og `aria-disabled` + selve sætningen — aldrig af farve (KR-D-022).
   MÅLT (WCAG 2.1, `test/bug585-601-knap-aarsag.test.tsx`) på de flader, en
   slukket knap står på: hvid 6,52 · grå-25 5,87 · linje 5,49 · sand 5,26 ·
   --flade-svag 6,17 · --flade-hvid-varm 6,24 (gemmebjælken) — alle ≥ 4,5:1. */
.knap-aarsag {
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid — se målingen ovenfor */
}

/* «I gang» er en tilstand, ikke en anden knap: teksten skifter, knappen låses,
   og skærmlæseren får beskeden gennem knappens eget aria-live. */
.knap[data-igang="true"] {
  cursor: progress;
}

/* =============================================================================
   26b. LINKS OG NAVIGATIONSPUNKTER
   =============================================================================
   FUNDET AF BROWSERHALVDELEN AF PORT 8, ikke af jsdom — og det er værd at sige
   højt, for det er præcis den slags, en DOM uden layout ikke kan se:
   et `<a>` uden en farveregel arver ikke `.paa-moerk`s tekstfarve. Det beholder
   browserens egen linkfarve, og på bordeaux måler den under 3:1. Tre
   navigationslinks i aktørportalens sidebjælke faldt på `color-contrast` og
   `target-size` i alle tre motorer, mens den samme markup var grøn i jsdom.

   Tokenfilens afsnit 24 og spec/13 afsnit 7 har allerede svaret på farven:
   «Link på sidebaggrund #E4003C på #F6F2F4 → 4,34:1 → RETTET til #B80031 →
   6,14:1». Den rettelse var aldrig bundet til en regel. Her er den.

   MÅLT:
     --knap-tekst-farve (#B80031) som link: hvid 6,81 · grå-25 6,14 · sand 5,50
     --paa-moerk-tekst (#FFFFFF) på bordeaux 16,57 · dyb 18,68 · grå-800 11,29

   Understregningen er ikke pynt: WCAG 1.4.1 forbyder, at farve alene skiller et
   link fra brødtekst.
   --------------------------------------------------------------------------- */
:where(a):not(.knap) {
  color: var(--knap-tekst-farve);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.paa-moerk :where(a):not(.knap) {
  color: var(--paa-moerk-tekst);
}

/* Et navigationspunkt ER et berøringsmål — modsat et link inde i en sætning,
   som WCAG 2.5.8 undtager. Det skal derfor bære --min-maalflade. */
.navpunkt {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  box-sizing: border-box;
  min-height: var(--min-maalflade);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  text-decoration: none;
}
.navpunkt[aria-current] {
  font-weight: 700;
  border-left: 3px solid var(--knap-primaer-flade);
}
.paa-moerk .navpunkt[aria-current] {
  background: var(--kant-dekorativ-paa-moerk);
}
.navliste {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* =============================================================================
   27. PRIMÆRHANDLINGSMØNSTRET (KR-D-009, KR-D-012, E12-S02 accept 5)
   =============================================================================
   ÉN handling må igangsætte en end-to-end-proces. Mønstret er derfor bygget om
   én primærknap: en handlingsgruppe må indeholde præcis én
   `[data-rolle="primaer"]` eller én `[data-rolle="destruktiv"]`. Reglen
   håndhæves i komponenten (`moenstre/Primaerhandling.tsx`) og efterprøves af
   `test/primaerhandling.test.tsx` — CSS kan ikke tælle.

   «Genbrug af allerede kendte oplysninger» er ikke en farve, men en visning:
   `.kendt-oplysning` viser det, systemet allerede ved, som TEKST med en vej til
   at rette det — ikke som et tomt felt, brugeren skal udfylde igen.
   --------------------------------------------------------------------------- */
.handlingsgruppe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--taethed-gab);
}
.kendt-oplysning {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  background: var(--flade-svag);
  border-left: 3px solid var(--kant-markant);
  font: var(--taethed-tekst);
  color: var(--tekst-primaer);           /* 15,70:1 mod --flade-svag */
}
.kendt-oplysning > .kendt-oplysning__navn {
  font: var(--type-label);
  letter-spacing: var(--label-spacing);
  text-transform: uppercase;
  color: var(--tekst-sekundaer);
}
.kendt-oplysning > .kendt-oplysning__vaerdi {
  font-variant-numeric: var(--tabular);
}

/* =============================================================================
   28. FORMULARFELTET — resten af anatomien (KR-D-017–020, S8 §2.5)
   =============================================================================
   Lag 1 afsnit 22.2 giver `.felt`, `.felt[aria-invalid]`, `.felt[disabled]` og
   `.felt-fejltekst`. Her er resten: label, hjælpetekst, tegntæller, valggruppe
   og den obligatoriske markering, hvis skærmlæserdel spec/13 afsnit 5.1 kræver.
   --------------------------------------------------------------------------- */
.feltgruppe {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.felt-label {
  font: var(--type-broed-s);
  font-weight: 600;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}
/* Stjernen er dekoration for øjet (aria-hidden); ordet «(skal udfyldes)» i
   .kun-skaermlaeser er den reelle markering. --tekst-fejl måler 6,81:1. */
.felt-label > .felt-obligatorisk {
  color: var(--tekst-fejl);
}
.felt-hjaelpetekst {
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
.felt-taeller {
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);
  font-variant-numeric: var(--tabular);
}
/* Fejlteksten arver farven fra lag 1's .felt-fejltekst; her kun ikonrækken, så
   fejlen bæres af ikon + tekst og ikke af farve (KR-D-022). */
.felt-fejltekst {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
}
.felt-fejltekst > .felt-fejltekst__ikon {
  flex: none;
  width: 1em;
  height: 1em;
  margin-top: 2px;
  fill: none;
  stroke: currentColor;
}
/* FEJLENS PLADS BLIVER STÅENDE, NÅR FEJLEN GÅR VÆK (brugertesten 24/8, fund
   32). Linjen stod og faldt med fejlen alene, og på checkouten — hvor «Betal»
   viser alle fejl, og hvert tastetryk validerer igen — rykkede ALT nedenunder
   32 px op i det øjeblik, et felt blev rettet. Testerens næste tryk landede
   uden for feltet.

   `Felt` tegner derfor en pladsholder med den SAMME række, når feltet HAR haft
   en fejl (se noten i `forms/Felt.tsx`). `visibility: hidden` og ikke
   `display: none` eller `opacity: 0`: den skjuler pladsholderen for både øjet
   og skærmlæseren, men lader den beholde nøjagtig den plads, fejlen fyldte —
   og et gættet `min-height`-tal kan derfor ikke skride fra skriftens egen
   linjehøjde. */
.felt-fejltekst--plads {
  visibility: hidden;
}
.felt:focus-visible {
  /* Fokusringen kommer fra lag 1 afsnit 22.3. Feltet skifter kun sin egen kant,
     så rammen ikke konkurrerer med ringen. */
  border-color: var(--kant-markant);
}
/* ÉN HØJDE FOR ALLE ENKELTLINJEKONTROLLER (QA-fund 21, 30/8 — se afsnit 25).
   Uden `height` bestemmes en kontrols ydre højde af dens EGEN indre: vælgeren
   klampes af browseren til sin menulist-højde, `<input type=date>` bærer en
   højere skyggekontrol end `type=text`, og et 18px-tal er 3,2px højere end et
   16px. Fem former, samme polstring, fem højder — 44,0 · 51,6 · 53,6 · 52,8 ·
   48 målt live. `height` + `padding-block: 0` flytter højden fra indholdet til
   tokenet; browseren centrerer selv en enkeltlinjekontrols indhold lodret, så
   der er intet at stille op med polstring.

   DET ÆLDRE WEBKIT-FUND STÅR STADIG, og reglen her er dens efterfølger: WebKit
   klampede vælgeren under berøringsmålet i den tætte tæthed, mens den samme
   markup var grøn i Chromium, i Gecko og i jsdom. `min-height` fra lag 1
   afsnit 22.2 løftede den ikke — en eksplicit `height` gør.

   `<textarea>` ER IKKE MED MED VILJE: den er flerlinjet, og en fast højde
   ville klippe teksten. Den beholder lag 1's polstring og `min-height`.
   `appearance` nulstilles IKKE: den native pil er den eneste ikke-farvebårne
   markering af, at feltet er en vælger og ikke et tekstfelt (KR-D-022). */
input.felt,
select.felt {
  box-sizing: border-box;
  height: var(--kontrol-hoejde);
  min-height: var(--kontrol-hoejde-min);
  padding-block: 0;
}
/* HUSETS FELTGRUPPE HAR INGEN KASSE (VQA-102, aktørportal-audit 30/8).
   =============================================================================
   Fire flader i aktørportalen viste en RÅ browser-fieldset: 2px indfattet
   ramme hele vejen rundt og `<legend>` ridende PÅ rammen — A0 «Modtag som»,
   A2 VISNING/VIS/STATUS, A3 PERIODE/TILSTAND og A16 SPROG/AKTIVITETSTYPER.
   Fælles for alle fire er, at de er `<fieldset>` UDEN en border-erklæring i
   deres egen CSS; kassen kom altså fra browserens standardark og ikke fra
   noget, nogen havde valgt.

   REGLEN ER DERFOR HUSETS OG IKKE BROWSERENS: en feltgruppe ser ud som et
   `Felt` — en label øverst og indholdet nedenunder, ingen ramme. Det er
   samme form som `.feltgruppe`/`.felt-label` i toppen af dette afsnit, og
   `<legend>` får ordret `.felt-label`s typografi, så en gruppe og et enkelt
   felt ikke kan gå fra hinanden.

   SELEKTORERNE VEJER (0,0,1) MED VILJE. Enhver klasseregel — `.valggruppe`
   nedenfor, `.d2-filter`, `.a3a__periode` — vinder over dem. En flade, der
   VIL have en kasse, får den stadig ved at sige det; en flade, der ikke har
   sagt noget, arver ikke længere browserens.

   `min-inline-size: 0` er den anden halvdel: `<fieldset>` har en indbygget
   minimumsbredde efter sit indhold, og uden linjen kan en gruppe i et
   gitter eller en flex-kolonne ikke krympe under sit bredeste barn — den
   skubber i stedet siden vandret. */
fieldset {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
fieldset > legend {
  padding: 0;
  font: var(--type-broed-s);
  font-weight: 600;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid — som .felt-label */
}

/* Radiogrupper og afkrydsningsgrupper: <fieldset> med <legend>, kant som
   komponentgrænse (--kant-ui, 3,74:1) og skillelinjer som ren dekoration.
   DENNE gruppe VIL have kassen: den samler stablede valgrækker, hvor rammen
   er det, der siger, hvor gruppen slutter (samtykkesættet, bookingflowets
   trin 8). Den er undtagelsen fra reglen ovenfor og siger det selv. */
.valggruppe {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: 0;
  border: var(--kant-komponent);
}
.valggruppe > legend {
  font: var(--type-broed-s);
  font-weight: 600;
  padding: 0 var(--sp-2);
}
.valggruppe .valgmulighed {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--min-maalflade);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  border-bottom: var(--kant-haar);
  cursor: pointer;
}
.valggruppe .valgmulighed:last-child {
  border-bottom: 0;
}
.valggruppe .valgmulighed[data-valgt="true"] {
  background: var(--flade-roed-svag);
  font-weight: 600;
}

/* =============================================================================
   29. TRININDIKATOREN (KR-D-011, KR-SY-020, S8 §3.2, spec/13 afsnit 5.2)
   =============================================================================
   Lag 1 afsnit 22.4 farvelægger `.trin`. Her er listens anatomi. Listen ER en
   <ol>, så antal og position annonceres; det aktive trin bærer
   aria-current="step"; hver tilstand bærer ikon OG tekst.

   FORMEN ER DESIGNLEVERANCENS (kortet «Trinindikator» og bookingflowets egen
   ramme): hvert trin er en KOLONNE — talboksen med forbindelseslinjen ud til
   næste trin øverst, navn og tilstandstekst nedenunder. Linjen er dekoration
   (`--kant-dekorativ`, som netop er tokenet for «rene skillelinjer uden
   betydning») og står ikke efter det sidste trin.

   ANATOMIEN HÆNGER PÅ `.trin__indhold`, IKKE PÅ `.trin`. Et gennemført trin er
   et link, så der kommer et <a> ind mellem <li> og indholdet. Var reglerne
   bundet med `>` til `.trin` — som de var — faldt de bort netop på de
   gennemførte trin: mærket mistede sin talboks, og navn og tilstandstekst løb
   sammen til «SprogUdfyldt».
   --------------------------------------------------------------------------- */
.trinindikator {
  display: flex;
  flex-wrap: wrap;
  gap: var(--taethed-gab) 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* INGEN UNDERSTREGNING AF DET AKTIVE TRIN (design l.684 og l.2970–2975;
   design-facit P1-4). Lag 1 afsnit 22.4 trækker en 2px `--kant-markant` under
   HELE det aktive trin. Designet har den streg ingen steder: aktiv-tilstanden
   bæres dér af mærkets røde flade, af vægt 700 og af tilstandsteksten «Du er
   her» — alle tre står stadig, så kravet om tekst OG ikon er uændret opfyldt.

   HVORFOR NEUTRALISERINGEN STÅR I LAG 2 OG IKKE VED REGLEN SELV. Lag 1 er
   `spec/12-designtokens.css` ORDRET, byte for byte, og `tokenlaget.test.ts`
   måler det: en rettelse dér ville skulle rettes i facitfilen først, og
   facitfiler rettes ikke af en byg-agent (CLAUDE.md «Når noget er galt i
   specs»). Lag 2 er additivt og har præcis den rolle. Samme specificitet, men
   senere i kaskaden, så den vinder — og den dag facitfilen selv taber stregen,
   er denne regel en no-op og kan fjernes. Kandidaten til spec-delta er meldt i
   rapporten for P1. */
.trin[aria-current="step"] {
  border-bottom: 0;
}

/* TRINBÅNDET ER EN OVERSIGT, IKKE BRØDTEKST (design l.687; design-facit P1-5).
   Designets trinnavn er 12,5 px i vægt 600, og tilstandsteksten under det
   11,5 px. Vi kørte begge på 14 px (`--taethed-tekst-lille` og
   `--type-broed-s`), og båndet fyldte derfor som et afsnit tekst i toppen af
   kortet. Skalaens nærmeste rolle for begge er `--type-label`; de to skilles
   ad på vægt, præcis som i designet — navnet halvfedt, tilstandsteksten
   normal. Det aktive trins vægt 700 kommer stadig fra afsnit 22.4 og vinder på
   specificitet.
   `font:`-GENVEJEN NULSTILLER `font-weight`, så vægten skal stå EFTER den —
   ikke før. */
.trin {
  display: flex;
  min-width: 120px;
  flex: 1 1 120px;
  font: var(--type-label);
  font-weight: 600;
}
.trin__indhold {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-2);
  width: 100%;
  padding-right: var(--sp-2);
  color: inherit;
  text-decoration: none;
}
/* Talboksens række: mærket og linjen ud mod næste trin. */
.trin__spor {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
}
/* FORBINDELSESLINJEN SKAL KUNNE SES MOD BÅNDETS EGEN FLADE (design l.685;
   design-facit P1-6). Den var `--kant-dekorativ` — rollen er rigtig, men
   værdien er kortfladens egen skillelinje, og trinbåndet står ikke på hvid:
   det er `--flade-svag`, og linjen forsvandt næsten. Designet bruger dér den
   dybere dæmpede flade, `--flade-daempet-2`. Linjen er stadig ren dekoration
   (`aria-hidden` i komponenten) og bærer stadig ingen oplysning. */
.trin__linje {
  flex: 1;
  height: 1px;
  background: var(--flade-daempet-2);
}
.trin .trin__maerke {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  height: 26px;
  border: 1px solid var(--kant-ui);      /* 3,74:1 — komponentgrænse */
  background: var(--dk-hvid);
  color: var(--tekst-sekundaer);
  font-weight: 700;
  font-variant-numeric: var(--tabular);
}
.trin[data-trin-tilstand="done"] .trin__maerke {
  background: var(--tone-success-tekst);
  border-color: var(--tone-success-tekst);
  color: var(--dk-hvid);                 /* hvid på --tone-success-tekst: 8,66:1 */
}
.trin[aria-current="step"] .trin__maerke {
  background: var(--knap-primaer-flade);
  border-color: var(--knap-primaer-flade);
  color: var(--dk-hvid);                 /* hvid på --knap-primaer-flade: 4,81:1 */
}
.trin[data-trin-tilstand="failed"] .trin__maerke {
  background: var(--tone-critical-flade);
  border-style: dashed;
  border-color: var(--tone-critical-tekst);
  color: var(--tone-critical-tekst);     /* på egen flade: 6,83:1 */
}
.trin[data-trin-tilstand="skipped"] .trin__maerke {
  background: var(--tone-muted-flade);
  border-color: var(--tone-muted-kant);
  color: var(--tone-muted-tekst);        /* på egen flade: 8,56:1 */
}
.trin .trin__tekst {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Se noten ved `.trin`: samme rolle, lettere vægt. `font-weight: 400`
   EKSPLICIT, fordi det aktive trins 700 ellers arves herned og gør «Du er her»
   lige så tung som trinnets navn. */
.trin__tilstandstekst {
  font: var(--type-label);
  font-weight: 400;
}
.trin__ikon {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
}

/* =============================================================================
   30. RESERVATIONSTIMEREN (KR-K-018, S8 §9.5, spec/13 afsnit 5.3)
   =============================================================================
   Lag 1 afsnit 22.6 giver tallene tabulær cifferbredde og advarselsfarven.
   Her er de tre tilstande, designleverancen viser: løber, advarsel, udløbet.
   aria-live og skiftet fra "polite" til "assertive" ligger i komponenten —
   CSS kan ikke annoncere.
   --------------------------------------------------------------------------- */
/* TIMEREN ER EN BJÆLKE PÅ ÉN LINJE (design l.691–695; design-facit P1-7 og
   P1-8). Designets bjælke er `align-items: center` med 13 px mellemrum og
   11/16 px polstring, og noten står `margin-left: auto` — altså skubbet helt
   ud til HØJRE i den samme bjælke. Vi havde `flex-start`, 16 px mellemrum,
   12/24 px polstring og noten under overskriften i venstre side; bjælken blev
   dermed to linjer høj og lignede et panel frem for en tidslinje i trinbåndet.
   Polstringen er nu skalaens egne 12/16 px i stedet for tæthedens 12/24 —
   timeren er designets samme bjælke i begge tætheder. */
.reservationstimer {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--dk-sand);
  border: var(--kant-komponent);         /* --kant-ui: 3,01:1 mod sand */
}
/* Tekstblokken er komponentens ENESTE ikke-ikon-barn (se `Reservationstimer`:
   ikonet og så én <div> med nedtælling, live-område og note). Den bliver selv
   en række, så noten kan finde bjælkens højre kant med `margin-left: auto`.
   `flex-wrap` er vagten: på en smal skærm brydes noten ned under nedtællingen
   i stedet for at klemme den. */
.reservationstimer > :not(.reservationstimer__ikon) {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  min-width: 0;
}
.reservationstimer > .reservationstimer__ikon {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
}
.reservationstimer__tal {
  font-variant-numeric: var(--tabular);
}
/* KUN FLADEN OG TEKSTEN SKIFTER — IKKE KANTEN (design l.691 og l.3067–3068;
   design-facit P1-9). Designets timer går under fem minutter over på den
   kritiske flade, men beholder komponentgrænsen `--kant-ui` hele vejen. Vi
   skiftede også kanten til `--tone-critical-kant`, og bjælken skiftede dermed
   form og ikke kun tone. Tekstfarven og vægten kommer fra afsnit 22.6 og er
   urørte; kanten står nu, hvor basisreglen satte den. */
.reservationstimer[data-advarsel="true"] {
  background: var(--tone-critical-flade);
}
.reservationstimer[data-udloebet="true"] {
  background: var(--tone-muted-flade);
  border-color: var(--tone-muted-kant);     /* 3,61:1 mod hvid, 3,02:1 mod egen flade */
  color: var(--tone-muted-tekst);           /* på egen flade: 8,56:1 */
  font-weight: 400;
}
/* Ved udløb skal der stå en HANDLING, ikke en alarm (S8 §9.5).
   NOTEN STÅR YDERST TIL HØJRE I BJÆLKEN (design l.694; design-facit P1-8).
   `margin-left: auto` er designets egen erklæring, og den virker, fordi
   tekstblokken ovenfor nu selv er en række. Ved udløb bærer samme klasse
   genopret-knappen, og den lander samme sted — bjælkens højre ende er
   handlingens plads, ikke kun notens. */
.reservationstimer__genopret {
  margin-left: auto;
  font: var(--type-broed-s);
  color: var(--tekst-primaer);
}

/* =============================================================================
   31. FORLØBSOVERSIGTEN (KR-D-010, E12-S02 accept 6)
   =============================================================================
   En gruppeaktivitet med flere sessioner skal kunne forstås uden en vejledning
   ved siden af. Forløbsoversigten er den lodrette søskende til trinindikatoren:
   trinindikatoren viser HVOR I FORMULAREN kunden er, forløbsoversigten viser
   HVAD DER SKER MED BOOKINGEN — én række pr. session, hver med sin egen status.

   Tonen sættes af `data-journey-state` eller af sessionens egen
   `data-session-status`; begge er allerede bundet i lag 1 afsnit 19. Der er
   derfor ingen ny farve her, kun en anatomi.
   --------------------------------------------------------------------------- */
.forloeb {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  border: var(--kant-komponent);
}
.forloeb__trin {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: start;
  gap: var(--sp-3);
  min-height: var(--taethed-raekke);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  border-bottom: var(--kant-haar);       /* ren skillelinje — dekorativ, uden information */
  font: var(--taethed-tekst);
}
.forloeb__trin:last-child {
  border-bottom: 0;
}
/* Sporet mellem to sessioner. Bærer ingen information — kun sammenhæng. */
.forloeb__spor {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 26px;
  color: var(--tone-tekst, var(--tone-neutral-tekst));
}
.forloeb__spor::after {
  content: "";
  position: absolute;
  top: 26px;
  bottom: calc(var(--taethed-pad-y) * -2);
  width: 1px;
  background: var(--kant-dekorativ);
}
.forloeb__trin:last-child > .forloeb__spor::after {
  display: none;
}
.forloeb__ikon {
  width: 1.25em;
  height: 1.25em;
  fill: currentColor;
}
/* TITEL OG BRØDTEKST ER TO LINJER, IKKE ÉN STRENG (uitest-fund 30b).
   Begge var inline-`<span>` i den samme forælder, og uden en linjeombrydning
   løb de sammen: kvitteringens tidslinje læste «Forespørgslen er modtagetVi
   har jeres forespørgsel og er gået i gang.» og «Enquiry receivedWe have your
   enquiry …». Skellet er typografisk i forvejen — vægt 600 mod dæmpet lille
   brødtekst — men et typografisk skel kan ikke ses, når der ikke er noget
   mellemrum at se det henover. `display: block` er den mindste rettelse: den
   rører hverken markup, farve eller skriftstørrelse. */
.forloeb__navn {
  display: block;
  font-weight: 600;
}
.forloeb__detalje {
  display: block;
  margin-top: var(--sp-1);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);
  font-variant-numeric: var(--tabular);
}

/* SMAL SKÆRM: STATUSMÆRKET FÅR SIN EGEN RÆKKE (uitest-fund 30c).
   Rækken er `grid-template-columns: auto 1fr auto`, og `1fr` er `minmax(auto,
   1fr)`: midtersporet må krympe helt ned til sit min-content. På 375 px tog
   ikonsporet og det brede statusmærke pladsen, og teksten blev presset ned i
   en spalte på ~10 tegn — ét til to ord pr. linje gennem hele tidslinjen.
   Under tabletbrydepunktet lægges mærket derfor UNDER teksten i sporets egen
   kolonne, så tekstsporet får hele bredden. Ingen oplysning falder bort, og
   rækkefølgen i DOM'en — og dermed oplæsningen — er uændret.

   Pixelværdien er literal, fordi var() ikke virker i en @media-forespørgsel
   (afsnit 6's egen note). 600 er `--bp-tablet`. */
@media (max-width: 599px) {
  .forloeb__trin {
    grid-template-columns: auto minmax(0, 1fr);
  }
  /* `.badge` ER `Statusmaerke`s rodklasse (afsnit 19). Kun DIREKTE børn:
     rækkens tre pladser er sporet, teksten og mærket. */
  .forloeb__trin > .badge {
    grid-column: 2;
    justify-self: start;
  }
}

/* =============================================================================
   32. KONSEKVENSVISNINGEN (KR-D-005, KR-D-010, E12-S02 accept 5 og 6)
   =============================================================================
   «Det sker, når du …»-listen fra designleverancens bekræftelsesdialoger,
   løftet ud som selvstændigt SYSTEM-mønster. Den bruges to steder:
     · i bekræftelsesdialogen før en kritisk handling (KR-D-005), og
     · inline, hvor et valg får følger, brugeren ikke kan se (KR-D-010).

   Tonen er ikke fast: en konsekvens kan være kritisk (aflysning), afventende
   (en frist løber) eller neutral (informativ). Derfor arver visningen `--tone-*`
   nøjagtigt som statusmærket. Standarden er attention — en konsekvens, ingen har
   taget stilling til, er noget, et menneske skal se på.

   STANDARDEN GÆLDER KUN UDEN `data-tone` (VISUEL-REST-C ønske 7, D10/D11's
   fund 20). Før stod de tre `--tone-*` på `.konsekvens` selv — samme
   specificitet (0,1,0) som lag 1's `[data-tone="critical"]` og 1.232 linjer
   senere i filen, så komponentens `tone="critical"` var INERT: enhver
   konsekvens blev attention-lilla. `:not([data-tone])` gør standarden til det,
   den skulle være — et fald tilbage for markup uden tone — og lader lag 1's
   attributregel vinde, når tonen ER sat. Målt i Chromium: `data-tone="critical"`
   giver `--tone-critical-flade` som baggrund (se AFVIGELSER-ui.md, ønske 7).
   --------------------------------------------------------------------------- */
.konsekvens:not([data-tone]) {
  --tone-tekst: var(--tone-attention-tekst);
  --tone-flade: var(--tone-attention-flade);
  --tone-kant: var(--tone-attention-kant);
}
.konsekvens {
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  background: var(--tone-flade);
  border: 1px solid var(--tone-kant);
  font: var(--taethed-tekst);
  color: var(--tekst-primaer);
}
.konsekvens > .konsekvens__overskrift {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-2);
  font: var(--type-broed-s);
  font-weight: 700;
  color: var(--tone-tekst);
}
.konsekvens > .konsekvens__liste {
  margin: 0;
  padding-left: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.konsekvens__ikon {
  width: 1em;
  height: 1em;
  fill: currentColor;
}

/* =============================================================================
   33. STATUSMÆRKET I TO TÆTHEDER
   =============================================================================
   Lag 1 afsnit 22.1 giver `.badge` med tone, ikon og tekst. Her følger den kun
   tætheden — farverne røres ikke.
   --------------------------------------------------------------------------- */
.badge {
  min-height: var(--taethed-hoejde-min);
}
[data-taethed="taet"] .badge {
  min-height: 0;
  padding: var(--sp-1) var(--sp-2);
  font: var(--type-broed-s);
  font-weight: 600;
}

/* DEN TÆTTE VARIANT PR. MÆRKE (VISUEL-REST-C ønske 2) — `Statusmaerke taet`.
   Designets tabelmærke er `font-size:11px;font-weight:600;padding:2px 7px`
   (l. 3460, D4/D14/D30's rammer). D4, D13, D14 og D30 tegnede hver sin lokale
   udgave af den regel; her er den ét sted.

   TALLENE: skriften er `--type-label` (12 px) — rammens 11 px findes ikke på
   spec/12's skala, og afvigelsen på 1 px står i registret; vægten sænkes til
   rammens 600. Linjehøjden sættes til 1, så mærket måler 12 + 2·2 = 16 px
   indvendigt og 18 px med kanten — det, D13 og D14 målte deres lokale udgaver
   til. Polstringen 2 px 7 px er rammens egen og ligger bevidst under
   spacing-skalaen (mindste trin 4 px): med `--sp-1` ville mærket være 4 px
   højere end designet. Ikonet følger med i `1em` og bliver 12 px — farve er
   stadig aldrig eneste bærer.

   Vægten (0,2,0) er den samme som tæthedsreglen ovenfor, og reglen står
   EFTER den med vilje: et tæt mærke er tæt, uanset hvilken tæthed fladen har. */
.badge[data-taet="true"] {
  gap: var(--sp-1);
  min-height: 0;
  padding: 2px 7px;
  font: var(--type-label);
  font-weight: 600;
  line-height: 1;
}

/* =============================================================================
   33b. DE MØRKE FLADER (spec/13 afsnit 5.5)
   =============================================================================
   Lag 1 afsnit 22.3 binder fokusringen til `.paa-moerk` og sætter tekstfarven.
   Her er de tre GODKENDTE bundflader fra lag 1 afsnit 6 — og kun de tre. En
   fjerde mørk flade findes ikke: hvid tekst er ikke målt mod andre end disse.

   MÅLT (lag 1 afsnit 6 og 7):
     hvid tekst og fokusring    bordeaux 16,57:1 · dyb 18,68:1 · grå-800 11,29:1
     --kant-ui-paa-moerk         bordeaux  3,30:1 · dyb  3,49:1 · grå-800  3,07:1
   --------------------------------------------------------------------------- */
.paa-moerk[data-moerk-flade="bordeaux"] {
  background: var(--dk-bordeaux);
}
.paa-moerk[data-moerk-flade="bordeaux-dyb"] {
  background: var(--dk-bordeaux-dyb);
}
.paa-moerk[data-moerk-flade="graa-800"] {
  background: var(--dk-graa-800);
}
/* Konturknappen og feltet vender om på mørk flade: kanten er den lyse. */
.paa-moerk .knap[data-rolle="kontur"] {
  background: none;
  color: var(--paa-moerk-tekst);
  border-color: var(--kant-ui-paa-moerk);   /* 3,30:1 mod bordeaux — består 1.4.11 */
}
.paa-moerk .knap[data-rolle="tekst"] {
  color: var(--paa-moerk-tekst);
}
.paa-moerk .felt-label,
.paa-moerk .felt-hjaelpetekst,
.paa-moerk .felt-taeller {
  color: var(--paa-moerk-tekst-sekundaer);  /* 12,67:1 mod bordeaux */
}

/* =============================================================================
   34. TÆTHEDEN VED BRYDEPUNKTERNE (KR-D-029, spec/13 afsnit 6.1)
   =============================================================================
   Pixelværdierne er LITERALE, fordi var() ikke virker i en @media-forespørgsel.
   De holdes synkrone med --bp-* gennem `src/tokens/brydepunkter.ts`, og prøven
   `test/tokenlaget.test.ts` læser BEGGE og kræver, at de er ens.

   600px er --bp-tablet. Først dér må den tætte variant gå under 44px:
   under brydepunktet er skærmen en telefon, og berøringsmålet vinder.
   --------------------------------------------------------------------------- */
@media (min-width: 600px) {
  [data-taethed="taet"] {
    --taethed-hoejde: 36px;              /* designleverancens cockpit-højde */
    --taethed-hoejde-min: 36px;
    --taethed-raekke: 36px;
  }
}

/* Cockpittets brede tabeller: vandret rul med fastfrosset første kolonne —
   ALDRIG skjulte kolonner (spec/13 afsnit 6.2). 1023px er --bp-tablet-max. */
@media (max-width: 1023px) {
  .rulbar {
    overflow-x: auto;
  }
  .rulbar [data-fastfrosset="true"] {
    position: sticky;
    left: 0;
    background: var(--dk-hvid);
  }
}

/* =============================================================================
   35. SAMTYKKEFELTET OG SAMTYKKESÆTTET (S8 §11.2–§11.4, spec/13 afsnit 2.2)
   =============================================================================
   Løftet fra kundeportalens onboarding (E13-S02), hvor komponenten blev bygget
   lokalt, fordi packages/ui kun må røres af én agent ad gangen. Anatomien er
   uændret; reglerne står nu ét sted, så alle tre frontends deler dem.

   TO FORMER, OG FORSKELLEN ER EN KANTREGEL, IKKE EN SMAGSSAG:

     data-form="enkeltstaaende"  feltet står alene og ER sin egen komponent.
                                 Det bærer derfor selv komponentgrænsen
                                 --kant-ui (3,74:1 mod hvid, 3,01:1 mod sand
                                 — begge over WCAG 1.4.11's krav på 3,0).
     data-form="i-gruppe"        feltet er en række i .valggruppe. GRUPPEN
                                 bærer grænsen; rækkerne skilles af den
                                 dekorative hårkant fra afsnit 28.

   Havde begge former haft en kant hele vejen rundt, ville et sæt på fem se ud
   som fem komponenter i stedet for ét afsnit — og en dobbeltkant om hver række
   er ikke bare grim, den er den forkerte information: den siger, at rækkerne
   ikke hører sammen.

   INGEN NY FARVE OG INGEN NY KONTRASTPÅSTAND. Hver farve herunder er en var()
   fra lag 1, og de målte forhold er lag 1's egne:
     --kant-ui            3,74:1 mod hvid  ·  3,01:1 mod sand   (krav 3,0)
     --tekst-primaer     16,57:1 mod hvid                       (krav 4,5)
     --tekst-sekundaer    6,52:1 mod hvid                       (krav 4,5)
     --knap-tekst-farve   6,81:1 mod hvid  ·  6,14:1 mod grå-25 (krav 4,5)
   --------------------------------------------------------------------------- */
.samtykke {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* RÆKKEN BÆRER SIT EGET BERØRINGSMÅL — og det er en RETTELSE, ikke en dublet.
   Afsnit 28's rækkeanatomi står som `.valggruppe .valgmulighed`, altså SCOPET
   til gruppen. Et enkeltstående samtykke har ingen `.valggruppe` over sig og
   fik derfor hverken flex, luft eller `min-height` — berøringsmålet på
   44 × 44 px (--min-maalflade, WCAG 2.5.8 og spec/13 afsnit 5.6) var aldrig
   sat på kundeportalens velkomstskærm, selv om markup'en bar `.valgmulighed`.
   Anatomien sættes derfor her, uafhængigt af kontekst.

   Inde i en gruppe vinder afsnit 28's regel (0,2,0 mod 0,1,0) på de
   egenskaber, den også sætter — med NØJAGTIGT de samme tokens — og bidrager
   sin skillelinje oveni. De to kan altså ikke skride fra hinanden på et
   berøringsmål; de kan kun være enige. Målt af `test/samtykke.test.tsx`. */
.samtykke__raekke {
  display: flex;
  gap: var(--sp-3);
  min-height: var(--min-maalflade);      /* 44px — berøringsmålet, WCAG 2.5.8 */
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  cursor: pointer;
  /* Ophænget for labelens dæk nedenfor. Se noten dér. */
  position: relative;
}

/* Her sættes kun det, rækken ikke selv har: en kant hele vejen rundt, når
   feltet står alene, så afkrydsningen står som sin egen komponent
   (--kant-ui, 3,74:1 mod hvid). `align-items: flex-start` fordi labelen kan
   løbe over to linjer — boksen skal blive stående ved den første, og
   specificiteten (0,3,0) er sat, så den også vinder inde i en gruppe, hvor
   afsnit 28 ellers ville centrere den. */
.samtykke[data-form="enkeltstaaende"] > .samtykke__raekke {
  border: var(--kant-komponent);
  align-items: flex-start;
}
.samtykke[data-form="i-gruppe"] > .samtykke__raekke {
  align-items: flex-start;
}

/* SKILLELINJEN SKAL SKILLE FELTER — IKKE SKÆRE ET FELT MIDT OVER
   (UI/UX-runden 24/8, fund 47).

   HVAD DER STOD LIVE: samtykkeafsnittet læstes som fire rækker i vilkårlig
   rækkefølge — «Jeg accepterer forretningsbetingelserne», hårkant,
   «Forretningsbetingelser: Gyldig fra 22. august 2026», «Jeg har læst
   privatlivspolitikken», hårkant, «Persondatapolitik: Gyldig fra …». Hvert
   dokuments linje stod altså i SAMME visuelle celle som det NÆSTE flueben og
   var skilt fra sit eget af en streg. Linket så ud til at høre til den forkerte
   afkrydsning, og det sidste stod alene i bunden.

   ÅRSAGEN VAR SCOPET, IKKE STREGEN. Afsnit 28 lægger hårkanten under
   `.valgmulighed` — altså under selve AFKRYDSNINGSRÆKKEN — og et samtykkefelt
   er mere end sin række: det er række + versionslinje + eventuel fejltekst,
   samlet i én `.samtykke`. Stregen flyttes derfor ud på feltet, hvor grænsen
   mellem to samtykker faktisk går. Kun inde i et `samtykkesaet`: et felt i en
   anden gruppe (kundeportalens samtykkeskærm) beholder afsnit 28's egen række.

   SPECIFICITETEN ER SAT MED VILJE: (0,4,0) og (0,2,0) mod afsnit 28's (0,2,0)
   og med trin 8's egne modregler over sig (0,3,0), så virkningen ikke afhænger
   af, i hvilken rækkefølge stilarkene indlæses. Trin 8 tegner efter design
   P4-35 sine samtykker HELT uden streger og slukker begge dele hos sig. */
.samtykkesaet__gruppe > .samtykke[data-form="i-gruppe"] > .samtykke__raekke {
  border-bottom: 0;
}
.samtykkesaet__gruppe > .samtykke {
  /* Luften i bunden er rækkens egen, gentaget for feltet: uden den ville
     stregen hugge hen over versionslinjens skriftbund. */
  padding-bottom: var(--taethed-pad-y);
  border-bottom: var(--kant-haar);
}
.samtykkesaet__gruppe > .samtykke:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

/* OG DOKUMENTLINJEN RYKKES IND I LABELENS TEKSTSØJLE (design-facit P4-25).
   Boksens bredde (--sp-4) plus rækkens mellemrum (--sp-3) er præcis dét, der
   ligger til venstre for labelens første bogstav — samme regnestykke som trin
   8 allerede gør med sin egen 20 px boks. Så flugter linjen med det flueben,
   den hører til, i stedet for med afkrydsningen. Dokumentlinjen UDEN flueben
   (S8 §11.6) rykkes ikke: der er ingen boks at rykke ind om, og en indrykning
   dér ville pege på et flueben, der ikke findes.

   (0,3,0), så trin 8's egen indrykning med samme regnestykke og sit eget
   bokstal (0,4,0) stadig vinder. */
.samtykke[data-form="i-gruppe"] > .samtykke__version {
  padding-left: calc(var(--taethed-pad-x) + var(--sp-4) + var(--sp-3));
}

/* Dokumentlinjen (S8 §11.6): aktivitetens egne betingelser står i SAMME liste
   som fluebenene, men uden afkrydsning. Den har derfor hverken række, boks
   eller kant — kun dokumentets egen linje, med samme lodrette luft som en
   række, så listen læses som én og ikke som «noget bagefter». */
.samtykke[data-form="dokumentlinje"] {
  padding: var(--taethed-pad-y) 0;
}

.samtykke__boks {
  flex: none;
  width: var(--sp-4);
  height: var(--sp-4);
  margin-top: var(--sp-1);
}

.samtykke__label {
  font: var(--type-broed-m);
  cursor: pointer;
}

/* HELE RÆKKEN ER BERØRINGSMÅLET (brugertesten 24/8, fund 31, WCAG 2.5.8 og
   spec/13 afsnit 5.6). Rækken har haft sine 44 px i højden hele tiden — men
   den var ikke KLIKBAR i hele sin flade: kun `<input>` og `<label>` tog imod,
   og boksen måler `--sp-4`, altså 16 × 16 px (målt i skærmbilledet: x 45–60,
   y 442–457). Testeren måtte ramme ordene ved siden af for at sætte de to
   obligatoriske hakker, og det er det sidste skridt før betaling.

   BOKSEN VOKSER IKKE. 16 px er designets afkrydsning, og en 44 px stor firkant
   ville være en anden komponent. I stedet strækkes LABELENS eget pseudoelement
   ud over rækken — nøjagtig samme greb som webshoppens `.wsh-kort__link::after`
   (fund 17): der kommer intet nyt interaktivt element ind i markup'en, så
   tastaturet og skærmlæseren møder præcis den ene kontrol og den ene label som
   før, og hele rækkens 44 px høje flade fører nu samme sted hen som ordene.
   Dækket ligger inden for rækken og kan derfor ikke nå dokumentlinjens link,
   som står UDEN FOR den. */
.samtykke__label::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* LINJERNE UNDER RÆKKEN ER INDRYKKET I BEGGE SIDER, ikke kun i venstre
   (brugertesten 24/8, fund 29). Her stod `padding-left` alene, mens rækken
   ovenover har `padding: … var(--taethed-pad-x)` på BEGGE sider. Følgen var, at
   en linje, der fyldte bredden, ombrød helt ude ved gruppens ramme: målt på
   telefon (375 px) løb fejlteksten «Du skal acceptere forretningsbetingelserne,
   før …» til x=356 med `<fieldset>`-kanten på x=358 — to pixel fra rammen, mens
   samme linje står 24 px inde i venstre side. Teksten var stadig inden for
   rammen, men den så ud til at løbe ud af den, og netop dér står kunden i
   forvejen og er i tvivl. `padding-inline` giver den samme luft i begge sider
   som rækken, den hører til. */
.samtykke__resume,
.samtykke__beskrivelse,
.samtykke__version {
  margin: 0;
  padding-inline: var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}

/* Versionsnummeret skal kunne LÆSES, ikke gættes (S8 §11.3). Tabulære tal, så
   to dokumenters versioner står under hinanden uden at cifrene hopper. */
.samtykke__versionsnummer {
  font-variant-numeric: var(--tabular);
  font-weight: 600;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}

.samtykke__titel {
  font-weight: 600;
  color: var(--tekst-primaer);
}

/* Titlen som knap, når fladen selv åbner dokumentet i en tastaturbetjenbar
   overlejring (S8 §11.3). Den skal LIGNE et link og opføre sig som en knap;
   fokusringen kommer fra lag 1 afsnit 22.3 og er ikke rørt her. */
button.samtykke__titel {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  /* Rollen ER en tekstknap på lys flade — derfor afsnit 26's egen farve og
     ikke en ny. Der findes intet --tekst-link i tokenlaget; #B80031 er den
     mørkere røde, spec/13 afsnit 7 indførte netop til rød tekst:
     6,81:1 mod hvid, 6,14:1 mod sidebaggrund, 5,50:1 mod sand. */
  color: var(--knap-tekst-farve);
  text-decoration: underline;
  cursor: pointer;
}

/* Samme indrykning i begge sider som linjerne ovenfor — fund 29 blev MÅLT
   netop her, på fejlteksten under «Forretningsbetingelser». */
.samtykke__fejl {
  padding-inline: var(--taethed-pad-x);
}

/* Sættet: to afsnit, hver med sin legende. Afstanden mellem dem er større end
   afstanden inde i dem — S8 §11.4's «eget afsnit» skal kunne SES, ikke kun
   læses op. */
.samtykkesaet {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
}
.samtykkesaet__overskrift {
  font: var(--type-broed-m);
  font-weight: 600;
  color: var(--tekst-primaer);
}
.samtykkesaet__brdtekst {
  margin: 0;
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);
  border-bottom: var(--kant-haar);
}

/* =============================================================================
   36. TILLÆGSFAMILIERNE — statusenums, spec/12 afsnit 18 ikke har
   =============================================================================
   Afsnit 19 farvelægger de 28 familier, tokenfilens afsnit 18 har besluttet.
   To skemaer i packages/contracts bærer en statusenum, afsnit 18 IKKE kender:

     InAppNotification.severity   info · action_required · critical
     SettlementStatus             pending · sent · completed · disputed

   Uden en binding faldt begge tilbage til tone-neutral: en notifikation, der
   kræver handling, ville se ud som en oplysning. Selektorerne står her og ikke
   i lag 1, fordi lag 1 er facit ORDRET (test/tokenlaget.test.ts måler det byte
   for byte) — og fordi hullet skal kunne SES som et hul. Bliver afsnit 18
   udvidet, flyttes disse regler væk igen, og TILLAEGSFAMILIER i
   src/status/tonemodel.ts flyttes op i ENUMFAMILIER samme dag.

   TONERNE ER AFSNIT 18's EGNE, ikke nye farver: hver værdi peger på de samme
   tre --tone-*-variabler, som søsterfamilierne comm.alert_severity og
   economy.payment_status allerede bruger. Begrundelsen pr. værdi står i
   src/status/tonemodel.ts. Målte forhold (lag 1 afsnit 8, uændrede):
     neutral    tekst på egen flade 6,75:1 · kant mod hvid 3,52:1
     waiting    tekst på egen flade 6,01:1 · kant mod hvid 3,46:1
     progress   tekst på egen flade 7,35:1 · kant mod hvid 3,55:1
     success    tekst på egen flade 7,36:1 · kant mod hvid 3,53:1
     attention  tekst på egen flade 8,18:1 · kant mod hvid 3,55:1
     critical   tekst på egen flade 6,83:1 · kant mod hvid 3,59:1

   Farve er stadig aldrig eneste informationsbærer: Statusmaerke tegner ikon OG
   tekst for hver af de syv toner (KR-D-022, KR-SY-021).
   --------------------------------------------------------------------------- */
[data-notification-severity="info"] {
  --tone-tekst: var(--tone-neutral-tekst);
  --tone-flade: var(--tone-neutral-flade);
  --tone-kant:  var(--tone-neutral-kant);
}
[data-settlement-status="pending"] {
  --tone-tekst: var(--tone-waiting-tekst);
  --tone-flade: var(--tone-waiting-flade);
  --tone-kant:  var(--tone-waiting-kant);
}
[data-settlement-status="sent"] {
  --tone-tekst: var(--tone-progress-tekst);
  --tone-flade: var(--tone-progress-flade);
  --tone-kant:  var(--tone-progress-kant);
}
[data-settlement-status="completed"] {
  --tone-tekst: var(--tone-success-tekst);
  --tone-flade: var(--tone-success-flade);
  --tone-kant:  var(--tone-success-kant);
}
[data-notification-severity="action_required"],
[data-settlement-status="disputed"] {
  --tone-tekst: var(--tone-attention-tekst);
  --tone-flade: var(--tone-attention-flade);
  --tone-kant:  var(--tone-attention-kant);
}
[data-notification-severity="critical"] {
  --tone-tekst: var(--tone-critical-tekst);
  --tone-flade: var(--tone-critical-flade);
  --tone-kant:  var(--tone-critical-kant);
}

/* =============================================================================
   37. SKRIFTERNE — SELVHOSTEDE (SPM-219 svar a, ORDRE-M2-FLOWOE-5)
   =============================================================================
   Lag 1's afsnit 12 NAVNGIVER de to familier. Indtil nu var der ingen, der
   HENTEDE dem. Designleverancen løste det med tre <link>-tags mod
   fonts.googleapis.com og fonts.gstatic.com — altså med et opslag hos en
   tredjepart for hver eneste besøgende. Martin afgjorde SPM-219 til SELVHOST
   (2026-08-20): begge familier er SIL Open Font License 1.1, licensteksterne
   ligger ved skrifterne i src/assets/fonts/, og ingen besøgendes IP-adresse
   forlader museets egne værter.

   HVORFOR BLOKKEN STÅR HER OG IKKE I TEMAET
   Denne fil er den ENE fil, E12-S01's kildeliste kopierer ind i temaet
   (hubspot/theme/src/kilder.ts), og den ENE fil, begge apps importerer i
   deres main. Lå @font-face i temaet alene, ville kundeportalen og den
   interne app stå på system-ui, mens temasiden stod på designets skrift —
   og de tre frontends ville ikke længere dele det samme udtryk (accept 1).

   STIEN ER RELATIV, OG DYBDEN ER MÅLT
   `../assets/fonts/` opløses mod den fil, reglen står i:
     packages/ui/src/tokens/   → packages/ui/src/assets/fonts/
     …/viborg-tema/styles/     → …/viborg-tema/assets/fonts/
   De to ligger i SAMME dybde under hver sin rod, og derfor kan én streng
   bære begge. Brandlaget bruger allerede nøjagtig den form (`../assets/
   brand/…` i temaets brand.css). test/skrifter.test.ts måler dybden i
   stedet for at stole på den.

   FAMILIENAVNENE ER LAG 1'S EGNE
   «Big Shoulders Display» og «Figtree» — ordret som i --font-display og
   --font-broed. Derfor ændrer denne blok ingen komponent: den fylder et
   navn ud, som allerede blev brugt.

   VARIABLE SKRIFTER, IKKE STATISKE VÆGTE
   Én fil pr. familie pr. tegnsæt dækker hele vægtaksen — 400-800 og
   300-800, præcis de intervaller designleverancens <link> bad om.
   `font-weight` med TO tal fortæller browseren, at aksen er sammenhængende;
   uden dem ville de 600, --type-display-* beder om, blive syntetiseret fed
   i stedet for tegnet.

   font-display: swap — teksten står læsbar i fald-tilbage-skriften, mens
   filen hentes. Fald-tilbage-kæderne i lag 1 er urørte, og de er TO
   FORSKELLIGE (spec/12 l.324-325 er facit):
     --font-display: 'Big Shoulders Display', sans-serif;
     --font-broed:   'Figtree', system-ui, sans-serif;
   Kun brødteksten falder tilbage til system-ui; overskrifterne falder direkte
   til sans-serif. Det er dem, der vises, hvis en fil ikke når frem.

   INGEN KURSIV. Designleverancen bad heller ikke om den: dens <link> har kun
   `wght`, ingen `ital`. Kursiv bliver derfor syntetisk hældning — nøjagtig
   som i designet, og uden to filer mere.

   TEGNSÆTTENE. `latin` bærer dansk og engelsk komplet: æ, ø, å, Æ, Ø, Å og
   « » ligger alle i U+0000-00FF. `latin-ext` er med for de kundenavne, en
   museumsbooking faktisk indeholder (Łukasz, Şeyma) — uden den ville netop
   de tegn falde til brødtekstens fald-tilbage-skrift midt i et ord.
   unicode-range gør valget gratis: browseren henter kun den fil, siden
   bruger — og BINDINGEN mellem område og fil måles nu: latin-blokken skal
   dække æ ø å, latin-ext-blokken må ikke, og latin-ext skal dække Ł og Ş.
   Uden den måling var de fire blokke fire navne, og en parvis ombytning stod
   grøn i begge pakker (DOM-FLOWOE5 fund 2).

   KILDE, FILNAVNE, STØRRELSER OG CHECKSUMS står i
   docs/adr/flowoe-5-selvhostede-skrifter.md. test/skrifter.test.ts holder
   bytes fast med sha256, så en skriftfil ikke kan skiftes ubemærket.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Big Shoulders Display";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../assets/fonts/big-shoulders-display-v24-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Big Shoulders Display";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("../assets/fonts/big-shoulders-display-v24-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../assets/fonts/figtree-v9-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../assets/fonts/figtree-v9-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* =============================================================================
   38. BEKRÆFTELSESDIALOGEN (KR-D-005, S9 §2.4, spec/13 §5.5 og §5.6)
   =============================================================================
   Løftet fra `apps/intern-app/src/faelles/faelles.css` (E14-S12), hvor
   overlejringen og dialogen blev bygget lokalt, fordi packages/ui kun må røres
   af én agent ad gangen. Anatomien er uændret; reglerne står nu ét sted, så de
   seks flader, der havde hver sin dialog, deler dem.

   INGEN NY FARVE OG INGEN NY KONTRASTPÅSTAND. Hver farve herunder er en var()
   fra lag 1, og de målte forhold er lag 1's egne:
     --tekst-primaer på --dk-hvid        16,57:1   (krav 4,5)
     --tekst-sekundaer på --dk-hvid       6,52:1   (krav 4,5)
     --fokus-farve-lys på --dk-hvid      16,57:1   (krav 3,0 — ringen)
   `--overlay-baggrund` er lag 1's eget navn på designleverancens modal-bagtæppe
   og bærer ingen information: den mørkner baggrunden, og dialogen ovenpå står
   på --dk-hvid med sine egne målte forhold.

   OVERLEJRINGEN ER IKKE `.paa-moerk` — OG DET ER EN MÅLT RETTELSE.
   TRE af repoets seks lokale dialoger sætter klassen på overlejringen med
   begrundelsen «så fokusringen skifter til den hvide» (spec/13 §5.5), og alle
   tre står i intern-appen: E14-S12's faelles-dialog, fravaer/Bekraeftelse og
   A22's Kalenderabonnement. De tre andre bærer den ikke — to har hver sit eget
   bloknavn på bagtæppet, og Kurvtrin har slet ingen overlejring — så de undgår
   fejlen uden at have valgt det. Men
   bagtæppet er det eneste mørke: DIALOGEN er et hvidt kort ovenpå, og
   `.paa-moerk` farver hele undertræet — `.felt-label` bliver en lys rosa på
   hvid, og en tekstknap bliver HVID på hvid. Browserhalvdelen af kvalitetsport
   8 fældede det med 27 prøver over tre motorer × tre bredder og én eneste
   overtrædelse: color-contrast på dialogens begrundelseslabel. jsdom kan ikke
   se det — `color-contrast` kræver layout.
   Dialogens indhold står altså på hvid og får de LYSE flades farver, herunder
   den mørke fokusring fra lag 1 afsnit 22.3. Der er intet fokuserbart på selve
   bagtæppet at give en hvid ring.
   --------------------------------------------------------------------------- */
.dialogoverlejring {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-4);
  background: var(--overlay-baggrund);
}

/* MOBILE-FIRST (KR-D-029). Basislaget er telefonen: dialogen fylder bredden,
   og et højt indhold RULLER inde i dialogen i stedet for at løbe ud over
   skærmkanten — «Ingen flade må tabe funktioner ved skift af brydepunkt»
   (spec/13 §6.2). Uden max-height ville annuller-knappen i en dialog med et
   begrundelsesfelt kunne stå uden for viewporten på en lille telefon. */
/* `box-sizing: border-box` ER RETTELSEN AF 8 PX-OVERLØBET (VISUEL-REST-C
   ønske 6, D17's Ø4). Målt ved 1440×900: en dialog med 1535 px indhold fik
   `height: 916` og `top: -8` — 8 px uden for skærmen foroven OG forneden.
   `max-height: 100%` resolver mod overlejringens indholdsboks (900 − 2·16 =
   868 px) og gjaldt INDHOLDSBOKSEN, hvorpå dialogens egen polstring (2·24 px)
   blev lagt: 868 + 48 = 916. Med border-box er 868 hele dialogen, og den
   står inden for overlejringens polstring på alle højder. Målt i Chromium
   ved 900/950/1000 px: `top` 16/16/16 ≥ 0 (AFVIGELSER-ui.md, ønske 6). */
.dialog {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--bredde-smal);
  max-height: 100%;
  overflow-y: auto;
  padding: var(--sp-5);
  border-radius: var(--radius-1);
  background: var(--dk-hvid);
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
  box-shadow: var(--skygge-overlay);
}
.dialog__titel {
  margin: 0 0 var(--sp-3);
  font: var(--type-display-s);
}
.dialog__genstand {
  margin: 0 0 var(--sp-3);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
.dialog__konsekvens {
  margin: 0 0 var(--sp-4);
  font: var(--type-broed-m);
}
/* KROPPEN RULLER, TITEL OG KNAPPER STÅR FAST (VISUEL-REST-C ønske 6).
   `Bekraeftelsestrin` lægger konsekvens, børn og begrundelse i `dialog__krop`.
   Loftet er D16's og D17's tal fra den samme sag (BUG-262): `58vh` binder på
   en lav skærm (900 px → 522 px), `30rem` (480 px) på en høj, hvor 58 % ellers
   ville være 812 px og dialogen igen fylde rammen. Under loftet: 522 px krop +
   ~230 px titel, genstand og knapper = under 868. Er skærmen så lav, at heller
   ikke det rækker, ruller dialogen selv (max-height ovenfor) — intet fjernes.

   `position: relative` er BUG-267: et `.kun-skaermlaeser`-element er absolut
   placeret, og uden en positioneret forfader bryder det ud af rulleområdet og
   giver hele siden en vandret rullebjælke. Rullebeholder ⇒ position: relative
   (PLAN-VISUEL-REST, husets regel). */
.dialog__krop {
  position: relative;
  max-height: min(58vh, 30rem);
  overflow: auto;
  /* BUG-1124: KROPPEN SIGER, AT DER ER MERE. Riggen 24/9 (X13): D15's «Ny
     aktørprofil» viste seks felter over knapperne og intet om de tre
     obligatoriske nedenunder; DP så dem først i fejlboksen. BUG-796 gav D19's
     dialoger rulleskyggen (`katalog.css`); her får ALLE dialoger den samme:
     to `local`-lag følger indholdet og dækker skyggen i den ende, der er
     nået, to `scroll`-lag står ved kanterne. Ingen JavaScript. Farve er ikke
     eneste bærer — det afskårne felt og selve rulningen bærer det også. */
  /* BUG-1337: SKYGGEN SES, SÅ SNART DER ER TEKST AT RULLE TIL. Et `local`-lag
     følger indholdets ende: med N px tilbage at rulle dækker det
     min(bånd, dække − N) px af skyggebåndet. BUG-1124's dække var 32 px
     (hvidt i 40 %, så falmende) over et bånd på 12 px — ved et overløb på
     10 px var hele båndet dækket, og ved 20 px stod skyggen stadig under et
     halvgennemsigtigt slør (D18d, BUG-1264). Nu er dækket HELT hvidt og præcis båndets højde: ved enden er
     skyggen væk, og ved N px tilbage står min(N, 12) px af den frem.
     `padding-bottom` er den anden halvdel: de sidste 8 px af rulleområdet er
     luft, så tekst kun kan stå skåret, når mere end 8 px er tilbage — og da
     viser skyggen mere end 8 px. Et overløb på få px skjuler kun luft. */
  padding-bottom: var(--sp-2);
  background-color: var(--dk-hvid);
  /* FARVERNE ER TOKENLAGETS: hvid og bordeaux (22 %), blandet mod
     `transparent` — komponentlaget indfører ingen farve (spec/13 afsnit 10). */
  background-image:
    linear-gradient(var(--dk-hvid), var(--dk-hvid)),
    linear-gradient(var(--dk-hvid), var(--dk-hvid)),
    linear-gradient(
      to bottom,
      color-mix(in srgb, var(--dk-bordeaux) 22%, transparent),
      transparent
    ),
    linear-gradient(
      to top,
      color-mix(in srgb, var(--dk-bordeaux) 22%, transparent),
      transparent
    );
  background-position:
    center top,
    center bottom,
    center top,
    center bottom;
  background-size:
    100% 12px,
    100% 12px,
    100% 12px,
    100% 12px;
  background-repeat: no-repeat;
  background-attachment: local, local, scroll, scroll;
}
/* BUG-1337 (runde 4): SKYGGEN STÅR OVER FELTERNE. Genmålingen 25/9 (I2) på
   VM-159 «Ret session» ved 1440×620: over TEKST virkede skyggen ovenfor, men
   når et formularfelt stod i kanten, sås intet bånd — Lokale-vælgeren skåret
   nederst, Voksne-feltet skåret øverst, begge uden markør. Årsagen er lagene:
   skyggen ovenfor er kroppens BAGGRUND, og et `input`/`select` med hvid
   baggrund maler oven på sin forfaders baggrund.
   Hvor browseren kan styre en animation efter rulningen, tegnes båndene derfor
   som to klæbende pseudoelementer OVER indholdet: `::before` klæber til
   toppen, `::after` til bunden, begge 12 px med −12 px margen, så de ikke
   flytter en eneste linje (margenen falder sammen med nabolinjens, og kroppen
   er en blokkontekst — målt i Chromium 26/9: alle børns placering og
   `scrollHeight` uændrede). `pointer-events: none` lader klik gå igennem til
   feltet under båndet, og `z-index: 1` løfter dem også over felter, der selv
   er positionerede. `bottom` er MINUS kroppens `padding-bottom`: `sticky`
   regner bunden fra indholdskanten, så `bottom: 0` stod 8 px over rammen
   (målt samme sted).
   Synligheden følger kroppens EGEN rulning (`scroll(nearest block)`:
   pseudoelementets nærmeste rullebeholder er kroppen): top-båndet tændes over
   de første 12 px, bund-båndet slukkes over de sidste 12 px — samme geometri
   som faldet (min(N, 12) px ved N px tilbage). Uden overløb er tidslinjen
   inaktiv, og grundværdien `opacity: 0` står: ingen skygge uden noget at
   rulle til (det gælder også D18d's krop uden loft, helligdage.css). Kroppens
   baggrundslag slås fra her, så skyggen aldrig tegnes to gange.
   UDEN UNDERSTØTTELSE står baggrundsformen ovenfor uændret som fald. Ingen
   JavaScript (BUG-1124's princip). Animationen har ingen varighed i tid — den
   følger brugerens egen rulning, og tokenlagets dæmper (afsnit 22.8) ændrer
   den ikke (målt: samme opacitet med `animation-duration: .01ms`). */
@supports (animation-timeline: scroll()) {
  .dialog__krop {
    background-image: none;
  }
  .dialog__krop::before,
  .dialog__krop::after {
    content: "";
    display: block;
    position: sticky;
    z-index: 1;
    height: 12px;
    pointer-events: none;
    opacity: 0;
    animation: dialog-krop-skygge linear both;
    animation-timeline: scroll(nearest block);
  }
  .dialog__krop::before {
    top: 0;
    margin-bottom: -12px;
    background-image: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--dk-bordeaux) 22%, transparent),
      transparent
    );
    animation-range: 0 12px;
  }
  .dialog__krop::after {
    bottom: calc(var(--sp-2) * -1);
    margin-top: -12px;
    background-image: linear-gradient(
      to top,
      color-mix(in srgb, var(--dk-bordeaux) 22%, transparent),
      transparent
    );
    animation-direction: reverse;
    animation-range: calc(100% - 12px) 100%;
  }
}
@keyframes dialog-krop-skygge {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
/* BUG-897: FEJLEN, DER SPÆRRER HANDLINGEN, STÅR FAST VED KNAPPERNE — uden for
   den rullende krop, så motorens grund aldrig ligger under folden. */
.dialog__fejl {
  margin: var(--sp-3) 0 0;
}
/* Handlingsrækken ER en `.handlingsgruppe` (afsnit 27) og arver dens gab.
   Her sættes kun retningen: den bekræftende handling står yderst til højre,
   hvor øjet slutter.
   KNAPPERNE FLUGTER FORAN (BUG-601): med årsagen UNDER en slukket knap (se
   nedenfor) er dens gruppe højere end naboknappen, og `.handlingsgruppe`s
   `align-items: center` ville sænke naboen et halvt årsagsniveau. */
.dialog__handlinger {
  justify-content: flex-end;
  align-items: flex-start;
}
/* EN SLUKKET KNAP FLYTTER SIG IKKE, NÅR ÅRSAGEN FORSVINDER (BUG-601).
   `Knap` tegner en slukket knap som `<span class="handlingsgruppe">` med
   knappen og `.knap-aarsag` som SØSKENDE. I rækken ovenfor (`flex-end`) stod
   årsagen til HØJRE for knappen, så knappen stod årsagens bredde længere
   til venstre, end den står tændt — og hoppede, i samme øjeblik årsagen
   forsvandt: D18d's «Tilføj dagen» fra x≈495 til x≈862, og riggens første
   klik ramte tomrum (v-opsaetning F5, 21/9; BUG-566 rettede det kun i dét
   ene vindue).
   ÅRSAGEN STÅR NU UNDER KNAPPEN, HØJRESTILLET: gruppens højre kant er den
   samme med og uden årsag, og knappen, der sidder i den kant, står fast.
   Rækkefølgen i markuppen er uændret (knap, så årsag — WCAG 1.3.2), og
   `aria-describedby` er urørt. LOFTET på årsagen holder gruppen smal nok til,
   at rækken ikke brydes om på to linjer i den smalle dialog (--bredde-smal:
   572 px indhold − naboknappen ≈ 150 − gab): et linjeskift ville flytte
   naboknappen i stedet. 24rem lader D18d's «Udfyld både dato og betegnelse,
   før du tilføjer dagen.» stå på ÉN linje (målt i Chromium), så dialogen
   vokser mindst muligt, mens årsagen står. */
.dialog__handlinger .handlingsgruppe {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: flex-end;
  gap: var(--sp-1);
}
.dialog__handlinger .knap-aarsag {
  max-inline-size: 24rem;
  text-align: end;
}
/* Dialogen selv får fokus ved åbning (`tabIndex={-1}`), så `alertdialog`
   annonceres FØR brugeren står på en destruktiv knap. Ringen kommer fra lag 1
   afsnit 22.3 — den er ikke rørt her; kun forskydningen vendes indad, så ringen
   ikke skæres af skærmkanten på en dialog, der fylder bredden. */
.dialog:focus-visible {
  outline-offset: calc(var(--fokus-offset) * -1);
}

/* =============================================================================
   39. FEJLOPSUMMERINGEN (S8 §2.4 regel A5, spec/13 §5.1)
   =============================================================================
   «Ved indsendelsesfejl vises en fejlopsummering øverst i formularen med links
   til hvert fejlbehæftet felt; fokus flyttes til opsummeringen.»

   TONEN ER CRITICAL, og den er hentet fra tonemodellen frem for valgt: en
   opsummering af det, der SPÆRRER indsendelsen, er nøjagtig den betydning,
   afsnit 8 giver tonen critical.

   MÅLTE FORHOLD — PÅ DEN FLADE, DE FAKTISK STÅR PÅ. Ingen ny farve er indført,
   men to af parrene er nye: linket og brødteksten står på TONENS EGEN FLADE og
   ikke på hvid. Lag 1's tal for de to farver (6,81:1 og 16,57:1 mod hvid) er
   derfor ikke dem, der gælder her. De rigtige er regnet af
   `test/a11y/kontrast.test.ts` med WCAG 2.1's formel:
     --tone-critical-tekst på --tone-critical-flade   6,83:1  (krav 4,5)
     --tone-critical-kant mod hvid                    3,59:1  (krav 3,0)
     --tone-critical-kant mod egen flade              3,01:1  (krav 3,0)
     --knap-tekst-farve på --tone-critical-flade      5,72:1  (krav 4,5)
     --tekst-primaer på --tone-critical-flade        13,93:1  (krav 4,5)

   INGEN REGEL FOR `[data-doedt-anker]`. Attributten er en MÅLING, ikke en
   tilstand, brugeren skal se: et anker, der peger forkert, skal fanges af en
   prøve og rettes — ikke tegnes med en anden farve, så fejlen bliver et
   designelement.
   --------------------------------------------------------------------------- */
.fejlopsummering {
  --tone-tekst: var(--tone-critical-tekst);
  --tone-flade: var(--tone-critical-flade);
  --tone-kant: var(--tone-critical-kant);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  background: var(--tone-flade);
  border: 1px solid var(--tone-kant);
  border-radius: var(--radius-0);
  font: var(--taethed-tekst);
  color: var(--tekst-primaer);
}
.fejlopsummering__overskrift {
  margin: 0;
  font: var(--type-broed-m);
  font-weight: 700;
  color: var(--tone-tekst);              /* 6,83:1 mod egen flade */
}
.fejlopsummering__liste {
  margin: 0;
  padding-left: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
/* Linket skal kunne SES som et link uden farve alene (KR-D-022) — derfor
   understregningen. Farven er den mørkere røde, spec/13 §7 indførte netop til
   rød tekst; MÅLT på den flade, den står på: 5,72:1 mod --tone-critical-flade. */
.fejlopsummering__link {
  color: var(--knap-tekst-farve);
  text-decoration: underline;
}
/* Punktet UDEN link — feltet er ikke tegnet. Det er stadig en fejl, der skal
   læses, så farven er tonens tekst og ikke en dæmpet: 6,83:1 mod egen flade. */
.fejlopsummering__uden-link {
  color: var(--tone-tekst);
}

/* =============================================================================
   40. FELTSÆTTET, RADIOGRUPPEN OG AFKRYDSNINGEN (spec/13 §5.1)
   =============================================================================
   «Radiogrupper og afkrydsningsgrupper i <fieldset> med <legend>.»

   FELTSÆTTET BÆRER OGSÅ `.valggruppe` (afsnit 28) og arver dermed
   komponentgrænsen --kant-komponent, rækkernes 44 px berøringsmål og den
   dekorative hårkant mellem dem. Reglerne herunder er DET, afsnit 28 ikke
   har: legendens markering, hjælpe- og fejlteksten, radioknappens note og den
   enkeltstående afkrydsnings egen række.

   MÅLTE FORHOLD (alle lag 1's egne):
     --kant-ui som komponentgrænse         3,74:1 mod hvid · 3,01:1 mod sand
     --tekst-primaer                      16,57:1 mod hvid
     --tekst-sekundaer                     6,52:1 mod hvid
     --tekst-fejl                          6,81:1 mod hvid
   --------------------------------------------------------------------------- */
.feltsaet {
  min-inline-size: 0;   /* et fieldset krymper ikke af sig selv i en flexboks */
}
.feltsaet__legende {
  font: var(--type-broed-s);
  font-weight: 600;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}
/* Stjernen er dekoration for øjet (aria-hidden); ordene «(skal udfyldes)» i
   .kun-skaermlaeser er den reelle markering. Samme snit som afsnit 28's
   .felt-label > .felt-obligatorisk, og samme token. */
.feltsaet__obligatorisk,
.radiogruppe__obligatorisk,
.afkrydsning__obligatorisk {
  color: var(--tekst-fejl);              /* 6,81:1 mod hvid */
}
.feltsaet__hjaelpetekst {
  margin: 0;
  padding: var(--sp-2) var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
/* Fejlteksten bæres af IKON og tekst, aldrig af farve alene (KR-D-022). Samme
   anatomi som afsnit 28's .felt-fejltekst — de to må ikke kunne skride fra
   hinanden, og derfor de samme tokens og den samme opbygning. */
.feltsaet__fejltekst,
.afkrydsning__fejltekst {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-2) var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-fejl);              /* 6,81:1 mod hvid */
}
.feltsaet__fejlikon,
.afkrydsning__fejlikon,
.radiogruppe__fejlikon {
  flex: none;
  width: 1em;
  height: 1em;
  margin-top: 2px;
  fill: none;
  stroke: currentColor;
}

/* --- Kontrollernes egen farve ---------------------------------------------- */

/* HUSETS FARVE PÅ DE NATIVE KONTROLLER (brugertesten 24/8, fund 43).
   Testerne så det, en DOM-prøve ikke kan se: de valgte radioknapper
   («Privatperson», «Kort», «MobilePay») og de satte flueben stod i browserens
   standardblå midt i en bordeauxrød flade. `accent-color` er den ene erklæring,
   der maler en native kontrol, og den lå indtil nu KUN i bookingflowets egne
   trin-stilark (trin 1, 2, 4, 5, 7, 8) — ikke i tokenlaget. Webshoppens
   checkout og ventelisteformular bruger de SAMME `packages/ui`-komponenter uden
   et trin-stilark over sig, og derfor stod de blå.

   FARVEN ER MARKØRKANTENS OG IKKE SIGNATURRØDEN — trin 7's fund 30 afgjorde
   det: `accent-color` maler HELE kontrollen, og --dk-roed gjorde den valgte
   radioknap knaldpink. `--kant-markant` er den samme værdi, de seks trin
   allerede bruger, så ingen kontrol i huset kan skride fra en anden.

   TRINNENES EGNE ERKLÆRINGER BLIVER STÅENDE. De rammer de samme kontroller med
   den samme værdi og er derfor virkningsløse dubletter — men de bor i en anden
   pakke, og «én agent ad gangen» gælder begge veje (se `trin8.css`s note, som
   netop meldte tokenlaget som det rigtige sted). */
.radiogruppe__radio,
.afkrydsning__boks,
.samtykke__boks,
.flervaelger__afkrydsning {
  accent-color: var(--kant-markant);
}

/* --- Radiogruppen ---------------------------------------------------------- */
.radiogruppe__liste {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Rækken ER en `.valgmulighed` og får sin højde, sin luft og sin skillelinje af
   afsnit 28. Her sættes kun ombrydningen: en note skal stå på sin egen linje
   under labelen og ikke presse labelen sammen. */
.radiogruppe__valgmulighed {
  flex-wrap: wrap;
  align-items: flex-start;
  /* Ophænget for labelens dæk nedenfor. Se noten dér. */
  position: relative;
}
.radiogruppe__radio {
  flex: none;
  width: var(--sp-4);
  height: var(--sp-4);
  margin-top: var(--sp-1);
}
.radiogruppe__label {
  flex: 1;
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
  cursor: pointer;
}
/* HELE RÆKKEN ER BERØRINGSMÅLET — samme rettelse og samme greb som afsnit 35's
   `.samtykke__label::after` (brugertesten 24/8, fund 31). Radioknappen måler
   `--sp-4` = 16 × 16 px, og testeren kunne kun vælge «Kort» ved at ramme ordet.
   Dækket lægger sig også over muligheden NOTE og ÅRSAG, som står på deres egen
   linje i den samme række — de er ren tekst, og et tryk på dem hører til det
   valg, de forklarer. */
.radiogruppe__label::after {
  content: "";
  position: absolute;
  inset: 0;
}
.radiogruppe__note,
.radiogruppe__aarsag {
  flex-basis: 100%;
  padding-left: var(--sp-7);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
/* Den låste mulighed. Tilstanden bæres af MØNSTER og af årsagsteksten ved
   siden af — aldrig af farve alene (KR-D-022, spec/13 §8 punkt 5). */
.radiogruppe__valgmulighed[data-deaktiveret="true"] {
  border-left: 3px dashed var(--kant-ui);
}
.radiogruppe__laest {
  margin: 0;
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  font: var(--type-broed-m);
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}
.radiogruppe__tom {
  margin: 0;
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}

/* --- Afkrydsningen --------------------------------------------------------- */
/* RÆKKEN BÆRER SIT EGET BERØRINGSMÅL — samme rettelse som afsnit 35's
   .samtykke__raekke, og af samme grund: afsnit 28's rækkeanatomi er SCOPET til
   .valggruppe, og en enkeltstående afkrydsning har ingen gruppe over sig. Uden
   reglen her ville de 44 × 44 px (--min-maalflade, WCAG 2.5.8) mangle netop
   dér, hvor afkrydsningen står alene.

   TOKENERNE ER NØJAGTIGT SAMTYKKEFELTETS. De to komponenter er søskende og
   ikke varianter, men rækken skal se ens ud — `test/valg.test.tsx` måler, at de
   to blokke bærer de samme tokens. */
.afkrydsning {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.afkrydsning__raekke {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  min-height: var(--min-maalflade);      /* 44px — berøringsmålet, WCAG 2.5.8 */
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  cursor: pointer;
  /* Ophænget for labelens dæk nedenfor. Se noten dér. */
  position: relative;
}
.afkrydsning[data-form="enkeltstaaende"] > .afkrydsning__raekke {
  border: var(--kant-komponent);         /* --kant-ui, 3,74:1 mod hvid */
}
.afkrydsning__boks {
  flex: none;
  width: var(--sp-4);
  height: var(--sp-4);
  margin-top: var(--sp-1);
}
.afkrydsning__label {
  font: var(--type-broed-m);
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
  cursor: pointer;
}
/* HELE RÆKKEN ER BERØRINGSMÅLET — samme greb som afsnit 35's
   `.samtykke__label::after` (fund 31). De to er søskende og skal blive ved med
   at kunne betjenes ens; boksen er `--sp-4` i begge. */
.afkrydsning__label::after {
  content: "";
  position: absolute;
  inset: 0;
}
/* Indrykket i BEGGE sider som rækken ovenover — samme rettelse som afsnit 35's
   `.samtykke__beskrivelse` (fund 29). Stod den ene med `padding-left` alene og
   den anden ikke, ville de to søskende ombryde forskelligt i den samme ramme. */
.afkrydsning__beskrivelse {
  margin: 0;
  padding-inline: var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
/* DEN LÅSTE AFKRYDSNING (SPM-264, Martins svar 2026-08-29 mulighed a).
   Tilstanden bæres af MØNSTER og af årsagsteksten ved siden af — aldrig af
   farve alene (KR-D-022, spec/13 §8 punkt 5). Kanten er ORDRET radiovalgets,
   så to låste kontroller på den samme skærm ikke ser ud som to tilstande.

   SELEKTOREN GÅR FRA RODEN OG IKKE FRA RÆKKEN, og det er kaskaden, der
   bestemmer det: den enkeltstående forms `border`-FORKORTELSE står ovenfor på
   `.afkrydsning[data-form=…] > .afkrydsning__raekke` med specificitet (0,3,0)
   og sætter også `border-left`. En regel på rækken alene ville stå i (0,2,0),
   tabe, og markeringen ville være usynlig netop dér, hvor afkrydsningen står
   alene. Herfra er de to lige specifikke, og denne står senest i kilden. */
.afkrydsning[data-deaktiveret="true"] > .afkrydsning__raekke {
  border-left: 3px dashed var(--kant-ui);
}
/* Årsagen sættes NØJAGTIGT som beskrivelsen ovenfor: de to står på hinandens
   plads i den samme komponent, og et forskelligt indryk ville få dem til at
   ombryde hver sin vej i den samme ramme. `test/valg.test.tsx` måler parret. */
.afkrydsning__aarsag {
  margin: 0;
  padding-inline: var(--taethed-pad-x);
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}

/* --- Foldeafsnittet -------------------------------------------------------- */
/* IKKE EN KOMPONENT — EN ANATOMI. `<details>`/`<summary>` er browserens egen
   sammenfoldning, og den er allerede tastaturbetjenbar og annonceret. Det, den
   mangler, er husets mål: et berøringsmål på 44 px (spec/13 §5.6), en
   komponentgrænse der består 1.4.11, og luft der følger tætheden.

   TO STEDER KRÆVER DEN. S8 §10.5's «Tilføj flere kontaktpersoner» i trin 7, og
   spec/13 §6.2's cockpit: «Filtre kollapser til et foldeafsnit, ikke væk.»
   Fokusfælden i `moenstre/fokusfaelde.ts` kender formen: `<summary>` er
   fokuserbar, og en kontrol inde i et LUKKET foldeafsnit er det ikke. */
.foldeafsnit {
  border: var(--kant-komponent);         /* --kant-ui, 3,74:1 mod hvid */
  border-radius: var(--radius-0);
}
.foldeafsnit__sammendrag {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--min-maalflade);      /* 44px — berøringsmålet */
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  font: var(--taethed-tekst);
  font-weight: 600;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
  cursor: pointer;
}
.foldeafsnit__indhold {
  display: flex;
  flex-direction: column;
  gap: var(--taethed-gab);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  border-top: var(--kant-haar);
}

/* =============================================================================
   41. FLERVÆLGEREN (S9 §3.15)
   =============================================================================
   Løftet fra `apps/intern-app/src/features/profilkompetencer/
   profilkompetencer.css` (E14-S13) sammen med komponenten.

   ÉN RETTELSE FULGTE MED, og den er en kantregel og ikke en smagssag. Den
   lokale regel skrev

       border: var(--kant-komponent) solid var(--kant-dekorativ);

   og --kant-komponent er selv `1px solid var(--kant-ui)`. Genfortolket bliver
   erklæringen `1px solid var(--kant-ui) solid var(--kant-dekorativ)`, som ikke
   er en gyldig `border`-forkortelse — browseren kasserer HELE erklæringen, og
   flervælgeren står i dag uden kant. Havde den virket efter ordlyden, ville
   den have haft --kant-dekorativ (1,35:1) omkring en gruppe af afkrydsninger,
   og spec/13 §7 er udtrykkelig: den kant «må ALDRIG omkranse et interaktivt
   element». Reglen her bruger --kant-komponent alene: --kant-ui, 3,74:1 mod
   hvid og 3,01:1 mod sand — begge over 1.4.11's krav. Fundet er ført i
   `spec-delta/ui-tillaeg-2.md` fund 5.
   --------------------------------------------------------------------------- */
.flervaelger {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  border: var(--kant-komponent);         /* RETTET — se hovedet. 3,74:1 mod hvid */
  border-radius: var(--radius-0);
  padding: var(--sp-3);
  margin: 0;
  min-inline-size: 0;
}
.flervaelger__legend {
  font: var(--type-label);
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
  padding-inline: var(--sp-1);
}
.flervaelger__obligatorisk {
  color: var(--tone-critical-tekst);     /* 8,13:1 mod hvid */
}
.flervaelger__liste,
.flervaelger__laest {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  list-style: none;
  margin: 0;
  padding: 0;
}
.flervaelger__post {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--min-maalflade);  /* 44px — berøringsmålet */
}
.flervaelger__label {
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
  flex: 1;
}
.flervaelger__laestpost {
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
}
.flervaelger__hjaelp,
.flervaelger__tom {
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
  margin: 0;
}
.flervaelger__fejl {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-1);
  font: var(--type-broed-s);
  color: var(--tone-critical-tekst);     /* 8,13:1 mod hvid */
  margin: 0;
}
.flervaelger__fejlikon {
  inline-size: 1em;
  block-size: 1em;
  flex: none;
  margin-block-start: 0.15em;
  fill: none;
  stroke: currentColor;
}

/* =============================================================================
   42. ANTALFELTET (S8 §7.2, spec/13 §5.6)
   =============================================================================
   Løftet fra `packages/bookingflow/src/trin4/trin4.css` (E12-S07) sammen med
   komponenten. Anatomien er uændret.

   spec/13 §5.6 nævner netop «tælleknapperne i trin 4» som under
   berøringsmålet i designleverancen. Bredden er derfor stadig 44px, og
   højden er nu RÆKKENS — se nedenfor.

   HØJDEN SIDDER PÅ RÆKKEN OG IKKE PÅ DE TRE BØRN (QA-fund 21, 30/8).
   Antalfeltet er ÉN kontrol for øjet: en ramme med to knapper og et tal
   imellem. Før bar hvert barn sit eget `min-height: 44px`, og rækkens ydre
   højde blev dermed talfeltets skrifthøjde (18px/1,6 = 28,8) plus lag 1's
   lodrette polstring (24) plus rammen (2) = 54,8 — 6,8px højere end
   knapperne ved siden af. Rækken bærer nu `--kontrol-hoejde` som border-box,
   børnene strækkes af `align-items: stretch`, og hele kontrollen står i
   nøjagtig samme højde som en knap, et tekstfelt og en vælger.

   BERØRINGSMÅLET FØLGER MED, OG DET ER MÅLT (chromium, 30/8): i den
   kundevendte tæthed er rækken 48px og knappens flade dermed 44 × 46 — over
   spec/13 §5.6's krav på begge led. Rammens 1px i top og bund er den eneste
   forskel mellem rækken og barnet.

   AFGRÆNSNING, SAGT HØJT: i den TÆTTE tæthed på mobil ville rækken være 44px
   og knappen dermed 42 — to pixels under husets eget gulv. Det tilfælde
   findes ikke i repoet: `.antalfelt__raekke` tegnes kun af `forms/Antalfelt`,
   som kun bruges kundevendt (kundeportalens webshop og bookingflowets trin 4
   og 5), og cockpittets A7/A8 har deres EGEN stepper-markup
   (`a7-antal__*`/`a8-minut__*`) med deres egen højde. Skulle antalfeltet en
   dag ind i en `[data-taethed="taet"]`-flade, er det her, gulvet skal
   genindføres — og ikke ved at give børnene deres `min-height` tilbage, for
   så er trappetrinnet tilbage med det samme.

   MÅLTE FORHOLD (lag 1's egne):
     --tekst-primaer på --flade-rolig    14,58:1  (krav 4,5)
     --tekst-primaer på --flade-daempet  11,78:1  (krav 4,5 — hover)
     --kant-ui som komponentgrænse        3,74:1  (krav 3,0)
   --------------------------------------------------------------------------- */
.antalfelt__raekke {
  display: flex;
  align-items: stretch;
  gap: 0;
  box-sizing: border-box;
  height: var(--kontrol-hoejde);         /* fælles kontrolhøjde — afsnit 25 */
  min-height: var(--kontrol-hoejde-min);
  border: var(--kant-komponent);         /* --kant-ui, 3,74:1 mod hvid */
  width: fit-content;
}
.antalfelt__knap {
  min-width: var(--min-maalflade);       /* 44px bredt — spec/13 §5.6 */
  min-height: 0;                         /* højden kommer fra rækken */
  border: 0;
  background: var(--flade-rolig);
  color: var(--tekst-primaer);           /* 14,58:1 mod --flade-rolig */
  font: var(--type-broed-l);
  font-weight: 700;
  cursor: pointer;
}
.antalfelt__knap:hover {
  background: var(--flade-daempet);      /* 11,78:1 med --tekst-primaer */
}
.antalfelt__knap[data-retning="ned"] {
  border-right: var(--kant-haar);
}
.antalfelt__knap[data-retning="op"] {
  border-left: var(--kant-haar);
}
.antalfelt__tal {
  width: 5rem;
  border: 0;
  text-align: center;
  font-variant-numeric: var(--tabular);
  font-weight: 700;
}
/* HØJDEN ER RÆKKENS, OG SELEKTOREN ER DERFOR RÆKKENS BARN og ikke klassen
   alene: talfeltet er OGSÅ `.felt`, og afsnit 28's `input.felt` giver hver
   enkeltlinjekontrol den fælles højde. Her skal rammen bære den i stedet, så
   de tre børn ikke kan gøre kontrollen højere end en knap.
   `.antalfelt__raekke >` løfter vægten over `input.felt`, så rækkefølgen i
   filen — og i det stilark, der måtte ligge efter — er ligegyldig. BREDDEN
   står med vilje tilbage i reglen ovenfor: bookingflowets trin 4 sætter sin
   egen (`trin4.css`), og den må ikke tabe til en vægt, den ikke bad om. */
.antalfelt__raekke > .antalfelt__tal {
  height: auto;
  min-height: 0;
}

/* =============================================================================
   43. SØJLEGRAFEN (S9 §5.23 D23c, SPM-266)
   =============================================================================
   Løftet fra `apps/intern-app/src/features/cockpit/rapporter/rapporter.css`
   (E14-S29's `.rap__soejle*`) sammen med komponenten. Anatomien er den samme:
   et gitter med tre spor — etiket, søjle, tal — så tallet står i en kolonne og
   ikke flyder med søjlens længde.

   ÉN RETTELSE FULGTE MED, OG DEN ER MÅLT. Den lokale regel tegnede fyldet med
   --tone-progress-kant (#7187BF) på et spor af --dk-graa-100 (#E4DCE0). Det
   forhold er 2,64:1 og ligger UNDER WCAG 1.4.11's krav på 3:1 til et grafisk
   objekt. Fyldet her er --tone-progress-tekst (#3B4A75), og forholdet mod
   sporet er 6,44:1. Fundet er ført som fund 2 i
   `spec-delta/k17-spm264-266.md`.

   AT SØJLEN OVERHOVEDET KAN BÆRE EN FARVE, DER FALDER, ER SELV EN PÅMINDELSE
   OM ANATOMIEN: søjlen er `aria-hidden`, og etiketten og tallet står som tekst
   ved siden af den. Farve bærer ingen information her — alle søjler har SAMME
   farve, og der findes ingen tone pr. punkt. 1.4.11 er alligevel opfyldt, fordi
   en regel, man kun opfylder ved at gøre grafikken undværlig, er en regel, den
   næste flade kommer til at bryde.

   MÅLTE FORHOLD (lag 1's egne værdier):
     --tone-progress-tekst mod --dk-graa-100    6,44:1  (krav 3,0 — 1.4.11)
     --tone-progress-tekst mod --dk-hvid        8,67:1  (krav 3,0)
     --tekst-sekundaer mod --dk-hvid            6,52:1  (krav 4,5 — tekst)
     --tekst-primaer mod --dk-hvid             16,57:1  (krav 4,5 — tekst)

   INGEN @media. De tre spor er sat med `minmax()` og falder sammen til godt
   11rem plus gab — det holder på 320px uden et brydepunkt at vedligeholde.
   --------------------------------------------------------------------------- */
.soejlegraf {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
/* Tekstækvivalenten er SYNLIG og ikke `.kun-skaermlaeser`: sætningen om, hvad
   grafen viser som helhed, hjælper alle. Se komponentens hoved, regel 3. */
.soejlegraf__tekstaekvivalent {
  margin: 0;
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}
.soejlegraf__soejler {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.soejlegraf__soejle {
  display: grid;
  grid-template-columns: minmax(6rem, 12rem) minmax(0, 1fr) minmax(5rem, auto);
  align-items: center;
  gap: var(--sp-3);
  font: var(--type-broed-s);
}
.soejlegraf__etiket {
  overflow-wrap: anywhere;
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}
.soejlegraf__spor {
  display: block;
  block-size: var(--sp-3);
  background: var(--dk-graa-100);
}
.soejlegraf__fyld {
  display: block;
  block-size: 100%;
  min-inline-size: 1px;                  /* En værdi på 0 skal stadig kunne ses */
  background: var(--tone-progress-tekst);/* 6,44:1 mod sporet — se hovedet */
}
.soejlegraf__tal {
  text-align: right;
  font-variant-numeric: var(--tabular);
  color: var(--tekst-primaer);           /* 16,57:1 mod hvid */
}
.soejlegraf__tom {
  margin: 0;
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);         /* 6,52:1 mod hvid */
}

/* =============================================================================
   44. VISUEL-REST-C — DET, TRE VISUELLE RUNDER BAD PAKKEN OM
   =============================================================================
   Bookinger-, Administration- og Drift-runderne meldte de samme ønsker tre
   gange (docs/ordrer/byg-visuel-rest/ORDRE-VISUEL-REST-C.md). De, der er
   CSS, står her: monospace-tokenet, chippen og radiogruppens retning og
   segmentform. Statusmærkets tætte variant står i afsnit 33, dialogens
   rettelser i afsnit 38 og konsekvensens tone i afsnit 32 — hver ved den
   regel, den retter.

   INGEN NY FARVE OG INGEN HEX. Alle målte forhold er lag 1's egne værdier,
   regnet efter med WCAG 2.1's formel (test/a11y/kontrast.test.ts, blok
   «VISUEL-REST-C»):
     --tekst-primaer på --dk-sand             13,37:1  (krav 4,5)
     --kant-ui mod --dk-sand                   3,01:1  (krav 3,0 — 1.4.11)
     --kant-ui mod --dk-hvid                   3,74:1
     --knap-tekst-farve på --flade-roed-svag   6,15:1  (krav 4,5)
     --dk-roed mod --flade-roed-svag           4,34:1  (krav 3,0 — kant)
     --dk-hvid på --dk-bordeaux               16,57:1
     --dk-hvid på --tone-*-tekst, laveste      6,87:1  (waiting)
     --fokus-farve-moerk på --dk-bordeaux     16,57:1  (ringen på den fyldte)
   --------------------------------------------------------------------------- */

/* --- 44.1 Monospace-tokenet (ønske 8) --------------------------------------
   Rettighedsnøgler (`actor.assignments.read`), rollenøgler og regelnøgler er
   maskinstrenge, og designet sætter dem i monospace (l. 4076 og l. 163–193's
   tokenkort). Familien er den ENESTE, lag 1 ikke navngiver — D15d, D17b, D18
   og helligdagsimporten skrev hver sin stak råt. `ui-monospace` er systemets
   egen (SF Mono, Cascadia, Menlo …) og hentes ikke udefra; resten er faldet
   tilbage for ældre motorer.

   NAVNET ER ORDRENS. Lag 1's konvention ville kalde familien `--font-mono`
   (ved siden af `--font-display` og `--font-broed`) og forbeholde `--type-*`
   til fulde font-forkortelser; det er ført som fund i
   spec-delta/visuel-rest-ui.md. Brug: `font-family: var(--type-mono)`. */
:root {
  --type-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* --- 44.2 Chippen (ønske 3) — `Chip` i forms/Chip.tsx ----------------------
   Anatomien er designets filterchip (l. 3460–3462): sand flade, `--kant-ui`-
   kant (rammens #C9BEC5 er 1,80:1 og derfor rettet til komponentgrænsen,
   spec/13 afsnit 7), det VALGTE i rosa med rød kant og rød tekst. Den fyldte
   form er D2's båndchip: mørk flade, hvid tekst.

   ROD OG DELE. `.chip` er en `<span>` uden polstring; polstringen sidder på
   `.chip__tekst`/`.chip__knap` og på `.chip__fjern`, så HELE chippen er
   klikflade, når den er en knap. Tonen kommer af `data-tone` (lag 1 afsnit 19)
   nøjagtigt som statusmærket; uden tone falder farverne tilbage på sand,
   `--kant-ui` og `--tekst-primaer`. */
.chip {
  display: inline-flex;
  align-items: stretch;
  box-sizing: border-box;
  max-width: 100%;
  border: 1px solid var(--tone-kant, var(--kant-ui));
  border-radius: var(--radius-1);
  background: var(--tone-flade, var(--dk-sand));
  color: var(--tone-tekst, var(--tekst-primaer));
  font: var(--type-broed-s);
  font-weight: 600;
  white-space: nowrap;
}
.chip__tekst,
.chip__knap {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
  padding: var(--sp-1) var(--sp-3);
  overflow: hidden;
  text-overflow: ellipsis;
}
/* KNAPPERNE ARVER CHIPPENS UDTRYK og bærer ingen egen flade. Mindst 24 px
   høje (`--sp-5`): WCAG 2.5.8's berøringsmål (AA i 2.2). Cockpittet er
   desktop først; på kundefladerne står chips i en `.valggruppe` eller på
   en flade med sine egne 44 px-regler. */
.chip__knap,
.chip__fjern {
  box-sizing: border-box;
  min-height: var(--sp-5);
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.chip__fjern {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--sp-5);
  padding: 0 var(--sp-2);
  font-weight: 700;
}
.chip__knap:hover,
.chip__fjern:hover {
  background: var(--flade-roed-svag);
}
/* VALGT — `aria-pressed="true"` bærer tilstanden; fladen og kanten følger
   (KR-D-022). Rammens l. 3462: rosa flade, rød kant, rød tekst. */
.chip[data-valgt="true"] {
  border-color: var(--dk-roed);         /* 4,34:1 mod --flade-roed-svag, 4,81 mod hvid */
  background: var(--flade-roed-svag);
  color: var(--knap-tekst-farve);       /* 6,15:1 mod --flade-roed-svag */
}
/* FYLDT — D2's båndchip. Med tone er fladen tonens TEKSTFARVE, som er den
   mørkeste af tonens tre og bærer hvid tekst med mindst 6,87:1 (waiting). */
.chip[data-form="fyldt"] {
  border-color: transparent;
  background: var(--tone-tekst, var(--dk-bordeaux));
  color: var(--dk-hvid);                /* 16,57:1 mod bordeaux */
}
.chip[data-form="fyldt"] .chip__knap:hover,
.chip[data-form="fyldt"] .chip__fjern:hover {
  background: none;
  text-decoration: underline;
}
/* FOKUSRINGEN PÅ DEN FYLDTE CHIP ER DEN HVIDE OG LIGGER INDENI (spec/13 §5.5).
   Lag 1's mørke ring ville stå bordeaux på bordeaux; den hvide ring uden på
   chippen ville stå hvid på sidens hvide. Derfor `--fokus-moerk` med negativ
   forskydning — samme greb som D2's `.d2-filterchip__fjern`. Vægten (0,4,0)
   slår lag 1's `:where(button):focus-visible` (0,1,0). */
.chip[data-form="fyldt"] .chip__knap:focus-visible,
.chip[data-form="fyldt"] .chip__fjern:focus-visible {
  outline: var(--fokus-moerk);
  outline-offset: calc(var(--fokus-offset) * -1);
}
/* DEN TÆTTE STØRRELSE — D5's og D4's mærke: 12 px, 2 px lodret luft. Samme
   tal og samme begrundelse som `.badge[data-taet="true"]` i afsnit 33. De
   interaktive dele holder stadig 24 px (reglen ovenfor); en tæt STATISK chip
   måler 12 + 2·2 + 2·1 = 18 px. */
.chip[data-taet="true"] {
  font: var(--type-label);
  font-weight: 600;
  line-height: 1;
}
.chip[data-taet="true"] .chip__tekst,
.chip[data-taet="true"] .chip__knap {
  gap: var(--sp-1);
  padding: 2px var(--sp-2);
}

/* --- 44.3 Radiogruppens retning og segmentform (ønske 4) -------------------
   `Feltsaet`/`Radiogruppe` skriver `data-retning="vandret"` og
   `data-form="segment"` — og INTET uden proppen, så standardformen er den
   samme som før. Reglerne er D6's (vandret), D15b's og D16b's (segment),
   løftet ind i pakken med de fælder, de tre registre målte:

     · RÆKKEN ER `.radiogruppe__liste`, IKKE FELTSÆTTET (D6-6): listen er
       `flex-direction: column` i afsnit 40, og en regel på feltsættet
       alene lægger legenden og listen på én linje, mens valgene stadig står
       stablet inde i listen.
     · Uden `min-width: 0` på labelen brød segmentrækken selv, og radioknappen
       endte OVER sin tekst (D15b).
     · Rammen flytter fra feltsættet til listen: en `<legend>` inde i en ramme
       tegnes I rammen, og designet har etiketten OVER den (D15b, D16b). */

/* VANDRET: rækkerne på én linje med ombrydning. Hårkanten under en række midt
   i en linje er en streg uden betydning og falder væk; berøringsmålet bliver
   (WCAG 2.5.8). Gælder både radiogruppens liste og et feltsæt af
   afkrydsninger — hjælpe- og fejltekst spænder da hele bredden. */
.valggruppe[data-retning="vandret"] {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-4);
}
.valggruppe[data-retning="vandret"] > legend {
  flex: none;
  float: none;
}
.valggruppe[data-retning="vandret"] .radiogruppe__liste {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-4);
}
.valggruppe[data-retning="vandret"] .valgmulighed {
  border-bottom: 0;
  padding-inline: var(--sp-2);
}
.valggruppe[data-retning="vandret"] > .feltsaet__hjaelpetekst,
.valggruppe[data-retning="vandret"] > .feltsaet__fejltekst {
  flex-basis: 100%;
}

/* SEGMENT: to–tre valg i ét felt med ramme, skillelinje imellem og tonet flade
   på det valgte (afsnit 28's `[data-valgt="true"]` gør det sidste allerede).
   Rammen er komponentgrænsen (--kant-komponent, 3,74:1); skillelinjerne er
   dekorative (--kant-haar) og omkranser intet. Mobil først: stablet i én
   ramme under 600 px, på én linje fra tablet. */
.valggruppe[data-form="segment"] {
  gap: var(--sp-1);
  border: 0;
}
.valggruppe[data-form="segment"] > legend {
  padding: 0;
}
.valggruppe[data-form="segment"] .radiogruppe__liste {
  border: var(--kant-komponent);
}
.valggruppe[data-form="segment"] .radiogruppe__liste > .valgmulighed {
  flex: 1 1 0;
  min-width: 0;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 0;
  border-top: var(--kant-haar);
}
.valggruppe[data-form="segment"] .radiogruppe__liste > .valgmulighed:first-child {
  border-top: 0;
}
/* Labelen må krympe under sit længste ord, så radioknappen bliver på linjen;
   noten (`flex-basis: 100%`) bryder stadig til sin egen linje. */
.valggruppe[data-form="segment"] .radiogruppe__label {
  min-width: 0;
}
.valggruppe[data-form="segment"] > .feltsaet__hjaelpetekst,
.valggruppe[data-form="segment"] > .feltsaet__fejltekst {
  padding-inline: 0;
}
/* 600px er --bp-tablet (afsnit 14, 23 og 34). */
@media (min-width: 600px) {
  .valggruppe[data-form="segment"]:not([data-retning="lodret"]) .radiogruppe__liste {
    flex-direction: row;
  }
  .valggruppe[data-form="segment"]:not([data-retning="lodret"]) .radiogruppe__liste > .valgmulighed {
    border-top: 0;
    border-left: var(--kant-haar);
  }
  .valggruppe[data-form="segment"]:not([data-retning="lodret"]) .radiogruppe__liste > .valgmulighed:first-child {
    border-left: 0;
  }
}

/* =============================================================================
   45. DET DANSKE DATO- OG KLOKKESLÆTSFELT (BUG-557/566/573/577, BUG-1231)
   =============================================================================
   Stilen flyttede med komponenten (`src/date/Datofelt.tsx`) fra intern-appens
   `faelles/faelles.css`, så bookingflowet, kundeportalen og temaets ø får den
   samme kontrol. Reglerne er de samme; intern-appens kopi er nu overflødig.

   Kontrollen er en TEKSTKONTROL og arver derfor `.felt`s fulde bredde. Et
   datofelt på 900 px er ikke en oplysning, det er en fejlkilde: bredden
   fortæller, hvor meget der skal skrives, og `dd.mm.åååå` er ti tegn.
   `max-width` og ikke `width`, så feltet stadig kan blive smallere end sin
   søjle på telefon (BUG-577 blev målt på 390×844). */
.datofelt .felt {
  max-width: 11rem;
}
.datofelt--tid .felt {
  max-width: 7rem;
}

/* DATO OG KLOKKESLÆT STÅR VED SIDEN AF HINANDEN, fordi de ER ét begreb — «Fra»
   er ikke to spørgsmål. De ombryder på smalle flader frem for at blive
   klippet. `fieldset` er nulstillet: rammen hører til feltgruppen, ikke til
   gruppen af to. */
.datotidsfelt {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}
.datotidsfelt__legende {
  padding: 0;
  font: var(--type-broed-s);
  font-weight: 600;
  color: var(--tekst-primaer);
}
.datotidsfelt__hjaelp {
  margin: var(--sp-1) 0 0;
}
.datotidsfelt__felter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-2);
}
