/* ==========================================================================
   Projektstyring — designsystem
   Soft UI / macOS-inspireret. Skygger > borders, bløde hjørner, varm baggrund.
   ========================================================================== */

/* ⚠️ FAVICONETS FARVER HØRER IKKE TIL HER, OG SKAL IKKE FLYTTES HERIND.

   `static/favicon.svg` og `static/apple-touch-icon.png` bærer fire faste
   værdier — #23262F, #FFFFFF, #5B8DEF og en hvid på 65 % — som IKKE er
   designtokens. De er et MÆRKE, ikke en flade, og de er MIDLERTIDIGE: hele
   designprofilen skal lægges om, og ikonet tegnes forfra i den omgang.

   Det er derfor de ikke står som variabler nedenfor. Et ikon der arvede
   `--color-accent` ville skifte udseende hver gang nogen justerede en
   knapfarve — og en fane- og bogmærkegrafik skal netop ligge stille, fordi
   den er dét brugeren genkender appen på. Går man den anden vej og
   "harmoniserer" de fire værdier ind i tokensættet, binder man to ting
   sammen der skal kunne ændres hver for sig.

   ⚠️ SVG'en kan ikke læse CSS-variabler herfra alligevel: den hentes som et
   selvstændigt dokument af browserens ikon-loader, uden for sidens kaskade.
   Et forsøg på at token-styre den ville ikke fejle — farven ville bare falde
   tilbage til ingenting. */

:root {
  color-scheme: light;

  /* ---- Accent (petrolgrøn — erstatter rød) ---- */
  --color-accent:          #0E5C51;
  --color-accent-hover:    #0B4A41;
  --color-accent-soft:     #E5F0EE;
  --color-accent-border:   #9EC4BC;   /* kant på sekundære knapper */
  --color-on-accent:       #FFFFFF;   /* tekst/ikon oven på accent-flader */

  /* ⚠️ ACCENT SOM TEKST ER ET EGET TOKEN, OG DET ER MØRK TILSTAND DER KRÆVER
     DET. Den fyldte accent i mørkt tema (#2E9C86) er for mørk til at bære
     12-13px tekst på #171D1B. Her i lyst tema peger navnet tilbage på fladen,
     så EN regel kan skrive var(--color-accent-text) og ramme rigtigt i begge
     temaer. Sættes den til en hexværdi her, forsvinder hele pointen. */
  --color-accent-text:     var(--color-accent);

  /* Milepæle i Gantt — adskilt fra både accent og "i dag"-linjen */
  --color-milepael:      #C9A227;
  --color-milepael-soft: rgba(201, 162, 39, 0.16);

  /* ⚠️ INFORMATION ER IKKE EN FEJL — OG SKAL IKKE SE UD SOM ÉN.
     `.info-besked` brugte `--color-accent-soft`, altså dengang en RØD tone,
     selvom den bærer vejledning: "Ingen faser defineret for Butiksprojekt
     endnu — gå til Faseopsætning". Egne tokens frem for at låne
     milepælsfarven, så en senere ændring af Gantt-farven ikke flytter
     betydningen af en informationsboks. Bemærk at accenten ikke længere er
     rød — men adskillelsen står ved magt, for lånte farver flytter stadig
     betydning når kun den ene ende ændres. */
  --color-info:          #4E7FD6;
  --color-info-soft:     rgba(78, 127, 214, 0.10);

  /* ---- Flader ---- */
  --color-bg:              #F5F7F7;   /* app-lærred */
  --color-surface:         #FFFFFF;   /* kort, tabel, inputs */
  --color-surface-2:       #F3F6F5;   /* tabelhoved, sidefane */
  --color-surface-3:       #EBEFEE;   /* segmenteret kontrol, spor */

  /* ---- Tekst ---- */
  --color-text-primary:    #10201D;
  --color-text-secondary:  #6B7772;
  --color-text-muted:      #8B958F;
  --color-text:            #10201D;   /* alias brugt enkelte steder */

  /* ---- Kanter ---- */
  --color-border:          #E4E9E8;   /* kort- og sektionskant */
  --color-border-strong:   #DFE5E4;   /* ydre kant mod lærredet */
  --color-row-border:      #EEF2F1;   /* linje mellem tabelrækker */
  --color-row-hover:       #F6FAF9;   /* rækkehover */
  --color-border-focus:    #0E5C51;
  --focus-ring:            0 0 0 3px rgba(14, 92, 81, 0.22);

  /* ---- Sidefane (ingen egen palet længere — peger på fladerne) ----

     ⚠️ DEN DÆMPEDE AKTIV-MARKERING ER OPHÆVET HER, OG DET ER BEVIDST.
     Tidligere var --color-accent og --color-red den SAMME hexværdi (#e4202c),
     og derfor måtte det aktive menupunkt ikke være en accentflade: det ville
     have konkurreret med stoplyset, RAG-status og heatmappets rød, hvor rød
     bærer et budskab. Den præmis gælder ikke længere — accenten er petrolgrøn
     og rød er skilt ud som ren destruktiv/RAG-farve. Aktiv må derfor gerne
     bære accent igen.

     ⚠️ Til gengæld deler aktiv og hover ikke længere farve, så skriftvægten
     er ikke længere det eneste der skiller dem. De tre `.active`-regler sætter
     stadig 600 — lad dem stå, de skader ikke. Rettes disse tokens, så ret
     BEGGE temaer; værdierne står to steder. */
  --sidebar-bg:            var(--color-surface-2);
  --sidebar-text:          #4B5854;
  --sidebar-text-muted:    #79857F;
  --sidebar-brand:         var(--color-text-primary);
  --sidebar-hover-bg:      #E8EEEC;
  --sidebar-hover-text:    var(--color-text-primary);
  --sidebar-active-bg:     var(--color-surface);
  --sidebar-active-text:   var(--color-accent);
  --sidebar-border:        var(--color-border);

  /* ---- Status / RAG ---- */
  --color-green:           #3FA98F;
  --color-blue:            #4E7FD6;   /* igangværende, milepælslinje */
  --color-yellow:          #DB9A2E;
  --color-grey:            #9AA6A2;   /* ikke startet */
  --color-red:             #C4776B;   /* kun destruktiv + RAG-rød */
  --rag-green-soft:        rgba(63, 169, 143, 0.16);
  --rag-yellow-soft:       rgba(219, 154, 46, 0.18);
  --rag-red-soft:          rgba(196, 119, 107, 0.16);

  /* ---- Status-badges ---- */
  --badge-neutral-bg:   #EEF2F1;  --badge-neutral-text:   #5D6A65;
  --badge-progress-bg:  #E7EEFA;  --badge-progress-text:  #2F5AA8;
  --badge-hold-bg:      #FAF1DF;  --badge-hold-text:      #8F6516;
  --badge-done-bg:      #E5F0EE;  --badge-done-text:      #0E5C51;
  --badge-cancelled-bg: #F6E9E7;  --badge-cancelled-text: #8F4A3F;
  --badge-followup-bg:  #FAF1DF;  --badge-followup-text:  #8F6516;

  /* ---- Skygger: afskaffet. Fladerne afgrænses af én tynd kant i stedet.
         ⚠️ NAVNENE BEHOLDES OG SÆTTES TIL none — de bruges 48 steder i
         filen, og en sletning her ville lade hver af dem falde tilbage til
         ingenting UDEN at nogen kunne se hvilke der manglede en kant. De
         fjernes én komponent ad gangen, og navnet er kvitteringen for at
         komponenten endnu ikke er gennemgået. ---- */
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: none;
  /* ⚠️ GRÆNSEN GÅR VED OVERLAY, IKKE VED "MODAL".
     --shadow-modal bruges af alt der ligger OVEN PÅ siden og ikke i dens flow:
     .modal, .th-filter-dropdown, .afh-dropdown, .klokke-dropdown,
     .bruger-dropdown og Gantt'ens .popup-wrapper. Flader i flowet — kort,
     paneler, tabeller, statuskort — får kant alene og ingen skygge.
     Grænsen er ikke hentet fra ingenting: handoffens afsnit 5 giver selv
     .popup-wrapper en --shadow-modal, altså en popover og ikke en modal. En
     hårfin kant er nok til at adskille to flader der ligger ved siden af
     hinanden, men ikke til at adskille en flade der SVÆVER over en anden —
     dér er der ingen kant at læse dybden ud af. */
  --shadow-modal: 0 24px 60px rgba(16, 32, 29, 0.18);  /* overlays, se noten */

  /* ---- Border-radius ---- */
  --radius-xs:   5px;    /* knapper i tabelrækker */
  --radius-sm:   7px;    /* knapper, inputs */
  --radius-md:   8px;    /* kort, paneler, sektioner */
  --radius-lg:   10px;   /* modaler, ydre rammer */
  --radius-pill: 999px;  /* badges, tags */

  /* ---- Afstande (4px-grid) ---- */
  --space-05:  4px;
  --space-1:   8px;
  --space-15: 12px;
  --space-2:  16px;
  --space-3:  24px;
  --space-4:  32px;
  --space-6:  48px;

  /* ---- Typografi ---- */
  /* ⚠️ DISSE TO TOKENS ER ERKLÆRET, MEN BRUGES IKKE — OG DE MÅ IKKE TAGES I
     BRUG SOM DE STÅR. Hverken "Public Sans" eller "IBM Plex Mono" indlæses af
     nogen side; appen kører på Inter, som ER hentet (`body`, længere nede).
     Skriver nogen `font-family: var(--font-sans)`, skifter hele fladen derfor
     tavst til system-skrifttypen — den ser plausibel ud, og ingen test i huset
     læser CSS. Skal de bruges, skal skrifttypen først indlæses i alle sider;
     ellers ret værdien til Inter, så navnet passer til det der faktisk sker. */
  --font-sans: "Public Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;   /* kun tal/koder hvis ønsket */
  --fs-h1:     24px;
  --fs-h2:     20px;
  --fs-h3:     15px;
  --fs-body:   14px;
  --fs-sm:     13px;
  --fs-xs:     12.5px;
  --fs-label:  11px;

  /* ---- Layout-mål ---- */
  --sidebar-width: 224px;
  --topbar-height: 54px;
  --row-height:      36px;   /* tabelrække, projektliste */
  --row-height-tal:  40px;   /* Gantt-række */

  /* ---- Transitions ---- */
  --transition-fast: 0.12s ease;
  --transition-base: 0.18s ease;
}

/* ---------- Mørkt tema: samme tokens, mørk petroltonet palette ----------

   ⚠️ SELEKTOREN ER BEVIDST TO. `auth-ui.js` sætter klassen på BÅDE
   documentElement og body, og head-scriptet på hver side sætter kun
   html-klassen (mod flash). `body.dark`-halvdelen er ikke overflødig: den
   bærer også `body.dark .sh-projekt-header` længere nede i filen. Skrives
   dette om til `html.dark` alene, falder den halvdel ud.

   ⚠️ Tokens der IKKE står her, arver med vilje fra :root: skyggerne (none),
   --color-milepael-soft, --color-info-soft og de tre --rag-*-soft. De fire
   sidste er rgba og virker på mørk bund, men er blødere end de værdier temaet
   havde før. Skal de være kraftigere, hører de hjemme her — ikke i :root. */
:root.dark,
body.dark {
  color-scheme: dark;

  --color-accent:          #2E9C86;   /* fyldte flader */
  --color-accent-hover:    #3FB89E;
  --color-accent-text:     #6FD3BC;   /* accent BRUGT SOM TEKST på mørk bund */
  --color-accent-soft:     #1B2926;
  --color-accent-border:   #33403C;
  --color-on-accent:       #08110F;

  --color-milepael:        #C9A227;

  /* Se noten i :root — information må ikke låne en anden betydnings farve. */
  --color-info:            #7C9CF5;

  --color-bg:              #131816;
  --color-surface:         #171D1B;
  --color-surface-2:       #1A211F;
  --color-surface-3:       #242E2B;

  --color-text-primary:    #E6EDEA;
  --color-text-secondary:  #8A968F;
  --color-text-muted:      #7C8A85;
  --color-text:            #E6EDEA;

  --color-border:          #232B28;
  --color-border-strong:   #242C29;
  --color-row-border:      #1F2724;
  --color-row-hover:       #1C2422;
  --color-border-focus:    #2E9C86;
  --focus-ring:            0 0 0 3px rgba(46, 156, 134, 0.30);

  /* --sidebar-bg, --sidebar-brand, --sidebar-hover-text og --sidebar-border
     peger i :root på flade- og tekst-tokens og følger derfor temaet af sig
     selv. Kun de fire med egne værdier står her. */
  --sidebar-text:          #98A5A0;
  --sidebar-text-muted:    #6E7C77;
  --sidebar-hover-bg:      #1E2624;
  --sidebar-active-bg:     #1B2926;
  --sidebar-active-text:   #6FD3BC;

  --color-green:           #4FBFA2;
  --color-blue:            #7C9CF5;
  --color-yellow:          #E0A63F;
  --color-grey:            #6E7887;
  --color-red:             #E08A7E;

  --badge-neutral-bg:   #212927;  --badge-neutral-text:   #A9B4AF;
  --badge-progress-bg:  #1C2433;  --badge-progress-text:  #9DB4F0;
  --badge-hold-bg:      #2A2418;  --badge-hold-text:      #E0BE72;
  --badge-done-bg:      #1B2926;  --badge-done-text:      #6FD3BC;
  --badge-cancelled-bg: #2C201E;  --badge-cancelled-text: #E0A398;
  --badge-followup-bg:  #2A2418;  --badge-followup-text:  #E0BE72;

  --shadow-modal: 0 24px 60px rgba(0, 0, 0, 0.55);
}

/* ---------- Reset / base ---------- */

* {
  box-sizing: border-box;
}

/* Genopretter [hidden]'s native display:none. UA-stilarket taber altid mod
   forfatter-CSS uanset specificitet, så ethvert element med en klasse der
   sætter display (fx .nav-item, .nav-doc, .nav-subitem) ville ellers forblive
   synligt selvom hidden-attributten er sat (kun .modal-overlay havde en lokal
   rettelse for dette — nu gælder det globalt, så data-krav-skjulning i
   auth-ui.js virker for ALLE elementer). */
[hidden] {
  display: none !important;
}

html, body {
  height: 100%;
}

body {
  margin: 0;
  font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  font-size: 14px;
  font-weight: 400;
  color: var(--color-text-primary);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p {
  margin: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ---------- Faste bannere øverst (emulering, preprod) ---------- */

/* Fælles sticky wrapper for alle top-bannere (auth-ui.js opretter/fylder den).
   KUN denne er sticky — de enkelte bannere er almindelige flex-børn i den, så
   flere bannere stakker naturligt i stedet for at overlappe hinanden (hvilket
   ville ske hvis hvert banner selv var "position: sticky; top: 0"). auth-ui.js
   sætter --top-banner-height på :root ud fra denne wrappers reelle højde, som
   .sidebar nedenfor bruger til at undgå at blive dækket af bannerne. */
#top-banners {
  position: sticky;
  top: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
}

.top-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 10px var(--space-3);
  background: #f0a01e;               /* distinkt amber — umuligt at overse, i begge temaer */
  color: #1a1a1a;
  font-size: 14px;
  font-weight: 600;
  /* Kanten er mørk og ikke --color-border: banneret har sin egen amber flade og
     sin egen mørke tekst, så husets lyse kantfarve ville forsvinde i den. */
  border-bottom: 1px solid rgba(0, 0, 0, 0.18);
}

.emulering-tekst {
  letter-spacing: 0.01em;
}

/* Informativ (ikke en advarsel som emulering/preprod), derfor en rolig blå i
   stedet for amber — og whiteSpace: pre-line så admin kan bruge linjeskift i
   beskeden (fx tidspunkt på egen linje). */
.vedligeholdelse-banner {
  background: #2563a8;
  color: #ffffff;
  white-space: pre-line;
  text-align: center;
}

.emulering-stop {
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: #1a1a1a;
  background: rgba(0, 0, 0, 0.10);
  border: 1px solid rgba(0, 0, 0, 0.35);
  border-radius: var(--radius-sm);
  padding: 4px 12px;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.emulering-stop:hover {
  background: rgba(0, 0, 0, 0.20);
}

/* ---------- App-skelet: sidebar + topbar + indhold ---------- */

.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  /* Kanten ALENE afgrænser sidefanen mod indholdet — skyggen er væk. Den var
     dobbelt afgrænsning allerede dengang, og med --sidebar-bg nu på
     --color-surface-2 er der desuden et fladeskift at se forskellen på. */
  border-right: 1px solid var(--sidebar-border);
  padding: var(--space-2) 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  /* Fast højde + egen scroll: uden dette stretcher sidebaren sammen med
     .app-shell (min-height: 100vh) når sidens indhold er højere end
     viewporten, og "position: sticky" holder den så på plads i viewporten i
     stedet for at scrolle væk med resten af siden.
     --top-banner-height (sat af auth-ui.js ud fra #top-banners' reelle højde,
     0px hvis ingen bannere vises) trækkes fra/lægges til, så sidebaren aldrig
     starter under eller bliver dækket af emulerings-/preprod-banneret. */
  height: calc(100vh - var(--top-banner-height, 0px));
  position: sticky;
  top: var(--top-banner-height, 0px);
  overflow-y: auto;
}

.sidebar-brand {
  padding: 0 var(--space-2);
  font-size: 15px;
  font-weight: 700;
  color: var(--sidebar-brand);
  text-transform: none;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 var(--space-1);
}

.nav-item {
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 var(--space-2);
  margin: 1px 4px;
  border-radius: var(--radius-md);
  font-size: 14px;
  font-weight: 500;
  color: var(--sidebar-text);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-item:hover {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-hover-text);
}

/* ⚠️ AKTIV OG HOVER DELER IKKE LÆNGERE BAGGRUND. Det gjorde de dengang accent
   og rød var samme hexværdi, og dér var skriftvægten det eneste der skilte dem.
   Nu er aktiv en hvid flade (--color-surface) med accentfarvet tekst mod
   hoverens dæmpede grønne. Vægten på 600 bliver stående alligevel — den koster
   ingenting og holder markeringen læsbar for den der ikke skelner farverne. */
.nav-item.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  font-weight: 600;
}

.nav-item.kommer-snart {
  cursor: default;
  color: var(--sidebar-text-muted);
}

.nav-item.kommer-snart:hover {
  background: none;
  color: var(--sidebar-text-muted);
}

.nav-item-label {
  flex: 1;
}

/* Tabler-ikon foran navigationsteksten — fylder lidt mere visuelt. */
.nav-item-ikon {
  margin-right: 10px;
  font-size: 20px;
  line-height: 1;
  flex-shrink: 0;
}

.nav-item-badge {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--sidebar-text-muted);
  background: var(--sidebar-hover-bg);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
}

.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.topbar {
  height: var(--topbar-height);
  flex-shrink: 0;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  padding: 0 var(--space-3);
  z-index: 1;
}

.topbar-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text-secondary);
}

.content {
  flex: 1;
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* ---------- Typografi ---------- */

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
}

.page-title {
  font-size: var(--fs-h1);
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--color-text-primary);
}

.page-subtitle {
  margin-top: 6px;
  font-size: 14px;
  color: var(--color-text-secondary);
}

h2 {
  font-size: 20px;
  font-weight: 600;
}

h3 {
  font-size: 16px;
  font-weight: 600;
}

.label {
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-secondary);
}

.link {
  color: var(--color-accent-text);
  text-decoration: none;
  font-weight: 500;
  transition: color var(--transition-fast);
}

.link:hover {
  color: var(--color-accent-hover);
  text-decoration: underline;
}

/* ---------- Kort / paneler ---------- */

.card {
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.card > h2 {
  margin-bottom: var(--space-2);
}

.card h3 .badge {
  margin-left: var(--space-1);
  vertical-align: middle;
}

.card h3 {
  margin-bottom: 6px;
}

a.card:hover,
.card.clickable:hover {
  border-color: var(--color-accent-border);
}

/* ---------- Knapper ---------- */

button {
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  background: var(--color-surface-2);
  color: var(--color-text-primary);
  padding: 9px 19px;
  transition: background var(--transition-fast),
              border-color var(--transition-fast),
              color var(--transition-fast);
}

button:hover {
  background: var(--color-border);
}

/* `button:active { transform: translateY(0) }` er fjernet sammen med de
   løft-hovers den nulstillede. Den var ikke en effekt i sig selv — kun
   modtrækket mod translateY(-1px) på submit- og gem-knappen. */

button:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* Primær knap: opret-formularens submit-knap */
form.opret-form button[type="submit"] {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border: none;
  padding: 10px 20px;
}

form.opret-form button[type="submit"]:hover {
  background: var(--color-accent-hover);
}

/* Sekundær knap: redigér / gem / annullér */
button.rediger,
button.annuller {
  background: var(--color-surface);
  color: var(--color-accent-text);
  border: 1px solid var(--color-accent-border);
  padding: 7px 15px;
}

button.rediger:hover,
button.annuller:hover {
  background: var(--color-accent-soft);
}

button.gem {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border: none;
  padding: 8.5px 16.5px;
}

button.gem:hover {
  background: var(--color-accent-hover);
}

/* Destruktiv knap: slet.

   ⚠️ DEN STOD PÅ --color-accent, OG DET VAR ALDRIG "BRANDFARVE" DER VAR MENT.
   Så længe --color-accent og --color-red var samme hexværdi (#e4202c), kunne
   en destruktiv knap skrive accent og alligevel se rød ud. Det var en
   tilfældighed, ikke en beslutning — og den holdt op med at gælde i det
   øjeblik accenten blev petrolgrøn. Uden denne rettelse er husets sletteknap
   grøn. Samme fælde findes i .fejl, .afh-pill-remove, .kommentar-slet og de
   tre advarsels-widgets; alle er rettet til --color-red i samme omgang. */
button.slet {
  background: transparent;
  color: var(--color-red);
  border: none;
  padding: 7px 15px;
}

button.slet:hover {
  background: var(--rag-red-soft);
}

/* ---------- Input / select ---------- */

input,
select {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-size: 14px;
  font-family: inherit;
  background: var(--color-surface);
  color: var(--color-text-primary);
  transition: border-color var(--transition-fast),
              box-shadow var(--transition-fast);
}

/* ⚠️ FOKUSRINGEN ER ET TOKEN NU (--focus-ring), IKKE EN LITERAL.
   Den stod tre steder som `0 0 0 3px var(--color-accent-soft)`. Det virkede
   kun så længe accent-soft var GENNEMSIGTIG; efter omlægningen er den en
   opak flade (#E5F0EE), og en 3px opak ring ville have set ud som en fejl.
   --focus-ring bærer sin egen rgba og sin egen mørke variant. */
input:focus,
select:focus {
  border-color: var(--color-border-focus);
  box-shadow: var(--focus-ring);
  outline: none;
}

/* ---------- Formular: opret ny ressource ---------- */

form.opret-form {
  display: flex;
  gap: var(--space-2);
  align-items: flex-end;
  flex-wrap: wrap;
}

form.opret-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-secondary);
}

form.opret-form input,
form.opret-form select {
  min-width: 180px;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}

/* ---------- Projektside: klikbare rækker + kompakte tabel-inputs ---------- */

tbody tr.klikbar-raekke {
  cursor: pointer;
}

td input,
td select {
  width: 100%;
  min-width: 90px;
  padding: 6px 8px;
}

td input[type="number"] {
  min-width: 70px;
}

/* Inline-redigerbare celler. Klik aktiverer redigering direkte i cellen.
   Brugt to steder, og klasserne er derfor IKKE opgavetabellens private:
   - opgavetabellen — Fase, Område, Tovholder, Start, Slut, % fremdrift
     (opsaetEditerbareCeller i projekt.js)
   - skabelonlisten — navn og beskrivelse (celleTilInput i skabeloner.js)
   Ændres de her, ændres begge steder. */
.celle-editerbar {
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.celle-editerbar:hover {
  background: var(--color-accent-soft);
}
.celle-redigeres {
  cursor: default;
  background: none;
}
.celle-redigeres:hover {
  background: none;
}

/* Tovholderen er siddende, men ikke på projektets team (018b) — en VISNING,
   ikke en spærre. Opgaven kan stadig gemmes, og den siddende tovholder falder
   aldrig ud af dropdownen (tovholdervalg.js). Forsvinder når hun tilføjes på
   Team-fanen, uden genindlæsning. */
.tovholder-udenfor-team {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Ansvarlig (021) — samme regel og samme begrundelse som Tovholder ovenfor,
   bare et andet felt (Task.ansvarlig_user_id). */
.ansvarlig-udenfor-team {
  color: var(--color-text-muted);
  font-style: italic;
}

/* ---------- % færdig-slider ---------- */

.procent-slider {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.procent-slider input[type="range"] {
  width: 100%;
  min-width: 90px;
  padding: 0;
  accent-color: var(--color-accent);
}

.procent-vaerdi {
  min-width: 38px;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-text-secondary);
  text-align: right;
}

form.opret-form .procent-slider {
  min-width: 180px;
}

/* Afhængigheds-dropdown i opgavetabellen */
.afh-select {
  min-width: 120px;
  max-width: 160px;
  font-size: 12px;
  padding: 4px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
}

.afh-select:focus {
  border-color: var(--color-border-focus);
  box-shadow: var(--focus-ring);
  outline: none;
}

/* ---------- Projektside: to-kolonne layout (tabel + Gantt) ---------- */

.projekt-layout {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

.projekt-kolonne-tabel {
  flex: 1 1 55%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.projekt-kolonne-gantt {
  flex: 1 1 45%;
  min-width: 0;
}

.gantt-card {
  position: sticky;
  top: var(--space-3);
}

.gantt-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-2);
  gap: var(--space-2);
}

.gantt-toolbar h2 {
  margin-bottom: 0;
}

/* Zoomknapperne var tre selvstændige omridsknapper med accentfyld på den
   aktive. De er nu SAMME segmenterede kontrol som .view-toggle — se noten
   dér for hvorfor det aktive segment ikke fyldes med accent. Sporet ligger på
   .gantt-zoom-knapper, så knapperne selv er flade. */
.gantt-zoom-knapper {
  display: flex;
  gap: 0;
  background: var(--color-surface-3);
  border-radius: var(--radius-md);
  padding: 3px;
}

.gantt-zoom-knap {
  background: transparent;
  color: var(--color-text-secondary);
  border: none;
  border-radius: var(--radius-sm);
  padding: 7px 14px;
  font-size: var(--fs-sm);
}

.gantt-zoom-knap:hover {
  background: transparent;
  color: var(--color-text-primary);
}

.gantt-zoom-knap.aktiv {
  background: var(--color-surface);
  color: var(--color-text-primary);
}

#gantt {
  overflow-x: auto;
}

@media (max-width: 1100px) {
  .projekt-layout {
    flex-direction: column;
  }

  .gantt-card {
    position: static;
  }
}

.projekt-meta {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: 6px;
  font-size: 14px;
  color: var(--color-text-secondary);
}

.tilbage-link {
  display: inline-block;
  margin-bottom: var(--space-1);
  font-size: 13px;
  font-weight: 500;
  color: var(--color-accent-text);
}

.tilbage-link:hover {
  text-decoration: underline;
}

/* ---------- Tabel ---------- */

.table-card {
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

table {
  width: 100%;
  border-collapse: collapse;
}

thead {
  background: var(--color-surface-2);
  border-bottom: 1px solid var(--color-border);
}

th {
  text-align: left;
  padding: 10px var(--space-15);
  font-size: var(--fs-label);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--color-text-secondary);
}

/* Højde frem for lodret padding: rækken skal være 36px UANSET om cellen
   indeholder ren tekst, et badge eller en .btn-xs. Med padding afgjorde det
   højeste element højden, og tabellen fik ujævne rækker. */
td {
  padding: 0 var(--space-15);
  height: var(--row-height);
  border-bottom: 1px solid var(--color-row-border);
  font-size: var(--fs-sm);
  color: var(--color-text-primary);
}

tbody tr:last-child td {
  border-bottom: none;
}

/* Zebrastribningen er væk — linjen mellem rækkerne bærer adskillelsen alene.
   Reglen `tbody tr:nth-child(even)` er SLETTET, ikke sat til transparent:
   en tom regel ville have overskrevet .opgave-raekke-valgt på lige rækker. */

tbody tr:hover {
  background: var(--color-row-hover);
}

td button + button {
  margin-left: 6px;
}

.opgave-raekke-klikbar {
  cursor: pointer;
}

/* Den ENESTE accentfarvede rækkeflade der er tilbage, og det er meningen:
   zebra er væk og hover er neutral, så accenten kan nu bruges til at sige
   "denne række er valgt" uden at konkurrere med noget. */
tbody tr.opgave-raekke-valgt {
  background-color: var(--color-accent-soft);
}

.opgave-kommentar-ikon {
  cursor: pointer;
  font-size: 13px;
  opacity: 0.7;
}
.opgave-kommentar-ikon:hover {
  opacity: 1;
}

/* ---------- Badge / pill (opgavestatus) ---------- */

.badge {
  display: inline-block;
  border-radius: var(--radius-pill);
  padding: 2px 9px;
  font-size: 11.5px;
  font-weight: 600;
}

/* Butiksprocestypen under projekttitlen. ⚠️ EGEN KLASSE, IKKE `.badge`:
   status-badges bærer en TILSTAND der skifter (ikke startet → færdig), mens
   dette er en KLASSIFIKATION der står fast. Genbrugte den samme klasse, ville
   en ændring af statusfarverne flytte betydningen af noget der ikke er en
   status — samme slags forveksling som `--color-accent` på en sletteknap.
   Dæmpet med vilje: badge'et skal kunne ses uden at konkurrere med titlen. */
.butiksproces-badge {
  display: inline-block;
  margin-top: 2px;
  border-radius: var(--radius-pill);
  padding: 2px 10px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--color-surface-2);
  color: var(--color-text-secondary);
}

.badge-ikke-startet   { background: var(--badge-neutral-bg);  color: var(--badge-neutral-text); }
.badge-igangvaerende  { background: var(--badge-progress-bg); color: var(--badge-progress-text); }
.badge-ophold         { background: var(--badge-hold-bg);     color: var(--badge-hold-text); }
.badge-faerdig        { background: var(--badge-done-bg);     color: var(--badge-done-text); }
.badge-udgaar         { background: var(--badge-cancelled-bg); color: var(--badge-cancelled-text); }
.badge-opfoelgning    { background: var(--badge-followup-bg); color: var(--badge-followup-text); }
.badge-uaktuel        { background: var(--badge-neutral-bg);  color: var(--badge-neutral-text); }

/* ---------- Cutoverplan ---------- */

.cutover-th-traek {
  width: 28px;
}

.cutover-traek-haandtag {
  cursor: grab;
  color: var(--color-text-muted);
  text-align: center;
  user-select: none;
}

.cutover-raekke-traekbar {
  cursor: default;
}

.cutover-traekkes {
  opacity: 0.5;
}

.cutover-drop-target {
  box-shadow: inset 0 2px 0 var(--color-accent);
}

.cutover-celle {
  cursor: text;
}

.cutover-celle:hover {
  background: var(--color-surface-2);
}

.cutover-inline-input {
  width: 100%;
  border: 1px solid var(--color-accent);
  border-radius: 4px;
  padding: 4px 6px;
  font: inherit;
  background: var(--color-bg);
  color: var(--color-text-primary);
}

/* ---------- Cutover-planens hoved (datoen for selve cutoveren) ---------- */

.cutover-plan-hoved {
  display: flex;
  align-items: center;
  gap: var(--space-2, 8px);
  flex-wrap: wrap;
  padding: 0 0 var(--space-3, 12px);
}

.cutover-plan-hoved label {
  font-weight: 600;
  color: var(--color-text-secondary);
}

.cutover-plan-dato {
  border: 1px solid var(--color-border);
  border-radius: 4px;
  padding: 4px 6px;
  font: inherit;
  background: var(--color-bg);
  color: var(--color-text-primary);
}

.cutover-plan-dato:disabled {
  opacity: .45;
  cursor: not-allowed;
}

.cutover-plan-hint {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Butiksdokumenter (016): "Uploader …"-status og "Slettet efter 90 dage" i
   tabellen — samme dæmpede stil som cutoverens antydning ovenfor. */
.dokumenter-status {
  color: var(--color-text-muted);
  font-style: italic;
}

/* ⚠️ EN ANTYDNING, IKKE EN VÆRDI — OG FORSKELLEN SKAL KUNNE SES UDEN AT KLIKKE.
   Cellen viser cutoverens dato når opgaven ikke har sin egen. To tilstande
   der ligner hinanden er præcis den tvetydighed "valgt men ikke gemt" kostede
   fire målerunder i opgavetabellen, så forskellen bæres af TRE ting samtidig
   og ikke af farve alene: parenteser om teksten (i JS), kursiv, og dæmpet
   farve. Dertil en `title` der siger det med ord.

   ⚠️ Brug ikke --color-text-secondary her: den er husets almindelige
   sekundærtekst og bruges til rigtige værdier andre steder i tabellen.
   --color-text-muted er svagere, og det er netop pointen. */
.cutover-dato-antydet {
  color: var(--color-text-muted);
  font-style: italic;
}

.modal-fieldset {
  border: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* .modal-form label sætter flex-direction: column — denne selektor skal være
   mere specifik for at slå det fra igen på radioknap-rækken.

   ⚠️ DEN KOLLISION ER SKET IGEN I 2.9 (`.modal-form .paamind-type`), og det
   er derfor et MØNSTER og ikke et enkelttilfælde: enhver ny label i en
   modal-formular der vil have noget ved SIDEN af sin tekst — radioknap,
   afkrydsningsfelt, ikon — arver `column` og stakker i stedet. Fejlen er ren
   visning, så ingen test fanger den; den kan kun ses ved at åbne dialogen. */
.modal-form .modal-radio {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  font-weight: 400;
}

.modal-radio input {
  width: auto;
}

/* ---------- Stoplys (portefølje RAG) ---------- */

/* ⚠️ HOVER ER OUTLINE-BREDDE, IKKE scale() OG IKKE FARVE.
   Afsnit 1 i handoffen siger "farveskift alene" som erstatning for transform.
   Det kan prikken ikke bruge: dens FARVE ER STATUSSEN. Skifter grøn farve på
   hover, siger den noget andet end den gør. Gløden er derfor blevet en
   outline (som handoffen foreskriver), og hover udvider den fra 2 til 3px.
   Outline påvirker ikke layout, så rækken hopper ikke. */
.stoplys {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  display: inline-block;
  cursor: pointer;
  transition: outline-width var(--transition-fast);
}

.stoplys:hover {
  outline-width: 3px;
}

.stoplys-groen  { background: var(--color-green);  outline: 2px solid var(--rag-green-soft); }
.stoplys-gul    { background: var(--color-yellow); outline: 2px solid var(--rag-yellow-soft); }
.stoplys-roed   { background: var(--color-red);    outline: 2px solid var(--rag-red-soft); }

/* ---------- Oversigt: dashboard-wrapper + tom-state ---------- */

.dashboard-indhold {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.sektion-titel {
  margin-bottom: var(--space-2);
}

.tom-state {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6) var(--space-4);
  text-align: center;
}

.tom-state-titel {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin-bottom: var(--space-1);
}

.tom-state-tekst {
  font-size: 14px;
  color: var(--color-text-secondary);
  max-width: 460px;
  margin: 0 auto;
}

/* ---------- Oversigt: projekt-status-kort ---------- */

.projekt-status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-2);
}

.projekt-status-kort {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-2);
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.projekt-status-kort:hover {
  border-color: var(--color-accent-border);
}

.psk-top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.psk-top .stoplys {
  cursor: default;
  flex-shrink: 0;
}

.psk-navn {
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.psk-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-1);
  font-size: 12.5px;
  color: var(--color-text-secondary);
}

.psk-bund {
  align-items: baseline;
}

.psk-deadline {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.psk-forsinket {
  flex-shrink: 0;
  font-weight: 600;
  color: var(--color-red);
}

/* ---------- Diverse tilstande ---------- */

/* Se noten ved button.slet: accent BETØD rød her, den var det ikke. */
.fejl {
  color: var(--color-red);
  background: var(--rag-red-soft);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font-size: 14px;
}

/* ⚠️ EN AFVISNING MAN IKKE KAN SE, LIGNER AT DER IKKE SKETE NOGET.
   Sidernes globale fejlboks `#fejl` ligger inde i `main.content` og er
   `position: static` uden z-index. `.modal-overlay` er `position: fixed;
   inset: 0` med `z-index: 1000`. Er en dialog åben, ligger beskeden altså BAG
   den — den skrives, men brugeren ser en dialog der ikke reagerer.

   ⚠️ DET ER MÅLT TO GANGE MED HVER SIT UDFALD, OG DET ER GRUNDEN TIL AT DEN
   LØSES GENERELT HER. Første gang var `629a8ba` (14/8), hvor "Gem" i
   projektsidens dialoger svarede 404 og beskeden landede bag dialogen;
   rettelsen dengang (`sidelaas.js`) lukkede kun projektsidens tilfælde. Anden
   gang var preprod-testen af 2.14.0, hvor en for stor videofil blev afvist
   uden at afvisningen kunne ses. Målt ved den lejlighed: mønstret findes på
   NI sider med 26 modaler i alt.

   Derfor hæves boksen over overlayet, så længe en dialog er åben. Ét sted
   frem for ni — og enhver ny modal er dækket uden at nogen skal huske det.

   ⚠️ `:has()` ER VALGT MED VILJE FREM FOR EN KLASSE PÅ `body`.
   En klasse ville kræve at hver af de 22 JS-filer der åbner en dialog satte
   OG ryddede den — 44 steder at glemme ét, og en glemt oprydning ville lade
   fejlboksen svæve efter at dialogen var lukket. Selektoren læser tilstanden
   direkte fra DOM'en og kan derfor ikke komme ud af trit. Præcedens findes i
   samme fil ved `.page-header-actions:has(.view-toggle)`.

   ⚠️ KUN `#fejl`, IKKE `.fejl`. `projekter.html` har tre `.fejl`-elementer og
   `skabeloner.html` to; de øvrige har egne id'er (`pl-fejl`, `fase-fejl` …) og
   sidder dér hvor de hører til. Ramte reglen klassen, ville en fejllinje der
   ALLEREDE står inde i en dialog blive revet ud og lagt oven på den.

   ⚠️ `:not([hidden])` er ikke pynt: uden det ville en tom, skjult boks stadig
   få `position: fixed`, og en senere `display`-regel kunne gøre den synlig et
   sted ingen forventer den. */
body:has(.modal-overlay:not([hidden])) #fejl:not([hidden]) {
  position: fixed;
  top: var(--space-2);
  left: 50%;
  transform: translateX(-50%);
  /* Over .modal-overlay (1000). Dialogen selv har intet højere. */
  z-index: 1001;
  max-width: min(600px, calc(100vw - 2 * var(--space-2)));
  /* Boksen står nu oven på dialogen og ikke på sidens baggrund, så den skal
     bære sin egen afgrænsning for ikke at flyde sammen med den. */
  border: 1px solid var(--color-red);
  box-shadow: var(--shadow-modal);
}

.tom-liste {
  color: var(--color-text-muted);
  font-style: italic;
}

/* ==========================================================================
   Kompakt projektside og modal
   ========================================================================== */

/* Kompakt layout */
.content-compact {
  padding: var(--space-2);
}

.page-header-compact {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: var(--space-2);
}

.page-title-compact {
  font-size: 20px;
  margin-bottom: 2px;
}

.projekt-meta-compact {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  font-size: 12px;
  color: var(--color-text-secondary);
}

.page-header-actions {
  display: flex;
  gap: var(--space-1);
}

/* Projektsidens sidehoved: titel og handlinger deler rækken efter en ANDEL,
   ikke efter hvem der fylder mest.

   ⚠️ DEN LODRETTE KOBLING, OG HVORFOR EN ANDEL FJERNER DEN.
   MÅLT 2026-08-09 ved 900px: `.page-header` er `space-between`, så
   titelkolonnens bredde var RESTEN af rækken. Færre handlingsknapper gav et
   smallere bånd, titlen fik mere plads og gik fra to linjer til én — og
   sidehovedet skiftede højde:

       tabel / gantt / team / cutover   sidehoved 184px   fanerække y=296
       ressourcestyring / stamkort      sidehoved 129px   fanerække y=241

   Fanerækken sprang altså 55px LODRET ved faneskift, selvom den vandret stod
   fast. Samme fejlform som før, blot på den anden akse.

   ⚠️ `flex: 1` PÅ TITLEN LØSER DET IKKE. Så er dens bredde stadig "resten",
   og resten afhænger stadig af båndet. Koblingen består. En andel af rækken
   ser derimod ikke på sine søskende: titlens bredde bliver en funktion af
   VINDUETS bredde alene, den brækker samme sted uanset hvor mange knapper der
   står til højre, og sidehovedets højde er dermed konstant ved konstruktion —
   ikke ved en modregning.

   ⚠️ `flex-grow: 0` OG `flex-shrink: 0` ER BEGGE NØDVENDIGE. Med grow ville
   kolonnen æde ledig plads når båndet er smalt; med shrink ville den give
   plads når båndet er bredt. Begge veje genskaber afhængigheden.
   `min-width: 0` fordi en flex-boks ellers ikke må blive smallere end sit
   længste ord — et langt projektnavn ville da skubbe andelen ud af kraft.

   ⚠️ ANDELEN ER MÅLT, IKKE GÆTTET. Efterprøvet 2026-08-09 i et RIGTIGT
   browservindue ved 960 / 1250 / 1680px, med et langt projektnavn
   ("Digitalisering af butiksprocesser i Storkøbenhavn — etape 2"). Knappernes
   NATURLIGE bredde blev fundet ved at sænke andelen til de holdt op med at
   ændre sig: 122/148/157px, altså 443px med mellemrum i cutover-visningen,
   som har det bredeste bånd. Derefter opad, målt ved 960px:

       37%   sidehoved 208px   titel 3 linjer   knapper 122/148/157 (naturlig)
       44%   sidehoved 178px   titel 3 linjer   knapper 105/126/133
       46%   sidehoved 153px   titel 2 linjer   knapper 101/121/128
       50%   sidehoved 153px   titel 2 linjer   knapper  94/112/117
       60%   sidehoved 153px   titel 2 linjer   knapper  82/ 83/ 86

   46 % er KNÆKPUNKTET hvor titlen falder fra tre linjer til to. Over det
   vinder titlen ingenting — den er allerede på to linjer — mens knapperne
   bare bliver smallere. Under det bliver sidehovedet 25-55px højere uden
   gevinst.

   ⚠️ VED 960px KAN MAN IKKE FÅ BEGGE DELE. Titlen på to linjer kræver 46 %;
   et ukomprimeret bånd kræver at titlen får højst ~37 %. Prioriteringen er
   bevidst: projektnavnet er sidens vigtigste tekst. Knapperne komprimeres til
   366px mod 443px naturlig — ingen tekst klippes (`scrollWidth` er mindre end
   bredden), de bliver blot strammere. Fra 1250px og op komprimeres intet.

   ⚠️ Og komprimeringen flytter INGENTING: den er ens på alle seks faner,
   fordi kolonnebredden er en andel af vinduet og ikke af søskendes indhold.
   Det er hele forskellen på denne løsning og de tidligere. */
.page-header-compact > .page-header-titel {
  flex: 0 0 46%;
  min-width: 0;
}

.page-header-titel + .page-header-actions {
  flex: 1 1 auto;
  justify-content: flex-end;
}

/* Fanerækken på projektsiden — fanelinjens EGEN række, under sidehovedet og
   lige over indholdet.

   ⚠️ HVORFOR EN RÆKKE FOR SIG. Fanelinjen stod indtil 2.7 inde i
   `.page-header-actions` sammen med handlingsknapperne. Den række skifter
   bredde, fordi `opdaterHeaderKnapper` viser forskellige knapper pr. fane, og
   fordi den er højrestillet, flyttede fanelinjen sig med — målt 253px spring
   ved skift til Ressourcestyring, tre forskellige positioner i alt.

   Her stod først en lap: `.page-header-actions:has(.view-toggle) { flex: 1 }`
   plus `margin-right: auto` på fanelinjen. Den bandt positionen, men lod
   navigation og handlinger blive i samme række — altså en modregel oveni det
   strukturelle problem frem for en løsning på det. Den er fjernet.

   ⚠️ INGEN MARGIN, OG DET ER MED VILJE. Rækken er direkte barn af `.content`,
   som er `flex-direction: column` med `gap: var(--space-3)`. Afstanden opad og
   nedad kommer derfra. En `margin` her ville lægge et andet afstandssystem ved
   siden af sidens eget, og de to ville skulle holdes i sync i hånden.

   Højrestillet, så fanelinjen flugter med indholdets højrekant: rækken er
   fuld bredde (blokelement i en kolonne-flex), og `flex-end` skubber
   fanelinjen ud til samme kant som kortene nedenfor. */
.view-toggle-bar {
  display: flex;
  justify-content: flex-end;
}

/* ---------- Milepæle (projekt-header) ---------- */

.projekt-milepaele {
  margin-top: var(--space-2);
}

.projekt-milepaele-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 4px;
}

.projekt-milepaele-titel {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-secondary);
}

.projekt-milepael-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  list-style: none;
  padding: 0;
  margin: 0;
}

.projekt-milepael-item {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--color-milepael-soft);
  border: 1px solid var(--color-milepael);
  border-radius: var(--radius-sm);
  padding: 3px 8px;
  font-size: 12px;
  color: var(--color-text-primary);
}

.projekt-milepael-item-navn {
  font-weight: 600;
}

.projekt-milepael-item-dato {
  color: var(--color-text-secondary);
}

.projekt-milepael-item-actions {
  display: flex;
  gap: 2px;
  margin-left: 4px;
}

.projekt-milepael-item-actions button {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 11px;
  color: var(--color-text-secondary);
  padding: 0 2px;
}

.projekt-milepael-item-actions button:hover {
  color: var(--color-accent-text);
}

.projekt-milepael-tom {
  font-size: 12px;
  color: var(--color-text-muted);
}

.projekt-milepael-item-fremhaevet {
  outline: 2px solid var(--color-milepael);
  outline-offset: 1px;
  transition: outline-color 0.3s ease;
}

/* Knapper */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-sm);
  padding: 9px 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast);
  text-decoration: none;
}

/* Løftet på hover er væk (afsnit 1: farveskift alene). Fokus er til gengæld
   blevet SYNLIGT — .btn havde ingen fokusmarkering overhovedet, fordi
   translateY var det eneste den reagerede med. */
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ⚠️ EN DEAKTIVERET KNAP SÅ INDTIL 2.14.0 UD PRÆCIS SOM EN AKTIV.
   Der fandtes ingen `:disabled`-styling for `.btn` overhovedet — kun
   `.status-inline`, `.btn-slet-diskret:hover` og `.hm-nav .btn` nævnte
   tilstanden. En slået-fra knap beholdt derfor sin fulde farve, sin kant og
   `cursor: pointer` fra reglen ovenfor, og læste som ØDELAGT frem for som slået
   fra. Dertil kommer at et `disabled`-element ingen musehændelser modtager, så
   dens `title` — den eneste forklaring der var — aldrig kunne vises.

   ⚠️ DET ER MÅLT SOM FEJL TO GANGE. `Rettigheder` kostede en fuld
   fejlsøgningsrunde i 2.0 ("reagerer ikke, ingen konsolfejl"), og `Emulér` blev
   meldt på nøjagtig samme måde i preprod-testen af 2.14.0. Begge de knapper
   forklarer sig nu i stedet for at være slået fra — se `.btn-xs.ret-forklarer`
   nedenfor, static/js/rettighedsknap.js og static/js/emulerknap.js.

   Denne regel er til RESTEN: `Deaktivér` og `Slet` på ens egen række, og enhver
   fremtidig knap. De skal reelt være uklikbare, og så skal de også SE sådan ud.
   Noteret som uløst i docs/features.md indtil nu.

   ⚠️ `cursor: not-allowed` FREM FOR `default`: den siger at knappen findes og
   er slået fra, hvor `default` blot ville få den til at ligne tekst.
   ⚠️ Ingen `:focus-visible`-undtagelse er nødvendig — et disabled element er
   ude af tab-rækkefølgen og kan ikke fokuseres. Netop dét er grunden til at
   forklarende knapper IKKE bruger `disabled`. */
.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ⚠️ INTET `pointer-events: none` HER, OG DET ER MÅLT FREM FOR ANTAGET.
   Reglen ovenfor havde den først, som et værn mod at en deaktiveret knap
   stadig skiftede farve under musen. Men de to udelukker hinanden: et element
   med `pointer-events: none` er ikke et musemål, så dets `cursor` bruges
   aldrig — markøren viser forælderens i stedet. Værnet ville altså have
   slukket den ENE visuelle besked knappen havde tilbage.
   Den er unødvendig i forvejen: et `disabled`-element modtager slet ingen
   musehændelser, så `:hover` matcher det ikke. Målt i browseren: opacity
   1 → 0.45, cursor pointer → not-allowed, og knappen kan ikke rammes. */

.btn-primary {
  background: var(--color-accent);
  color: var(--color-on-accent);
}
.btn-primary:hover { background: var(--color-accent-hover); }

.btn-secondary {
  background: var(--color-surface);
  color: var(--color-accent-text);
  border: 1px solid var(--color-accent-border);
}
.btn-secondary:hover { background: var(--color-accent-soft); }

/* ⚠️ Hover var --color-accent-soft, altså dengang en rød tone. Den ville nu
   have gjort en SLET-knap grøn ved berøring. Se noten ved button.slet. */
.btn-danger {
  background: transparent;
  color: var(--color-red);
}
.btn-danger:hover { background: rgba(196, 119, 107, .10); }

.btn-sm { padding: 6px 12px; font-size: var(--fs-xs); }
.btn-xs { padding: 5px 11px; font-size: 12px; border-radius: var(--radius-xs); }

/* Kompakt tabel */
.card-compact { padding: 0; }

.table-scroll {
  /* Altid synlig vandret scrollbar (ikke auto-hidden/overlay), så det er
     tydeligt at den brede redigeringstabel kan scrolles for at se mere. En
     lodret scrollbar dukker op når der er flere rækker end der er plads til. */
  overflow-x: scroll;
  overflow-y: auto;
  max-height: 65vh;
}
.table-scroll::-webkit-scrollbar {
  width: 12px;                           /* lodret bar */
  height: 12px;                          /* vandret bar — Chrome/Safari: klassisk, ikke-overlay */
}

/* ⚠️⚠️ `scrollbar-width` OG `scrollbar-color` ER FLYTTET HERNED BAG EN
   FIREFOX-GATE — OG DET ER IKKE KOSMETIK. LÆS FØR DU FLYTTER DEM TILBAGE.

   De to stod ovenfor i `.table-scroll` og var tilføjet for Firefox. I Chrome
   gør de noget helt andet: **er en af dem sat, IGNORERES hele
   `::-webkit-scrollbar`-blokken.** Chrome falder da tilbage på macOS'
   OVERLAY-scrollbar, som fylder NUL pixels og er usynlig indtil man ruller.

   MÅLT 2026-08-10 på et frisk element, én egenskab ad gangen:

     kun ::-webkit-scrollbar ................ 14 px
     + scrollbar-width: thin ................  0 px
     + scrollbar-color ......................  0 px
     begge ..................................  0 px

   Følgen var at den brede opgavetabel på projektsiden IKKE havde nogen synlig
   måde at rulle på. Indholdet var der, og `scrollLeft` virkede — men en bruger
   med en mus uden vandret hjul havde ingen vej til Handlinger-kolonnen. Det er
   præcis dét kommentaren tre linjer oppe lover ikke sker: løftet var
   ubesvaret fra den dag de to linjer blev tilføjet.

   ⚠️ Fejlen er tavs og RAMTE ALLE `.table-scroll`-tabeller — arkiv,
   alle-opgaver, cutover-admin, skabelon, projekter og projektsidens fem — ikke
   kun den ene der blev rapporteret. Den blev først synlig da Påmind-knappen i
   2.9.0 gjorde opgaverækken bred nok til at klippe på en almindelig skærm.

   Gaten er en Firefox-only feature query: `::-moz-range-track` findes kun
   dér, så Chrome springer blokken over og beholder sin klassiske bar. */
@supports selector(::-moz-range-track) {
  .table-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--color-text-muted) var(--color-border);
  }
}
/* Fast tabel-header, så kolonnenavne bliver synlige når man scroller lodret. */
/* Kanten sidder på th og ikke på thead: et sticky th løftes ud af rækkens
   normale maling, så thead'ens egen border-bottom ville blive stående og
   rulle væk under de rækker headeren skal ligge oven på. */
.table-scroll .table-compact thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--color-surface-2);
  border-bottom: 1px solid var(--color-border);
}
.table-scroll::-webkit-scrollbar-track {
  background: var(--color-border);
  border-radius: var(--radius-pill);
}
.table-scroll::-webkit-scrollbar-thumb {
  background: var(--color-text-muted);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
.table-scroll::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-secondary);
  background-clip: content-box;
}

.table-compact th {
  padding: 8px 10px;
  font-size: var(--fs-label);
  white-space: nowrap;
}

/* Samme greb som på den almindelige td: fast højde frem for lodret padding,
   så rækken er 32px uanset hvad cellen indeholder. */
.table-compact td {
  padding: 0 10px;
  height: 32px;
  font-size: 12.5px;
  white-space: nowrap;
}

/* Sættes af laasKolonneBredder() i projekt.js, når brugeren begynder at
   trække i en kolonne (eller får gemte bredder genskabt).
   `table-layout: fixed` er DET der gør en kolonne smallere end sit indhold
   mulig: i den normale auto-layout er en angivet width kun et ønske, og
   browseren nægter at gå under indholdets minimumsbredde. Klassen sættes
   først når den skal bruges, så tabellen ellers ser præcis ud som før. */
.table-compact.kolonner-laast {
  table-layout: fixed;
  /* ⚠️ TABELLENS EGEN BREDDE SÆTTES I JS (sikrLaasteKolonneBredder) til
     summen af kolonnerne — en EKSPLICIT px-værdi, fordi `table-layout: fixed`
     kun gælder når `width` ikke er `auto`. `min-width` fylder containeren ud
     når summen er mindre, uden at spænde tabellen fast når den er større.
     Uden dette blev de angivne kolonnebredder til ANDELE af containeren, og
     Handlinger-kolonnen kunne klemmes smallere end sine knapper. */
  min-width: 100%;
}

/* Klip indhold der ikke kan være i en smal kolonne, i stedet for at lade det
   flyde ud over nabocellen. Kun relevant i låst tilstand. */
.table-compact.kolonner-laast th,
.table-compact.kolonner-laast td {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Cellernes indhold er ofte et element (select/input/knapper) frem for ren
   tekst — text-overflow virker kun på tekst, så vi sikrer at elementerne selv
   ikke tvinger cellen bredere end den er sat til. */
.table-compact.kolonner-laast td > * {
  max-width: 100%;
}

/* Tekstombrydning (030): "Ombryd tekst"-togglen i værktøjslinjen sætter denne
   klasse på selve tabellen, se anvendTekstOmbrydningsKlasse i
   tekstombrydning.js. Ophæver klipningen ovenfor i stedet for at tilføje en
   ny, så en smal kolonne ombryder i stedet for at skjule tekst. */
.table-compact.tekst-ombrudt th,
.table-compact.tekst-ombrudt td {
  white-space: normal;
  overflow-wrap: break-word;
}

/* Den faste rækkehøjde (se .table-compact td ovenfor) skal kunne vokse med
   indholdet, ikke klippe det lodret. */
.table-compact.tekst-ombrudt td {
  height: auto;
  min-height: 32px;
}

/* Ophæver PRÆCIS ".kolonner-laast"s klippe-regel ovenfor — kun når begge
   klasser er sat, ikke kolonner-laast alene. */
.table-compact.tekst-ombrudt.kolonner-laast th,
.table-compact.tekst-ombrudt.kolonner-laast td {
  overflow: visible;
  text-overflow: clip;
}

/* Ekstra kolonner (023) klipper til 16rem uanset kolonner-laast (se
   .ekstra-celle nedenfor) — ombrydningen skal gælde dem med. */
.table-compact.tekst-ombrudt td.ekstra-celle {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
}

/* Ombryd tekst-toggle: lille switch i tabellens værktøjslinje, samme
   opbygning som mørkt tema-toggle i brugermenuen (se .toggle-switch).
   Samme gap som .tabel-filter-bar (var(--space-2)) mellem "Viser …" og
   etiketten, så afstanden er ens på begge sider af togglen. */
.tabel-ombryd-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--color-text-muted);
  cursor: pointer;
}

/* .toggle-switch er tegnet til at stå ved siden af 14px menutekst (36×20).
   Her er sidetekstens linje kun ca. 14,5px høj (font-size: 12px) — uskaleret
   ville switchen matematisk CENTRERES på samme akse som teksten (begge deler
   .tabel-filter-bars fælles midte), men den ekstra højde gør den alligevel
   påfaldende større end linjen den står på. Skaleret til værktøjslinjens
   tekst i stedet, samme forhold (36:20 ≈ 26:15, kant 2px, håndtag 11px). */
.tabel-ombryd-toggle .toggle-switch {
  width: 26px;
  height: 15px;
}

/* ⚠️ box-sizing: border-box ER PÅKRÆVET, IKKE KOSMETISK. Basisreglens
   ::after ligger i content-box (arvet fra 36×20-versionen, hvor width/height
   angiver INDHOLDET og den 1px kant lægges udenpå — 16px content + 2px kant
   = 18px rendered i et 20px spor). Uden dette ville 11px content + 2px kant
   blive 13px i et 15px spor, med `top: 2px` arvet uændret fra spor på 20px —
   2px margin foroven, 0px forneden: håndtaget rører sporets kant. Med
   border-box ER width/height den fulde, synlige størrelse, så top/left kan
   beregnes direkte ud fra sporets egne mål: (15 - 11) / 2 = 2px margin hele
   vejen rundt, i begge tilstande — se target/translateX nedenfor. */
.tabel-ombryd-toggle .toggle-switch::after {
  box-sizing: border-box;
  top: 2px;
  left: 2px;
  width: 11px;
  height: 11px;
}

/* Håndtagets VENSTRE kant skal ende ved (sporbredde − margin − håndtagbredde)
   = 26 − 2 − 11 = 13, altså 11px længere mod højre end start (2px):
   translateX(11px). Rører/overskrider IKKE sporets højre kant: 2 + 11 + 11
   = 24, og sporet er 26 bredt — 2px margin til højre, symmetrisk med
   venstre. Højden/top røres ikke af transformen, så den lodrette centrering
   er den samme i begge tilstande. */
.tabel-ombryd-toggle .toggle-switch.on::after {
  transform: translateX(11px);
}

/* ---------- Kolonne-filtrering (Excel-stil), Tabel-view ---------- */

.tabel-filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-2) var(--space-1);
  font-size: 12px;
  color: var(--color-text-muted);
}

/* Søgefeltet i brugeradministrationen. Ligger i .tabel-filter-bar ovenfor, så
   den genbruger dens flex og afstande — kun feltets eget udseende står her. */
.soegefelt {
  flex: 0 1 320px;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--fs-sm);
}

/* Samme fokusmarkering som resten af husets felter. Den stod som sin egen
   2px outline fra 2.12.0 og var dermed det eneste felt i appen der markerede
   fokus anderledes end alle andre — se noten ved input:focus. */
.soegefelt:focus {
  border-color: var(--color-border-focus);
  box-shadow: var(--focus-ring);
  outline: none;
}

/* Tælleren står tom når intet er filtreret — se opdaterBrugerAntal. */
.filter-antal {
  color: var(--color-text-muted);
}

.alle-opgaver-projekt-filter {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 500;
}
.alle-opgaver-projekt-filter select {
  padding: 4px 8px;
  font-size: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text);
}
/* Kun når projekt-filteret er til stede (alle-opgaver.html) skal
   antal-teksten skubbes til højre — ellers ville .tabel-filter-antal (delt
   med projekt.html) rykke sig uintenderet der også. */
.alle-opgaver-projekt-filter + .tabel-filter-antal {
  margin-left: auto;
}

/* Sorterbar kolonneoverskrift (alle-opgaver.html) — pil vises kun på den
   aktive sorteringskolonne, retning styret af data-sortretning. */
.th-label-sorterbar {
  cursor: pointer;
  user-select: none;
}
.th-label-sorterbar:hover {
  color: var(--color-text);
}
.th-label-sorteret::after {
  content: "▲";
  font-size: 9px;
  margin-left: 4px;
  display: inline-block;
}
.th-label-sorteret[data-sortretning="desc"]::after {
  content: "▼";
}

/* NB: display:flex må ALDRIG sættes på selve <th> — det tager cellen ud af
   tabellens cellelayout-algoritme og får rækken til at knække visuelt
   (fundet ved browser-test). Flex-styringen sidder derfor på en indre
   wrapper (.th-filter-wrap), ikke på th[data-felt] selv. */
.th-filter-wrap {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}

.th-filter-knap {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  font-size: 9px;
  line-height: 1;
  padding: 2px 3px;
  border-radius: var(--radius-xs);
  cursor: pointer;
}

.th-filter-knap:hover {
  background: var(--color-surface);
  color: var(--color-text-primary);
}

/* --color-accent-text og ikke --color-accent: chevronen er TEKST i en
   tabeloverskrift, og den fyldte accent er for mørk til 9px på mørk bund. */
.th-filter-knap-aktiv {
  color: var(--color-accent-text);
  font-weight: 700;
}

/* Overlay — se noten ved --shadow-modal. */
.th-filter-dropdown {
  position: fixed;
  z-index: 900;
  min-width: 160px;
  max-width: 240px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  padding: 6px;
}

.th-filter-dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px;
  border-radius: var(--radius-xs);
  font-size: var(--fs-xs);
  font-weight: 400;
  white-space: normal;
  cursor: pointer;
}

.th-filter-dropdown-item:hover {
  background: var(--color-row-hover);
}

.th-filter-dropdown-item input {
  width: auto;
  flex-shrink: 0;
}

.th-filter-dropdown-tom {
  font-size: 12px;
  color: var(--color-text-muted);
  padding: 5px 6px;
  margin: 0;
}

.th-filter-dropdown-dato {
  min-width: 180px;
}

.th-filter-dato-label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11px;
  font-weight: 500;
  color: var(--color-text-secondary);
  padding: 4px 6px;
}

.th-filter-dato-label input {
  font-size: var(--fs-xs);
  padding: 5px 6px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text-primary);
}

.th-filter-dato-label input:focus {
  border-color: var(--color-border-focus);
  outline: none;
}

.table-compact input,
.table-compact select {
  font-size: 11px;
  padding: 4px 6px;
}

.table-compact input[type="date"] {
  width: 110px;
}

/* Ekstra kolonner (023): fritekst der kan være lang. Cellen afkortes med en
   ellipsis — den fulde tekst står i cellens title — så en lang værdi ikke gør
   kolonnen uendelig bred i tabellens auto-layout. */
.table-compact td.ekstra-celle {
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Inline-redigeringen af en ekstra kolonne er en textarea (den bevarer
   linjeskift), som i øvrigt står i browserens monospace uden en stil. */
.table-compact textarea.celle-input {
  width: 100%;
  min-width: 12rem;
  padding: 4px 6px;
  font-family: inherit;
  font-size: 11px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-primary);
  resize: vertical;
}

.table-compact textarea.celle-input:focus {
  border-color: var(--color-border-focus);
  box-shadow: var(--focus-ring);
  outline: none;
}

/* Etiketfeltet på Projektkortets sektion "Ekstra kolonner". */
.table-compact input.ekstra-etiket-input {
  min-width: 12rem;
}

.handlinger-celle {
  white-space: nowrap;
}

.badge-sm {
  font-size: 10px;
  padding: 2px 6px;
}

/* Inline status-dropdown i opgavetabellen: ligner et badge, men er klikbar.
   Farven kommer fra badge-*-klasserne (samme variabler som badge'et). */
.status-inline {
  border: none;
  border-radius: var(--radius-pill);
  padding: 3px 22px 3px 10px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-repeat: no-repeat;
  background-position: right 7px center;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}
.status-inline:focus-visible {
  outline: 2px solid var(--accent, #4f46e5);
  outline-offset: 1px;
}
.status-inline:disabled {
  opacity: 0.6;
  cursor: progress;
}

.afh-select-compact {
  min-width: 80px;
  max-width: 100px;
  font-size: 10px;
}

/* Modal */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.modal-overlay[hidden] {
  display: none;
}

/* Overlay — se noten ved --shadow-modal. */
.modal {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  width: 100%;
  max-width: 420px;
  max-height: 90vh;
  overflow-y: auto;
}

/* Bredere variant (fx rettighedsmodalen, hvor tabellen har flere kolonner). */
.modal.modal-bred {
  max-width: 700px;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

.modal-header h2 {
  font-size: 16px;
  font-weight: 600;
}

.modal-luk {
  background: none;
  border: none;
  font-size: 24px;
  color: var(--color-text-secondary);
  cursor: pointer;
  line-height: 1;
  padding: 0;
}
.modal-luk:hover { color: var(--color-text-primary); }

.modal-form {
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.modal-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text-secondary);
}

.udloeb-felter {
  display: flex;
  gap: var(--space-2);
}

.modal-form input,
.modal-form select {
  padding: 8px 10px;
  font-size: 13px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.modal-form input:focus,
.modal-form select:focus {
  border-color: var(--color-border-focus);
  box-shadow: var(--focus-ring);
  outline: none;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-1);
  padding-top: var(--space-1);
}

/* Gantt fuld bredde */
.gantt-fullwidth {
  padding: var(--space-2);
}

.gantt-fullwidth #gantt {
  min-height: 400px;
}

/* ---------- Milepæle-overlay i Gantt ----------
   Additivt DOM-lag oven på frappe-gantts eget SVG (aldrig inde i det), så det
   ikke overskrives ved gentegning. Genskabes hver gang tegnGantt() kører. */

.gantt-milepael-lag {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  z-index: 998; /* under popup-wrapper (1000), over grid */
}

.gantt-milepael-linje {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--color-milepael);
  opacity: 1;
}

.gantt-milepael-label {
  position: absolute;
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--color-milepael);
  color: #ffffff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  pointer-events: auto;
  cursor: pointer;
  /* Mørk egen kant, ikke --color-border: etiketten ligger på sin egen
     milepælsfarve oven på Gantt-gitteret, hvor husets lyse kant forsvinder. */
  border: 1px solid rgba(0, 0, 0, 0.15);
}

/* ==========================================================================
   Gantt — husets udtryk oven på frappe-gantt
   ==========================================================================

   ⚠️ HVER REGEL ER PRÆFIKSET MED #gantt, OG DET ER IKKE PYNT.
   `static/projekt.html` indlæser style.css (linje 14) FØR
   `vendor/frappe-gantt/frappe-gantt.css` (linje 17). Ved samme specificitet
   vinder den sidst indlæste. En regel skrevet som `.gantt .grid-row { … }`
   ville derfor tabe til vendorens egen `.gantt .grid-row` — uden fejl, uden
   advarsel, og med et resultat der ligner "CSS'en virkede bare ikke".
   #gantt er mountpunktet (`projekt.html:308`, eneste sted i huset), og et id
   løfter specificiteten over alt hvad vendoren kan stille op. Fjernes
   præfikset, holder blokken op med at virke.

   ⚠️ FARVER SÆTTES GENNEM VENDORENS EGNE --g-*-VARIABLER, ikke ved at
   overskrive dens regler. Variablerne arves ned gennem hele gitteret, så ét
   sted rammer også de regler vi ikke har læst. Kun dét der ingen variabel har
   — bjælkens rx/ry, skriftstørrelser, og de tre steder vendoren har hardkodet
   #fff — står som regeloverskrivning nedenfor. Vi sætter 24 af vendorens 37
   variabler; de 13 øvrige arves uændret fra dens egen :root, for en variabel
   man ikke sætter, skæres ikke af.

   ⚠️ HELE BLOKKEN HÆNGER PÅ VENDORENS EGNE KLASSENAVNE OG KNÆKKER TAVST VED EN
   OPDATERING. `.grid-background`, `.grid-row`, `.row-line`, `.tick`,
   `.bar-wrapper`, `.bar-label`, `.popup-wrapper`, `.current-upper` og alle
   --g-*-navnene er @workiom/frappe-gantts interne API — ikke et offentligt et.
   Vendoret version står i `static/vendor/frappe-gantt/VERSION.txt`
   (**1.0.27**, hentet 4/7). Omdøber en ny version en klasse eller en variabel,
   holder reglen her op med at ramme noget: ingen fejl, ingen advarsel, kun et
   Gantt der ser forkert ud. Handoffens afsnit 5 var skrevet mod en ANDEN
   version og ramte allerede to navne forbi — se de to punkter nedenfor.
   ⚠️ **Ved enhver opgradering af biblioteket: gennemgå hver selektor i denne
   blok mod den nye `frappe-gantt.css`, og mål i browseren bagefter.**

   ⚠️ GANTT'EN VAR HARDKODET LYS FØR DETTE. Vendorens standardværdier er #fff,
   #fdfdfd og #c7c7c7 skrevet direkte i filen uden hensyn til tema, så i mørk
   tilstand stod gitteret som en hvid kasse midt på en mørk side. Det er ikke
   noget omlægningen har lavet — det er noget den lukker.

   ⚠️ TO TING I HANDOFFENS AFSNIT 5 PASSER IKKE PÅ DENNE VERSION AF BIBLIOTEKET:
   `.gantt .grid-row:nth-child(even)` (zebra) findes ikke — vendoren farver
   alle rækker ens gennem --g-row-color, så der er ingen striber at fjerne. Og
   `.today-highlight` findes ikke som klasse; i dag-markeringen hedder
   `.current-highlight`/`.current-ball-highlight` og styres af
   --g-today-highlight. Begge er skrevet om herefter, ikke kopieret. */

#gantt {
  --g-row-color:              var(--color-surface);
  --g-border-color:           var(--color-row-border);
  --g-row-border-color:       var(--color-border);
  --g-tick-color:             var(--color-row-border);
  --g-tick-color-thick:       var(--color-border);
  --g-header-background:      var(--color-surface-2);
  --g-task-column-bg:         var(--color-surface);
  --g-task-row-bg:            var(--color-surface);
  --g-weekend-highlight-color: var(--color-surface-2);

  /* Bjælken er grå og fremdriften accent — status-farvede bjælker sættes
     ovenpå via frappe-gantts custom_class, hvis de bliver ønsket. */
  --g-bar-color:              var(--color-grey);
  --g-bar-border:             var(--color-grey);
  --g-progress-color:         var(--color-accent);
  --g-expected-progress:      var(--color-surface-3);

  --g-text-dark:              var(--color-text-primary);
  --g-text-muted:             var(--color-text-secondary);
  --g-text-light:             var(--color-on-accent);

  --g-today-highlight:        var(--color-accent);
  --g-actions-background:     var(--color-surface-3);
  --g-popup-actions:          var(--color-surface-3);
  --g-arrow-color:            var(--color-text-secondary);
  --g-arrow-hover-color:      var(--color-accent);
  --g-connector-fill:         var(--color-surface);
  --g-arrow-type-dropdown-bg: var(--color-surface);
  --g-arrow-type-dropdown-border: var(--color-border);
}

/* ⚠️⚠️ RØR IKKE `fill` HER. `none` ER DEN RIGTIGE VÆRDI, OG ALT ANDET SKJULER
   HELE DIAGRAMMET.

   `rect.grid-background` er det SIDSTE barn af SVG'en — målt 16/8 i den
   levende side:

     0  g.grid    (78 børn)      3  g.bar   (72 børn)
     1  g.arrow                  4  g.linking
     2  g.progress               5  rect.grid-background   ← sidst

   SVG maler i dokumentorden, så den ligger ØVERST, ikke nederst. Navnet siger
   "background"; placeringen gør den til et forgrundslag på 3640x3549 px, altså
   hele lærredet. Med `fill: none` er den usynlig og ligegyldig. Får den en
   uigennemsigtig farve, bliver den en plade over gitter, bjælker og etiketter.

   ⚠️ DET SKETE. Omlægningen satte `fill: var(--color-surface)` med den
   begrundelse at "gitteret skal ligge på husets fladefarve som alt andet".
   Rækkefladen bæres allerede af `--g-row-color` på `.grid-row`, så reglen
   tilføjede intet ud over fejlen: alle 72 bjælker og 72 etiketter forsvandt.

   ⚠️ FEJLFORMEN ER GRUND TIL AT LÆSE RESTEN AF DENNE FIL LANGSOMT. Intet
   fejlede. Elementerne fandtes, havde rigtige koordinater, rigtig størrelse og
   rigtig `fill` — en måling af DOM og beregnede værdier gav grønt lys, fordi
   tildækning ikke kan ses dér. Kun `document.elementFromPoint()` på bjælkens
   midtpunkt afslørede det: den svarede `rect.grid-background` i stedet for
   bjælken. Måler du på denne blok, så mål hvad der ligger ØVERST — ikke om
   elementet findes. */
#gantt .gantt .grid-background {
  fill: none;
}

#gantt .gantt .bar-wrapper .bar {
  rx: 8;
  ry: 8;
}

/* font-family: inherit — vendoren hardkoder Helvetica på bjælkeetiketten, og
   den ville stå som den eneste skrifttype i huset der ikke er sidens egen. */
#gantt .gantt .bar-label {
  font-family: inherit;
  font-size: 12.5px;
}

/* To af de tre steder vendoren har skrevet #fff direkte ind: baggrunden bag
   hver popup, og sidehovedets sticky venstrekant. Uden dem står der hvide
   felter tilbage i mørk tilstand. Det tredje — `.extras .adjust` — er hvid
   TEKST på en næsten sort knap og er rigtig i begge temaer; den er med vilje
   ladt urørt, så ingen leder efter en rettelse der ikke skal laves. */
#gantt .gantt-container .popup-wrapper {
  background: var(--color-surface);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
}

#gantt .gantt-container .current-upper {
  background: var(--color-surface-2);
}

/* ==========================================================================
   Afhængigheds UI (knap + dropdown + pills)
   ========================================================================== */

.afh-container {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 140px;
}

.afh-btn {
  background: var(--color-surface);
  color: var(--color-accent-text);
  border: 1px solid var(--color-accent-border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition-fast);
}

.afh-btn:hover {
  background: var(--color-accent-soft);
}

/* ⚠️ Dropdownen er et barn af <body>, IKKE af cellen — og skal blive det.
   Lå den inde i sin <td>, blev den klippet væk af
   `.table-compact.kolonner-laast td { overflow: hidden }` så snart brugeren
   havde trukket i en kolonne: knappen så ud til ikke at reagere, uden
   konsolfejl. z-index hjælper ikke mod en overflow-klipning — kun det at
   ligge uden for det klippende element gør. Placeringen sættes inline af
   aabnAfhDropdown() ud fra knappens getBoundingClientRect(), samme mønster
   som .th-filter-dropdown ovenfor. */
/* Overlay — se noten ved --shadow-modal. */
.afh-dropdown {
  position: fixed;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);
  max-height: 200px;
  overflow-y: auto;
  z-index: 900;
  min-width: 200px;
}

.afh-dropdown-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.afh-dropdown-item:hover {
  background: var(--color-row-hover);
}

.afh-dropdown-item.selected {
  background: var(--color-accent-soft);
}

.afh-checkbox {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: 1px solid var(--color-border);
  border-radius: 3px;
  font-size: 10px;
  color: var(--color-accent-text);
  font-weight: bold;
}

.afh-dropdown-item.selected .afh-checkbox {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border-color: var(--color-accent);
}

.afh-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 2px;
}

.afh-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--color-accent-soft);
  color: var(--color-accent-text);
  border-radius: var(--radius-pill);
  padding: 2px 6px 2px 8px;
  font-size: 10px;
  font-weight: 500;
}

/* ⚠️ ×'et FJERNER en afhængighed — det er destruktivt, ikke dekorativt.
   Farven stod på --color-accent og hoveren på en hardkodet rgba(228,32,44),
   altså den GAMLE brandrød skrevet direkte ind. Begge dele pegede på rød;
   kun den ene gjorde det gennem et token. Efter omlægningen ville knappen
   have været grøn med en rød hover — se noten ved button.slet. */
.afh-pill-remove {
  background: none;
  border: none;
  color: var(--color-red);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  margin: 0;
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  transition: background var(--transition-fast);
}

.afh-pill-remove:hover {
  background: var(--rag-red-soft);
}

/* ==========================================================================
   View Toggle (Tabel / Gantt)
   ========================================================================== */

/* ⚠️ DEN SEGMENTEREDE KONTROL ER HUSETS MØNSTER — .gantt-zoom-knap deler den.
   Sporet er --color-surface-3 (en flade, ikke en kant), og det AKTIVE segment
   løftes med en hvid flade og PRIMÆR tekst, ikke med accentfyld. Accentfyld
   ville gøre "hvilken visning ser jeg" til den kraftigste farve på siden, og
   det er stoplysenes plads. Rettes udtrykket her, skal .gantt-zoom-knap.aktiv
   med — de to skal ikke kunne skride fra hinanden. */
.view-toggle {
  display: flex;
  gap: 0;
  background: var(--color-surface-3);
  border-radius: var(--radius-md);
  padding: 3px;
}

.view-toggle-btn {
  display: inline-block;
  background: transparent;
  color: var(--color-text-secondary);
  border: none;
  border-radius: var(--radius-sm);
  padding: 7px 14px;
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.view-toggle-btn:hover {
  color: var(--color-text-primary);
}

.view-toggle-btn.active {
  background: var(--color-surface);
  color: var(--color-text-primary);
}

/* Gantt toolbar i view */
.gantt-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--space-2);
}

/* ==========================================================================
   Portfolio Grid
   ========================================================================== */

.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--space-3);
}

.portfolio-kort {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.portfolio-kort:hover {
  border-color: var(--color-accent-border);
}

.portfolio-kort-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: var(--space-2);
}

/* Titel + butiksprocesbadge under den. Blokken findes for at badge'et kan
   ligge UNDER titlen mens stoplyset bliver i headerens højre side — headeren
   selv er `space-between`, så uden en fælles wrapper ville badge'et blive et
   tredje flex-barn og lande ved siden af titlen. `min-width: 0` lader lange
   projektnavne brydes frem for at skubbe stoplyset ud. */
.portfolio-kort-titelblok {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

/* Badge'et arver .butiksproces-badge fra projektsiden — samme oplysning skal
   se ens ud begge steder. Her kun placeringen: `align-self` holder det i
   tekstens bredde frem for at strække det over hele kolonnen. */
.portfolio-kort-titelblok .butiksproces-badge {
  align-self: flex-start;
}

.portfolio-kort-titel {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0;
  flex: 1;
}

.portfolio-stoplys-container {
  flex-shrink: 0;
  margin-left: var(--space-2);
}

.portfolio-kort-meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: 13px;
  color: var(--color-text-secondary);
  margin-bottom: var(--space-3);
}

.portfolio-kort-meta strong {
  font-weight: 600;
  color: var(--color-text-primary);
}

.portfolio-kort-actions {
  display: flex;
  justify-content: flex-end;
}

/* ==========================================================================
   BI-dashboard (porteføljeside): nøgletal + widgets
   ========================================================================== */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.stat-kort {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

/* Markeringen var en inset box-shadow oven i dybdeskyggen. Nu hvor kortet
   HAR en kant, kan den venstre kant bare gøres tyk og rød — samme udtryk som
   .widget-kort-advarsel, som allerede brugte border-left. Rød og ikke accent:
   se noten ved button.slet. */
.stat-kort-advarsel {
  border-left: 3px solid var(--color-red);
}

.stat-vaerdi {
  font-size: 32px;
  font-weight: 700;
  color: var(--color-text-primary);
  line-height: 1.1;
}

.stat-kort-advarsel .stat-vaerdi {
  color: var(--color-red);
}

.stat-label {
  margin-top: var(--space-1);
  font-size: 13px;
  color: var(--color-text-secondary);
}

.dashboard-widgets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.widget-kort {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

/* Rød og ikke accent — se noten ved button.slet. */
.widget-kort-advarsel {
  border-left: 3px solid var(--color-red);
}

.widget-titel {
  font-size: 16px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0 0 var(--space-2);
}

.widget-titel-advarsel {
  color: var(--color-red);
}

.widget-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  /* Intern scroll ved mange opgaver — samme mønster som .table-scroll
     ("Alle opgaver"): en lodret scrollbar dukker op frem for at listen vokser
     ubegrænset. Ikke foldet sammen, bare scrollbar. */
  overflow-y: auto;
  max-height: 65vh;
  scrollbar-width: thin;
  scrollbar-color: var(--color-text-muted) var(--color-border);
}
.widget-liste::-webkit-scrollbar {
  width: 12px;
}
.widget-liste::-webkit-scrollbar-track {
  background: var(--color-border);
  border-radius: var(--radius-pill);
}
.widget-liste::-webkit-scrollbar-thumb {
  background: var(--color-text-muted);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
.widget-liste::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-secondary);
  background-clip: content-box;
}

.widget-raekke {
  display: block;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  text-decoration: none;
  color: inherit;
  transition: background var(--transition-fast);
}

.widget-raekke:hover {
  background: var(--color-accent-soft);
}

.widget-raekke-forsinket {
  border-left: 3px solid var(--color-accent);
}

.widget-raekke-hoved {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1);
}

.widget-raekke-titel {
  font-weight: 500;
  color: var(--color-text-primary);
  font-size: 14px;
}

.widget-raekke-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: 2px;
  font-size: 12px;
  color: var(--color-text-secondary);
}

.badge-forsinket {
  display: inline-block;
  border-radius: var(--radius-pill);
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  /* Forsinket er en NEGATIV status og skal være rød — den var det også før,
     dengang accent OG rød var #e4202c. .psk-forsinket ved siden af stod
     allerede på --color-red; de to skal ikke skride fra hinanden. */
  background: var(--rag-red-soft);
  color: var(--color-red);
  white-space: nowrap;
}

/* ==========================================================================
   Opgavebeskrivelse (vis mere) og foreslået tovholder
   ========================================================================== */

/* Detalje-række under en opgave med den fulde beskrivelse. */
.beskrivelse-raekke > td {
  background: var(--color-accent-soft);
  padding: var(--space-2) var(--space-3);
}

.beskrivelse-tekst {
  white-space: pre-wrap;
  color: var(--color-text);
  font-size: 14px;
  line-height: 1.5;
  max-width: 900px;
}

/* Foreslået tovholder (fritekst) vises mere afdæmpet end en rigtig ressource. */
.foreslaet-tovholder {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Kommentar-modal (åbnes via "Kommentarer"-knappen på opgaverækken, se
   projekt.js og projekt.html#kommentar-modal). Genbruger .modal/.modal-form
   fra det generelle modal-mønster ovenfor. */
.kommentar-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.kommentar-status {
  color: var(--color-text-muted);
  font-size: 13px;
  margin: 0;
}

.kommentar {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
}

.kommentar-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 12px;
  color: var(--color-text-muted);
  margin-bottom: 4px;
}

.kommentar-forfatter {
  font-weight: 600;
  color: var(--color-text);
}

.kommentar-slet {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 4px;
}

.kommentar-slet:hover {
  color: var(--color-red);
}

.kommentar-tekst-visning {
  white-space: pre-wrap;
  font-size: 14px;
  line-height: 1.5;
}

#kommentar-modal-tekst {
  resize: vertical;
}

/* ==========================================================================
   Faseopsætning + samlet redigeringstilstand
   ========================================================================== */

/* Koblingen fra en projektskabelon til en cutover-skabelon (skabelon.html). */
.cutover-kobling {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.cutover-kobling-label {
  font-weight: 600;
  font-size: 14px;
}

.cutover-kobling-hjaelp {
  flex-basis: 100%;
  margin: 0;
  font-size: 13px;
  color: var(--color-text-secondary);
}

.cutover-kobling-kvittering {
  font-size: 13px;
  color: var(--color-text-secondary);
}

/* Informations-banner (fx "ingen faser defineret").
   ⚠️ Baggrunden var `--color-accent-soft` — husets RØDE fejltone, den samme
   som `.fejl` bruger. Klassen bærer vejledning, ikke fejl, og rødt fik den til
   at læse som et problem. Venstrekanten adskiller den yderligere fra
   fejlboksen, så de to ikke kun kendes fra hinanden på farvens mætning.
   Rammer alle fem brug: `skabelon.html` (ingen faser), `ressourcestyring.html`
   (kapacitet mangler), `admin.html` (kvittering + admin-note),
   `vedligeholdelse-admin.html` ("Gemt.") og feedback-kvitteringen. Alle fem
   er information.

   ⚠️ Læs "husets RØDE fejltone" som en HISTORISK oplysning: accenten er
   petrolgrøn efter designomlægningen, og --color-accent-soft er ikke længere
   rød. Adskillelsen står ved magt alligevel — .fejl er flyttet til
   --color-red, så de to ville stadig have lånt hinandens betydning hvis
   .info-besked var blevet stående på accent. */
.info-besked {
  color: var(--color-text);
  background: var(--color-info-soft);
  border-left: 3px solid var(--color-info);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  font-size: 14px;
  margin-bottom: var(--space-2);
}

/* "Overblikket vises ikke for dig" på index.html — en INFORMATIONSBOKS, ikke
   en fejlboks. Arver .info-besked og tilføjer kun luft mellem afsnittene. */
.up-hoved {
  margin: 0 0 var(--space-1) 0;
}

.up-tekst {
  margin: 0 0 var(--space-1) 0;
  max-width: 68ch;
}

.up-note {
  margin-bottom: 0;
  color: var(--color-text-secondary);
  font-size: 13px;
}

/* Den navngivende første linje i ALLE FIRE slet-modaler — to trin på
   `admin.html` (bruger) og to på `projekter.html` (projekt).
   ⚠️ Uden margin klistrede "Slet brugeren "X" permanent?" op ad afsnittet
   under sig, så de læste som én sammenhængende sætning. Fanget da dialogen
   blev åbnet på en rigtig flade første gang (preprod, 2.6.0); ingen test kan
   se linjeafstand.
   ⚠️ Begge sider står i samme regel MED VILJE. De to dialoger er samme
   mønster, og en fælles regel er billigere end to der skal holdes i sync. */
#slet-bruger-bekraeft-tekst,
#slet-bruger-input-tekst,
#slet-bekraeft-tekst,
#slet-input-tekst {
  margin: 0 0 var(--space-2) 0;
}

/* Forklaringsafsnittene i slet-bruger-bekræftelsen (admin.html). De bærer
   forskellen på Slet og Deaktivér — teksten er hele grunden til at dialogen
   findes, så den må ikke se ud som finskrift. */
.slet-bruger-forklaring {
  margin: 0 0 var(--space-2) 0;
  max-width: 60ch;
  font-size: 14px;
  color: var(--color-text-secondary);
}

/* Fase-liste i faseopsætnings-modalen. */
.fase-liste {
  list-style: none;
  margin: var(--space-2) 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.fase-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.fase-item .fase-navn-input {
  flex: 1;
}

.fase-item-knapper {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

.fase-tilfoej {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

.fase-tilfoej input {
  flex: 1;
}

/* Rækker i samlet redigeringstilstand. */
tr.raekke-slettes td {
  opacity: 0.5;
  text-decoration: line-through;
}

tr.raekke-ny td {
  background: var(--color-accent-soft);
}

.ny-raekke-badge {
  display: inline-block;
  border-radius: var(--radius-pill);
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  background: var(--color-accent-soft);
  color: var(--color-accent-text);
}

/* ==========================================================================
   Login-side
   ========================================================================== */

.login-side {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
}

.login-kort {
  width: 100%;
  max-width: 380px;
  padding: var(--space-4);
}

.login-titel {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
}

.login-undertitel {
  margin: 4px 0 var(--space-3);
  color: var(--color-text-muted);
  font-size: 14px;
}

.login-kort .btn {
  margin-top: var(--space-2);
  width: 100%;
  justify-content: center;
}

/* Tjekliste over kravene til et nyt kodeord.
   ⚠️ KVITTERER MENS DER SKRIVES — den er ikke en fejlbesked bagefter. Derfor
   har den ingen fejlfarve: et krav der endnu ikke er opfyldt, er ikke en fejl,
   det er en oplysning om hvad der mangler. Rød ville sige at brugeren har
   gjort noget forkert, allerede før hun er færdig med at skrive.
   Farverne er tokens (ikke faste værdier), så listen følger lys/mørk. */
.kodeordskrav {
  list-style: none;
  margin: var(--space-1) 0 var(--space-2);
  padding: 0;
  font-size: 13px;
}

.kodeordskrav li {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--color-text-muted);
  line-height: 1.7;
}

.kodeordskrav li::before {
  content: "○";
  font-size: 12px;
  width: 1em;
  text-align: center;
}

.kodeordskrav li.opfyldt {
  color: var(--color-green);
}

.kodeordskrav li.opfyldt::before {
  content: "●";
}

/* ==========================================================================
   Brugeradministration
   ========================================================================== */

/* Bruger-menu i topbarens højre side (indsat af auth-ui.js). */
/* ⚠️ `margin-left: auto` ER FLYTTET HERTIL FRA `.topbar-bruger-menu`.
   Klokken injiceres af auth-ui.js FØR brugermenuen og står derfor til venstre
   for den. Begge er flex-børn i `.topbar`.

   Stod attributtet BEGGE steder, ville den frie plads blive delt mellem to
   auto-margener: klokken ville lande midt i bjælken og brugermenuen i højre
   side, med et hul imellem. Præcis ét element i rækken må skubbe. */
.topbar-klokke {
  margin-left: auto;
  position: relative;
}

.klokke-knap {
  position: relative;
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 8px;
  border-radius: var(--radius-sm);
  color: var(--color-text);
}

.klokke-knap:hover {
  background: var(--color-accent-soft);
}

/* Tælleren. ⚠️ Bevidst i `--color-red` og ikke i `--color-accent`: de to er
   SAMME hexværdi i begge temaer (se noten ved `--sidebar-active-bg`), så en
   accentfarvet badge ville konkurrere med RAG, stoplyset og heatmappet om
   samme betydning. Her ER rødt betydningsbærende — der er noget ulæst. */
.klokke-taeller {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--color-red);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* Samme form som `.bruger-dropdown`, så de to menuer i topbaren ser ud som
   ét system. Bredere, fordi indholdet er tekst og ikke etiketter. */
.klokke-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  width: 340px;
  max-width: calc(100vw - 32px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);   /* overlay — se noten ved --shadow-modal */
  z-index: 20;
  overflow: hidden;
}

.klokke-hoved {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 10px 12px;
  border-bottom: 1px solid var(--color-border);
}

.klokke-overskrift {
  font-size: 13px;
  font-weight: 600;
}

.klokke-laes-alle {
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  color: var(--color-text-secondary);
  padding: 2px 4px;
  border-radius: var(--radius-sm);
}

.klokke-laes-alle:hover {
  background: var(--color-accent-soft);
  color: var(--color-text);
}

/* Højden er begrænset, så en lang liste ikke dækker hele siden. Rullen ligger
   INDE i dropdownen — se princippet om at bredt indhold skal rulle i sin egen
   beholder, ikke i sidens body. */
.klokke-liste {
  max-height: 420px;
  overflow-y: auto;
}

.klokke-post {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-bottom: 1px solid var(--color-border);
  padding: 10px 12px;
  cursor: pointer;
  font: inherit;
  color: var(--color-text);
}

.klokke-post:last-child {
  border-bottom: none;
}

.klokke-post:hover {
  background: var(--color-accent-soft);
}

/* ⚠️ ULÆST BÆRES AF SKRIFTVÆGT OG EN KANT, IKKE AF EN BAGGRUNDSFARVE ALENE.
   Samme valg som det aktive menupunkt i 2.8: en farvet flade konkurrerer med
   hover, og de to ville ikke kunne skelnes når musen er over rækken. */
.klokke-post.ulaest {
  border-left: 3px solid var(--color-red);
  padding-left: 9px;
}

.klokke-post.ulaest .klokke-post-titel {
  font-weight: 700;
}

.klokke-post-titel {
  font-size: 13px;
  font-weight: 500;
}

.klokke-post-tekst {
  font-size: 12px;
  color: var(--color-text-secondary);
  white-space: pre-line;
}

.klokke-post-tid {
  font-size: 11px;
  color: var(--color-text-secondary);
}

.klokke-tom {
  padding: 16px 12px;
  font-size: 13px;
  color: var(--color-text-secondary);
  text-align: center;
}

.topbar-bruger-menu {
  position: relative;
}

.bruger-knap {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font: inherit;
}

.bruger-knap:hover {
  background: var(--color-accent-soft);
}

.bruger-navn {
  font-size: 14px;
  font-weight: 500;
}

.bruger-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  min-width: 180px;
  padding: 4px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-modal);   /* overlay — se noten ved --shadow-modal */
  z-index: 20;
}

.bruger-dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  color: var(--color-text);
}

.bruger-dropdown-item:hover {
  background: var(--color-accent-soft);
}

/* Tema-toggle (Mørkt tema) i bruger-dropdownen */
.bruger-dropdown-item.tema-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.toggle-switch {
  width: 36px;
  height: 20px;
  flex-shrink: 0;
  border-radius: var(--radius-pill);
  background: var(--color-border);
  position: relative;
  transition: background var(--transition-fast);
}

.toggle-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  transition: transform var(--transition-fast);
}

.toggle-switch.on {
  background: var(--color-accent);
}

.toggle-switch.on::after {
  transform: translateX(16px);
}

/* Blødt tema-skift på flader/tekst (undgå hårdt farvespring ved toggle) */
body,
.sidebar,
.topbar,
.card,
.modal {
  transition: background-color var(--transition-base), color var(--transition-base),
    border-color var(--transition-base);
}

.checkbox-label {
  flex-direction: row !important;
  align-items: center;
  gap: var(--space-2);
}

.ret-tabel {
  width: 100%;
  border-collapse: collapse;
  margin: var(--space-2) 0;
}

.ret-tabel th,
.ret-tabel td {
  text-align: center;
  padding: 6px 8px;
}

.ret-tabel th:first-child,
.ret-tabel td:first-child {
  text-align: left;
}

/* Rettigheder-kolonnen: stak tekst over knap, og reservér plads til teksten så
   knappen står samme sted i alle rækker (uanset hvor meget rettighedstekst). */
.ret-resume {
  font-size: 13px;
  color: var(--color-text-muted);
  vertical-align: top;
}

.ret-resume-tekst {
  display: block;
  min-height: 2.6em;   /* reservér ~2 linjer, så knappen aligner på tværs af rækker */
  line-height: 1.3;
  margin-bottom: var(--space-1);
}

.ret-resume .btn {
  margin-left: 0;
}

/* Knappen åbner ikke dialogen, den forklarer hvorfor ikke. Den skal SE
   anderledes ud end en knap der handler — ellers er den misvisende — men den
   er hverken deaktiveret eller ikke-interaktiv.
   ⚠️ NOTEN HER SAGDE INDTIL 2.14.0 at der ingen :disabled-styling fandtes, og
   at `Emulér`, `Deaktivér` og `Slet` derfor så ud som aktive knapper når de var
   slået fra. Det holdt op med at være sandt: `.btn:disabled` findes nu (se
   noten dér), og `Emulér` bruger samme forklarende vej som denne knap — se
   static/js/emulerknap.js. Forudsigelsen var rigtig; den kostede en runde af
   preprod-testen på 2.14.0 før nogen faldt over den igen.
   Sættes med en klasse fra rettighedsknapForklaring(), ikke fra en
   disabled-attribut: knappen SKAL forblive klikbar og fokuserbar.
   Bevidst INGEN aria-disabled — den er klikbar, og en skærmlæser skal ikke
   få noget andet at vide. */
.btn-xs.ret-forklarer {
  color: var(--color-text-muted);
  border-color: var(--color-border);
  /* "her kan du få noget at vide", ikke "her sker en handling". */
  cursor: help;
}
/* Ingen farveskift og intet løft ved hover — .btn og .btn-secondary giver
   ellers begge dele, og de lover en handling.
   ⚠️ `outline` sættes bevidst INTET sted i denne regel. Appen har ingen egen
   fokus-styling på .btn, så fokusringen er browserens standard (outline: auto
   via :focus-visible). Rører man outline her, forsvinder den eneste
   fokusmarkering knappen har — og hele pointen med ikke at bruge disabled var
   netop at bevare tastaturvejen. */
.btn-xs.ret-forklarer:hover {
  background: var(--color-surface);
  color: var(--color-text-muted);
  transform: none;
}

/* Forklaringen på hvorfor dialogen ikke åbner. Skjult indtil knappen klikkes
   (hidden-attributten), så den ikke bliver til permanent tekst i tabellen —
   ved hover står den samme tekst i knappens title. */
/* ⚠️ `.handling-forklaring` ER MED HER FREM FOR AT VÆRE SIN EGEN REGEL, fordi
   den gør nøjagtig det samme: forklarer hvorfor en knap i rækken ikke gjorde
   noget. Den ligger blot i Handlinger-cellen i stedet for i rettigheds-cellen.

   ⚠️ HVORFOR TO STEDER OVERHOVEDET. Handlinger-kolonnen står yderst til højre
   i en bred tabel, og rettigheds-cellen kan være mange hundrede pixels væk.
   Lagde Emulér-knappen sin forklaring dér, ville teksten kunne stå uden for
   det brugeren kigger på — samme fejlform som fejlboksen bag dialogen, bare
   vandret. Forklaringen hører hjemme ved den knap der blev trykket på. */
.ret-forklaring,
.handling-forklaring {
  display: block;
  max-width: 32ch;
  margin-top: var(--space-1);
  font-size: 12px;
  line-height: 1.35;
  color: var(--color-text-muted);
}


/* ==========================================================================
   Udfoldelig nav-gruppe (Projekter) + undermenu
   ========================================================================== */

.nav-group-toggle {
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  color: var(--sidebar-text);
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

/* Hovedet i Projekter-gruppen: etiketten er et LINK til Overblik, pilen er en
   selvstændig knap ved siden af. De to er søskende, så et klik på pilen aldrig
   kan nå linket — se markuppen for hvorfor det blev valgt frem for
   stopPropagation. */
.nav-group-head {
  display: flex;
  align-items: center;
}

/* Linket fylder resten af rækken, så hele etiketten er klikbar og ikke kun
   ordet. `min-width: 0` så et langt navn kan afkortes frem for at skubbe pilen
   ud over kanten. */
.nav-group-link {
  flex: 1 1 auto;
  min-width: 0;
  margin-right: 4px;
}

/* Pilens eget klikområde. Højden følger .nav-item (44px), så etiket og pil står
   på linje og rækken ikke skifter højde.
   ⚠️ `padding: 0` ER NØDVENDIG. Den globale `button`-regel (se Knapper) sætter
   `padding: 9px 19px`, og .nav-group-toggle ovenfor nulstiller kun baggrund og
   ramme. Uden linjen her klemmes chevronen ud af sit eget felt — samme fælde
   som da `button:hover` slog igennem på "Mine projekter"-knappen. */
.nav-group-pil {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 32px;
  height: 44px;
  padding: 0;
  margin: 4px 8px 4px 0;
  border-radius: var(--radius-sm);
  color: var(--sidebar-text-muted);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-group-pil:hover {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-hover-text);
}

.nav-chevron {
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

/* ⚠️ `> .nav-group-toggle` ER IKKE PYNT. Reglen hed
   `.nav-group.udfoldet .nav-chevron` — en efterkommer-selektor, der rammer
   ENHVER chevron inde i gruppen, uanset hvor dybt den ligger. Det gik godt så
   længe der kun var én, men "Mine projekter" fik sin egen foldeknap inde i
   undermenuen, og dens pil blev dermed styret af PROJEKTER-gruppens tilstand.
   Fejlen var særligt svær at se, fordi de to tilstande næsten altid følges ad:
   Projekter-gruppen SKAL være udfoldet for at listen overhovedet er synlig, så
   pilen pegede permanent nedad og reagerede ikke på klik.
   En gruppe må kun rotere sin EGEN knaps pil.
   ⚠️ TO FORMER, FORDI DE TO GRUPPER ER BYGGET FORSKELLIGT. Admin-gruppen har
   stadig knappen som direkte barn; Projekter-gruppen har den inde i sit
   `.nav-group-head` ved siden af linket. Begge stier er skrevet ud frem for at
   falde tilbage på en efterkommer-selektor — dét var netop fejlen ovenfor. */
.nav-group.udfoldet > .nav-group-toggle .nav-chevron,
.nav-group.udfoldet > .nav-group-head > .nav-group-toggle .nav-chevron {
  transform: rotate(90deg);
}

.nav-subnav {
  display: none;
  flex-direction: column;
  gap: 2px;
}

.nav-group.udfoldet .nav-subnav {
  display: flex;
}

.nav-subitem {
  display: flex;
  align-items: center;
  height: 38px;
  padding: 0 var(--space-2);
  margin: 2px 8px 2px 22px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--sidebar-text-muted);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-subitem:hover {
  color: var(--sidebar-hover-text);
  background: var(--sidebar-hover-bg);
}

/* Vægten bærer forskellen mod hover — se --sidebar-active-bg. */
.nav-subitem.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  font-weight: 600;
}

/* ---------- Sidebar-footer: dokumentationsknap i bunden ---------- */

.sidebar-footer {
  margin-top: auto;             /* skub knappen ned i bunden når navigationen er kort */
  /* Sticky bottom: holder knappen synlig i bunden af sidebarens EGEN scroll
     (.sidebar har overflow-y: auto), også når navigationspunkterne er så
     mange at de scroller internt — uden dette skulle man scrolle sidebaren
     helt til enden for at nå knappen i det tilfælde. */
  position: sticky;
  bottom: 0;
  background: var(--sidebar-bg); /* forhindrer at scrollede nav-punkter skinner igennem bag den faste bund */
  padding: var(--space-1) 0 0;
  border-top: 1px solid var(--sidebar-border);
}

/* Diskret versionsnummer over dokumentationsknappen — hentes dynamisk fra
   CHANGELOG.md via /api/version (se auth-ui.js). Tom indtil hentet, og
   skjules helt hvis backend ikke kan finde en version. */
.sidebar-version {
  padding: 2px var(--space-2) 0;
  margin: 4px 8px 0;
  font-size: 11px;
  color: var(--sidebar-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-doc {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 44px;
  padding: 0 var(--space-2);
  margin: 4px 8px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 500;
  color: var(--sidebar-text);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-doc:hover {
  background: var(--sidebar-hover-bg);
  color: var(--sidebar-hover-text);
}

/* Vægten bærer forskellen mod hover — se --sidebar-active-bg. */
.nav-doc.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active-text);
  font-weight: 600;
}

.nav-doc-ikon {
  flex-shrink: 0;
}

/* ---------- Foldbart dokumentations-træ i footeren ----------
   Samme foldemønster som .nav-group i hovednavigationen, men bygget på
   footerens .nav-doc-knap. Undertræets indhold (Læringsvideoer + wiki.md's
   sektioner) fyldes af auth-ui.js. */

.nav-doc-toggle {
  width: calc(100% - 16px);     /* .nav-doc har margin: 4px 8px */
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

.nav-doc-toggle .nav-chevron {
  margin-left: auto;            /* skub pilen ud til højre kant */
}

/* Samme afgrænsning som .nav-group ovenfor. Footerens træer har ingen indlejret
   chevron i dag, så dette retter ikke noget synligt — men de to regler er samme
   mønster, og en af dem må ikke være den fælde den anden lige er blevet. */
.nav-doc-group.udfoldet > .nav-doc-toggle .nav-chevron {
  transform: rotate(90deg);
}

.nav-doc-subnav {
  display: none;
  flex-direction: column;
  gap: 2px;
  /* Antallet af sektioner vokser med wiki.md. Begræns højden, så træet ikke
     overtager sidebaren i en lav browser, og lad det scrolle internt i stedet. */
  max-height: 40vh;
  overflow-y: auto;
  padding-bottom: var(--space-1);
}

.nav-doc-group.udfoldet .nav-doc-subnav {
  display: flex;
}

/* Sektionstitler fra wiki.md er fri tekst og kan være lange — lad dem ombryde
   frem for at blive klippet af. .nav-subitem har ellers fast højde. */
.nav-doc-subnav .nav-subitem {
  height: auto;
  min-height: 34px;
  padding-top: 6px;
  padding-bottom: 6px;
  line-height: 1.3;
}

/* Status under fil-upload i videoadministrationen (uploader…/uploadet). */
.video-form-filstatus {
  margin: calc(-1 * var(--space-1)) 0 0;
  font-size: 13px;
  color: var(--color-text-muted);
}

/* ---------- Læring & vejledning: to sektioner på én side ---------- */

.laering-sektion {
  /* Afstand mellem de to sektioner, så de læses som adskilte blokke.
     scroll-margin-top: sektionerne nås via #ankre fra sidebaren — uden den
     ville overskriften lande klos op ad topbaren. */
  margin-bottom: var(--space-6, 40px);
  scroll-margin-top: var(--space-4, 24px);
}

.laering-sektion-titel {
  margin: 0 0 var(--space-1) 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--color-text-primary);
}

.laering-sektion-intro {
  margin: 0 0 var(--space-3) 0;
  color: var(--color-text-muted);
}

/* ---------- Dokumentationsside: renderet markdown + mermaid ---------- */

.doc-content {
  max-width: 900px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-4) var(--space-6);
  line-height: 1.65;
  color: var(--color-text-primary);
}

.doc-henter {
  color: var(--color-text-secondary);
}

.doc-content h1 {
  font-size: 26px;
  font-weight: 700;
  margin: 0 0 var(--space-2);
}

.doc-content h2 {
  font-size: 20px;
  font-weight: 600;
  margin: var(--space-4) 0 var(--space-2);
  padding-bottom: 6px;
  border-bottom: 1px solid var(--color-border);
}

.doc-content h3 {
  font-size: 16px;
  font-weight: 600;
  margin: var(--space-3) 0 var(--space-1);
}

.doc-content p {
  margin: 0 0 var(--space-2);
}

.doc-content ul,
.doc-content ol {
  margin: 0 0 var(--space-2);
  padding-left: var(--space-3);
}

.doc-content li {
  margin: 4px 0;
}

.doc-content a {
  color: var(--color-accent-text);
}

.doc-content a:hover {
  text-decoration: underline;
}

.doc-content code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: 1px 5px;
}

.doc-content pre {
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  overflow-x: auto;
  margin: 0 0 var(--space-2);
}

.doc-content pre code {
  background: none;
  border: none;
  padding: 0;
}

.doc-content blockquote {
  margin: 0 0 var(--space-2);
  padding: 6px var(--space-2);
  border-left: 3px solid var(--color-accent);
  background: var(--color-accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--color-text-secondary);
}

/* Brede tabeller i dokumentationen må ikke flyde ud over siden. docs.js pakker
   hver <table> i .doc-tabel-wrap efter markdown-rendering, så disse regler gælder
   automatisk for alle nuværende og fremtidige tabeller. */
.doc-tabel-wrap {
  overflow-x: auto;
  max-width: 100%;
  margin: 0 0 var(--space-2);
}

.doc-content table {
  border-collapse: collapse;
  width: 100%;
  max-width: 100%;
  margin: 0;
  font-size: 13px;
}

.doc-content th,
.doc-content td {
  border: 1px solid var(--color-border);
  padding: 6px 10px;
  text-align: left;
  word-break: break-word;   /* bryd lang tekst så cellen ikke tvinger tabellen bred */
  min-width: 80px;          /* men hold kolonner læsbare, ikke for smalle */
}

.doc-content th {
  background: var(--color-surface-2);
  font-weight: 600;
}

.doc-content hr {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: var(--space-3) 0;
}

/* Mermaid-diagrammer: centrér og lad brede diagrammer scrolle vandret. */
.doc-content .mermaid {
  margin: var(--space-2) 0 var(--space-3);
  text-align: center;
  overflow-x: auto;
}

/* SVG-UI-illustrationer i "Sådan bruger du systemet" (sektion 6): en
   ramme om skabelonens håndtegnede skærmbillede + nummererede klik-punkter.
   SVG'en selv bruger de samme CSS-variabler som resten af appen (fill/stroke
   via var(--color-...)), så den følger lyst/mørkt tema automatisk. */
.doc-content .vejledning-illustration {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  margin: 0 0 var(--space-2);
  padding: var(--space-2);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.doc-content .vejledning-illustration svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* ---------- Tovholder-oversigt ---------- */

.sh-projekter {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.sh-projekt {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* Mørkeblå projekt-header (jf. skitse). Fast navy der virker i begge temaer. */
.sh-projekt-header {
  background: #1f3a5f;
  color: #ffffff;
  font-weight: 600;
  font-size: 15px;
  padding: 14px var(--space-3);
}
:root.dark .sh-projekt-header,
body.dark .sh-projekt-header {
  background: #17335a;
}

.sh-opgaver {
  display: flex;
  flex-direction: column;
}

.sh-opgave {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 12px var(--space-3);
  border-top: 1px solid var(--color-border);
}
.sh-opgave:first-child {
  border-top: none;
}

.sh-opgave-tekst {
  min-width: 0;
}
.sh-opgave-navn {
  font-weight: 500;
  color: var(--color-text-primary);
}
.sh-opgave-fase {
  font-weight: 400;
  font-size: 12px;
  color: var(--color-text-muted);
  margin-left: 6px;
}
.sh-opgave-beskrivelse {
  margin-top: 3px;
  font-size: 13px;
  color: var(--color-text-secondary);
}

/* Fold-ud til beskrivelsen (skjult som standard, se tovholder.js). */
.sh-opgave-detaljer {
  margin-top: 3px;
}
.sh-opgave-detaljer summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--color-text-muted);
  list-style: none;
}
.sh-opgave-detaljer summary::-webkit-details-marker {
  display: none;
}
.sh-opgave-detaljer summary::before {
  content: "▸ ";
}
.sh-opgave-detaljer[open] summary::before {
  content: "▾ ";
}
.sh-opgave-detaljer .sh-opgave-beskrivelse {
  margin-top: 4px;
}

.sh-opgave-status {
  flex-shrink: 0;
}

.sh-tom {
  padding: 14px var(--space-3);
  color: var(--color-text-muted);
  font-size: 13px;
}

/* ---------- Projektleder-overblik (forsiden) ---------- */

.pl-overblik {
  margin-bottom: var(--space-4);
}
.pl-overblik-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
  margin-bottom: var(--space-2);
}
.pl-overblik-top .sektion-titel {
  margin: 0;
}

/* ---------- Alle opgaver (foldbar sektion på projekter.html) ---------- */

.alle-opgaver-sektion {
  margin-top: var(--space-4);
}

.alle-opgaver-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
  text-align: left;
}

.alle-opgaver-toggle .nav-chevron {
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

.alle-opgaver-toggle[aria-expanded="true"] .nav-chevron {
  transform: rotate(90deg);
}

.alle-opgaver-toggle .sektion-titel {
  margin: 0;
}

.alle-opgaver-toggle-hint {
  color: var(--color-text-muted);
  font-size: 13px;
  font-weight: 400;
}

.alle-opgaver-indhold {
  margin-top: var(--space-3);
}

.pl-liste {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.pl-projekt {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.pl-projekt-hoved {
  display: flex;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  flex-wrap: wrap;
  padding: 12px var(--space-3);
}
.pl-projekt-info {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-width: 180px;
  flex: 1 1 220px;
}
.pl-projekt-navn {
  font-weight: 600;
  font-size: 15px;
  color: var(--color-text-primary);
  text-decoration: none;
}
.pl-projekt-navn:hover { text-decoration: underline; }

.pl-projekt-status {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.pl-status-tal {
  font-size: 13px;
  color: var(--color-text-secondary);
}

.pl-kategori {
  border-top: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border);
  padding: 10px var(--space-3);
}
.pl-kategori-overskredet { border-left-color: var(--color-red); }
.pl-kategori-idag        { border-left-color: var(--color-yellow); }
.pl-kategori-upcoming    { border-left-color: #e8833a; }
/* Genbrugt i tovholder.js's start-baserede kategorier (se tovholder.js). */
.pl-kategori-forsinket   { border-left-color: var(--color-red); }
.pl-kategori-kommende    { border-left-color: #e8833a; }
.pl-kategori-oevrige     { border-left-color: var(--color-text-muted); }

.pl-kategori-titel {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-secondary);
  margin-bottom: var(--space-1);
}
.pl-kategori-antal {
  color: var(--color-text-muted);
  font-weight: 500;
}
.pl-kategori-opgaver {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  /* Intern scroll ved mange opgaver i én kategori — samme mønster som
     .table-scroll ("Alle opgaver"). Bruges af både tovholder-overblikket
     (tovholder.js) og projektleder-overblikket (pl-overblik.js). */
  overflow-y: auto;
  max-height: 65vh;
  scrollbar-width: thin;
  scrollbar-color: var(--color-text-muted) var(--color-border);
}
.pl-kategori-opgaver::-webkit-scrollbar {
  width: 12px;
}
.pl-kategori-opgaver::-webkit-scrollbar-track {
  background: var(--color-border);
  border-radius: var(--radius-pill);
}
.pl-kategori-opgaver::-webkit-scrollbar-thumb {
  background: var(--color-text-muted);
  border-radius: var(--radius-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
.pl-kategori-opgaver::-webkit-scrollbar-thumb:hover {
  background: var(--color-text-secondary);
  background-clip: content-box;
}

.pl-opgave {
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: var(--color-bg);
}
.pl-opgave-hoved {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}
.pl-opgave-navn {
  font-weight: 500;
  color: var(--color-text-primary);
}
.pl-opgave-besk {
  margin-top: 2px;
  font-size: 13px;
  color: var(--color-text-secondary);
}
.pl-opgave-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px var(--space-2);
  margin-top: 4px;
  font-size: 12px;
  color: var(--color-text-muted);
}
.pl-meta-deadline {
  font-weight: 500;
  color: var(--color-text-secondary);
}

/* Udfoldet opgave-del af et projekt-kort. */
.pl-projekt-opgaver {
  border-top: 1px solid var(--color-border);
}
.pl-projekt-opgaver > .pl-kategori:first-child {
  border-top: none;   /* undgå dobbelt-streg mod header */
}
.pl-ingen-deadlines {
  margin: 0;
  padding: 12px var(--space-3);
  color: var(--color-text-muted);
  font-size: 13px;
}

/* ==========================================================================
   Videoer (LMS): offentlig visning (videoer.html) + admin (video-admin.html)
   ========================================================================== */

.vid-sektion {
  margin-bottom: var(--space-4);
}

.vid-sektion-titel {
  font-size: 18px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0 0 4px;
}

.vid-sektion-beskrivelse {
  color: var(--color-text-secondary);
  font-size: 13px;
  margin: 0 0 var(--space-2);
}

.vid-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-2);
}

.vid-kort {
  background: var(--color-surface);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  /* ⚠️ `border: none` nulstiller <button>-arven og SKAL derfor stå EFTER
     kortets egen kant, ellers fjerner den den igen. Kortet er en knap. */
  border: 1px solid var(--color-border);
  padding: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  font: inherit;
  color: inherit;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.vid-kort:hover {
  border-color: var(--color-accent-border);
}

.vid-kort-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--color-surface-2);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.vid-kort-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.vid-kort-play {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}

/* Afspil-trekanten i et HJØRNE frem for i midten.
   ⚠️ Trekanten fjernes ALDRIG — den er kortets eneste signal om at det er en
   video og ikke et dokument. På titelskærmen flyttes den blot, så den ikke
   konkurrerer med teksten. */
.vid-kort-play-hjoerne {
  position: absolute;
  left: 8px;
  bottom: 8px;
  width: 28px;
  height: 28px;
}

/* Titelskærmen: fald-tilbage når en video ingen thumbnail har.
   ⚠️ INGEN BILLEDFIL. Kortet tegnes af appens egne CSS-variabler, så det
   følger temaskift og en rettet titel automatisk. Se static/js/video-miniature.js
   for hvorfor en genereret fil blev valgt fra. */
.vid-titelskaerm {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-2) 34px;
  background: linear-gradient(
    135deg,
    var(--color-surface-2) 0%,
    var(--color-surface) 100%
  );
  /* Diskret indramning, så titelskærmen ikke forveksles med et billede der
     ikke blev hentet — en helt flad flade ligner en fejl. */
  box-shadow: inset 0 0 0 1px var(--color-border);
}

.vid-titelskaerm-tekst {
  color: var(--color-text);
  /* ⚠️ TYDELIGT STØRRE END TITLEN I KORTETS KROP (14px), og det er ikke pynt.
     Titlen står to steder på et kort uden thumbnail — på forsiden og under
     den. I næsten samme størrelse læses det som en dublet, altså som en fejl.
     Med den her forskel læses forsiden som et COVER, hvilket er hvad den er. */
  font-size: 19px;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.25;
  /* ⚠️ Klippes efter to linjer. En lang titel må ikke kunne vokse ud over
     16:9-rammen og skubbe gitteret skævt — og kroppen under viser alligevel
     titlen i fuld længde. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.vid-kort-varighed {
  position: absolute;
  right: 6px;
  bottom: 6px;
  background: rgba(0, 0, 0, 0.75);
  color: #fff;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 4px;
  line-height: 1.4;
}

.vid-kort-body {
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.vid-kort-titel {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0;
}

.vid-kort-beskrivelse {
  font-size: 12px;
  color: var(--color-text-secondary);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Afspilnings-modal */
.vid-modal .modal {
  max-width: 860px;
  width: 90vw;
}

.vid-modal-player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.vid-modal-player iframe,
.vid-modal-player video {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.vid-modal-beskrivelse {
  color: var(--color-text-secondary);
  font-size: 13px;
  margin: var(--space-2) 0 0;
}

/* Admin: kategori-liste (samme mønster som .fase-liste/.fase-item) */
.vid-kategori-liste {
  list-style: none;
  margin: var(--space-2) 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.vid-kategori-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.vid-kategori-item .vid-kategori-navn-input {
  flex: 1;
}

.vid-kategori-item-knapper {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}

/* Admin: video-gruppe pr. kategori */
.vid-admin-gruppe {
  margin-bottom: var(--space-3);
}

.vid-admin-gruppe-titel {
  font-size: 15px;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0 0 var(--space-1);
}

/* ==========================================================================
   Feedback (widget + administration)
   ========================================================================== */

/* Type/status-badges — samme farvevariabler som opgave-badgene ovenfor, bare
   med egne navne så feedback-koden ikke skal genbruge opgave-terminologi. */
.badge-fb-bug         { background: var(--badge-hold-bg);     color: var(--badge-hold-text); }
.badge-fb-oenske      { background: var(--badge-progress-bg); color: var(--badge-progress-text); }
.badge-fb-ny          { background: var(--badge-neutral-bg);  color: var(--badge-neutral-text); }
.badge-fb-behandling  { background: var(--badge-progress-bg); color: var(--badge-progress-text); }
.badge-fb-loest       { background: var(--badge-done-bg);     color: var(--badge-done-text); }

/* Widget: to store valgknapper i stedet for almindelige radioknapper. */
.fb-type-valg {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.fb-type-knap {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: var(--space-3) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.fb-type-knap .fb-type-ikon {
  font-size: 22px;
  line-height: 1;
}

.fb-type-knap.valgt {
  border-color: var(--color-accent);
  color: var(--color-accent-text);
  box-shadow: 0 0 0 1px var(--color-accent);
}

.fb-billede-info {
  font-size: 12px;
  color: var(--color-text-muted);
  margin: -4px 0 0;
}

/* Admin: besked-forhåndsvisning i tabellen (trunkeret), fuld tekst i detaljer. */
.fb-besked-kort {
  max-width: 360px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fb-detalje-besked {
  white-space: pre-line;
  margin: 0 0 var(--space-2);
}

.fb-billeder {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.fb-thumbnail {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  cursor: pointer;
}

.fb-status-select {
  font-size: 12px;
  padding: 2px 6px;
}

/* Svar til den der meldte ind.
   ⚠️ INGEN NYE FARVETOKENS. Blokken låner husets eksisterende variabler, så
   den følger temaskiftet uden at nogen skal huske at vedligeholde et par
   hex-værdier mere — se noten om --color-accent i toppen af denne fil om hvad
   et token der betyder noget andet end det hedder koster. */
.fb-svar {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
}

.fb-svar-post {
  border-left: 3px solid var(--color-border);
  padding-left: var(--space-2);
}

.fb-svar-meta {
  display: block;
  font-size: 12px;
  color: var(--color-text-muted);
}

.fb-svar-tekst {
  white-space: pre-line;
  margin: 2px 0 0;
}

.fb-svar-label {
  display: block;
  margin: var(--space-3) 0 var(--space-1);
  font-weight: 500;
}

/* ⚠️ `font: inherit` ER IKKE PYNT — UDEN DEN ER FELTET MONOSPACE.
   Browserens UA-stylesheet giver <textarea> monospace, og huset har kun
   `font-family: inherit` på `button`, ikke på felter. Målt i browseren 22/8:
   feltet stod på "monospace" 13.33px mens siden kører Inter.
   ⚠️ Samme fejl rammer appens ØVRIGE textareas, heriblandt widgettens
   `#fb-besked` — den er ældre end denne bid og er ikke rettet her.
   ⚠️ `.skabelon-form textarea` er monospace MED VILJE (skabelontekster med
   {tokens}) — den regel skal ikke rulles ind i en app-bred oprydning. */
#fb-svar-tekst {
  width: 100%;
  resize: vertical;
  font: inherit;
}

/* ==========================================================================
   Organisationshierarki (admin) — Afdeling → Team → Gruppe
   ========================================================================== */

.org-trae {
  padding: var(--space-2);
}

.org-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Indrykning pr. niveau: hver indlejret liste rykkes ind og får en lodret
   guide-streg, så hierarkiet er visuelt aflæseligt uden ikoner. */
.org-liste .org-liste {
  margin-left: var(--space-3);
  padding-left: var(--space-2);
  border-left: 1px solid var(--color-border);
  margin-top: 4px;
}

.org-enhed {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px var(--space-2);
  border-radius: var(--radius-sm);
}

.org-enhed:hover {
  background: var(--color-surface-2);
}

.org-navn {
  font-weight: 500;
}

.org-niveau-badge {
  background: var(--color-surface-2);
  color: var(--color-text-muted);
}

/* Lederen står ved siden af navnet, dæmpet, så træets struktur læses først.
   "Ingen leder" vises som en synlig vakance frem for et tomt felt — samme
   princip som Team-fanens "Ukendt" (se stoplys.js): en manglende værdi skal
   kunne skelnes fra en værdi ingen har taget stilling til. */
.org-leder {
  font-size: 13px;
  color: var(--color-text-muted);
}

.org-leder-mangler {
  font-style: italic;
  opacity: 0.7;
}

/* Handlingsknapperne skubbes til højre og vises først ved hover, så træet
   er roligt at læse — samme idé som .afh-pills på projektsiden. */
.org-handlinger {
  margin-left: auto;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.org-enhed:hover .org-handlinger,
.org-handlinger:focus-within {
  opacity: 1;
}

/* ---------- Kolonne-resize på opgavetabellen ---------- */

/* <th> skal være position:relative for at håndtaget kan placeres i kanten.
   .table-compact th har allerede sticky-positionering i .table-scroll, så vi
   sætter kun relative hvor det ikke er tilfældet. */
#tabel-view thead th {
  position: relative;
}

.kolonne-resize-haandtag {
  position: absolute;
  top: 0;
  right: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  /* Usynligt indtil hover — kolonneoverskrifterne skal ikke støjes til. */
  background: transparent;
  user-select: none;
}

.kolonne-resize-haandtag:hover,
body.kolonne-resizes .kolonne-resize-haandtag:active {
  background: var(--color-accent);
}

/* Under selve trækket: undgå at teksten markeres, og hold col-resize-markøren
   uanset hvor musen befinder sig på siden. */
body.kolonne-resizes {
  cursor: col-resize;
  user-select: none;
}

/* ---------- Kolonnerækkefølge på opgavetabellen (026) ---------- */
/* Samme mønster som Cutoverplanens rækketræk (.cutover-traekkes/-drop-target)
   ovenfor, bare vandret: et træk her flytter en KOLONNE, ikke en række.
   Handlinger er (efter Mortens omgørelse) en kolonne som alle de andre og får
   samme klasser — se opsaetKolonneDragDrop i projekt.js. */
#tabel-view thead th[draggable="true"] {
  cursor: grab;
}

.th-traekkes {
  opacity: 0.5;
}

.th-drop-target {
  /* Venstre kant, ikke top: flytKolonne indsætter kilden lige FØR målet. */
  box-shadow: inset 2px 0 0 var(--color-accent);
}

/* ---------- Team-fanen (2.0 Ressourcestyring) ---------- */

/* Stoplys for en persons samlede ugentlige belastning på TVÆRS af projekter.
   Farven beregnes server-side (app/routers/team.py) — frontend vælger kun
   klassen, så de to aldrig kan blive uenige. */
.team-stoplys {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  white-space: nowrap;
}

.team-stoplys-groen {
  background: var(--color-success-soft, #e6f4ea);
  color: var(--color-success, #1e7e34);
}

.team-stoplys-gul {
  background: var(--color-warning-soft, #fff4e5);
  color: var(--color-warning, #a15c00);
}

.team-stoplys-roed {
  background: var(--color-danger-soft, #fdeaea);
  color: var(--color-danger, #b3261e);
}

/* "Ukendt" er IKKE grøn: brugeren mangler ugentlig arbejdstid eller global
   projekt-allokering, så belastningen kan ikke beregnes. Neutral/stiplet, så
   den ikke forveksles med en blåstempling. */
.team-stoplys-ukendt {
  background: transparent;
  color: var(--color-text-muted);
  border: 1px dashed var(--color-border);
}

.team-email {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* ---------- Team-fanens to blokke ----------
   ⚠️ DE TO SKAL KUNNE SKELNES VED ET BLIK, OG DET ER EN RETTELSE (14/8).
   "Områdeansvarlige" og "Holdet" havde hverken overskrift eller egen flade, og
   deres tilføj-rækker delte klassen `.team-tilfoej` — samme layout, samme blå
   knap, lige under hinanden. Morten forvekslede dem i manuel test og tilføjede
   tre personer som bidragydere i den tro at han udnævnte områdeansvarlige.
   De to skriver til hver sin tabel (projekt_rolle mod project_team_member)
   gennem hver sit endpoint med hver sin rettighedsregel.
   ⚠️ Adskillelsen er BÅDE overskrift, baggrund og en farvet kant. Kun én af
   delene ville falde bort i mørkt tema eller for en farveblind læser. */
.team-blok-titel {
  margin: 0;
  padding: var(--space-3) var(--space-3) var(--space-1);
  font-size: 0.9375rem;
}

.team-blok-note {
  margin: 0;
  padding: 0 var(--space-3) var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Ansvarsblokken får sin egen flade, så den læses som et afsnit for sig og
   ikke som toppen af holdtabellen. */
.team-blok-ansvar {
  background: var(--color-surface-2);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);
}

/* Fejllinjen ved kontrollen. `flex-basis: 100%` giver den sin egen linje under
   felterne i stedet for at klemme sig ind ved siden af knappen — beskederne er
   hele sætninger fra serveren ("En områdeansvarlig skal have et område. Vælg
   en enhed i organisationen."), ikke etiketter. */
.team-blok-fejl {
  flex-basis: 100%;
  margin: 0;
}

/* Forklaringen der står i stedet for ansvarsblokken. Neutral flade, ikke
   fejlfarve: at et projekt ikke er en butiksproces er en TILSTAND, ikke en
   fejl — samme skelnen som den rolige boks ved påmindelsernes 409. */
.team-blok-forklaring {
  padding: var(--space-3);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

.team-tilfoej {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.team-tilfoej #team-bruger {
  min-width: 220px;
}

.team-tilfoej #team-timer {
  width: 120px;
}

/* Sletning af en bruger er undtagelsen, ikke den normale vej ud — se
   static/js/admin.js. Knappen skal kunne findes, men ikke invitere: ingen
   fyldfarve, dæmpet tekst, og først rød når man har markøren på den. */
.btn-slet-diskret {
  background: transparent;
  border: 1px solid transparent;
  color: var(--color-text-muted);
  text-decoration: underline;
}

.btn-slet-diskret:hover:not(:disabled) {
  color: var(--color-danger, #b3261e);
  border-color: currentColor;
  text-decoration: none;
}

/* Værste uge vises ved siden af stoplyset (2.5c) — uden den er tallet
   udiagnosticerbart. Dæmpet: det er en henvisning, ikke en vurdering. */
.team-vaerste-uge {
  margin-left: var(--space-2);
  font-size: 0.6875rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* Ingen uger i horisonten. Neutral som "Ukendt", men visuelt adskilt — de to
   kræver modsatte handlinger: den ene "ret brugerens felter", den anden "her
   er ledig kapacitet". */
.team-stoplys-ingen {
  color: var(--color-text-muted);
  border: 1px dashed var(--color-border);
}

/* ---------- Ugegitter (2.5b) ---------- */

.uge-topbar {
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.uge-forklaring {
  margin: 0 0 var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  max-width: 60ch;
}

.uge-signatur {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.uge-signatur li {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.uge-signatur-prik {
  display: inline-block;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 2px;
  border: 1px solid var(--color-border);
}

.uge-signatur-maerke {
  flex-basis: 100%;
}

.uge-udenfor,
.uge-udenfor-liste {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: var(--space-2) var(--space-3);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
}

.uge-udenfor-liste {
  display: block;
  max-width: 70ch;
}

.uge-tom {
  padding: var(--space-3);
}

/* Et årelangt projekt giver 52+ kolonner. Kun gitteret scroller vandret —
   ikke siden — og medlemsnavnene bliver stående. */
.uge-scroll {
  overflow-x: auto;
  max-width: 100%;
}

.uge-gitter {
  border-collapse: separate;
  border-spacing: 0;
}

.uge-gitter th,
.uge-gitter td {
  border-bottom: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  padding: 2px 4px;
}

/* ⚠️ Navnekolonnen er sticky. Uden den mister man rækken af syne så snart man
   scroller ud i ugerne, og gitteret bliver ubrugeligt på lange projekter. */
.uge-navn-kolonne {
  position: sticky;
  left: 0;
  z-index: 2;
  min-width: 11rem;
  text-align: left;
  font-weight: 500;
  background: var(--color-surface, #fff);
  box-shadow: 1px 0 0 var(--color-border);
}

.uge-baseline {
  display: block;
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--color-text-muted);
}

.uge-gitter thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-surface, #fff);
}

.uge-gitter thead .uge-navn-kolonne {
  z-index: 3;
}

.uge-kolonne {
  min-width: 3.25rem;
  text-align: center;
  font-weight: 500;
  vertical-align: bottom;
}

/* Året vises kun når det skifter — så det er netop dér, øjet skal fanges. */
.uge-aar {
  display: block;
  font-size: 0.625rem;
  color: var(--color-text-muted);
}

.uge-nr {
  display: block;
  font-size: 0.75rem;
}

.uge-celle {
  text-align: center;
  min-width: 3.25rem;
}

.uge-input {
  width: 2.75rem;
  border: 1px solid transparent;
  border-radius: 2px;
  background: transparent;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--color-text);
  padding: 2px 0;
}

.uge-input:hover {
  border-color: var(--color-border);
}

.uge-input:focus {
  outline: none;
  border-color: var(--color-text);
  background: var(--color-surface, #fff);
}

/* ⚠️ ARVET BASELINE VS. BEVIDST PLANLAGT — samme tal, to tilstande.
   Placeholderen (arvet) står gråt og i kursiv; en sat værdi står normalt og
   får en markering i venstre kant. Uden skellet kan projektlederen ikke se
   hvad der er taget stilling til. */
.uge-input::placeholder {
  color: var(--color-text-muted);
  font-style: italic;
  opacity: 0.75;
}

.uge-celle:not(.uge-celle-baseline) {
  box-shadow: inset 2px 0 0 var(--color-text-muted);
}

.uge-celle-arvet {
  color: var(--color-text-muted);
  font-style: italic;
}

/* Baggrunden er personens SAMLEDE belastning i ugen — ikke tallet i feltet.
   Samme farver som stoplyset og risikomatrixen.

   ⚠️ "SAMME FARVER SOM STOPLYSET" VAR ET LØFTE, IKKE EN MEKANISME. De tre
   værdier stod som hardkodede rgba'er ved siden af --rag-*-soft, og de var
   ikke engang identiske med dem (0.16/0.20/0.18 mod 0.18/0.20/0.14). Da
   accenten blev lagt om, fulgte tokenerne med og disse tre gjorde ikke — den
   røde ville have stået tilbage i den gamle brandrød, synlig kun når en
   person FAKTISK er overbelastet. Nu peger de på tokenerne, så løftet holdes
   af koden i stedet for af en kommentar. Samme rettelse i .risiko-niveau-*. */
.uge-stoplys-groen, .hm-stoplys-groen { background: var(--rag-green-soft); }
.uge-stoplys-gul, .hm-stoplys-gul   { background: var(--rag-yellow-soft); }
.uge-stoplys-roed, .hm-stoplys-roed  { background: var(--rag-red-soft); }

/* ---------- Risikomatrix (2.4b) ---------- */

.stamkort-hoved-underafsnit {
  border-top: 1px solid var(--color-border);
  border-bottom: none;
}

.stamkort-underoverskrift-inline {
  padding: 0;
  border: none;
}

.stamkort-hoved-knapper {
  display: flex;
  gap: var(--space-2);
}

.risiko-tom {
  padding: var(--space-3);
}

.risiko-matrix-wrap {
  padding: var(--space-3);
  overflow-x: auto;
}

.risiko-matrix {
  border-collapse: collapse;
}

.risiko-matrix-caption {
  caption-side: bottom;
  padding-top: var(--space-2);
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-align: left;
}

/* Aksernes ordetiketter står UNDER tallet — de er hele pointen med skalaen,
   men må ikke skubbe cellerne fra hinanden. */
.risiko-matrix th {
  padding: var(--space-1) var(--space-2);
  font-weight: 500;
  text-align: left;
  vertical-align: bottom;
}

.risiko-akse-tal {
  display: block;
  font-size: 0.8125rem;
}

.risiko-akse-tekst {
  display: block;
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--color-text-muted);
  max-width: 7rem;
}

.risiko-celle {
  padding: 2px;
}

.risiko-celle-knap {
  width: 3rem;
  height: 2.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm, 3px);
  background: transparent;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--color-text);
  cursor: pointer;
}

.risiko-celle-knap:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 1px;
}

/* Farven følger cellens EGEN score — ikke antallet i den. Se
   static/js/risiko.js. */
/* Tokener og ikke hardkodede rgba'er — se noten ved .uge-stoplys-*. */
.risiko-niveau-groen { background: var(--rag-green-soft); }
.risiko-niveau-gul   { background: var(--rag-yellow-soft); }
.risiko-niveau-roed  { background: var(--rag-red-soft); }

.risiko-score {
  display: inline-block;
  min-width: 1.75rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-sm, 3px);
  text-align: center;
  font-weight: 600;
}

/* ⚠️ Accepterede risici er TILBAGETRUKNE, ikke skjulte og ikke flyttet. Øjet
   skal kunne springe dem over når man scanner efter noget at handle på, mens
   de bliver stående på deres plads i score-rækkefølgen. */
.risiko-raekke-accepteret {
  opacity: 0.62;
}

.risiko-raekke-accepteret td:first-child {
  border-left: 2px dashed var(--color-border);
  padding-left: var(--space-2);
}

.risiko-modal-krop {
  padding: var(--space-3);
}

.risiko-filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
}

.risiko-vis-lukkede {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.risiko-filter-bar .btn-primary {
  margin-left: auto;
}

.risiko-form {
  border-top: 1px solid var(--color-border);
  margin-top: var(--space-3);
  padding-left: 0;
  padding-right: 0;
}

/* Sletning er visuelt adskilt fra Gem/Annullér — ikke ved farve (rød er
   primærfarven i dette designsystem), men ved at ligge for sig selv under en
   streg med en forklaring der peger på "lukket" som alternativet. */
.risiko-slet-afsnit {
  grid-column: 1 / -1;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--color-border);
}

.risiko-slet-forklaring {
  margin: 0 0 var(--space-2);
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

/* ---------- Projektstamkort (2.3c) ---------- */

.stamkort-hoved {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.stamkort-titel {
  margin: 0;
  font-size: 1rem;
}

.stamkort-underoverskrift {
  margin: 0;
  padding: var(--space-3);
  font-size: 0.9375rem;
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

/* To kolonner på brede skærme, én på smalle. Formålsfeltet fylder begge. */
.stamkort-felter,
.stamkort-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-3);
}

.stamkort-felt {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.stamkort-felt-bred {
  grid-column: 1 / -1;
}

.stamkort-felt dt,
.stamkort-felt > span {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

.stamkort-felt dd {
  margin: 0;
  /* Formålsteksten er fritekst og kan indeholde linjeskift og lange ord. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.stamkort-form-knapper {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

/* Manglende drift/projekt-split (2.3d). Mærket står ved siden af stoplyset,
   ikke i stedet for — belastning og datagrundlag er to akser. */
.team-split-maerke {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 0 var(--space-1);
  font-size: 0.6875rem;
  white-space: nowrap;
  border-radius: var(--radius-sm, 3px);
  color: var(--color-text-muted);
  border: 1px dashed var(--color-border);
}

.team-split-advarsel {
  margin: var(--space-2) 0 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Afkrydsningsfeltet fylder begge kolonner og har teksten ved siden af boksen
   frem for over den, som de øvrige stamkort-felter. */
.stamkort-felt-afkryds {
  grid-column: 1 / -1;
}

.stamkort-felt-afkryds .afkryds {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  text-transform: none;
  letter-spacing: normal;
}

/* ---------- Rolle-afkrydsningsfelter i brugeradmin ---------- */

/* is_admin og is_tovholder er UAFHÆNGIGE flag, ikke tre gensidigt
   udelukkende roller — derfor checkboxes frem for en <select>. */
.afkryds {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 500;
}

.afkryds input[type="checkbox"] {
  width: auto;
  margin: 0;
  flex: none;
}

.hjaelpetekst {
  font-weight: 400;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* ---------- "Mine projekter" i sidebaren ---------- */

/* Overskriften er KONTROLLEN der folder listen sammen, men den skal LIGNE de
   øvrige menupunkter. Derfor bærer elementet `.nav-subitem` som alle andre
   punkter i undermenuen, og denne regel nulstiller kun det en <button> selv
   slæber med sig. Der er ikke længere en `.nav-projekt-titel`: den satte sin
   egen skriftstørrelse, vægt, versaler og bogstavafstand, OG genberegnede
   indrykningen som `38px = 22 + 16` — altså præcis dét .nav-subitem giver af
   sig selv med margin 22 og padding 16. To regler om samme sag med hver sine
   tal er dét der lod overskriften drive fra menupunkterne.
   ⚠️ `font-family: inherit` er ikke pynt: en <button> arver den ikke selv, og
   uden linjen skifter overskriften til browserens knap-skrifttype — netop den
   slags forskel man leder efter alle andre steder end i en manglende arv. */
.nav-projekt-toggle {
  /* ⚠️ EN <button> STRÆKKER SIG IKKE SOM ET <a>. Undermenuen er en
     kolonne-flexbox, hvor `align-items: stretch` giver ankrene fuld bredde af
     sig selv — men en formkontrol beholder sin shrink-to-fit-bredde, og
     `align-self: stretch` ændrer det ikke (målt: 138px mod ankrenes 173px).
     Uden fuld bredde er der ingen ledig plads at fordele, og chevronens
     `margin-left: auto` nedenfor resolverer til 0. Pilen glider da ind til
     teksten i stedet for at stå i højre kant.
     ⚠️ `width: 100%` er IKKE svaret: en procent måles mod containerens bredde
     og kender ikke .nav-subitem's 22px + 8px margener, så knappen løb 30px ud
     over kanten. `stretch` (og de to ældre stavemåder) betyder netop "fyld
     containeren MINUS mine egne margener" — derfor holder den, uanset hvad
     margenerne senere ændres til. Målt: 173px, nøjagtig som ankrene. */
  width: -moz-available;
  width: -webkit-fill-available;
  width: stretch;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  /* ⚠️ `text-align: left` ER IKKE OVERFLØDIG, selvom knappen er en flexbox.
     En <button> centrerer sin tekst som standard, og .nav-item-label har
     `flex: 1` — etiketten strækker sig altså over hele den ledige bredde og
     centrerer teksten INDE I SIG SELV. Resultatet er at overskriften rykker
     ind til midten og holder op med at flugte med "Skabeloner" og
     projektnavnene, mens elementets egen venstrekant står helt korrekt.
     Fejlen er derfor svær at måle sig frem til: både knappen og etiketten
     ligger præcis hvor de skal. .nav-group-toggle har linjen af samme grund. */
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

/* ⚠️ INGEN EGEN :hover-REGEL MERE. Den stod her for at holde den globale
   `button:hover` ude — dén sætter `var(--color-border)`, en INDHOLDS-farve,
   inde i en sidefane med sine egne tokens. Nu bærer elementet `.nav-subitem`,
   hvis `:hover` har både højere specificitet end `button:hover` og præcis de
   samme to værdier. En kopi ved siden af ville være to steder at rette. */

/* Skub pilen ud til højre kant — samme greb som .nav-doc-toggle i footeren. */
.nav-projekt-toggle .nav-chevron {
  margin-left: auto;
}

/* Samme foldemønster som .nav-group og .nav-doc-group: klassen `udfoldet`
   styrer både pilens retning og indholdets synlighed. Pilen peger til højre
   når listen er foldet sammen, og nedad når den er åben.
   ⚠️ Listen har bevidst INGEN egen hidden-attribut mere. Gruppen bærer den —
   og [hidden] { display: none !important } (se Reset/base) ville alligevel slå
   enhver klasse her, så to mekanismer på samme element ville før eller siden
   trække i hver sin retning. */
.nav-projekt-gruppe.udfoldet > .nav-projekt-toggle .nav-chevron {
  transform: rotate(90deg);
}

.nav-projekt-gruppe:not(.udfoldet) .nav-projekt-liste {
  display: none;
}

/* INTERN SCROLL, ikke et loft. Samme mønster som 1.11.2 indførte for
   "Denne uges opgaver", tovholder-overblikket og projektleder-overblikket.
   Et loft ("vis kun de 10 første") ville skjule projekter man ikke kan nå på
   anden vis fra sidebaren — for et navigationselement er det en fejl, ikke en
   begrænsning. */
.nav-projekt-liste {
  max-height: 40vh;
  overflow-y: auto;
}

/* Projekterne rykkes ét trin længere ind end overskriften, så det kan SES at de
   hører under den — en foldet gruppe siger ellers ikke hvad der forsvandt.
   ⚠️ 44 = 22 + 22, altså .nav-subitem's egen margin-left brugt to gange. Det er
   ikke en ny indrykning, men det samme trin som fra topniveau til undermenu,
   anvendt en gang mere. Samme skrivemåde som `38px` ovenfor, hvor tallet også
   er en sum af eksisterende værdier og ikke en aflæsning. Ændres .nav-subitem's
   22px, skal begge steder følge med. */
.nav-projekt-item {
  margin-left: 44px;
}

/* Projektnavne kan være lange; de afkortes frem for at bryde sidebarens
   bredde. Det fulde navn ligger i title-attributten. */
.nav-projekt-item .nav-item-label {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* ==========================================================================
   Ledelses-heatmap (ressourcestyring.html)
   ========================================================================== */

/* Samme greb som ugegitteret i 2.5b: kun gitteret scroller, ikke siden. Et
   årsspænd i uge-visning giver 52+ kolonner, og uden det ville hele siden
   skride vandret. */
.hm-scroll {
  overflow-x: auto;
  max-width: 100%;
}

.hm-gitter {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}

.hm-gitter th,
.hm-gitter td {
  border-bottom: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  padding: 4px 6px;
  font-size: 0.8125rem;
}

/* ⚠️ Navnekolonnen er sticky vandret. Uden den mister man rækken af syne så
   snart man scroller ud i perioderne — og et heatmap hvor man ikke ved hvis
   række man kigger på er ubrugeligt. */
.hm-navn-kolonne {
  position: sticky;
  left: 0;
  z-index: 2;
  min-width: 12rem;
  text-align: left;
  font-weight: 500;
  background: var(--color-surface, #fff);
  box-shadow: 1px 0 0 var(--color-border);
}

/* Overskrifterne er sticky lodret: mange rækker betyder at man ellers ikke
   kan se hvilken periode en celle langt nede hører til. */
.hm-gitter thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-surface, #fff);
}

.hm-gitter thead .hm-navn-kolonne {
  z-index: 3;
}

.hm-kolonne {
  min-width: 4.5rem;
  text-align: center;
  font-weight: 500;
  /* Overskriften bærer et tooltip med det faktiske ugeinterval — se
     heatmapPeriodeTitel. Markøren skal røbe at der er noget at læse. */
  cursor: help;
}

.hm-celle {
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Farverne deles med ugegitteret (.uge-stoplys-*) — ÉN deklaration, to navne,
   så de to visninger ikke kan komme til at vise hver sin grønne. */

/* De tre tomme tilstande skal se FORSKELLIGE ud. De ligner hinanden i data,
   men kræver modsatte handlinger. */
.hm-ukendt {
  color: var(--color-text-muted);
  background: repeating-linear-gradient(
    45deg,
    transparent,
    transparent 4px,
    var(--color-border) 4px,
    var(--color-border) 5px
  );
}

.hm-nul-pulje {
  background: var(--color-red);
  color: #fff;
  font-weight: 700;
}

.hm-ingen-horisont {
  color: var(--color-text-muted);
  font-style: italic;
  text-align: left;
  padding-left: 12px;
}

/* ⚠️ Mærket for manglende drift/projekt-split er GRAFISK, ikke tekst. Omkring
   halvdelen af rækkerne bærer det i praksis, og en sætning i hver celle ville
   fylde mere end tallene. Stiplet ramme er samme greb som accepterede risici i
   2.4b — etableret mønster i denne app. Den fulde tekst står i cellens title. */
.hm-mangler-split {
  outline: 2px dashed var(--color-text-muted);
  outline-offset: -3px;
}

.hm-navn-maerke {
  color: var(--color-yellow);
  cursor: help;
}

/* Vælger og filter i sidehovedet */
.hm-vaelger,
.hm-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.hm-filter {
  margin-left: var(--space-4);
  cursor: pointer;
}

.hm-select {
  font-size: 0.8125rem;
  padding: 4px 8px;
}

.hm-tom-tekst {
  margin: 0;
  color: var(--color-text-muted);
}

/* Signaturforklaringen */
.hm-signatur {
  margin-top: var(--space-4);
}

.hm-signatur-titel {
  font-size: 0.9375rem;
  margin: 0 0 var(--space-3);
}

.hm-signatur-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-4);
}

.hm-signatur-overskrift {
  font-size: 0.8125rem;
  font-weight: 600;
  margin: 0 0 var(--space-2);
}

.hm-signatur-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.hm-signatur-liste li {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

.hm-signatur-note {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin: var(--space-3) 0 0;
}

.hm-prik {
  display: inline-block;
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  line-height: 1.25rem;
  text-align: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  font-size: 0.75rem;
}

.hm-prik-tom {
  background: var(--color-surface);
}

/* ⚠️ PASSEREDE UGER: DÆMPET MED GENNEMSIGTIGHED, IKKE MED GRÅTONE.
   Valget er ikke kosmetisk. Gråtone siger "andet slags data — arkiv", og det
   er præcis den misforståelse der skal undgås: en passeret celle er IKKE
   historik. Den viser hvad der I DAG er planlagt for den uge, ikke hvad der
   var planlagt dengang — allokeringer kan være redigeret siden.
   Nedsat opacitet siger "samme data, mindre presserende", og det er sandt.
   ⚠️ Klassen hedder PASSERET, ikke historik. Ordet må ikke sive ind i
   kodebasen, heller ikke som et klassenavn. */
.hm-celle-passeret,
.hm-kolonne-passeret {
  opacity: 0.45;
}

/* Skellet skal kunne ses uden at læse noget. */
.hm-kolonne-idag {
  box-shadow: inset 2px 0 0 var(--color-accent);
}

.hm-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: var(--space-4);
}

.hm-spaend {
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  min-width: 8rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.hm-nav .btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ==========================================================================
   Enheder en bruger leder (brugeradministration)
   ========================================================================== */

.enheder-liste {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 320px;
  overflow-y: auto;
}

/* Én række pr. enhed med to uafhængige afkrydsninger. Navnet fylder, de to
   valg står til højre i fast bredde, så kolonnerne kan læses lodret. */
.enheder-raekke {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px var(--space-2);
  border-radius: var(--radius-sm);
}

.enheder-raekke:hover {
  background: var(--color-surface-2);
}

.enheder-navn {
  flex: 1;
  min-width: 0;
}

.enheder-valg {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--color-text-muted);
  cursor: pointer;
  white-space: nowrap;
}

/* At enheden allerede ledes af en anden er en OPLYSNING, ikke en spærre: et
   kryds overtager lederskabet. Dæmpet, så listen stadig læses som en liste. */
.enheder-anden-leder {
  color: var(--color-text-muted);
  font-size: 12px;
}

/* ===========================================================================
   Kassediagram over organisationen (organisation-diagram.html)
   ===========================================================================

   ⚠️ INGEN JS TIL LAYOUT. Formen er indlejrede <ul>/<li> plus ::before/::after
   til forbindelseslinjerne; browseren beregner bredderne ud fra indhold. Der
   er derfor ingen kolonnespænd at sætte og intet at regne ud — se noten i
   static/js/organisation-trae.js om de tre funktioner det gjorde overflødige.

   ⚠️ EGET PRÆFIKS `.orgd-`. Org-chartet (organisation-admin.html) ejer `.org-`,
   og de to sider tegner det samme træ på hver sin måde. Fælles klasser ville
   binde dem sammen, så en ændring det ene sted flyttede det andet.

   Linjeføringen, som den er tænkt:

       ┌───────┐        hver <li> har to halve vandrette streger over sig
       │  rod  │        (::before til venstre, ::after til højre) plus en
       └───┬───┘        lodret stump ned fra ::after.
       ┌───┴───┐        Første barn mangler sin venstre halvdel, sidste barn
     ┌─┴─┐   ┌─┴─┐      sin højre — så enderne ikke stikker ud.
     │ A │   │ B │      Et enebarn får kun den lodrette stump.
     └───┘   └───┘
   =========================================================================== */

.orgd-trae {
  /* ⚠️ Vandret rulning er PRISEN ved formen, ikke en fejl. Fire afdelinger med
     teams under bliver bredere end en skærm. Rulningen ligger her, ikke på
     <body>, så resten af siden står stille. */
  overflow-x: auto;
  padding: var(--space-3) var(--space-2);
}

.orgd-liste {
  display: flex;
  justify-content: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

.orgd-gren {
  position: relative;
  padding: var(--space-3) var(--space-1) 0;
  text-align: center;
}

/* De to halve vandrette streger over hver knude. */
.orgd-gren::before,
.orgd-gren::after {
  content: "";
  position: absolute;
  top: 0;
  width: 50%;
  height: var(--space-3);
  border-top: 1px solid var(--color-border);
}
.orgd-gren::before {
  right: 50%;
}
.orgd-gren::after {
  left: 50%;
  border-left: 1px solid var(--color-border);
}

/* Enderne: første barn har ingen venstre halvdel, sidste ingen højre. */
.orgd-gren:first-child::before {
  border: 0;
}
.orgd-gren:last-child::after {
  border-top: 0;
}

/* Et enebarn får kun den lodrette stump — ingen vandret streg at forbinde. */
.orgd-gren:only-child::before {
  border: 0;
}
.orgd-gren:only-child::after {
  border-top: 0;
}

/* Rødderne har ingen forælder at forbindes til. */
.orgd-trae > .orgd-liste > .orgd-gren {
  padding-top: 0;
}
.orgd-trae > .orgd-liste > .orgd-gren::before,
.orgd-trae > .orgd-liste > .orgd-gren::after {
  display: none;
}

/* Stilken ned fra en kasse til sine børn. */
.orgd-gren > .orgd-liste {
  position: relative;
  padding-top: var(--space-3);
}
.orgd-gren > .orgd-liste::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  height: var(--space-3);
  border-left: 1px solid var(--color-border);
}

/* ---------- Selve kassen ---------- */

.orgd-kasse {
  display: inline-flex;
  flex-direction: column;
  gap: 2px;
  min-width: 140px;
  max-width: 200px;
  padding: var(--space-2);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  text-align: left;
}

.orgd-navn {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  overflow-wrap: anywhere;
}

.orgd-leder {
  font-size: 12px;
  color: var(--color-text-secondary);
  overflow-wrap: anywhere;
}

/* ⚠️ Egen klasse, ikke bare en dæmpet farve: "ingen leder" er en GYLDIG
   tilstand, ikke en manglende udfyldning. Kursiv skiller den fra et navn. */
.orgd-leder-mangler {
  font-style: italic;
  color: var(--color-text-muted);
}

.orgd-niveau {
  align-self: flex-start;
  margin-top: 4px;
}

/* ---------- Afvigelser ---------- */

/* ⚠️ En forældreløs enhed eller en ring skal kunne SES som en afvigelse, ikke
   tegnes som en almindelig rod. Uden markeringen ville et brud i data ligne
   en organisation med flere topenheder. */
.orgd-afvigelse {
  margin-top: var(--space-3);
  padding: var(--space-2);
  border: 1px dashed var(--color-border-focus);
  border-radius: var(--radius-md);
  background: var(--color-surface-2);
}

.orgd-afvigelse-note {
  margin: 0 0 var(--space-2);
  font-size: 13px;
  color: var(--color-text-secondary);
}

/* Kassen der selv er afvigelsen. */
.orgd-kasse-afvigelse {
  border-color: var(--color-border-focus);
}

/* ⚠️ Vises når enhed.niveau ikke passer til kassens FAKTISKE dybde i træet.
   Se noten i organisation-diagram.js om hvilken der vinder.
   ⚠️ Vises ALDRIG på en afvigende rod (forældreløs eller ring): dér er
   placeringen ukendt, og både badge og note er udeladt med vilje. */
.orgd-niveau-uenig {
  font-size: 11px;
  color: var(--color-text-muted);
  font-style: italic;
}

/* ---------- Notifikationscentrets administration ---------- */

.kort-titel {
  font-size: 15px;
  font-weight: 600;
  margin-bottom: var(--space-2);
}

.flettefelt-liste {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: var(--space-2) 0 var(--space-3);
}

/* ⚠️ DE VALGFRIE FELTER SKAL KUNNE SKELNES PÅ ET BLIK, fordi de er dem der
   bærer en regel: de skal stå sidst på deres linje, ellers river
   linjebortfaldet meningsfuld tekst med sig. En ensartet chip ville gøre
   reglen usynlig indtil man ramte 400'eren. Forskellen bæres af en stiplet
   kant og ikke af farve alene — se princippet om at farve skal bære
   betydning. */
.flettefelt {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: var(--color-surface-alt, transparent);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--color-text);
  cursor: help;
}

.flettefelt.valgfri {
  border-style: dashed;
  color: var(--color-text-secondary);
}

.skabelon-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-border);
}

.skabelon-titel {
  font-size: 14px;
  font-weight: 600;
}

.skabelon-form textarea {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  line-height: 1.5;
}

/* ---------- Manuel påmindelse (2.9, commit 11) ---------- */

.paamind-typer {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Radioknap og etiket i samme label, så hele linjen er klikbar — en
   radioknap alene er et lille mål.

   ⚠️ SELEKTOREN ER `.modal-form .paamind-type` OG IKKE BARE `.paamind-type`.
   `.modal-form label` sætter `flex-direction: column` (etiket over felt), og
   den vandt: radioknappen stod OVER sin tekst, centreret. Fundet ved at åbne
   dialogen — ingen test kan se det.

   Samme kollision og samme modtræk som `.modal-form .modal-radio` længere
   oppe, hvor noten allerede står. Løst med SPECIFICITET frem for
   `!important` (som `.checkbox-label` bruger), fordi et `!important` også
   spærrer for den næste der har en god grund til at overstyre. */
.modal-form .paamind-type {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
  padding: 6px 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-weight: 400;
}

.modal-form .paamind-type:hover {
  background: var(--color-accent-soft);
}

.modal-form .paamind-type input {
  flex-shrink: 0;
}

/* ---------- Tidligere projektleder / ubesat koordinator (15/8) ---------- */

/* ⚠️ TILSTANDEN SKAL KUNNE SES, IKKE KUN LÆSES. "Tidligere: Morten S. Lund" i
   samme vægt og farve som et almindeligt navn bliver skimmet som et navn —
   ordet foran redder ikke et blik der løber ned ad en kolonne. Dæmpningen gør
   forskellen synlig før teksten er læst.
   Samme greb og samme variabel som `.hjaelpetekst`; kursiven adskiller den fra
   en almindelig sekundær tekst. */
.pl-tidligere {
  color: var(--color-text-muted);
  font-style: italic;
}

/* ⚠️⚠️ PROJEKTLISTEN SKAL KUNNE RULLES VANDRET — MÅLT 15/8, DA DEN SYVENDE
   KOLONNE KOM TIL. **FJERN DEN IKKE.**

   Tabellen er `table-layout: auto`, så den har et NATURLIGT gulv: den holder op
   med at skrumpe når indholdet ikke kan blive smallere. Målt på projekter.html
   med 15 rækker:

     6 kolonner (før 15/8)   gulv 650 px
     7 kolonner (efter)      gulv 775 px   ← koordinator-kolonnen kostede 125 px
     8 kolonner (22/8)       gulv 850 px   ← butiksproces-kolonnen kostede 130 px

   ⚠️ De tre tal er målt med FORSKELLIGE datasæt og kan ikke sammenlignes
   direkte: 650/775 er fra 15/8 med 15 rækker, 850 er fra 22/8. Samme dag
   målte 7 kolonner 720 px på det datasæt, så de 130 px er forskellen MELLEM
   to målinger på samme grundlag — ikke 850 minus 775.

   ⚠️⚠️ **PROJEKTLISTEN HAR INTET JS-GULV, OG DET ER IKKE EN FORGLEMMELSE.**
   Spørgsmålet kommer igen hver gang en kolonne tilføjes, så her står svaret:

   - Gulvet er `table-layout: auto`s NATURLIGE gulv — det punkt hvor indholdet
     ikke kan blive smallere. Det beregnes af browseren, ikke af os, og det
     flytter sig med indholdet (længere projektnavne → højere gulv). Derfor er
     tallene ovenfor målt med 15 rækker og gælder ikke som konstanter.
   - Løsningen er RULLEBJÆLKEN (`.table-card-rul` nedenfor), ikke et gulv. En
     kolonne mere skal derfor ikke "med i gulv-beregningen"; den skal måles for
     at bekræfte at rullebjælken stadig gør indholdet NÅELIGT.
   - `sikrLaasteKolonneBredder` i static/js/projekt.js hører til
     OPGAVETABELLEN, som er `table-layout: fixed` med gemte kolonnebredder.
     Dét er en anden mekanisme mod en anden fejl (cellen klippede sit eget
     indhold, så `scrollWidth` ikke voksede og der var intet at rulle til).
     Den funktion må ikke kaldes herfra.

   ⚠️ MÅL NÅELIGHED, IKKE KUN BREDDE. At Handlinger-kolonnen FINDES i DOM'en
   ved 700 px siger intet om at den kan nås — det var netop fejlen 15/8.
   Brug `document.elementFromPoint()` på knappens midtpunkt efter at have
   rullet kortet helt til højre. Samme lære som Gantt-pladen: et element kan
   have rigtige koordinater og alligevel være utilgængeligt.

   Under det gulv vokser tabellen ud over sin container — og `.table-card` har
   `overflow: hidden`. Målt ved en container på 620 px: Handlinger-kolonnen lå
   **155 px uden for kortet**, og `scrollWidth - clientWidth` var netop 155.
   Indholdet FANDTES altså, men kunne ikke nås: der var ingen rullebjælke.

   ⚠️ DET ER EN ANDEN FEJL END DEN FRA 10/8, selvom symptomet ligner. Dér var
   tabellen `fixed` og cellen klippede sit EGET indhold (`scrollWidth` voksede
   ikke, så der var intet at rulle til). Her er cellerne intakte — målt:
   knapperne ligger inden for deres celle ved hver eneste bredde — og det er
   KORTET der skjuler dem. Derfor er rettelsen en rullebjælke og ikke et gulv;
   `sikrLaasteKolonneBredder` i projekt.js hører til den anden fejl og gælder
   ikke her.

   ⚠️ SCOPET PR. TABEL, IKKE TIL `.table-card`. Klassen bruges 11 steder på 8
   sider. To af dem bærer nu `table-card-rul`: projekter.html og admin.html —
   sidstnævnte målt for sig 16/8 (700 px beholder, 961 px tabel, 263 px uden
   for kortet). **De ni øvrige er UMÅLTE**, ikke fundet i orden. En global
   ændring på `.table-card` ville lukke dem alle i forbifarten uden at nogen
   havde set på om de overhovedet løber over — og et kort der får en
   rullebjælke det ikke har brug for, er sin egen fejl.

   `overflow-y: hidden` bevares, så de runde hjørner stadig klipper lodret. */
.table-card-rul {
  overflow-x: auto;
  overflow-y: hidden;
}

/* ---------- Excel-import (025b) ----------
   Dialogen har fem trin i samme modal (static/js/excelimport-dialog.js). Kun
   husets tokens, så det mørke tema følger med uden egne værdier. Tabellerne
   ligger i .import-rul, så en bred fil (mange kolonner) ruller i dialogen i
   stedet for at sprænge den. */
/* ⚠️ `.modal.modal-bred` (700px) har højere specificitet end `.import-modal` alene. */
.modal.import-modal { max-width: 960px; }
/* Under et kald til serveren: intet i trinnet kan ændres (se opdaterKnapper). */
.import-optaget { opacity: 0.6; pointer-events: none; }

.import-krop {
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.import-trinlinje {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-secondary);
}

.import-fil-felt {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-text-secondary);
}
.import-fil-felt[hidden] { display: none; }

.import-valg {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: 12px;
  color: var(--color-text-secondary);
}
.import-valg label { display: flex; flex-direction: column; gap: 4px; }
.import-valg input[type="number"] { width: 90px; }

.import-hjaelp {
  font-size: 12px;
  color: var(--color-text-secondary);
}

.import-hovedlinje {
  font-size: 16px;
  font-weight: 600;
}

.import-overskrift {
  font-size: 13px;
  font-weight: 600;
  margin-top: var(--space-1);
}

.import-rul {
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.import-tabel {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}
.import-tabel th,
.import-tabel td {
  padding: var(--space-05) var(--space-1);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--color-row-border);
  white-space: nowrap;
}
.import-tabel th {
  background: var(--color-surface-2);
  font-weight: 600;
}
.import-tabel .import-eksempel {
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--color-text-secondary);
}
.import-tabel .import-ekstra { display: flex; gap: var(--space-1); }
.import-tabel .import-raekkenr { color: var(--color-text-muted); }

.import-bogstav {
  display: inline-block;
  min-width: 18px;
  text-align: center;
  font-weight: 600;
  color: var(--color-text-secondary);
}

.import-mappingfejl {
  color: var(--color-red);
  background: var(--rag-red-soft);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-3);
  font-size: 13px;
}

.import-ekstra-advarsel {
  display: inline-block;
  margin-top: var(--space-05);
  padding: var(--space-05) var(--space-1);
  background: var(--rag-yellow-soft);
  border-radius: var(--radius-sm);
  font-weight: 600;
}

.import-fod {
  display: flex;
  justify-content: space-between;
  padding: var(--space-2);
  border-top: 1px solid var(--color-border);
}
.import-fod button[hidden] { display: none; }
.import-fod #import-naeste { margin-left: auto; }
