/* grundlag.css — temaets basisudtryk.
 *
 * Filen indeholder INGEN farve-, typografi- eller spacingværdi. Hver eneste
 * står i tokenlaget (_designtokens.genereret.css), som scripts/synk-kilder.sh
 * henter fra sin kilde ved hvert build. Prøven `ingen løse farver i temaet`
 * i test/tokenlag.test.ts afviser en hex- eller rgb()-værdi hvor som helst i
 * denne mappe.
 *
 * Temaets EGNE variabler bærer præfikset --tema-. Det er den eneste måde at se
 * på en linje, om en værdi er facit eller opfundet her.
 *
 * Brydepunkterne skrives med literale pixelværdier, fordi var() ikke virker i
 * en @media-forespørgsel (S13 afsnit 6.1). Tallene er --bp-tablet 600,
 * --bp-desktop 1024 og --bp-desktop-bred 1440 fra tokenlagets afsnit 14, og
 * prøven `brydepunkterne følger tokenlaget` holder dem sammen. */

/* TOKENLAGET STÅR HELLER IKKE HER LÆNGERE (BUG-009, 23/8): @import'en gav
 * 404 i portalen, da denne fil flyttede build (raw_assets/46), mens den
 * uændrede tokenfil blev stående på sit gamle buildnummer — browseren
 * opløser en rå @import relativt til DENNE fils adresse, og naboskabet
 * knækker ved hvert build, hvor kun én af filerne ændres. Samme fejlklasse
 * og samme kur som brandlaget (BUG-002): layoutet henter tokenlaget med
 * `require_css(get_asset_url(...))` FØR dette ark, så HubSpot selv minter
 * adressen pr. fil. ALT styling forsvandt live, da dette ramte — flyt den
 * ALDRIG tilbage til en @import. */

/* BRANDLAGET STÅR IKKE HER LÆNGERE (BUG-002). `@import "./brand.css"` gav 404
 * i portalen, mens denne fil og tokenlaget kom frem fra samme mappe. Layoutet
 * henter nu brand.css med sit eget
 * `require_css(get_asset_url("../../styles/brand.css"))`, lige efter dette
 * ark — samme rækkefølge, samme kaskade, men en adresse HubSpot selv har
 * mintet i stedet for en, browseren skulle danne. Begrundelsen står ved
 * kaldet i templates/layouts/grundlag.hubl.html. */

/* --- Dokumentet ----------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Kunden skal kunne zoome. Ingen maximum-scale, ingen fast rem-størrelse. */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
  background: var(--dk-graa-25);
}

/* --- Typografi der skal ARVES ---------------------------------------------
 *
 * SKRIFTEN. `--font-broed` og `--font-display` er tokenlagets, og temaet
 * hverken vælger eller indlæser en skrift. Tokenfilens afsnit 12 siger hvorfor:
 * «Big Shoulders Display + Figtree er STAND-IN, indtil museets licensfiler
 * foreligger». S13 afsnit 8, punkt 13 fører skriftlicenserne som et af de tre
 * spørgsmål, der SKAL besvares før kodning, og de er ikke besvaret endnu.
 *
 * Derfor står der hverken en `@font-face` eller et `<link>` til en fremmed
 * vært nogen steder i temaet. Et CDN ville sende hver besøgendes IP-adresse
 * til tredjepart uden hjemmel i specs, og en `@font-face` mod filer, der ikke
 * findes, ville give en 404 pr. sidevisning og ingen skrift. Indtil filerne
 * foreligger, bærer tokenets egen reservekæde udtrykket — `system-ui,
 * sans-serif` for brødteksten. Behovet er meldt til orkestratoren, som fører
 * det i spørgsmålskøen (husregel B6-70); det er en licensbeslutning og ikke et
 * valg, en byggende agent træffer selv. Prøven `temaet henter ingen skrift fra
 * en fremmed vært` i test/tokenkobling.test.ts holder porten lukket, indtil
 * der er truffet en beslutning.
 *
 * ARVEN. En formularkontrol arver IKKE skrift fra `body` — browseren giver den
 * sin egen (Arial/Helvetica på de fleste maskiner). Uden linjerne herunder står
 * hvert felt, hver vælger og hver knap uden klasse i systemets skrift midt i en
 * side sat i museets. Målt på demoen 20-08-2026.
 *
 * `--type-broed-m` er 16px, og det er ikke tilfældigt: iOS Safari zoomer
 * automatisk ind på et felt med mindre skrift end 16px, og bookingflowet er
 * mobile-first (S13 afsnit 6.2). */

button,
input,
select,
textarea,
optgroup {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
}

/* Mobile-first (KR-D-029, S13 afsnit 6.2): basislaget ER mobil. */
.tema-side {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ÉN KOLONNE PÅ HELE SIDEN. Indholdet, brandhovedet og sidefoden bruger
   NØJAGTIG den samme vandrette polstringsformel, så de tre flader flugter ved
   enhver skærmbredde. Formen er den samme for alle tre: en fuldbredde-flade med
   `max(gutter, (100% - --bredde-side) / 2)` i siderne. Under --bredde-side
   vinder gutteren, og over den centreres en kolonne på præcis --bredde-side.

   Det RETTER en måling fra dommen: `max-width: var(--bredde-side)` + egen
   polstring gav en kolonne på `--bredde-side` MINUS polstringen, mens
   brandhovedets indhold stod i en kolonne på hele --bredde-side. Forskellen var
   32 px mod 24 px fra 600 px og op — og 32 px forskudt venstrekant ved 1440 px.
   Designleverancen har 32 px i BEGGE flader (sidehovedets `padding:20px 32px`
   og indholdskortets egen 32 px gutter), så flugtningen er designets, ikke en
   opfindelse her. Prøven `sidens tre flader står i den samme kolonne` i
   test/tokenkobling.test.ts holder de tre formler ens. */

.tema-indhold {
  width: 100%;
  padding-block: var(--sp-5);
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  flex: 1 0 auto;
}

/* Brydepunkterne står i filens SIDSTE afsnit og ikke her. En @media-blok giver
   ingen ekstra specificitet, så det er kilderækkefølgen alene, der afgør, om
   den overskriver basislaget — se noten dér. */

/* --- Overskrifter --------------------------------------------------------- */

/* VERSALER FØLGER SKRIFTEN, IKKE NIVEAUET. Designleverancen er entydig, målt
   tag for tag: h1 11/11, h2 39/39, h3 28/29 og h4 4/4 står i versaler — og den
   ENE h3 uden er også den ene, der ikke er sat i displayskriften
   (`font-size:14px;font-weight:700` uden font-family). Reglen i designet er
   altså: er overskriften sat i Big Shoulders Display, står den i versaler.
   Temaet følger den regel og ikke tallene: h1–h3 bærer --type-display-*, og de
   får versaler; h4–h5 bærer brødskriften, fordi typografiskalaen har fire
   display-niveauer og standser der (afvigelse 2 i spec-delta/flowoe-4.md), og
   de får dem derfor ikke. h6 er en etiket og har sin egen versalregel nedenfor.

   Versalen sættes HER og ikke i tokenet: versal-tekst på engelsk bliver markant
   bredere, og valget hører til fladen (tokenlagets afsnit 12). Prøven
   `overskrifter i displayskrift står i versaler` i test/tokenkobling.test.ts
   binder de to sammen — fjernes versalen fra h2 eller h3, bliver den rød ved
   navn på niveauet. */

h1 {
  font: var(--type-display-l);
  text-transform: uppercase;
  margin: 0 0 var(--sp-5);
}

h2 {
  font: var(--type-display-m);
  text-transform: uppercase;
  margin: 0 0 var(--sp-4);
}

h3 {
  font: var(--type-display-s);
  text-transform: uppercase;
  margin: 0 0 var(--sp-3);
}

/* Skalaen i tokenlagets afsnit 12 har fire display-niveauer og standser der.
   h4–h6 findes stadig i redaktørens indhold, og en overskrift uden regel falder
   tilbage til browserens `2em bold serif` — en anden skrift midt i siden.
   De tre bærer derfor brødskriften i faldende vægt og størrelse, så
   overskriftshierarkiet holder uden at opfinde et femte display-niveau. */

h4 {
  font: var(--type-broed-l);
  font-weight: 700;
  margin: 0 0 var(--sp-3);
}

h5,
h6 {
  font: var(--type-broed-m);
  font-weight: 700;
  margin: 0 0 var(--sp-2);
}

h6 {
  font: var(--type-label);
  text-transform: uppercase;
  letter-spacing: var(--label-spacing);
}

/* --- Brødtekst ------------------------------------------------------------ */

p {
  margin: 0 0 var(--sp-4);
}

/* Sidste afsnit i en beholder skal ikke skubbe beholderens bund ned. */
p:last-child {
  margin-bottom: 0;
}

/* --- Links ---------------------------------------------------------------- */

a {
  color: var(--dk-roed-dyb);
  text-decoration: underline;
  /* Understregningen er der, fordi farve aldrig må være eneste
     informationsbærer (KR-D-022, KR-SY-021). Den fjernes ikke ved hover. */
  text-underline-offset: 0.15em;
}

/* --- Springlink (WCAG 2.4.1) ---------------------------------------------- */

.tema-springlink {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 100;
  padding: var(--sp-3) var(--sp-4);
  background: var(--dk-hvid);
  color: var(--tekst-primaer);
  border: var(--kant-komponent);
  border-radius: var(--radius-0);
  font: var(--type-broed-m);
  /* Skjult indtil det får fokus — ikke display:none, for så kan det ikke
     tabbes til. */
  transform: translateY(-200%);
}

.tema-springlink:focus {
  transform: translateY(0);
}

/* --- Siderammen: topbjælken over brandlinjen ------------------------------
 *
 * DESIGNET ER FACIT FOR RAMMEN (ADR 2026-08-20). S13 er tavs om siderammen
 * (målt), så formen er designleverancens eget sidehoved — og den er den samme
 * som domkirkekvarteret.dk's i `design/uploads/` (KR-D-015, KR-SY-018):
 * topbjælken med attraktionsvælger, søgefelt og den røde billetblok ØVERST, og
 * brandlinjen med bomærke og de tre navigationspunkter UNDER.
 *
 * DESIGNETS MÅL, oversat til tokens:
 *
 *   `border-bottom:1px solid #450019` under topbjælken  →  --kant-markant
 *   cellernes `padding:13px 20px`                       →  --sp-3 / --sp-5
 *   den røde bloks `padding:13px 28px` og `#E4003C`     →  --sp-3 --sp-6, --dk-roed
 *   celleskillelinjen `1px solid #C9BEC5`               →  --dk-graa-300
 *   søgetekstens `color:#7A5265`                        →  --tekst-sekundaer
 *   `font-size:17/19px` i Big Shoulders                 →  --type-display-s
 *
 * De 17 og 19 px bliver til --type-display-s' 20 px af samme grund som
 * hovedmenuens (se noten dér): typografiskalaen er facit over designfilens
 * flade punktstørrelser, facit-hierarkiet trin 4 over trin 5.
 *
 * --dk-graa-300 bærer skillelinjen MELLEM cellerne. Tokenlagets «RETTET
 * ROLLE» på den forbyder den som KOMPONENTGRÆNSE (1,80:1 mod hvid er for lidt
 * til 1.4.11) — og det er den ikke her: cellerne skelnes af deres egen tekst
 * og af den røde bloks flade, og stregen bærer ingen betydning alene.
 *
 * TOPBJÆLKEN STÅR I DEN SAMME KOLONNE som brandlinjen, indholdet og sidefoden.
 * Formlen er ordret de andres — det er den, der holder de fire flader på linje
 * ved enhver skærmbredde. */

.tema-sideramme {
  background: var(--dk-hvid);
}

/* MOBILFORMEN ER VALGT HER OG IKKE MÅLT (designleverancen har tre mobilrammer
   og ingen af dem viser topbjælken — S13 §4.1). Den enkleste form, der ikke
   taber en flade: rækken BRYDER. Attraktionsvælgeren og billetblokken deler
   den første linje, søgefeltet og sprogfanen den anden med en streg over. Fra
   --bp-tablet står de fire på én linje som i designet. Ingen funktion falder
   bort ved skiftet (S13 §6.2) — kun luften og rækkefølgen ændrer sig. */

.tema-topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  border-bottom: 1px solid var(--kant-markant);
}

/* MOBILENS LINJESKIFT — OG DET ER EN RETTELSE (P1's A4, verifikat 24/8).
   Ordren er, at sprogfanen står VANDRET, YDERST TIL HØJRE I SØGEFELTETS RÆKKE
   (række 2). Søgefeltet havde `flex: 1 1 100%` og fyldte dermed hele linjen
   selv, så fanen blev skubbet ned på en TREDJE, venstrestillet række — præcis
   den form, verifikatet dømte.

   Pseudo-elementet er flexboksens egen linjeskifter: et barn med
   `flex-basis: 100%` og `height: 0` tvinger et brud uden at optage plads eller
   bære indhold. Det er det mindste greb, der virker — alternativet var at gætte
   en fast bredde til søgefeltet, og den ville skride med hver ny etiket.
   Fra --bp-tablet slås det fra igen sammen med ombrydningen. */
.tema-topbar::before {
  content: "";
  order: 3;
  flex-basis: 100%;
  height: 0;
}

/* Attraktionsvælgeren har INGEN funktion i platformen endnu og er derfor
   `aria-disabled` i markup'en — ikke `disabled`, så den stadig kan tabbes til
   og opdages. Udtrykket følger det: dæmpet tekst og `cursor: not-allowed`.
   Farven er ikke eneste bærer af den besked — knappen har `aria-disabled`, en
   titel OG siden UI/UX-runden 24/8 (fund 42) et SYNLIGT «Kommer senere»-mærke:
   en `title` findes ikke på en touchskærm, så mobilbrugeren stod med en knap,
   der hverken gjorde noget eller sagde hvorfor. */

/* Samme rettelse som søgefeltet nedenfor, og af samme grund: knappen målte
   47,0 px — berøringsmålets 44 plus display-skriftens egen linjehøjde ud over
   polstringen — ved siden af topbjælkens 48. Højden læses nu ad tokenet
   (afsnit 25), og den lodrette polstring sættes til 0, så indholdets
   linjehøjde ikke længere er med til at bestemme den ydre. */
.tema-topbar__attraktion {
  order: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 1 1 auto;
  box-sizing: border-box;
  height: var(--kontrol-hoejde);
  min-height: var(--kontrol-hoejde-min);
  padding: 0 var(--sp-5);
  font: var(--type-display-s);
  text-transform: uppercase;
  text-align: left;
  color: var(--tekst-deaktiveret);
  background: none;
  /* SKILLESTREGEN STÅR I @media-blokken NEDERST og ikke her — den er kun en
     skillestreg, når der står noget til højre for den. Se noten dér. */
  border: 0;
  border-radius: var(--radius-0);
  cursor: not-allowed;
}

.tema-topbar__pil {
  flex: none;
}

/* MÆRKET «KOMMER SENERE» (fund 42). Det er en STILLE etiket og ikke en
   statusfarve: tonemodellens flader hører til bookingens tilstande, og et
   farvet mærke i museets eget hoved ville læse som en besked om noget, der
   ER sket. Formen er derfor tokenlagets etiketrolle i den dæmpede tekstfarve,
   med en hårkant om — synlig nok til at forklare knappen, stille nok til ikke
   at konkurrere med den røde billetblok ved siden af. */
.tema-topbar__snart {
  flex: none;
  padding: 0 var(--sp-2);
  font: var(--type-label);
  letter-spacing: var(--label-spacing);
  text-transform: uppercase;
  color: var(--tekst-deaktiveret);
  border: 1px solid var(--dk-graa-300);
  border-radius: var(--radius-0);
}

/* `flex: 1 1 auto` OG IKKE `1 1 100%`: linjeskiftet ligger i `::before`
   ovenfor, og søgefeltet skal dele række 2 med sprogfanen. `min-width: 0` er
   dét, der lader feltet krympe i stedet for at skubbe fanen ud af rækken.

   MOBILEN HAR STRAMMERE BÅND END TABLETTEN OG OP (UI-testrunden 24/8's fund
   14). Ved 375 px stod pladsholderen som «Søgning kommer sener» — det sidste
   «e» klippet af feltets bredde, uden en trepunktum til at vise det. Rækken
   deles med sprogfanen, så pladsen kan kun komme fra cellens eget bånd:
   `--sp-5` bliver til `--sp-4` og mellemrummet til lupen til `--sp-2`, og de
   ~20 px er nok til hele teksten. Tokenlagets desktopmål er sat tilbage i
   @media-blokken nederst, så den brede visning står som før. */
.tema-topbar__soeg {
  order: 4;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  color: var(--tekst-sekundaer);
  border-top: 1px solid var(--dk-graa-300);
}

.tema-topbar__lup {
  flex: none;
}

/* Feltet er skrivebeskyttet, fordi søgningen ikke findes endnu, og der er
   ingen <form> om det: modulet er serverrenderet, så en indsendelse ville føre
   kunden til en side, der ikke kan søge. `min-width: 0` er det, der lader
   feltet krympe i stedet for at skubbe den røde blok ud af rækken. */

/* HØJDEN KOMMER FRA `--kontrol-hoejde` OG IKKE FRA BERØRINGSMÅLET
   (QA's genmåling 30/8, den ene af to højde-rester efter K26a). Feltet stod
   44,0 px, mens katalogets fem filterkontroller og knapperne under det stod
   48 — og de tre ting ses i samme øjekast på katalogsiden. Årsagen var, at
   `min-height: var(--min-maalflade)` er GULVET (44) og ikke husets
   kontrolhøjde: feltet spurgte om det mindste, det måtte være, og fik det.
   Tokenlagets afsnit 25 er det ene sted, alle kontrolformer læser højden, og
   feltet læser den nu ad samme navn. Gulvet holder stadig — `--kontrol-hoejde-
   min` ER `--min-maalflade` i den kundevendte tæthed. */
.tema-topbar__soegefelt {
  flex: 1 1 auto;
  min-width: 0;
  box-sizing: border-box;
  height: var(--kontrol-hoejde);
  min-height: var(--kontrol-hoejde-min);
  padding-block: 0;
  font: var(--type-broed-m);
  color: var(--tekst-sekundaer);
  background: none;
  border: 0;
  border-radius: var(--radius-0);
  /* SIKKERHEDSNETTET UNDER FUND 14. Båndene ovenfor giver plads til den
     nuværende tekst; en længere etiket — eller en anden skriftstørrelse i
     browseren — ville klippe igen. En trepunktum siger i det mindste, at der
     står mere, i stedet for at tie om det manglende bogstav. */
  text-overflow: ellipsis;
}

.tema-topbar__billet {
  order: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-height: var(--min-maalflade);
  padding: var(--sp-3) var(--sp-6);
  font: var(--type-display-s);
  text-transform: uppercase;
  color: var(--dk-hvid);
  background: var(--dk-roed);
  /* Understregningen er væk HER og kun her, som på menupunkterne: blokken er
     en fyldt flade og skelnes på den, ikke på farven (WCAG 1.4.1). Den kommer
     tilbage på hover og fokus. */
  text-decoration: none;
}

.tema-topbar__billet:hover,
.tema-topbar__billet:focus-visible {
  background: var(--knap-primaer-flade-hover);
  text-decoration: underline;
}

/* FOKUSRINGEN PÅ DEN MØRKE FLADE (S13 afsnit 5.5). Tokenlagets globale ring er
   --fokus-lys, altså bordeaux, og den forsvinder på museets signalrøde. Blokken
   får derfor den hvide ring, tokenlaget allerede har til netop det. Reglen
   står her og ikke som en `.paa-moerk` på elementet: tokenlagets mørke regel er
   en EFTERKOMMER-vælger (`.paa-moerk :where(a, …)`), og en klasse på selve
   ankeret ville ikke ramme. */

.tema-topbar__billet:focus-visible {
  outline: var(--fokus-moerk);
  outline-offset: var(--fokus-offset);
}

/* --- Sprogfanen (design l.671; P1's A4) ----------------------------------- */

/* DEN LODRETTE FORM ER TABLETTENS OG OP — se @media-blokken i filens sidste
   afsnit. MOBILE-FIRST (KR-D-029, S13 §6.2) betyder, at basislaget her er den
   VANDRETTE form: designleverancens tre mobilrammer viser ingen topbjælke
   overhovedet (S13 §4.1), så mobilformen er valgt og ikke målt, og den
   enkleste, der ikke taber en flade, er den samme række som søgefeltets med
   fanen yderst til højre og en streg som skille. Valget står i
   `spec-delta/tema-sideramme.md`.

   `order: 5` lægger den efter søgefeltet I SAMME brudte række — linjeskiftet
   er `.tema-topbar::before`, ikke søgefeltets bredde (se noten dér). På tablet
   og op står de fire — vælger, søgefelt, billetblok, fane — igen på én linje.

   STREGEN OVER FANEN ER RÆKKENS OG IKKE FANENS. Søgefeltet tegner række 2's
   overkant; uden den samme kant på fanen ville stregen stoppe midt i rækken.
   Den går væk igen på tablet, hvor der ikke er nogen række 2.

   STØRRELSEN ER SKALAENS OG IKKE DESIGNFILENS. Designet har 11 px, og
   typografiskalaen standser ved `--type-label` (12 px). Facit-hierarkiets trin
   4 (tokenfilen) vinder over trin 5 (designleverancen), så der rundes OP —
   den anden vej ville betyde en ny størrelse i skalaen for én fanes skyld, og
   en mindre tekst end skalaens mindste er desuden det forkerte sted at spare.

   MÅLFLADEN NÅS PÅ LANGS. `--min-maalflade` (44 px) er sat som `min-height`;
   på tværs er fanen designets ~30 px brede, og en 44 px bred lodret fane ville
   være en anden komponent end den, designet viser. WCAG 2.5.8's undtagelse for
   «inline»-mål gælder ikke her, så afvigelsen er noteret i spec-delta sammen
   med mobilformen — fanens funktion findes desuden også som trin 1's
   ENGLISH-kort, der er et fuldt målflade-kort. */

.tema-topbar__sprogfane {
  order: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-height: var(--min-maalflade);
  padding: var(--sp-3) var(--sp-4);
  font: var(--type-label);
  letter-spacing: var(--label-spacing);
  color: var(--tekst-sekundaer);
  border-top: 1px solid var(--dk-graa-300);
  border-left: 1px solid var(--dk-graa-300);
  /* Understregningen er væk HER og kun her, som på menupunkterne og
     billetblokken: fanen står i sin egen indrammede flade og skelnes på den,
     ikke på farven (WCAG 1.4.1). Den kommer tilbage på hover og fokus. */
  text-decoration: none;
}

.tema-topbar__sprogfane:hover,
.tema-topbar__sprogfane:focus-visible {
  color: var(--tekst-primaer);
  text-decoration: underline;
}

.tema-topbar__sprogfane:focus-visible {
  outline: var(--fokus-lys);
  outline-offset: var(--fokus-offset);
}

/* --- Brandhoved og sidefod ------------------------------------------------ */

/* Bagfladen går fra kant til kant, mens INDHOLDET står i den samme kolonne som
   .tema-indhold. Det gøres med den vandrette polstring og ikke med en indre
   beholder, fordi markup'en ikke har en: modulet rendrer mærke og menu som
   direkte børn af <header> (components/modules/indhold-brandhoved). På en
   skærm smallere end --bredde-side vinder --sp-4, så mobil beholder sin
   kantafstand — mobile-first, KR-D-029. */

.tema-brandhoved {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-4);
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  background: var(--dk-hvid);
  border-bottom: var(--kant-haar);
}

.tema-brandmaerke {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  font: var(--type-display-s);
  color: var(--tekst-primaer);
  text-decoration: none;
  min-height: var(--min-maalflade);
}

.tema-brandmaerke__logo {
  /* Logoet er portalens temafelt (logoer.logo_lys), sat én gang på :root af
     layoutets temalag (MT-T2). Har portalen intet logo, sætter temalaget
     --tema-indgang-logo-visning: none, og ordmærket (navnet ved siden af)
     står alene i stedet for efter en tom 32 px-plads. Uden variablen er
     visningen block, som den altid har været.

     Tidligere: museets rigtige mærkefil, valgt af brandlaget i brand.css.
     Det er DEKORATIVT her: indgangens navn står som tekst ved siden af, så
     mærket skal ikke annonceres to gange (WCAG 1.1.1).

     32 px er designleverancens eget mål (`img … style="width:32px;height:32px"`
     i sidehovedet) og er samtidig --sp-6. Målfladen på 44 px står på ankeret
     nedenfor, ikke på billedet, så mærket kan følge designet uden at gøre
     tastaturmålet mindre (S13 afsnit 5.6). */
  display: var(--tema-indgang-logo-visning, block);
  flex: none;
  width: var(--sp-6);
  height: var(--sp-6);
  background-image: var(--tema-indgang-logo);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

.tema-brandmaerke__navn {
  /* Versaler som i designet. INGEN letter-spacing: designleverancens ordmærke
     sætter ingen, og --label-spacing hører til etiketter i brødskriften.

     ORDMÆRKET ER ÉN LINJE (SPM-228, Martin 2026-08-28, mulighed (a)).
     Designets brandlinje (l.675, målt) stabler DOMKIRKE / KVARTERET / VIBORG,
     men den form er Domkirkekvarterets LOGOTYPE og er lukket som en form,
     bookingsiden ikke bruger — se `spec-delta/spm-228.md`. Ordmærket her er
     indgangens navn, «Viborg Museum», sat på én linje.

     DER STABLES DERFOR IKKE. Kolonneflexen stod her ALENE for at bære de tre
     linjer; med én tekst gør den intet andet end at gøre det billigt at
     stable igen. Ingen `flex-direction: column`, ingen `white-space: pre-line`
     og intet `<br>` i modulet: hvert af de tre ville lave ordmærket om til
     flere synlige linjer, som ankerets tilgængelige navn ikke kan følge med i
     (WCAG 2.5.3). `sideramme.test.ts` måler netop de tre.

     LINJEHØJDEN BLIVER STÅENDE OG ER KOMPONENT-LOKAL. Designets .98 er et
     ORDMÆRKES sammentrækning — den holder mærkets optiske højde nede mod
     bomærket ved siden af — og har ingen tokenrolle: typografiskalaen giver
     `--type-display-s` sin egen linjehøjde til brødtekstens rytme.
     Størrelsen kommer stadig fra skalaen (arvet fra `.tema-brandmaerke`), som
     er facit over designfilens flade 16 px. */
  display: block;
  line-height: 0.98;
  text-transform: uppercase;
}

/* Hovedmenuen står i designets displayskrift og versaler, ikke i brødteksten
   (designleverancen: Big Shoulders 600, versaler, gap 26 px). Afstanden er
   --sp-5 = 24 px, skalaens nærmeste; punktstørrelsen kommer fra
   --type-display-s, fordi typografiskalaen er facit over designfilens flade
   17 px (facit-hierarkiet trin 4 over trin 5). */

.tema-menu {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* MENUENS FARVER ER DESIGNETS, MÅLT I DESIGNFILEN.
 *
 * Sidehovedets menurække (designfilen, sidehovedets `<div style="display:flex;
 * gap:26px…">`): det AKTIVE punkt sætter ingen egen farve og arver derfor
 * `body{color:#450019}`, mens de to inaktive står med `color:#7A5265`.
 *
 *   #450019 = --tekst-primaer (tokenlagets afsnit 4: «= --dk-bordeaux»)
 *   #7A5265 = --tekst-sekundaer (afsnit 4: «= --dk-graa-600»)
 *
 * Uden en egen `color` her arvede menupunkterne linkfarven, og hovedmenuen stod
 * i signalrødt #B80031 — dommens fund. Rigtigt nok tokenlagets
 * `:where(a):not(.knap)` (--knap-tekst-farve), som slår filens egen `a`-regel:
 * `:not(.knap)` tæller som en klasse og vejer tungere end elementvælgeren. De
 * to peger i øvrigt på samme hex, så farven var den samme uanset hvem der vandt
 * — og ingen af dem er menuens. Farverne er nu bundet med prøven
 * `hovedmenuen bærer designets farver` i test/tokenkobling.test.ts, som er rød
 * ved navn, hvis et andet token sniger sig ind.
 *
 * KONTRAST: #7A5265 på hvid er 6,52:1, #450019 er 16,57:1 (begge målt i
 * tokenlagets afsnit 4) — begge over 4,5:1 (WCAG 1.4.3). Farven er heller ikke
 * eneste skel: det aktive punkt bærer en 2 px streg OG aria-current. */

.tema-menu a {
  display: inline-flex;
  align-items: center;
  min-height: var(--min-maalflade);
  font: var(--type-display-s);
  text-transform: uppercase;
  color: var(--tekst-sekundaer);
  /* Understregningen er væk HER og kun her. Et menupunkt står ikke i en
     tekststrøm, så det skelnes på placering og ikke på farve — WCAG 1.4.1 er
     opfyldt uden den, og designet har ingen. Den kommer tilbage på hover og
     fokus, så pegeredskabet stadig får en bekræftelse. */
  text-decoration: none;
}

/* Designets egen hover-regel for links er `a:hover{color:#450019}`. Menuen
   følger den: punktet mørkner til --tekst-primaer OG får understregning. */

.tema-menu a:hover,
.tema-menu a:focus-visible {
  color: var(--tekst-primaer);
  text-decoration: underline;
}

/* Det aktive punkt bærer designets egen markering: fuld tekstfarve og en 2 px
   streg under punktet i brandfarven. Klassen er HubSpots egen fra <Menu>.
   Stregen er IKKE eneste informationsbærer — <nav> og punktets eget
   aria-current annonceres af skærmlæseren (KR-D-022, KR-SY-021). */

.tema-menu .active > a,
.tema-menu a[aria-current] {
  color: var(--tekst-primaer);
  border-bottom: 2px solid var(--kant-markant);
}

.tema-sidefod {
  /* Samme kolonne som brandhovedet og indholdet. Se noten dér. */
  padding-block: var(--sp-6);
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  background: var(--dk-bordeaux);
  color: var(--paa-moerk-tekst);
  flex: none;
}

.tema-sidefod a {
  color: var(--paa-moerk-tekst);
}

.tema-sidefod__liste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin: 0 0 var(--sp-4);
  padding: 0;
  list-style: none;
}

.tema-sidefod__liste a {
  display: inline-flex;
  align-items: center;
  min-height: var(--min-maalflade);
}

/* --- Ø-beholderen --------------------------------------------------------- */

/* KLEMMEN ER SIDENS KOLONNE OG IKKE FLOWETS (lynfix 23/8, målt live på #51).
 *
 * Klassen bar `max-width: var(--bredde-flow)` — bookingflowets 700 px. Det var
 * rigtigt, dengang flowet selv stod i 700 px hele vejen op, men flowet har
 * siden fået designets desktopform: `packages/bookingflow/src/booking.css`
 * sætter `.bookingflow { max-width: var(--bredde-side) }` fra --bp-desktop, så
 * kortet fylder indholdsbredden ud i stedet for at efterlade en tom
 * højremargin. Den ændring kunne ikke ses live, for TEMAETS ydre lag klemte
 * stadig ved 700 px, og et barn kan ikke blive bredere end sin forælder:
 * indholdet stod smalt og med al luften i højre side.
 *
 * `--bredde-side` er tokenlagets egen rolle for netop det — «Ydre
 * indholdsbredde i cockpit og kundeflader» — og det er den SAMME bredde, som
 * `.tema-indhold`, `.tema-brandhoved`, `.tema-topbar` og `.tema-sidefod`
 * centrerer deres kolonne om. Øen står altså nu i sidens kolonne, og det er
 * fladen SELV, der bestemmer, hvor smal den vil være: flowet holder sine
 * 700 px under 1024 px, og hvert trins brødtekst er stadig bundet af
 * `--bredde-tekst`.
 *
 * KLEMMEN FORSVINDER IKKE. Uden en `max-width` ville øen løbe helt ud til
 * gutteren på en bred skærm og stå ude af flugt med sidehoved og sidefod. De
 * to interne flader, der SKAL have hele bredden, har deres egen klasse —
 * `.tema-oe-fuld` nedenfor — og prøverne i `internapp-oe.test.tsx` og
 * `kundeportal-oe.test.tsx` måler, at de to ikke blandes sammen. */

.tema-oe {
  /* En React-ø fylder sin plads, også før den er hydreret, så siden ikke
     hopper når klientkoden lander. */
  display: block;
  width: 100%;
  max-width: var(--bredde-side);
  margin: 0 auto;
}

/* --- Webshoppens skelet, mens bundtet hentes (BUG-422) --------------------
 *
 * Webshoppens ø er `clientOnly`, fordi fladen bærer HELE sin rute i sidens
 * FRAGMENT og serveren derfor ikke kan tegne den rute, klienten viser — se
 * modulets egen note. Prisen er, at øens `<div>` kommer TOM fra serveren, og
 * skelettet her holder pladsen, så siden ikke står med et hul og ikke hopper,
 * når butikken lander.
 *
 * REGLEN ER SØSKENDEVÆLGEREN OG INGEN JS. `.tema-oe:not(:empty)` bliver sand i
 * samme øjeblik, klienten har tegnet noget i øen, og skelettet forsvinder af
 * sig selv. Der er derfor ingen oprydning at glemme, og skelettet kan ikke
 * blive stående oven på butikken.
 *
 * `:empty` TÆLLER OGSÅ TEKSTKNUDER, og det er netop det, der gør vælgeren
 * pålidelig her: `clientOnly` tegner beholderen uden ét eneste barn, og alt,
 * hvad klienten sætter ind, gør den ikke-tom.
 *
 * STILARKET HØR HER OG IKKE I ØENS EGET. `webshop.css` følger med BUNDTET, og
 * skelettet skal netop stå, FØR bundtet er hentet. Lå reglen der, ville
 * pladsholderen være ustylet i præcis det sekund, den findes for.
 *
 * KUN GEOMETRI, INGEN ANIMATION. En pulserende flade ville være bevægelse,
 * ingen har bedt om (WCAG 2.3.3 om `prefers-reduced-motion` ville da også
 * skulle håndteres); skelettet er rolige flader i husets egen kantfarve. */

.wsh-skelet {
  display: block;
  width: 100%;
  max-width: var(--bredde-side);
  margin: 0 auto;
}

.tema-oe:not(:empty) + .wsh-skelet {
  display: none;
}

.wsh-skelet__ramme {
  display: grid;
  gap: var(--sp-5);
  padding-block: var(--sp-6);
}

.wsh-skelet__filter,
.wsh-skelet__kort {
  display: block;
  /* HUSETS EGNE TOKENS, MÅLT OG IKKE GÆTTET. `--flade-sekundaer` og
     `--radius-komponent` findes ikke i tokenlaget (målt: 0 forekomster);
     `--flade-rolig` er «rolig indholdsflade», og `--radius-0` er
     Domkirkekvarterets retkantede udtryk. */
  border: var(--kant-komponent);
  border-radius: var(--radius-0);
  background: var(--flade-rolig);
}

.wsh-skelet__filter {
  height: 56px;
}

.wsh-skelet__liste {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: 1fr;
}

.wsh-skelet__kort {
  height: 320px;
}

/* Samme brydepunkt som katalogets egen liste, så pladsholderen har den
   geometri, indholdet får — ellers ville siden hoppe ved skiftet. */
@media (min-width: 600px) {
  .wsh-skelet__liste {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .wsh-skelet__liste {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Bookingsiden monterer TO øer — bookingflowet og webshoppen [B]. Uden en
   afstand mellem dem støder de sammen, når begge er tændt. Reglen rammer kun
   den anden og de følgende, så en side med én ø ikke får et hul foroven. */
.tema-oe + .tema-oe {
  margin-top: var(--sp-7);
}

/* --- Ø-beholderen UDEN klemme: de to interne flader -----------------------
 *
 * Aktørportalen og DP-cockpittet monterer `apps/intern-app`, og den app bærer
 * SINE EGNE brydepunkter: `skal.css` lægger navigationen i en skuffe under
 * 1024 px, og skærmarkene bærer de vandrette rul med fastfrosset første
 * kolonne. Brydningen sker på VIEWPORT.
 *
 * `.tema-oe` ovenfor klemmer sit indhold ind i `--bredde-flow` = 700 px —
 * BOOKINGFLOWETS kolonne (spec/12). En viewport-brydning inde i en 700 px bred
 * beholder giver desktoplayoutet på en 1440 px-skærm, presset ned i under
 * halvdelen af pladsen: cockpittets tabeller og aktørportalens kalender kan
 * ikke stå der, og S13 §6.2's «ingen central funktion må falde bort under
 * 1024 px» er brudt den anden vej rundt (RETBRIEF-M2-OEMONT-2, K2).
 *
 * KLASSEN STÅR ALENE og er ikke en BEM-modifikator: blev den brugt SAMMEN med
 * `.tema-oe`, ville klemmen følge med tilbage, og en prøve kunne ikke se
 * forskel på «rettet» og «rettet halvt». `test/internapp-oe.test.tsx` måler
 * derfor de to fladers faktiske klasseliste MOD reglerne i denne fil og gør en
 * genplantet `tema-oe` rød.
 *
 * INGEN MINDSTEBREDDE. Aktørportalen er mobile-first (S13 §6.2), og en fast
 * `min-width` her ville tvinge et vandret rul på en telefon. Den ene ramme,
 * fladen har, er sidens egen kolonne — `.tema-indhold`s
 * `max(gutter, (100% - --bredde-side) / 2)`, hvor `--bredde-side` er
 * cockpittets egne 1180 px. */

.tema-oe-fuld {
  /* Som `.tema-oe`: øen fylder sin plads, også før den er hydreret, så siden
     ikke hopper når klientkoden lander. Men uden en `max-width`. */
  display: block;
  width: 100%;
}

/* --- Fokus på mørke flader (S13 afsnit 5.5) -------------------------------
 *
 * Reglen selv står i tokenlagets afsnit 22.3 og gælder alt inde i en
 * `.paa-moerk`. Sidefoden bærer klassen (components/modules/indhold-sidefod).
 * Linjen her er kun sikringen af, at ringen har luft at stå i: står et link
 * klemt op mod bordeauxfladen, tegnes ringen ind over teksten, og de 16,57:1
 * bliver ikke til den synlighed, tallet lover. */

.tema-sidefod :focus-visible {
  outline-offset: var(--fokus-offset);
}

/* --- Membership-systemsiderne (templates/system/) -------------------------
 *
 * HubSpots Private content har fire egne sider — login, registrering, glemt
 * kodeord og vælg nyt kodeord — og uden en skabelon pr. type serverer portalen
 * sin RÅ standardside midt i vores eget flow. Skabelonerne ligger i
 * `templates/system/` og arver grundlayoutet, så de får hele stilkæden med.
 *
 * REGLERNE STÅR HER OG IKKE I ET EGET ARK. Temaet har i dag ÉT håndskrevet
 * sideark (denne fil) plus brandlaget, og hver ny CSS-fil er en ny adresse i
 * kæden, browseren eller HubSpot skal kunne danne — det er BUG-002's og
 * BUG-009's fejlklasse, og den koster mere end de få kilobytes, disse regler
 * fylder på de øvrige sider.
 *
 * VÆLGERNE ER ELEMENTER OG IKKE VORES KLASSER, og det er ikke sjusk.
 * member_login-tagget og dets tre søskende rendrer HubSpots EGEN markup
 * (HubL-formen står bevidst IKKE ordret her: et rå-aktiv med procent-tuborg
 * klassificeres af projekt-builderen som skabelon og fælder hele buildet):
 * felternes klasser og id'er hører til platformen, og der findes ingen
 * parameter, der kan lægge `.felt` eller `.knap` på dem. Det, skabelonen ejer,
 * er beholderen — `.tema-medlemsside__formular` — så udtrykket bygges indefra
 * den. Værdierne er ORDRET tokenlagets `.felt` (afsnit 22.2) og `.knap`
 * (afsnit 27), så systemsiderne og appens egne skærme ser ens ud.
 *
 * De tre id'er er HubSpots egne og målt i HubSpots CMS-boilerplate
 * (`src/css/templates/system.css`): `#hs-login-widget-remember` er «Husk
 * mig»-afkrydsningsfeltet, `#hs_login_reset` er «Glemt dit kodeord?»-linket, og
 * `.hs-error-msgs` er listen med formularens fejlbeskeder. */

.tema-medlemsside {
  /* --bredde-smal er tokenlagets egen bredde til «Login, L1/L2, fejlsider». */
  max-width: var(--bredde-smal);
  margin-inline: auto;
}

.tema-medlemsside__intro {
  color: var(--tekst-sekundaer);
}

/* Kodeordskravet. Samme form som kundeportalens egne oplysningsafsnit: en
   dæmpet flade med en streg i brandfarven, så det læses som en oplysning og
   ikke som en fejl. */
.tema-medlemsside__krav {
  font: var(--type-broed-s);
  color: var(--tekst-primaer);
  background: var(--dk-sand);
  border-left: 3px solid var(--dk-roed-dyb);
  padding: var(--sp-3) var(--sp-4);
  margin: 0 0 var(--sp-4);
}

.tema-medlemsside__formular {
  background: var(--dk-hvid);
  border: var(--kant-komponent);
  border-radius: var(--radius-0);
  padding: var(--sp-5);
  margin-block: var(--sp-5);
}

.tema-medlemsside__formular label {
  display: block;
  font: var(--type-broed-s);
  font-weight: 700;
  color: var(--tekst-primaer);
  margin-bottom: var(--sp-2);
}

/* Feltet. Værdierne er tokenlagets `.felt` — 16px skrift, fordi iOS Safari
   zoomer ind på mindre, og --min-maalflade i højden (WCAG 2.5.8). */
.tema-medlemsside__formular input[type="email"],
.tema-medlemsside__formular input[type="password"],
.tema-medlemsside__formular input[type="text"] {
  display: block;
  width: 100%;
  min-height: var(--min-maalflade);
  font: var(--type-broed-m);
  color: var(--tekst-primaer);
  background: var(--dk-hvid);
  border: 1px solid var(--kant-felt);
  border-radius: var(--radius-0);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
}

/* Fejltilstanden bæres af BÅDE kant og tekst — HubSpot sætter selv
   aria-invalid, og fejlteksten står i .hs-error-msgs nedenfor. Farven er
   derfor aldrig eneste informationsbærer (KR-D-022, KR-SY-021). */
.tema-medlemsside__formular input[aria-invalid="true"] {
  border-color: var(--kant-felt-fejl);
  border-width: 2px;
}

.tema-medlemsside__formular .hs-error-msgs {
  font: var(--type-broed-s);
  color: var(--tekst-fejl);
  list-style: none;
  margin: 0 0 var(--sp-4);
  padding: 0;
}

/* «Husk mig» er et afkrydsningsfelt og må IKKE arve feltets fulde bredde. */
#hs-login-widget-remember {
  display: inline-block;
  width: auto;
  min-height: 0;
  margin: 0 var(--sp-2) var(--sp-4) 0;
  vertical-align: middle;
}

#hs-login-widget-remember ~ label {
  display: inline-block;
  margin-bottom: var(--sp-4);
  vertical-align: middle;
}

/* «Glemt dit kodeord?» — et link i en formular, så det skal have
   tastaturmålets 44 px ligesom menuens og sidefodens links. */
#hs_login_reset {
  display: inline-flex;
  align-items: center;
  min-height: var(--min-maalflade);
  margin-bottom: var(--sp-3);
}

/* Knappen. Værdierne er tokenlagets `.knap[data-rolle="primaer"]`. Fuld bredde
   på mobil, fordi basislaget ER mobil (KR-D-029); fra tablet står den i sin
   egen bredde — se brydepunktet nederst i filen. */
.tema-medlemsside__formular input[type="submit"],
.tema-medlemsside__formular button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--taethed-hoejde-min);
  height: var(--taethed-hoejde);
  padding: var(--taethed-pad-y) var(--taethed-pad-x);
  font: var(--taethed-tekst);
  font-weight: 600;
  color: var(--dk-hvid);
  background: var(--knap-primaer-flade);
  border: 1px solid transparent;
  border-radius: var(--radius-0);
  text-align: center;
  cursor: pointer;
}

.tema-medlemsside__formular input[type="submit"]:hover,
.tema-medlemsside__formular button[type="submit"]:hover {
  background: var(--knap-primaer-flade-hover);
}

.tema-medlemsside__hjaelp {
  font: var(--type-broed-s);
  color: var(--tekst-sekundaer);
}

/* --- Bookingsidens ÉNE ramme (design l.664–677; P1's A10) ------------------ */

/* HVAD DER VAR GALT. Designleverancens bookingside er ét hvidt kort med kant
   hele vejen rundt på en lys grå flade, og kortet BÆRER topbjælken og
   brandlinjen som sine to øverste bånd; derefter kommer trinbåndet uden
   mellemrum. Hos os var topbjælken og brandlinjen fuldbrede hvide bånd ud til
   viewportens kanter, så kom et gråt mellemrum, og så begyndte kortet. Begge
   dele stod i den samme kolonne — det var ikke flugtningen, der manglede, men
   gestalten: to løsrevne flader i stedet for én ramme.

   KLASSEN SÆTTES AF SKABELONEN OG IKKE AF TEMAET. `.tema-side--flowramme`
   kommer fra `templates/booking.hubl.html` gennem layoutets `sideklasse`-blok.
   Kundeportalen, aktørportalen, cockpittet og forsiden deler det samme
   grundlayout, og en ændring i `.tema-topbar` selv ville ramme dem alle — de
   skal se ud, som de gør i dag. Alle reglerne herunder hænger derfor på
   klassen, og ingen af dem rører de bare vælgere.

   POLSTRINGSFORMLEN ER OGSÅ EN ANDEN HER, og det er med vilje: de tre flader
   uden for rammen bruger `max(gutter, (100% - --bredde-side) / 2)` på en
   FULDBREDDE-flade, mens rammens bånd er en kolonne med sin egen kant. Formlen
   ville ikke kunne tegne kanten — den ville lægge sig i viewportens kant.
   `max-width` + `margin-inline: auto` giver den samme kolonne, med kanterne
   det rigtige sted. Prøven «sidens tre flader står i den samme kolonne»
   (test/tokenkobling.test.ts) måler de bare vælgere og er urørt. */

.tema-side--flowramme {
  background: var(--dk-graa-25);
}

/* Bagfladen slippes, så den grå side kan ses omkring kortet.

   TOPLUFTEN ER DESIGNETS (l.664: `padding: 28px 64px 64px` om kortet; P1's
   A10-rest, verifikat 24/8). Uden den klæbede kortets overkant til viewportens
   allerøverste pixel, og «ét kort på en grå flade» blev til «en side, der
   begynder med en kant». Luften lægges på SIDERAMMEN og ikke på kortet: det er
   siderammen, der er kortets første bånd her, og en margin på flowet selv
   ville lægge sig MELLEM brandlinjen og trinbåndet — præcis det mellemrum,
   A10 lukkede.

   28 PX FINDES IKKE I TRINSKALAEN. `--sp-5` (24) og `--sp-6` (32) er de to
   naboer, og skalaen vinder over designfilen (facit-hierarkiets trin 4 over
   trin 5). Der vælges den mindre, som filen allerede gør det for søjlens
   26 px: luft, der er lidt for lille, læses som stram — luft, der er for stor,
   løsner kortet fra sidens top igen. */
.tema-side--flowramme .tema-sideramme {
  padding-top: var(--sp-5);
  background: none;
}

.tema-side--flowramme .tema-topbar,
.tema-side--flowramme .tema-brandhoved {
  box-sizing: border-box;
  max-width: var(--bredde-side);
  margin-inline: auto;
  padding-inline: var(--sp-4);
  background: var(--dk-hvid);
  /* Kortets egne sidekanter, ført op gennem de to øverste bånd. `--kant-ui` er
     en REN FARVE og skrives derfor med `1px solid` foran; det sammensatte
     `--kant-komponent` kan ikke bruges til én akse. */
  border-inline: 1px solid var(--kant-ui);
}

/* Kortets overkant. Topbjælken er rammens FØRSTE bånd, så den bærer den. */
.tema-side--flowramme .tema-topbar {
  border-top: 1px solid var(--kant-ui);
}

/* MELLEMRUMMET LUKKES. `.tema-indhold`s egen polstring i toppen er dét, der
   skilte brandlinjen fra kortet; her støder de to sammen, og brandlinjens
   underkant bliver skillelinjen mellem dem — præcis som mellem kortets øvrige
   bånd. Polstringen i BUNDEN bliver, så kortet ikke klistrer til sidefoden. */
.tema-side--flowramme .tema-indhold {
  padding-top: 0;
}

/* Kortets egen overkant udgår, hvor brandlinjen allerede har tegnet den. To
   hårkanter oven på hinanden er den 2 px streg, designet ikke har. */
.tema-side--flowramme .bookingflow {
  border-top: 0;
}

/* --- Portalsidens HELHVIDE flade (K1-brief afvigelse 6) ------------------- */

/* HVAD DER VAR GALT (K1-verifikatets afvigelse 6, deploy #63). Designets
   kundeportal er HELHVID KANT TIL KANT — 2-1/2-2-billederne har hverken
   flanker eller en grå bund; den ydre ramme i mockuppen er billedets egen
   browserchrome. Live stod portalen som en centreret hvid blok på en grå
   flade: ~130 px grå i hver side ved 1440 og et gråt bånd under foden.

   HVOR DEN GRÅ KOM FRA — og det var IKKE portalens eget stilark. `.skal` har
   båret `background: var(--dk-hvid)` hele tiden. Det grå var `body`s
   `--dk-graa-25`, der SÅS GENNEM `.tema-indhold`s egen polstring:
   `padding-inline: max(--sp-4, (100% - --bredde-side) / 2)` er præcis
   (1440 − 1180) / 2 = 130 px i hver side, og `padding-block` lagde båndet
   over og under. Polstringen er rigtig for en side, hvor indholdet ER en
   tekstkolonne på en flade. Kundeportalen er ikke dét: den er en HEL FLADE med
   sin egen header, sin egen fod og sin egen `--bredde-side`-kolonne inde i sig
   (`apps/kundeportal/src/skal/skal.css`). To kolonner uden om hinanden giver
   én kolonne for meget — og den grå, der ses imellem dem.

   KLASSEN SÆTTES AF SKABELONEN OG IKKE AF TEMAET, ordret som
   `.tema-side--flowramme` ovenfor: `templates/kundeportal.hubl.html` sætter
   den gennem layoutets `sideklasse`-blok. Booking-, aktør-, cockpit- og
   forsiden deler samme grundlayout og skal se ud, som de gør i dag, så ingen
   af reglerne herunder rører en bar vælger. Prøven «sidens tre flader står i
   den samme kolonne» (test/tokenkobling.test.ts) måler netop de bare vælgere
   og er urørt.

   ØEN ER I FORVEJEN `tema-oe-fuld` (uden `max-width`), så det er alene
   polstringen, der har stået i vejen for kant-til-kant. */

.tema-side--portalflade {
  background: var(--dk-hvid);
}

/* Polstringen falder HELT bort — ikke bare den vandrette. Båndet over headeren
   og under foden var `padding-block`, og designets flade har ingen af dem.
   Kolonnen forsvinder ikke: portalens egen `.skal__indhold` og `.skal__fodliste`
   bærer `max-width: var(--bredde-side)` med `margin-inline: auto`, altså
   NØJAGTIG den kolonne, `.tema-indhold` ellers ville have lagt — bare inde i
   den hvide flade i stedet for uden om den. Headerens bordeaux bundlinje når
   derfor viewportens kanter, som den gør i designet. */
.tema-side--portalflade .tema-indhold {
  padding: 0;
}

/* --- Værktøjssidens FULDE BREDDE (VQA-610, Martins ejerbeslutning 31/8) --- */

/* HVAD DER VAR GALT. QA målte cockpittets `.skal` til 1.180 px ved BÅDE 1440 og
   1920 px viewport — 740 px ubrugt luft og 61 % udnyttelse på en 1920-skærm.
   Bredden er IKKE appens egen: `.skal` sætter ingen `max-width`, og øen er i
   forvejen `tema-oe-fuld`. Den kom af `.tema-indhold`s polstringsformel
   `max(gutter, (100% - --bredde-side) / 2)`, som ved 1440 er (1440−1180)/2 =
   130 px i hver side og ved 1920 er 370 px. Fladen fulgte altså facit —
   `--bredde-side` er tokenlagets «ydre indholdsbredde i cockpit og kundeflader»
   (spec/12 l.384) — men ejeren har afgjort, at et ARBEJDSVÆRKTØJ skal bruge
   skærmen. Spec-ordlyden rettes af kuratorvindue 7 bagefter (Backends #276);
   fundet står i `spec-delta/k36b.md`.

   KUNDEFLADERNE RØRES IKKE. Tokenen står uændret, den bare `.tema-indhold`
   beholder sin formel i alle tre lag, og booking-, webshop- og forsiden er
   urørte. Klassen sættes af SKABELONEN gennem layoutets `sideklasse`-blok,
   ordret som `.tema-side--flowramme` og `.tema-side--portalflade` — og den
   hænger KUN på `cockpit.hubl.html`.

   POLSTRINGEN FALDER HELT BORT, ikke bare den vandrette: `padding-block` lagde
   et bånd over cockpittets egen topbjælke, og værktøjet skal starte i sidens
   top. Luften forsvinder ikke — appens `.skal__indhold` bærer allerede
   `padding: var(--sp-5)` med sine egne brydepunkter (`skal.css`). BAGGRUNDEN
   SÆTTES IKKE HER: `.skal` bærer selv `background: var(--flade-svag)` og fylder
   nu hele fladen, så `body`s grå ikke længere ses igennem. */
.tema-side--vaerktoejsflade .tema-indhold {
  padding: 0;
}

/* --- Samtykkebanneret (K20; E16-S13, KR-SY-142) --------------------------- */

/* BANNERET ER FASTGJORT I BUNDEN OG IKKE EN MODAL OVERLEJRING.
   S8 §2.9: bookingfladen «må fungere fuldt ud uden samtykke til sporing».
   Der er derfor ingen mørk bagflade, ingen fokusfælde og intet, der spærrer
   siden — kunden kan læse, rulle og booke, mens banneret står.

   `z-index` er springlinkets (100) plus ét: banneret må ligge over sidens
   indhold, men aldrig over det springlink, en tastaturbruger rammer først. */
.tema-cookiesamtykke__baand {
  padding-block: var(--sp-2);
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  background: var(--dk-bordeaux);
}

/* BÅNDET STÅR PÅ BORDEAUX SOM SIDEFODEN — det er dens sidste linje, ikke et
   fremmed element under siden. Båndet BÆRER `.paa-moerk` (BUG-1269). Her stod,
   at det bevidst ikke gjorde, fordi knappen bar ringen selv — men så vandt
   tokenlagets `.knap[data-rolle="tekst"]` (0,2,0, lys flades #B80031) over
   `.tema-cookiesamtykke__skift` (0,1,0) nedenfor, og «Cookieindstillinger»
   stod 2,4:1 på bordeaux. Med `.paa-moerk` gælder tokenlagets
   `.paa-moerk .knap[data-rolle="tekst"]` (0,3,0, hvid, 16,57:1). Farven
   nedenfor bliver stående som dokumentation af hensigten; den vinder ikke.

   SELEKTORERNE NÆVNER IKKE KOMPONENTKLASSEN, OG DET ER EN MÅLT BESLUTNING.
   Knapperne bærer designsystemets `knap` i markuppen — men skrives klassen
   HER i temaets eget ark, får `findUstyledeKomponenter` (tokenkoblingens
   mutationsprøve) en regel at finde, også når tokenlaget er faldet tilbage til
   spec/12, som ingen komponentregler har. Prøven «tokenlaget skiftes til
   fald-tilbage-formen → rød ved navn på .knap» blev grøn på en grå Arial-knap.
   Temaets egne klasser justerer derfor kun det, der er temaets — mål, farve på
   mørk flade og understregning. */
.tema-cookiesamtykke__skift {
  min-height: var(--min-maalflade);
  padding-inline: 0;
  color: var(--paa-moerk-tekst);
  font: var(--type-broed-s);
  text-decoration: underline;
}

.tema-cookiesamtykke__skift:focus-visible {
  outline: var(--fokus-moerk);
  outline-offset: var(--fokus-offset);
}

.tema-cookiebanner {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 101;
  box-sizing: border-box;
  padding-block: var(--sp-4);
  padding-inline: max(var(--sp-4), calc((100% - var(--bredde-side)) / 2));
  background: var(--dk-hvid);
  color: var(--tekst-primaer);
  border-block-start: var(--kant-komponent);
  box-shadow: var(--skygge-loeftet);
}

.tema-cookiebanner__titel {
  margin: 0 0 var(--sp-2);
  font: var(--type-display-s);
  text-transform: uppercase;
  letter-spacing: var(--label-spacing);
}

.tema-cookiebanner__tekst {
  margin: 0 0 var(--sp-4);
  max-width: var(--bredde-tekst);
  font: var(--type-broed-s);
}

/* KNAPPERNE OMBRYDER OG FALDER ALDRIG UD AF SKÆRMEN (S13 afsnit 6.2, A7:
   betjenbar ved 320 px uden tovejsscroll). `flex-wrap` er hele svaret —
   ingen af de tre led forsvinder ved et brydepunktskift, de lægger sig bare
   under hinanden. */
.tema-cookiebanner__valg {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
}

/* Målfladen sikres på temaets egen klasse og ikke på komponentklassen — se
   noten ved `.tema-cookiesamtykke__skift`. */
.tema-cookiebanner__knap {
  min-height: var(--min-maalflade);
}

.tema-cookiebanner__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--min-maalflade);
  font: var(--type-broed-s);
}

/* --- Brydepunkterne ------------------------------------------------------- */

/* SIDST I FILEN, OG DET ER EN RETTELSE. En @media-forespørgsel tilføjer INGEN
   specificitet: `@media (min-width: 600px) { .tema-brandhoved { … } }` og
   `.tema-brandhoved { … }` vejer nøjagtig det samme, og så er det
   kilderækkefølgen, der afgør. Blokkene stod før sidehovedets og sidefodens
   egne regler, så basislaget vandt fra 600 px og op: sidehovedet beholdt
   16 px lodret og 16 px gutter i stedet for designets 24/32. Målt, da
   kolonneflugtningen blev bundet med en prøve — de to flader havde de samme
   værdier i hver sit lag, men i modsat rækkefølge. Nu står hvert brydepunkt
   efter alt det, det skal overskrive.

   Tallene står literalt, fordi var() ikke virker i en @media-forespørgsel
   (S13 afsnit 6.1). De er tokenlagets --bp-tablet (600) og --bp-desktop
   (1024), og prøven `brydepunkterne følger tokenlaget` i
   test/tokenlag.test.ts afviser et tal, der ikke svarer til et --bp-*.

   INGEN FUNKTION FALDER BORT VED ET SKIFT (S13 afsnit 6.2). Det, der ændrer
   sig herunder, er udelukkende luft. */

@media (min-width: 600px) {
  /* Designleverancens sidehoved er `padding:20px 32px`. 24 px (--sp-5) er
     skalaens nærmeste lodrette mål, og 32 px (--sp-6) er den vandrette gutter
     ORDRET. Mobil beholder 16 px, som designets tre mobilrammer selv bruger.
     Den vandrette formel er den SAMME i de tre flader — det er den, der holder
     dem i én kolonne. */

  .tema-indhold {
    padding-block: var(--sp-6);
    padding-inline: max(var(--sp-6), calc((100% - var(--bredde-side)) / 2));
  }

  .tema-brandhoved {
    padding-block: var(--sp-5);
    padding-inline: max(var(--sp-6), calc((100% - var(--bredde-side)) / 2));
  }

  /* TOPBJÆLKEN BLIVER ÉN RÆKKE, som designet viser den. Under --bp-tablet
     brød rækken, og søgefeltet stod på sin egen linje; her står de tre celler
     side om side, og søgefeltet tager pladsen imellem. INGEN funktion falder
     bort ved skiftet (S13 §6.2) — de samme tre flader står der, i den samme
     rækkefølge. */

  .tema-topbar {
    flex-wrap: nowrap;
    padding-inline: max(var(--sp-6), calc((100% - var(--bredde-side)) / 2));
  }

  /* MOBILENS LINJESKIFTER FALDER BORT SAMMEN MED OMBRYDNINGEN. Uden denne
     linje ville pseudo-elementets `flex-basis: 100%` blive et fjerde felt i en
     `nowrap`-række og klemme de fire rigtige celler sammen. */
  .tema-topbar::before {
    display: none;
  }

  /* SKILLESTREGEN HØRER TIL ÉN RÆKKE, OG DERFOR STÅR DEN HER (brugertesten
     24/8, fund 55). `border-right` stod i basislaget, og på telefon bryder
     rækken: attraktionsvælgeren står ALENE på linje 1 med `flex: 1 1 auto` og
     fylder den, mens billetblokken er skubbet ned på sin egen linje. Kanten
     blev dermed en løs, lodret hårstreg i rækkens højre ende — målt i
     skærmbilledet ved x=358 fra y=0 til y=47, i `--dk-graa-300` — med
     topbjælkens polstring som hvid strimmel derude til skærmkanten ved x=375.
     Den skilte ingenting og lignede en halvfærdig bjælke; testeren kunne selv
     kun se, at striben var der, ikke hvad den var.

     Fra --bp-tablet er rækken `nowrap`, og kanten skiller igen dét, den blev
     skrevet til: vælgeren fra søgefeltet. Under brydepunktet er der ingen
     skillestreg at savne — den røde billetblok er en FYLDT flade og skelnes
     på den, præcis som dens egen note siger om understregningen. */
  .tema-topbar__attraktion {
    order: 1;
    flex: none;
    border-right: 1px solid var(--dk-graa-300);
  }

  /* DESKTOPBÅNDET ER TILBAGE. Basislaget strammede cellen for at få hele
     pladsholderen med på 375 px (fund 14); her er der rigelig plads, og
     tokenlagets egne mål gælder igen. */
  .tema-topbar__soeg {
    order: 2;
    flex: 1 1 auto;
    gap: var(--sp-3);
    padding-inline: var(--sp-5);
    border-top: 0;
  }

  .tema-topbar__billet {
    order: 3;
  }

  /* SPROGFANEN BLIVER LODRET (design l.671; P1's A4). Designets fane står i
     topbjælkens højre kant med teksten drejet en kvart omgang — `vertical-rl`
     er designleverancens egen erklæring. Polstringen bytter akse med den:
     designets 13/8 px bliver `--sp-3` på tekstens langside og `--sp-2` på
     dens tværside.

     MÅLFLADEN FØLGER MED I DREJNINGEN. `min-height` holdt fanen 44 px høj i
     den vandrette form; lodret er højden fanens LANGSIDE, og målfladen nås
     dermed af sig selv, mens bredden er designets ~30 px. Se noten ved
     basislaget om, hvorfor tværaksen ikke kan nå 44 px. */
  .tema-topbar__sprogfane {
    order: 4;
    writing-mode: vertical-rl;
    padding: var(--sp-3) var(--sp-2);
    /* Række 2 findes ikke her, og dens overkant skal derfor heller ikke. */
    border-top: 0;
  }

  .tema-sidefod {
    padding-block: var(--sp-7);
    padding-inline: max(var(--sp-6), calc((100% - var(--bredde-side)) / 2));
  }

  /* RAMMENS BÅND FØLGER KORTETS EGEN RYTME (design l.674/679/699/1066:
     32 px vandret på alle bånd). Under brydepunktet er det 16 px, som
     designets mobilrammer selv bruger. Kolonnen — `--bredde-side` — er
     uændret; det er polstringen INDE i den, der vokser. */
  .tema-side--flowramme .tema-topbar,
  .tema-side--flowramme .tema-brandhoved {
    padding-inline: var(--sp-6);
  }

  /* Systemsidernes kort får designets desktopgutter, og knappen står i sin
     egen bredde. INGEN funktion falder bort — kun luften ændrer sig
     (S13 afsnit 6.2). */
  .tema-medlemsside__formular {
    padding: var(--sp-6);
  }

  .tema-medlemsside__formular input[type="submit"],
  .tema-medlemsside__formular button[type="submit"] {
    width: auto;
  }
}

@media (min-width: 1024px) {
  /* Kun luften over og under vokser. Den vandrette formel står fast, fordi det
     er den, der holder kolonnen på linje med sidehoved og sidefod. */
  .tema-indhold {
    padding-block: var(--sp-7);
  }
}
