/* ==========================================================================
   TodoIT Platform — designsystem
   Eget layout-sprog (app-shell, sidebar, page-header, bento) oven på en
   minimal Bootstrap-brug: Public Sans, bløde skygger, bolde overskrifter,
   pille-knapper — men i støvet blå.
   ========================================================================== */

@font-face {
    font-family: "Public Sans";
    src: url("fonts/public-sans-latin.woff2") format("woff2");
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
}

:root {
    --font: "Public Sans", "Segoe UI", system-ui, sans-serif;

    /* Accenten på det valgte punkt i menuen.
       Eget token og ikke --brass: brass skifter med temaet (mørkebrun i lyst tema), men MENUEN er
       marineblå i begge temaer. Brass ville derfor blive mørkebrunt på mørkeblåt, hver gang nogen
       slog lyst tema til — en fejl, der kun rammer halvdelen af brugerne, og som derfor kunne stå
       længe. Værdien er den lyse brass, der hører til en mørk flade. Efterregnet i
       tests/kontrastcheck mod --navy-950. */
    --side-accent: #e6bd7c;

    /* Støvet blå skala */
    --navy-950: #131c28;
    --navy-900: #1b2735;
    --navy-800: #243449;
    --navy-700: #33475f;
    --navy-600: #4a6485;
    --blue-500: #5c7fa8;
    --blue-400: #7c9bc0;
    --blue-300: #a5bcd5;
    --blue-200: #c8d8e7;
    --blue-100: #dfe9f2;
    --blue-50: #eff4f9;

    /* Varme neutraler */
    --paper: #ffffff;
    /* Fladen er varm, ikke kold. Paletten HAR haft varme neutraler hele tiden (--clay-*), men
       selve siden brugte dem ikke — den lå på en kold blågrå, og så trak alt på skærmen mod blåt.
       Retning A, 25. august 2026: papiret bliver varmt, og den blå bliver noget, man bruger, i
       stedet for noget, alting ligger i. */
    --shell: #f6f4f1;
    --clay-100: #f5efe8;
    --clay-200: #e6d8c8;

    /* Messing — den ENESTE accent.
       Værdien er ikke ny: den er --warn-ink, som allerede er efterregnet i tests/kontrastcheck.
       Den er bevidst genbrugt frem for opfundet, så paletten ikke vokser med endnu en tone.
       Bruges til eyebrow, gruppeoverskrifter og aktiv menupost — ALDRIG til status. Status har
       sine egne tre farver, og en accent, der også kan betyde «advarsel», er ikke en accent. */
    --brass: #7d5a24;

    /* Grafernes linjer. Én farve pr. slags linje, brugt af linjen, forklaringens nøgle OG aflæsningens swatch,
       så de tre ikke kan glide fra hinanden i et af temaerne: now (grafens linje), prev (perioden før / den anden
       måling, stiplet og dæmpet), in/out (ind/ud på et netværkskort — de stod som hex inde i live-panelet). */
    --series-now: var(--navy-800);
    --series-prev: var(--muted);
    --series-in: #1d9e75;
    --series-out: #378add;

    --ink: #16202e;
    --ink-2: #3b4a5d;
    /* Aliaser: disse tokens blev refereret rundt i filen uden at være defineret, så de faldt
       tilbage på off-palette-farver (Tailwind-hex eller forkert tone). De peger nu på den
       rigtige palette-værdi ét sted. --ink-1 = primær, --ink-3 = tertiær (lysere end --ink-2);
       --brand = accent til fokus-ringe; --blue-600 = mørkere blå til link-hover. */
    --ink-1: var(--ink);
    --ink-3: var(--muted);
    --brand: var(--blue-400);
    --blue-600: var(--navy-700);
    /* The keyboard focus ring (KC, 6 October 2026). --blue-400 was 2.87:1 on --paper and 2.62:1 on
       --shell, under the 3:1 a focus indicator needs (WCAG 1.4.11). --blue-500 is 4.15:1 on --paper,
       3.78:1 on --shell and 3.38:1 on --blue-100. The dark theme sets its own (see there). */
    --focus-ring: var(--blue-500);
    /* Begge er TEKSTfarver, ikke pynt. --faint stod på #94a2b4 = 2,60:1 mod papiret og
       blev brugt som rigtig brødtekst 237 steder: tidsstempler, tomme tilstande, tal i
       diagrammer. --muted lå på 4,44:1 og faldt også, bare knap. Begge måles nu i
       tests/kontrastcheck mod både --paper og --shell, så det ikke kan ske igen.
       Rangordenen mellem dem er bevaret — faint er stadig den lyseste af de to. */
    --muted: #5d6c80;
    --faint: #627183;

    --line: rgba(19, 28, 40, 0.085);
    --line-2: rgba(19, 28, 40, 0.16);

    --shadow-xs: 0 1px 2px rgba(19, 28, 40, 0.05);
    --shadow-sm: 0 4px 14px rgba(19, 28, 40, 0.06);
    --shadow-md: 0 14px 34px rgba(19, 28, 40, 0.09);
    --shadow-lg: 0 26px 58px rgba(19, 28, 40, 0.14);

    --r-sm: 10px;
    --r-md: 14px;
    --r-lg: 20px;
    --r-xl: 28px;

    /* Knapper var pillefformede (999px). En pille er en etiket — den ser ud som noget, man læser,
       ikke som noget, man trykker på. Egen token, så den kan rulles tilbage alene, hvis den skurrer. */
    --r-btn: 8px;

    --good: #3f8a5c;
    --good-bg: #e8f2ec;
    --warn: #b07d33;
    --warn-bg: #f8f0e2;
    --crit: #ac4a41;
    --crit-bg: #f8eae8;

    /* Tekstfarver til brug PÅ de tre baggrunde ovenfor. --good og --warn er valgt
       som accentfarver og har ikke kontrast nok til at være tekst på deres egen
       lyse baggrund — --warn lander på 3,2:1, hvor kravet er 4,5. Disse er mørknet,
       til de holder. Verificeret i tests/kontrastcheck. */
    --good-ink: #2f6b46;
    --warn-ink: #7d5a24;
    --crit-ink: #8e3a32;
    /* Stjernevurdering (kundetilfredshed). Egen guld — de øvrige gule (--warn) er for brune til en stjerne. */
    --gold: #f5a623;

    --sidebar-w: 268px;

    /* Rammen om en sides indhold. 1360 px kom med den første commit uden en begrundelse og blev
       aldrig rørt; den bandt fra omkring 1638 px vindue, så alt derover blev tomt felt i højre
       side — 282 px ved 1920, 1802 px ved 3440. Loftet binder nu først ved 2078 px, så en 1920-
       skærm bruger hele bredden. Over det holder et loft stadig igen, fordi det, der vokser
       ukontrolleret, er fritekst-kolonner i tabeller, som ingen wrapper styrer. */
    --indhold-max: 1800px;

    /* Semantiske link-farver. Den blå/navy-skala er dobbeltarbejdende — den er BÅDE mørke
       flader (sidebar, knapper) OG tekst/links. Links kan derfor ikke bare bruge et
       skala-trin direkte, for så kan et mørkt tema ikke lysne linket uden også at lysne
       fladen. Links går nu gennem disse to, så det mørke tema flipper dem alene. */
    --link: var(--navy-700);
    --link-hover: var(--navy-950);

    /* The overview tiles (Components/Shared/Tiles, the Tiles block after .status). One big-number size in the platform:
       --tile-fs-num = .stat__value. The lamp, band and bar colours are mixes of the status and blue tokens, so the dark
       theme only redefines the mix. */
    --tile-gap: 1rem;
    --tile-pad: 1rem 1.15rem 0.95rem 1.4rem;
    --tile-stripe: 4px;
    --tile-fs-num: 2.15rem;
    --tile-fs-of: 1.02rem;
    --tile-fs-label: 0.68rem;
    --tile-fs-text: 0.875rem;
    --tile-fs-meta: 0.78rem;
    --lamp: 0.72rem;
    --lamp-big: 1.05rem;
    --lamp-gap: 0.26rem;
    /* Full --good in the light theme, not the specimen's 82 % mix: measured in tests/feltcheck, the softer green lamp
       fell to 2.65:1 on the critical tile's surface and 2.96:1 on an area cell - under the 3:1 a meaningful graphic needs. */
    --lamp-ok: var(--good);
    --lamp-hollow: color-mix(in srgb, var(--muted) 60%, transparent);
    --band-ok: color-mix(in srgb, var(--good) 45%, var(--paper));
    --band-none: color-mix(in srgb, var(--ink) 8%, var(--paper));
    --bar: color-mix(in srgb, var(--blue-400) 62%, var(--paper));
    --bar-now: var(--blue-500);
    --bar-zero: var(--line-2);
    --area-bg: color-mix(in srgb, var(--ink) 2.5%, var(--paper));

    color-scheme: light;

    /* Bootstrap-broer (kun det vi faktisk bruger) */
    --bs-body-bg: var(--shell);
    --bs-body-color: var(--ink);
    --bs-secondary-color: var(--muted);
    --bs-border-color: var(--line);
    --bs-border-color-translucent: var(--line);
    --bs-primary: var(--navy-800);
    --bs-primary-rgb: 36, 52, 73;
    --bs-link-color: var(--link);
    --bs-link-hover-color: var(--link-hover);
    --bs-success: var(--good);
    --bs-warning: var(--warn);
    --bs-danger: var(--crit);
    --bs-secondary: var(--muted);
    --bs-font-sans-serif: var(--font);
}

/* ==========================================================================
   Mørkt tema.
   Hele appen er bygget på de semantiske tokens ovenfor, så temaet er i alt
   væsentligt ét sæt omdefinerede tokens. Vi overskriver KUN det, der bærer
   lyshed: neutraler, status-tints, streger, skygger, de lyseste blå trin (der
   bruges som lyse baggrunde) og link-farven. De mørke navy-trin er allerede
   mørke og bruges til flader, der er mørke i BEGGE temaer (sidebar, topbar,
   knapper) — dem rører vi ikke.

   Temaet vælges af et lille script i <head> (tema.js), der sætter data-theme
   FØR første maling ud fra brugerens valg, ellers systemets indstilling — så
   der ikke blinker en lys side, før det mørke tema når frem. Derfor er der ingen
   @media-dublet her; CSS'en behøver kun [data-theme="dark"]. */
:root[data-theme="dark"] {
    /* Neutraler — hele flippen sker her */
    --paper: #1a2431;   /* kort og paneler — en anelse lysere end siden */
    --shell: #10161f;   /* side-baggrund, mørkest */
    --clay-100: #221d18; /* varme neutraler, mørk udgave (bruges sjældent) */
    --clay-200: #33291f;

    --ink: #e8eef5;     /* primær tekst — næsten hvid */
    --ink-2: #b4c1d1;   /* sekundær tekst */
    --muted: #96a5b8;   /* dæmpet tekst — lysnet, så kontrasten holder på mørkt */
    --faint: #8494a7;   /* svag tekst */

    --line: rgba(255, 255, 255, 0.10);
    --line-2: rgba(255, 255, 255, 0.19);

    /* Skygger skal være sorte og dybere på mørkt — de blålige forsvinder. */
    --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.40);
    --shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.45);
    --shadow-md: 0 14px 34px rgba(0, 0, 0, 0.50);
    --shadow-lg: 0 26px 58px rgba(0, 0, 0, 0.62);

    /* Status: accenten løftes en smule; -bg bliver en mørk tint; -ink en lys tekst. */
    --good: #4c9d6d;   --good-bg: #16241b;  --good-ink: #83cf9f;
    --warn: #cc9a48;   --warn-bg: #26200f;  --warn-ink: #e6bd7c;
    --crit: #cf5f55;   --crit-bg: #291715;  --crit-ink: #ec938a;
    --gold: #f5b73f;

    /* Messing bærer lyshed og skal derfor flippe. Samme greb som i det lyse tema: værdien er
       temaets egen --warn-ink, altså allerede efterregnet mod den mørke flade. */
    --brass: #e6bd7c;

    /* Grafernes kurve var mørk navy — det samme som fladen bag den i det mørke tema (1,24:1), så kurven, der er hele
       pointen med en graf, forsvandt næsten. Den løftes her, i tokenet, og ikke med en regel på .chart__line: sådan
       en regel slog også ind/ud og perioden før, så båndbreddens to linjer fik samme farve. */
    --series-now: var(--blue-300);
    --series-in: #4fc49c;
    --series-out: #6aa9ee;

    /* Kun --blue-50 flipper — det bruges UDELUKKENDE som lys hover-/panel-baggrund og
       ville ellers stå som lyse pletter. --blue-100 og opefter er lyse nok til tekst på
       mørk bund (bl.a. sidemenuens tekst = var(--blue-100)) og beholdes; de få steder,
       der bruger dem som lys BAGGRUND, får en målrettet mørk regel nedenfor. */
    --blue-50: #1c2836;   /* subtil hover-baggrund */

    /* Links lysner alene (mørke navy-flader er urørte). */
    --link: var(--blue-300);
    --link-hover: var(--blue-200);

    /* The focus ring stays --blue-400 here: 5.45:1 on --paper, 6.32:1 on --shell, 5.20:1 on --blue-50.
       (--blue-500 would hold 3:1 too, at 3.60:1 on --blue-50, but the lighter one is the clearer ring.) */
    --focus-ring: var(--blue-400);

    /* The overview tiles: the mixes that carry lightness. */
    --lamp-ok: color-mix(in srgb, var(--good) 88%, var(--paper));
    --band-ok: color-mix(in srgb, var(--good) 55%, var(--paper));
    --bar: color-mix(in srgb, var(--blue-300) 50%, var(--paper));
    --bar-now: var(--blue-300);

    color-scheme: dark;

    /* Bootstrap-broer, der pegede på mørke navy-værdier og skal lysne på mørkt. */
    --bs-primary: var(--blue-500);
    --bs-primary-rgb: 92, 127, 168;
    --bs-link-color: var(--link);
    --bs-link-hover-color: var(--link-hover);

    /* Bootstraps «fremhævede» tekst og dens to flader. Platformens mørke tema er vores eget
       (data-theme), ikke Bootstraps (data-bs-theme), så uden de her linjer blev de stående på
       Bootstraps LYSE værdier: #000 og #f8f9fa/#e9ecef.

       Og det så man. Bootstrap afleder mindst ni farver af --bs-emphasis-color — tabellers
       hover-, stribe- og aktiv-tekst, listeelementers hover og aktiv, den aktive fane og
       tooltip'ens flade. Målt i headless Edge med den rigtige app.css den 18. september 2026:
       en tabelrække, man holdt musen over, skrev rgb(0, 0, 0) på den mørke hover-flade — sort
       på næsten sort — og et listeelement fik sort tekst på en næsten HVID flade. KC's
       skærmbillede var «Tid der afventer fakturering» på Tidsoverblikket.

       Kun her i det mørke tema, så det lyse er pixel for pixel, som det var. Fladerne peger på
       platformens egne: hover er --blue-50 (som .table's egen hover allerede bruger), og den
       lidt kraftigere «aktiv/deaktiveret» ligger mellem papir og hover. */
    --bs-emphasis-color: var(--ink);
    --bs-emphasis-color-rgb: 232, 238, 245;
    --bs-tertiary-bg: var(--blue-50);
    --bs-tertiary-bg-rgb: 28, 40, 54;
    --bs-secondary-bg: #243142;
    --bs-secondary-bg-rgb: 36, 49, 66;

    /* Bootstraps rgb-tripletter for brødtekst og side. --bs-body-color var broet, men ikke dens
       -rgb, og det er tripletten, Bootstrap bruger med gennemsigtighed: den svævende etiket i et
       .form-floating-felt fik rgba(33,37,41,.65) — Bootstraps lyse — oven på den mørke side, 1,11:1.
       Etiketten i login-feltet forsvandt i det øjeblik, man begyndte at skrive. Dækker også
       .text-body, .bg-body, .toast og .card-hovedet. Fundet af søgningen efter mørk-på-mørk,
       18. september 2026, målt i headless Edge. */
    --bs-body-color-rgb: 232, 238, 245;
    --bs-body-bg-rgb: 16, 22, 31;

    /* «Sekundær» som dæmpet flade: .alert-secondary, .bg-secondary-subtle, .list-group-item-secondary.
       Stod på Bootstraps lysegrå #e2e3e5 — en lys plade midt i mørket, hvor kontakten for kundekontakt
       på Indstillinger havde en titel, man ikke kunne læse (1,10:1). --blue-50 og ikke --shell, så
       kontaktens spor (--shell) stadig står frem inde i boksen. */
    --bs-secondary-text-emphasis: var(--ink-2);
    --bs-secondary-bg-subtle: var(--blue-50);
    --bs-secondary-border-subtle: var(--line-2);
}

/* --- Mørkt tema: komponenter, der hardkoder en lys værdi (pastel, hvid, mørk navy-tekst)
   og derfor ikke flipper med tokens. Hver får en målrettet mørk variant. --- */

/* Topbar-knapper og bruger-pillen: den halvhvide flade ville stå som en lys plet på den
   nu mørke topbar. Giv dem en mørk flade, så tekst og ikon (nu lyse) træder frem. */
:root[data-theme="dark"] .topbar__user { background: var(--paper); }
:root[data-theme="dark"] .notif__btn,
:root[data-theme="dark"] .topbar__signout { background: var(--paper); }
:root[data-theme="dark"] .notif__btn:hover,
:root[data-theme="dark"] .topbar__signout:hover { background: var(--blue-50); color: var(--ink); }
:root[data-theme="dark"] .brugermenu__knap:hover { background: var(--blue-50); }

/* Dokument-type-badges: lyse pasteller → mørke tints med lys tekst. */
:root[data-theme="dark"] .doc__ext--pdf   { background: #3a2320; color: #f0a79e; }
:root[data-theme="dark"] .doc__ext--doc   { background: #21304a; color: #a9c3ea; }
:root[data-theme="dark"] .doc__ext--sheet { background: #1c3326; color: #8fd3a9; }
:root[data-theme="dark"] .doc__ext--img   { background: #2e2440; color: #cba9e2; }
:root[data-theme="dark"] .doc__ext--zip   { color: #e2c69c; }

/* «Se som kunde»-banner: varm lys amber → mørk amber. */
:root[data-theme="dark"] .viewas {
    background: linear-gradient(90deg, #2a2314, #211d10);
    border-bottom-color: #4a3d1f;
    color: #e6c98a;
}
:root[data-theme="dark"] .viewas__exit {
    background: rgba(255, 255, 255, 0.06);
    border-color: #6a5628;
    color: #e6c98a;
}
:root[data-theme="dark"] .viewas__exit:hover { background: rgba(255, 255, 255, 0.12); }

/* Blazor-fejl-toast: egen lys amber → mørk. */
:root[data-theme="dark"] #blazor-error-ui {
    color-scheme: dark;
    background: #2a2114;
    color: #e6c98a;
    border-top-color: #4a3d1f;
}

/* Info-boks: mørk navy-tekst ville forsvinde på den nu mørke blå baggrund. */
:root[data-theme="dark"] .alert-info { color: var(--blue-200); border-color: var(--line-2); }

/* Sags-chip: lys blå flade + mørk tekst → mørk flade + lys tekst. */
:root[data-theme="dark"] .tkt-chip { background: var(--shell); color: var(--ink-2); }
:root[data-theme="dark"] .tkt-chip:hover { background: var(--blue-50); }

/* Opfølger- og vidensbase-links bruger mørk navy som tekst → lysnes. */
:root[data-theme="dark"] .tkt-opfoelger a,
:root[data-theme="dark"] .kb-article a { color: var(--link); }

/* Vidensbasens kode/citat brugte lyseblå (blue-100) som flade/kant. */
:root[data-theme="dark"] .kb-article code { background: var(--shell); color: var(--ink); }
:root[data-theme="dark"] .kb-article pre { background: var(--shell); }
:root[data-theme="dark"] .kb-article blockquote { border-left-color: var(--line-2); }
:root[data-theme="dark"] .kb-article hr { border-top-color: var(--line-2); }
:root[data-theme="dark"] .kb-article th,
:root[data-theme="dark"] .kb-article td { border-bottom-color: var(--line-2); }
:root[data-theme="dark"] .kb-article .kb-opgave input { accent-color: var(--link); }

/* Mørk navy brugt som TEKST/ikon står ulæseligt på en nu mørk flade. Det ramte bl.a.
   outline-knapperne («Ny mappe», «Tjek alle», «Tjek de N vi måler udefra»), et par
   ikon-/link-farver og et par badges. Her lysnes de, så de kan læses. */
:root[data-theme="dark"] .btn-outline-primary,
:root[data-theme="dark"] .btn-outline-secondary {
    color: var(--ink);
    border-color: var(--line-2);

    /* Tastaturfokus og tryk bruger Bootstraps egne udfyldninger, ikke :hover-reglen herunder — og de
       var lyse nok til at give 3,85:1 bag lys tekst. Nu samme flader som resten af det mørke tema. */
    --bs-btn-hover-bg: var(--blue-50);
    --bs-btn-hover-border-color: var(--blue-400);
    --bs-btn-active-bg: var(--bs-secondary-bg);
    --bs-btn-active-border-color: var(--blue-400);
}
:root[data-theme="dark"] .btn-outline-primary:hover,
:root[data-theme="dark"] .btn-outline-secondary:hover { color: var(--ink); border-color: var(--blue-400); }

/* Rød og grøn outline samt grøn tekst brugte Bootstraps faste farver (#dc3545, #198754), som står
   lige under læsbar på mørkt (3,46:1). Temaets egne -ink-farver er beregnet til netop den flade. */
:root[data-theme="dark"] .btn-outline-danger  { --bs-btn-color: var(--crit-ink); --bs-btn-border-color: var(--crit); }
:root[data-theme="dark"] .btn-outline-success { --bs-btn-color: var(--good-ink); --bs-btn-border-color: var(--good); }
:root[data-theme="dark"] .text-success { color: var(--good-ink) !important; }
:root[data-theme="dark"] .text-danger,
:root[data-theme="dark"] .validation-message { color: var(--crit-ink) !important; }

/* Pilen i en valgmenu er et SVG med Bootstraps mørke streg (#343a40), som Bootstrap kun bytter under
   sit EGET mørke tema. På vores mørke flade var den næsten usynlig (1,36:1), så ~124 valgmenuer
   lignede tekstfelter. Samme pil, lys streg (= mørk --ink-2). */
:root[data-theme="dark"] .form-select {
    --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23b4c1d1' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* En kontakt i «fra»-stilling: knappen er en cirkel med 25 % sort — usynlig mod det mørke spor
   (1,04:1), så en slået-fra kontakt stod som en tom pille, og man kunne ikke se, at den var en
   kontakt. Lys knap (= mørk --muted). «Til» og fokus har deres egne regler og røres ikke.
   Since 6 October 2026 the knob no longer changes on focus either (it turned Bootstrap blue after a
   click and stayed so): focus is shown by the keyboard ring alone, so this rule holds while focused. */
:root[data-theme="dark"] .form-switch .form-check-input:not(:checked) {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2396a5b8'/%3e%3c/svg%3e");
}
:root[data-theme="dark"] .form-check-input { --bs-border-color: var(--line-2); }

/* .table-light sætter sine egne tabelvariabler (#000 på #f8f9fa) og overtrumfer dermed .table's —
   en hvid stribe midt i en mørk tabel. Én forekomst (DmarcMailbox, gruppehovedet), men reglen her
   gælder den næste, der bruger klassen, også. */
:root[data-theme="dark"] .table-light {
    --bs-table-color: var(--ink);
    --bs-table-bg: var(--blue-50);
    --bs-table-border-color: var(--line);
    --bs-table-striped-color: var(--ink);
    --bs-table-striped-bg: var(--bs-secondary-bg);
    --bs-table-active-color: var(--ink);
    --bs-table-active-bg: var(--bs-secondary-bg);
    --bs-table-hover-color: var(--ink);
    --bs-table-hover-bg: var(--bs-secondary-bg);
}

:root[data-theme="dark"] .stat__dot { color: var(--blue-300); }
:root[data-theme="dark"] .mods__row .icon { color: var(--blue-300); }
:root[data-theme="dark"] .sscore__hvem > summary { color: var(--link); }
:root[data-theme="dark"] .notif__lyd { color: var(--ink-2); }
:root[data-theme="dark"] .form-check-input:checked { background-color: var(--blue-500); border-color: var(--blue-500); }

/* Badges med lys blå flade + mørk navy-tekst. */
:root[data-theme="dark"] .badge.bg-primary { background: var(--shell) !important; color: var(--ink) !important; }
:root[data-theme="dark"] .badge.bg-info { color: var(--blue-200) !important; }

* { box-sizing: border-box; }

html { height: 100%; }

body {
    margin: 0;
    min-height: 100%;
    font-family: var(--font);
    color: var(--ink);
    background: var(--shell);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5 {
    font-family: var(--font);
    color: var(--ink);
    font-weight: 700;
    letter-spacing: -0.015em;
    margin: 0;
}

/* Blazor's enhanced navigation programmatically focuses the page's <h1> after each
   navigation (for screen readers). Det fokus er ikke noget en seende bruger nogensinde
   selv har tabbet sig til — h1 er ikke i tab-rækkefølgen — så vi skjuler ringen helt
   i stedet for bare at style den, ellers popper den grimt op ved hvert sideskift. */
h1:focus, h1:focus-visible {
    outline: none;
}

p { margin: 0; }

a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hover); }

/* ==========================================================================
   Scrollbars — diskrete i stedet for Windows' tykke grå standard, der især
   dominerer i den mørke sidemenu.

   To lag, fordi ingen browser kan begge: den moderne standard (scrollbar-width/
   -color, arves fra html) dækker Firefox; ::-webkit-scrollbar dækker Chromium/
   Edge/Safari. Thumben holdes tynd med en gennemsigtig kant + background-clip,
   så den flyder som en smal pille i stedet for at fylde hele sporet.
   ========================================================================== */
/* scrollbar-width arves ikke pålideligt til indre scroll-områder, så den sættes bredt
   (rammer kun elementer, der faktisk kan rulle). Gælder Firefox; Chromium/Edge/Safari
   styres af ::-webkit-scrollbar nedenfor. */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(19, 28, 40, 0.22) transparent;
}

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
    background: rgba(19, 28, 40, 0.22);
    border-radius: 999px;
    border: 3px solid transparent;
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(19, 28, 40, 0.36); }

/* Den mørke sidemenu: en mørk thumb ville forsvinde — lys, men stadig diskret. */
.side__nav { scrollbar-color: rgba(255, 255, 255, 0.24) transparent; }
.side__nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.24); }
.side__nav::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.42); }

/* ==========================================================================
   App shell
   ========================================================================== */

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

.app__main {
    flex: 1;
    min-width: 0;
    position: relative;
    background:
        radial-gradient(1100px 520px at 78% -8%, rgba(168, 192, 216, 0.28), transparent 65%),
        radial-gradient(760px 420px at 8% 108%, rgba(230, 216, 200, 0.32), transparent 62%),
        var(--shell);
}

/* Stadig en almindelig blok — se advarslen nedenfor. Ikke centreret: topbjælken er i fuld bredde med den
   samme 2,5rem venstre-padding, så indhold og topbjælke deler venstrekant. Centrering ville bryde den
   flugt for at lave en ny. Læseflader og formularer har hver deres eget loft, dér hvor de bor. */
.app__content {
    max-width: var(--indhold-max);
    padding: 2.25rem 2.5rem 3.5rem;
}

/* One vertical rhythm for stacked page blocks. .panel carried no bottom margin, so two panels — or a
   panel next to another card — sat flush against each other, while .hero/.bento/.status/.aftale each
   brought their own margin; the spacing between top-level cards was therefore uneven from page to page.
   This gives every top-level block the same gap above it. Adjacent vertical margins collapse in this
   block container, so the existing per-card margins are absorbed into this one value rather than doubling.
   IMPORTANT: keep .app__content a plain block — do NOT add display:flex/grid, overflow, or contain to it,
   or margin-collapse stops and every gap becomes additive (a header's 1.9rem + this 1.5rem = 3.4rem). */
.app__content > * + * { margin-top: 1.5rem; }

/* The same rhythm for the few page bodies that do NOT sit directly under .app__content, so their stacked
   panels/cards are grandchildren the rule above cannot reach: a page wrapped in one max-width column
   (.doc-col), the account-settings content column (.acct__col), the public pages under PublicLayout
   (.pub__inner) and the auth/receipt card (.auth__card). Same collapsing owl selector, so no doubling. */
.doc-col { max-width: 52rem; }

/* Kontosidernes indholdskolonne havde kun rytme-reglen, intet loft: den fulgte rammen hele vejen ud.
   Samme mål som læsespalten — det er formularer og korte afsnit, ikke en tabel. */
.acct__col { max-width: 52rem; }
.doc-col > * + *,
.acct__col > * + *,
.pub__inner > * + * { margin-top: 1.5rem; }
.auth__card > .panel + .panel,
.auth__card > .panel + .alert { margin-top: 1.25rem; }

/* Two panels stacked inside one bento cell (e.g. the ticket-detail columns): the bento's own gap spaces
   the cells, not siblings within a cell, and .panel has no margin — match the bento gap between them. */
.bento .panel + .panel { margin-top: 1.15rem; }

/* ==========================================================================
   Sidebar
   ========================================================================== */

.side {
    width: var(--sidebar-w);
    flex-shrink: 0;
    background: linear-gradient(178deg, var(--navy-900) 0%, var(--navy-950) 100%);
    color: var(--blue-100);

    /* Menuen er navigation — ikke tekst man markerer. Uden dette markerer et dobbeltklik (eller et
       lille træk) på en sektionsoverskrift som «Administration» linjerne omkring den, og browserens
       markeringsfarve lægger sig som en bjælke hen over overskriften. Overskrifterne selv var allerede
       umarkerbare, men linkene rundt om var det ikke — så markeringen spændte hen over dem. */
    -webkit-user-select: none;
    user-select: none;

    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    transition: width 0.18s ease;
    /* Klip alt der stikker uden for de 100vh. .side__nav ruller selv indeni (overflow-y:auto), men de
       absolut-positionerede fold-checkbokse (checkbox-hacket for de sammenklappelige sektioner) lå ellers
       nederst i menu-flowet UDEN for højden og forlængede hele sidens rullehøjde — så man kunne rulle ned i
       tomt hvidt rum under indholdet på moduler, hvor menuen var højere end selve siden. */
    overflow: hidden;
}

/* ==========================================================================
   Test-/demo-miljøbanner (App.razor)
   Banneret ligger fast øverst i en 24px stribe. Når det er der (body.har-testbanner),
   skubbes hele app-shellen ned under det, så det ikke længere dækker top-baren eller
   sidemenuen. De top-forankrede sticky-elementer (.topbar, .side) klæber nu under
   banneret i stedet for op under det.
   ========================================================================== */
body.har-testbanner { padding-top: 24px; }
body.har-testbanner .app { min-height: calc(100vh - 24px); }
body.har-testbanner .topbar { top: 24px; }

@media (min-width: 901px) {
    /* Kun på desktop er .side sticky/100vh — på mobil er den relativ og flyder selv
       med under banneret via body-paddingen, så den må ikke røres her. */
    body.har-testbanner .side { top: 24px; height: calc(100vh - 24px); }
}

/* Menuen og topbaren bliver staaende, mens en dialog er aaben. Det haandteres i
   todoitModal i shortcuts.js — se klaebTilbage() dér. Det er med vilje ikke loest
   her i CSS: forskydningen maales paa det enkelte element frem for at blive regnet
   ud, saa den ogsaa passer for klaebende elementer laengere nede paa siden. */

.side__brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 1.4rem 1.35rem 1.25rem;
    color: #fff;
}

/* Den globale "a:hover" nedenfor slår ellers ordmærket mørkt (næsten usynligt på den mørke sidebar). */
.side__brand:hover { color: #fff; }

.side__mark {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    background: linear-gradient(140deg, var(--blue-400), var(--navy-600));
    display: grid;
    place-items: center;
    font-weight: 800;
    font-size: 0.86rem;
    letter-spacing: -0.02em;
    color: #fff;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
    flex-shrink: 0;
}

.side__wordmark {
    font-weight: 800;
    font-size: 1rem;
    letter-spacing: -0.01em;
    line-height: 1.15;
}

.side__wordmark span {
    display: block;
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--blue-400);
}

.side__nav {
    flex: 1;
    /* min-height:0 er nødvendig: uden den har et flex-barn min-height:auto og kan ikke krympe under
       sit indhold — så en menu, der er højere end skærmen (fx når «Administration» foldes ud), RULLER
       ikke indeni, men vokser i stedet forbi skærmen og skubber fold-knappen ned med et mørkt tomrum
       under sig. Med min-height:0 ruller .side__nav selv, og skinnen bliver stående nederst. */
    min-height: 0;
    overflow-y: auto;
    padding: 0.4rem 0.85rem 1rem;
}

.side__section {
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(165, 188, 213, 0.62);
    padding: 1.15rem 0.75rem 0.45rem;
}

.side__link {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.75rem;
    border-radius: 11px;
    color: var(--blue-200);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.3;
    margin-bottom: 2px;
    transition: background-color 0.13s ease, color 0.13s ease;
}

.side__link:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
}

.side__link.active {
    background: rgba(124, 155, 192, 0.22);
    color: #fff;
    box-shadow: inset 0 0 0 1px rgba(165, 188, 213, 0.2);
}

/* Et FASTGJORT punkt står to steder: som genvej i toppen og på sin egen plads i modullisten.
   Kun genvejen lyser. Originalen beholder sin «active» fra NavLink — den er bare ikke tegnet
   som aktiv her, så markeringen bliver ved med at betyde ét sted, ikke to.
   Sættes af pins.js; se side__row--dublet dér. */
.side__row--dublet > .side__link.active {
    background: transparent;
    color: var(--blue-200);
    box-shadow: none;
}

.side__row--dublet > .side__link.active:hover {
    background: rgba(255, 255, 255, 0.07);
    color: #fff;
}

.side__row--dublet > .side__link.active .icon { opacity: 0.85; }

.side__link .icon { flex-shrink: 0; opacity: 0.85; }

/* Ikonet tager accenten på det valgte punkt.
   Uden den var det aktive punkt kun en blågrå vask — samme familie som resten af menuen, så øjet
   skulle lede efter det. Accenten sidder på IKONET og ikke på teksten: teksten er allerede hvid og
   fed, og en farvet etiket oveni ville gøre punktet skrigende frem for tydeligt. */
.side__link.active .icon { opacity: 1; color: var(--side-accent); }

/* Dubletten skal heller ikke have accenten — ellers ville den lyse på anden vis end resten af
   listen og stadig se ud som «her er du». Se .side__row--dublet. */
.side__row--dublet > .side__link.active .icon { color: inherit; }

.side__toggle { display: none; }

/* Foldbare menu-sektioner. Selve foldningen er ren CSS: en skjult checkbox pr. sektion, hvis
   :checked-tilstand styrer, om gruppen under den vises. nav-fold.js husker blot valget pr. bruger. */
.side__fold {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.side__section--fold {
    display: flex;
    align-items: center;
    cursor: pointer;
    user-select: none;
    transition: color 0.12s ease;
}

.side__section--fold:hover { color: rgba(165, 188, 213, 0.92); }

/* Pilen: peger til højre når foldet, ned når åben. */
.side__section--fold::after {
    content: "";
    margin-left: auto;
    width: 5px;
    height: 5px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
    opacity: 0.7;
}

.side__fold:checked ~ .side__section--fold::after { transform: rotate(45deg); }

.side__fold:not(:checked) ~ .side__group { display: none; }

/* Fastgør-knappen ligger over linkets højre ende og vises kun ved hover, så den ikke
   støjer. Er punktet fastgjort, står den gyldne stift fast — også som markering. */
.side__row { position: relative; }
.side__row .side__link { padding-right: 2.1rem; }

/* Tallet ved et menupunkt («3 åbne hændelser»).
   Tegnes fra data-tal på rækken og ikke som markup, fordi de fastgjorte genveje er KLONER — se
   menutal.js. Klonen arver attributtet og dermed mærket, uden at der skal gøres noget.

   Nul findes ikke: menutal.js fjerner attributtet i stedet for at skrive "0". Et menupunkt med et
   gråt 0 ved siden af ligner noget, der er gået i stå — er der ingenting, står der ingenting. */
.side__row[data-tal]:not([data-tal=""])::after {
    content: attr(data-tal);
    position: absolute;

    /* Til venstre for nålen, som sidder på 6px. Uden for redigeringstilstand er nålen usynlig,
       men pladsen er den samme — så tallet flytter sig ikke, når man slår rediger til. */
    right: 1.6rem;
    top: 50%;
    transform: translateY(-50%);

    font-size: 0.68rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    color: var(--crit);
    pointer-events: none;
}

/* Sammenklappet menu: der er ikke plads til et tal ved siden af ikonet, så det bliver til en
   prik oppe i hjørnet. Tallet er væk, men «her er noget» er det, der skal bæres videre — ellers
   ville en sammenklappet menu tie om et nedbrud. */
:root[data-rail="1"] .side__row[data-tal]:not([data-tal=""])::after {
    content: "";
    right: 8px;
    top: 7px;
    transform: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--crit);
}

/* A folded section that holds an item with a number gets a dot after its title (25 October 2026), the rail's rule: the
   number is hidden, «something is here» is not. The error log's badge sits in a section that starts folded, and so does
   every section a person has folded away. Pure CSS on the same data-tal, so menutal.js keeps it live without knowing.
   The chevron is ordered last, so the dot stands by the title and the chevron stays at the right edge.
   The staff menu only (review of 25 October 2026): a customer's menu is drawn with the same fold markup, and the change
   was for Todo-IT's menu. NavMenu sets data-menu; "view as customer" gives a customer's menu, without the dot. */
.side__nav[data-menu="staff"] .side__section--fold::after { order: 2; }

.side__nav[data-menu="staff"] .side__fold:not(:checked) ~ .side__section--fold:has(~ .side__group .side__row[data-tal]:not([data-tal=""]))::before {
    content: "";
    order: 1;
    width: 6px;
    height: 6px;
    margin-left: 0.45rem;
    border-radius: 50%;
    background: var(--crit);
}

.side__pin {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: none;
    color: var(--blue-300);
    cursor: pointer;
    padding: 4px;
    line-height: 0;
    border-radius: 6px;
    /* Skjult uden for rediger-tilstand: menuen er ren, og ét tryk navigerer — også på mobil,
       hvor en synlig nål før stjal det første tryk. Nålene vises kun i «rediger genveje». */
    display: none;
    opacity: 0.55;
    transition: opacity 0.12s ease, color 0.12s ease, background-color 0.12s ease;
}

.side--edit .side__pin { display: inline-flex; }
.side--edit .side__pin:hover { opacity: 1; background: rgba(255, 255, 255, 0.12); color: #fff; }
.side__pin--on { opacity: 1; color: var(--gold); }
.side__pin--on .icon { fill: currentColor; }

/* «Genveje»-sektionen bruger de samme rækker/links som resten af menuen — ingen særlig stil
   udover en anelse luft under sig. */
.side__genveje { margin-bottom: 0.35rem; }

/* Genveje kan omordnes ved træk-og-slip. Gribe-markøren er selve signalet om, at rækkerne kan
   trækkes; klik navigerer stadig. (pins.js håndterer trækket; kun desktop — touch har ikke HTML5-DND.) */
/* Genveje kan omordnes ved at trække håndtaget — kun i rediger-tilstand. */
.side--edit .side__genveje .side__row { cursor: grab; }
.side__row--traekker { opacity: 0.4; cursor: grabbing; }
/* Indsæt-streg, der viser hvor rækken lander — tegnet med en inderskygge, så den ikke flytter layout. */
.side__row--drop-foer { box-shadow: inset 0 2px 0 0 var(--gold); }
.side__row--drop-efter { box-shadow: inset 0 -2px 0 0 var(--gold); }

/* Trækhåndtag i Genveje — kun synligt i rediger-tilstand (nålen ligger til højre, håndtaget til
   venstre). I rediger fanger håndtaget selv trækket (pointer-events:auto) med touch-action:none,
   så en finger kan trække uden at rulle siden — virker med både mus og berøring (iPad/mobil).
   pins.js indsætter ⠿-tegnet i klonerne. */
.side--edit #side-genveje-list .side__row .side__link { padding-left: 1.75rem; }
.side__grip {
    position: absolute;
    left: 8px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--faint);
    font-size: 0.95rem;
    line-height: 1;
    user-select: none;
    display: none;
}
.side--edit .side__grip { display: block; cursor: grab; opacity: 0.75; pointer-events: auto; touch-action: none; }
.side--edit .side__grip:hover { opacity: 1; color: var(--muted); }
/* I skinne-tilstand er linkene kun ikoner og centreret — hverken plads til grebet eller
   den ekstra venstremargen. */
:root[data-rail="1"] .side__grip { display: none; }
:root[data-rail="1"] #side-genveje-list .side__row .side__link { padding-left: 0; }

/* I skinne-tilstand er der hverken plads til eller mening i fastgør-knapper. */
:root[data-rail="1"] .side__pin { display: none; }
:root[data-rail="1"] .side__row .side__link { padding-right: 0; }

/* ==========================================================================
   Ikon-skinne: sidemenuen foldet til kun ikoner.
   Tilstanden (data-rail på <html>) sættes af nav.js — før første maling, så
   bredden ikke hopper — og genanvendes efter Blazor-navigation, ligesom temaet.
   ========================================================================== */

/* Sidemenuens bund: «Rediger genveje» + «Fold sammen/ud», som en samlet fod frem for en
   løs knap, der før sad og flød nederst. */
.side__foot { margin: 0.35rem 0.7rem 0.7rem; flex-shrink: 0; }
.side__edit-hint {
    display: none;
    font-size: 0.72rem;
    color: var(--muted);
    line-height: 1.4;
    padding: 0 0.3rem 0.5rem;
}
.side--edit .side__edit-hint { display: block; }
.side__foot-row { display: flex; gap: 0.4rem; }
.side__foot-btn {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.7rem;
    border: 0;
    border-radius: 11px;
    background: rgba(255, 255, 255, 0.05);
    color: var(--blue-300);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.13s ease, color 0.13s ease;
}
.side__foot-btn:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
.side__foot-btn .icon { flex-shrink: 0; }
/* «Rediger genveje» fylder bredden; «Fold sammen» er kun et ikon ved siden af. */
.side__edit { flex: 1 1 auto; }
.side__edit[aria-pressed="true"] { background: rgba(212, 175, 55, 0.16); color: var(--gold); }
.side__rail { flex: 0 0 auto; }

/* ==========================================================================
   Host-monitor picker («Overvåg en vært») — opdag → flueben → tærskel-dialogen.
   ========================================================================== */
.hm-sec { margin-top: 1rem; }
.hm-sec__title {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.35rem;
}
.hm-count { font-weight: 600; color: var(--gold); margin-left: 0.3rem; }
.hm-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.3rem;
    cursor: pointer;
    border-radius: 7px;
}
.hm-row:hover { background: rgba(127, 127, 127, 0.09); }
.hm-row input[type="checkbox"] { flex-shrink: 0; margin: 0; }
.hm-row__name { flex: 1 1 auto; min-width: 0; }
.hm-row__detail { color: var(--muted); font-size: 0.82rem; margin-left: 0.4rem; }
.hm-row__thr {
    flex-shrink: 0;
    font-size: 0.8rem;
    color: var(--muted);
    display: flex;
    align-items: center;
    gap: 0.35rem;
}
.hm-num {
    width: 4.4rem;
    padding: 0.25rem 0.45rem;
    border-radius: 7px;
    border: 1px solid rgba(127, 127, 127, 0.35);
    background: var(--paper, transparent);
    color: inherit;
    font: inherit;
    font-size: 0.85rem;
}
.hm-num:disabled { opacity: 0.5; }
.hm-list {
    max-height: 260px;
    overflow-y: auto;
    margin-top: 0.45rem;
    border: 1px solid rgba(127, 127, 127, 0.22);
    border-radius: 9px;
    padding: 0.25rem 0.45rem;
}

/* Sensor management: one card per reading, thresholds that WRAP so nothing is ever clipped
   off the right edge of the modal (the old wide table hid "critical above"). */
.sensor-edit { display: flex; flex-direction: column; gap: 0.6rem; }
.sensor-edit__row {
    border: 1px solid rgba(127, 127, 127, 0.22);
    border-radius: 9px;
    padding: 0.55rem 0.7rem;
}
.sensor-edit__head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; }
.sensor-edit__name { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.sensor-edit__thr { display: flex; flex-wrap: wrap; gap: 0.45rem 0.9rem; margin-top: 0.55rem; }
.sensor-edit__thr label {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--muted);
}
.sensor-edit__note { margin-top: 0.4rem; font-size: 0.78rem; color: var(--muted); }

:root[data-rail="1"] .side { width: 66px; }
:root[data-rail="1"] .side__brand { justify-content: center; padding-left: 0; padding-right: 0; }
:root[data-rail="1"] .side__wordmark { display: none; }
:root[data-rail="1"] .side__label { display: none; }
/* Skjuler både fold-overskrifterne og «Genveje»/«Konto»-overskrifterne. */
:root[data-rail="1"] .side__section { display: none; }
:root[data-rail="1"] .side__nav { padding-left: 0.5rem; padding-right: 0.5rem; }
:root[data-rail="1"] .side__link { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
/* Skinnen viser ALLE ikoner: fold-tilstanden ignoreres, så intet er skjult bag en foldet sektion. */
:root[data-rail="1"] .side__group { display: block !important; }
/* I skinne-tilstand stables fod-knapperne og vises kun som ikoner; hintet giver ingen mening der. */
:root[data-rail="1"] .side__foot { margin-left: 0.5rem; margin-right: 0.5rem; }
:root[data-rail="1"] .side__foot-row { flex-direction: column; }
:root[data-rail="1"] .side__foot-btn { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
:root[data-rail="1"] .side__foot-label { display: none; }
:root[data-rail="1"] .side__edit-hint { display: none !important; }

/* ==========================================================================
   Topbar (bruger + notifikationer, øverst til højre)
   ========================================================================== */

/* Bliver stående i toppen. Klokken opdaterer sig selv nu, og en klokke, der ruller
   ud af skærmen, kan lyse så meget den vil uden at nogen ser det. Søgefeltet får
   den samme tur med — det er alligevel det, man rækker ud efter først.

   z-index under 900: hurtig tidsregistrering (900), modaler og notifikationspanelet
   (950/951) skal stadig ligge ovenpå. */
.topbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 2.5rem 0.85rem;

    position: sticky;
    top: 0;
    z-index: 800;

    border-bottom: 1px solid transparent;
}

/* Baggrunden og sløringen ligger i et pseudoelement, ikke på baren selv.

   Grunden er ikke kosmetisk: backdrop-filter gør elementet til holdeblok for
   efterkommere med position: fixed. Notifikationspanelet er på mobil et bundark
   med position: fixed og bottom: 0 — og det målte pludselig fra topbarens bund i
   stedet for skærmens. Panelet landede på y −426, altså over skærmkanten, og man
   kunne kun se den nederste stump. Meldt ind som sag #1016.

   Et pseudoelement har ingen efterkommere, så filteret kan ikke fange noget. */
.topbar::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;

    /* Sløringen lader farverne bag skinne igennem, så baren ikke bliver en kasse
       oven på den tonede baggrund. */
    background: color-mix(in srgb, var(--shell) 82%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* Kanten kommer først, når der faktisk er rullet — ellers ligger der en streg
   under baren på en side, der ikke kan rulle. */
.topbar--rullet {
    border-bottom-color: var(--line);
    box-shadow: 0 6px 18px -12px rgba(22, 32, 46, 0.35);
}

/* Global søgning. Ligger til venstre i topbaren, hvor øjet lander først. */
.topsearch {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    flex: 0 1 26rem;
    padding: 0.42rem 0.85rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 999px;
    color: var(--muted);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* The search field's focus border is its cue: --focus-ring, 3:1 in both themes (KC, 6 October 2026). */
.topsearch:focus-within {
    border-color: var(--focus-ring);
    box-shadow: 0 0 0 3px rgba(94, 129, 172, 0.14);
}

.topsearch__input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 0.86rem;
    color: var(--ink);
    outline: none;
}

.topsearch__input::placeholder { color: var(--faint); }

/* Krydset i type="search" er browserens eget og passer ikke ind i feltet. */
.topsearch__input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* Tema-skifteren (sol/måne) i topbaren. Token-drevet, så den selv følger temaet:
   lys knap + dæmpet ikon på lyst, mørk knap + lyst ikon på mørkt. */
.themetoggle {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 0;
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--muted);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    cursor: pointer;
    transition: color 0.15s ease, background 0.15s ease;
}

.themetoggle:hover { background: var(--blue-50); color: var(--ink); }

/* «Spørg platformen» — diskret ikon i topbaren, samme runde form som tema-skifteren,
   så AI'en ikke fylder et helt menupunkt. */
.topbar__ask {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--muted);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    text-decoration: none;
    transition: color 0.15s ease, background 0.15s ease;
}

.topbar__ask:hover { background: var(--blue-50); color: var(--ink); }

/* The panel grid's layout control (js/gitter.js): an icon beside the others while the page is locked, with
   a small menu under it. Empty — and gone — on pages without a grid. */
.topbar__gitter {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.topbar__gitter:empty { display: none; }

.gitter-knap {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 50%;
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--muted);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    cursor: pointer;
    transition: color 0.15s ease, background 0.15s ease;
}

.gitter-knap:hover,
.gitter-knap[aria-expanded="true"],
.gitter-knap--aktiv { background: var(--blue-50); color: var(--ink); }

/* How many panels the layout hides — on the icon, so it is seen without opening anything. */
.gitter-knap { position: relative; }

.gitter-knap__antal {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    color: #fff;
    background: var(--blue-500, #3b6fd8);
    box-shadow: 0 0 0 2px var(--paper);
    pointer-events: none;
}

/* Capped: a long error must not push the bell and the user menu out of the top bar. The whole text is in
   the title and read out by the script. */
.gitter-knap__besked {
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.78rem;
    color: var(--muted);
    white-space: nowrap;
}

.gitter-knap__besked--fejl { color: var(--crit-ink); }

/* z-index: without it the menu is an ordinary positioned element and paints in document order — so in a
   list, the NEXT row's buttons (themselves positioned) were drawn on top of an open menu. Above page
   content and the layout overlay (40), well below the sticky topbar (800) and dialogues (950). */
.gitter-menu {
    position: absolute;
    z-index: 50;
    top: calc(100% + 0.5rem);
    right: 0;
    min-width: 14rem;
    /* The top bar is sticky, so a menu taller than the screen could not be scrolled into view — with many
       own layouts on a low screen the last entries would sit below the edge. */
    max-height: calc(100vh - 6.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.35rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: 0 14px 34px -14px rgba(22, 32, 46, 0.45);
}

.gitter-menu__etiket {
    padding: 0.45rem 0.6rem 0.2rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--faint);
}

.gitter-menu__punkt {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    width: 100%;
    padding: 0.4rem 0.6rem;
    border: 0;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: 0.85rem;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}

.gitter-menu__punkt:hover { background: var(--blue-50); }

/* The background alone is next to invisible against the menu (about 1.05:1 in the dark theme), so keyboard
   focus keeps a ring — drawn inside, where the menu's padding has room for it. */
.gitter-menu__punkt:focus-visible {
    background: var(--blue-50);
    outline: 2px solid var(--focus-ring);
    outline-offset: -2px;
}

.gitter-menu__maerke {
    width: 1rem;
    flex-shrink: 0;
    color: var(--blue-500, #3b6fd8);
    font-weight: 700;
}

.gitter-menu__skille {
    height: 1px;
    margin: 0.35rem 0.3rem;
    background: var(--line);
}

/* Ikonet følger [data-theme] i CSS, så det aldrig kommer ud af sync med det faktiske tema.
   Lyst tema viser månen (klik → mørkt); mørkt tema viser solen (klik → lyst). */
.themetoggle__ikon { display: none; }
.themetoggle__ikon--maane { display: inline-flex; }
:root[data-theme="dark"] .themetoggle__ikon--maane { display: none; }
:root[data-theme="dark"] .themetoggle__ikon--sol { display: inline-flex; }

.topbar__right {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.topbar__user {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.3rem 0.75rem 0.3rem 0.3rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.7);
    box-shadow: inset 0 0 0 1px var(--line);
}

.topbar__avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--blue-400), var(--navy-700));
    display: grid;
    place-items: center;
    font-size: 0.73rem;
    font-weight: 800;
    color: #fff;
    flex-shrink: 0;
}

.topbar__avatar:hover { color: #fff; }

.topbar__who { min-width: 0; line-height: 1.2; }

.topbar__who b {
    display: block;
    font-size: 0.79rem;
    font-weight: 700;
    color: var(--ink);
    max-width: 15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topbar__who span {
    display: block;
    font-size: 0.68rem;
    color: var(--muted);
}

.topbar__signout {
    background: rgba(255, 255, 255, 0.7);
    border: 0;
    box-shadow: inset 0 0 0 1px var(--line);
    width: 34px;
    height: 34px;
    border-radius: 50%;
    color: var(--muted);
    cursor: pointer;
    display: grid;
    place-items: center;
}

.topbar__signout:hover { background: #fff; color: var(--ink); }

/* Topbaren giver allerede luft i toppen — undgå dobbelt padding på indholdet. */
.topbar ~ .app__content { padding-top: 1.25rem; }

/* Trykmål på telefon.
   Ikonerne i topbjælken måler 32–34 px, hvilket er fint at ramme med en mus og for
   småt til en tommelfinger. Apple og Google anbefaler begge 44. Cirklen vokser ikke
   — det er trykfeltet omkring den, der gør, via padding. Så ser den ens ud, men
   rammer bedre. */
@media (max-width: 700px) {
    .topbar__avatar,
    .topbar__signout,
    .notif__btn {
        min-width: 44px;
        min-height: 44px;
    }

    /* Avataren har sin egen baggrund og må ikke blive en stor firkant — den
       centreres i stedet inde i det større trykfelt. */
    .topbar__avatar {
        background-clip: content-box;
        padding: 6px;
    }
}

/* ==========================================================================
   "Se som kunde"-banner
   ========================================================================== */

.viewas {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.7rem 2.5rem;
    background: linear-gradient(90deg, #f3e6cd, #f8f0e2);
    border-bottom: 1px solid #e3cfa5;
    color: #6d4d16;
    font-size: 0.87rem;
    font-weight: 600;
}

.viewas__dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--warn);
    flex-shrink: 0;
    box-shadow: 0 0 0 3px rgba(176, 125, 51, 0.22);
}

.viewas form { margin-left: auto; }

.viewas__exit {
    border: 1px solid #d9bd8a;
    background: rgba(255, 255, 255, 0.75);
    color: #6d4d16;
    border-radius: 999px;
    padding: 0.3rem 0.9rem;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}

.viewas__exit:hover { background: #fff; border-color: var(--warn); }

@media (max-width: 900px) {
    .viewas { padding: 0.7rem 1.25rem; }
}

/* ==========================================================================
   Page header
   ========================================================================== */

.ph {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.9rem;
}

.ph__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--brass);
    margin-bottom: 0.7rem;
}

/* Stregen er tyndere og uden opacity: 1 px i fuld farve læses skarpere end 2 px i 75 %,
   som bare bliver grumset. */
.ph__eyebrow::before {
    content: "";
    width: 22px;
    height: 1px;
    background: currentColor;
}

.ph__title {
    font-size: clamp(1.7rem, 2.6vw, 2.35rem);
    font-weight: 800;
    letter-spacing: -0.028em;
    line-height: 1.08;
}

.ph__help {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.45rem;
    height: 1.45rem;
    margin-left: 0.55rem;
    vertical-align: middle;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1;
    color: var(--muted);
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    border-radius: 999px;
    text-decoration: none;
    transition: background 0.12s, color 0.12s;
}

.ph__help:hover,
.ph__help:focus-visible { color: #fff; background: var(--blue-500); }

.ph__lead {
    margin-top: 0.5rem;
    color: var(--muted);
    font-size: 1rem;
    max-width: 62ch;
}

.ph__actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }

/* Hard state under the title (PageHeader.Badges): dot-and-word marks in a row that wraps. */
.ph__badges { display: flex; flex-wrap: wrap; gap: 0.35rem 1.1rem; margin-top: 0.6rem; }

/* På smal skærm bliver knapperne ÉN linje, man kan rulle i — ikke tre stablede.
   Målt på driftsovervågningen den 13. september 2026: fem knapper brød til tre rækker og fyldte
   151 px, alle sammen handlinger der OPRETTER noget, oven over den første måling — på den skærm
   der har mindst plads. Én rullelinje koster 47 px. Intet er skjult, og den afskårne kant på den
   sidste knap er selve signalet om, at der er mere. */
@media (max-width: 780px) {
    .ph__actions { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.2rem; }
    .ph__actions > * { flex: 0 0 auto; }
    /* The phone block's flex: 1 1 auto on .ph__actions .btn outranks the line above, and a .btn wraps its text: the
       buttons shrank to their longest word and broke onto two lines. Kept on one line, the row scrolls as meant. */
    .ph__actions .btn { white-space: nowrap; }
    /* A menu in the header (a details element: the monitoring page's add menu, the customer page's more menu) hangs
       below its button; the scrolling row would clip it to the row's own height. While one is open the row lets it
       out, and wraps rather than pushing the page sideways. */
    .ph__actions:has(> details[open]) { overflow: visible; flex-wrap: wrap; }
}

/* ==========================================================================
   Surfaces
   ========================================================================== */

/* Skygge er hierarki, ikke pynt.
   Hvert panel havde --shadow-sm, og når alt er løftet, er intet løftet — øjet får ingen hjælp til
   at finde det, der haster. Panelet står nu på en hårstreg, og elevationen er flyttet til
   .panel--haster, som må optræde ÉN gang pr. side. */
.panel {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    padding: 1.5rem 1.6rem;
}

/* Den ene forhøjede flade: det, der kræver handling nu.
   Venstrekanten bærer status-farven, så panelet siger hvad OG hvor slemt uden en overskrift.
   Sættes med --haster-farve; standard er kritisk, fordi det er den hyppigste brug. */
.panel--haster {
    --haster-farve: var(--crit);
    border-color: color-mix(in srgb, var(--haster-farve) 30%, var(--line));
    border-left: 3px solid var(--haster-farve);
    border-radius: 4px var(--r-lg) var(--r-lg) 4px;
    box-shadow: var(--shadow-md);
}

.panel--haster.panel--obs  { --haster-farve: var(--warn); }
.panel--haster.panel--ok   { --haster-farve: var(--good); }

/* Målestregen — signaturmotivet i retning A.
   En fin skala under et nøgletal, som på et måleinstrument. Den siger ingenting præcist, og det
   er meningen: den fortæller, at tallet ER en måling og ikke bare et tal, nogen har skrevet.
   Rent dekorativt, derfor aria-hidden i markup.
   Tegnet med gradienter frem for SVG, så farven følger currentColor og dermed temaet. */
.maalestreg {
    height: 9px;
    margin-top: 0.5rem;
    color: color-mix(in srgb, var(--ink) 22%, transparent);
    border-bottom: 1px solid currentColor;
    background:
        linear-gradient(currentColor, currentColor) left bottom / 1px 9px no-repeat,
        linear-gradient(currentColor, currentColor) right bottom / 1px 9px no-repeat,
        repeating-linear-gradient(to right, currentColor 0 1px, transparent 1px 20%) left bottom / 100% 5px no-repeat;
}

/* Nøgletal med målestreg. Tallet er helten, mærkatet er lille, noten er dæmpet — og stregen
   under fortæller, at tallet ER en måling. Bruges på forsiden og hører til overalt, hvor et
   tal skal læses frem for tælles. */
.noegletal {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 2.4rem;
    margin-bottom: 2.2rem;
}

.noegletal__mærkat {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--muted);
}

.noegletal__tal {
    font-size: 2.5rem;
    font-weight: 800;
    letter-spacing: -0.04em;
    line-height: 1.05;
    margin-top: 0.4rem;
    font-variant-numeric: tabular-nums;
}

.noegletal__tal--obs  { color: var(--warn-ink); }
.noegletal__tal--krit { color: var(--crit-ink); }

.noegletal__note {
    font-size: 0.8rem;
    color: var(--muted);
    margin-top: 0.55rem;
}

.maalestreg--ok   { color: color-mix(in srgb, var(--good) 38%, transparent); }
.maalestreg--obs  { color: color-mix(in srgb, var(--warn) 38%, transparent); }
.maalestreg--krit { color: color-mix(in srgb, var(--crit) 38%, transparent); }

.panel--flush { padding: 0; overflow: hidden; }

.panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 1.15rem;
}

.panel__title {
    font-size: 1.02rem;
    font-weight: 700;
    letter-spacing: -0.012em;
}

.panel__sub {
    font-size: 0.83rem;
    color: var(--muted);
    margin-top: 0.15rem;
}

/* Hero band */
.hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--r-xl);
    padding: 1.9rem 2.1rem;
    margin-bottom: 1.5rem;
    color: #fff;
    background: linear-gradient(128deg, var(--navy-900) 0%, var(--navy-800) 46%, var(--navy-600) 100%);
    box-shadow: var(--shadow-md);
}

.hero::after {
    content: "";
    position: absolute;
    right: -70px;
    top: -90px;
    width: 320px;
    height: 320px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(197, 217, 236, 0.24), transparent 68%);
    pointer-events: none;
}

.hero__eyebrow {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--blue-300);
}

.hero__title {
    font-size: clamp(1.75rem, 3vw, 2.5rem);
    font-weight: 800;
    letter-spacing: -0.03em;
    color: #fff;
    margin-top: 0.4rem;
    line-height: 1.05;
}

.hero__chips {
    display: flex;
    gap: 0.55rem;
    flex-wrap: wrap;
    margin-top: 1.2rem;
    position: relative;
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.4rem 0.85rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 700;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.16);
    backdrop-filter: blur(4px);
}

.chip--good { background: rgba(94, 186, 133, 0.2); border-color: rgba(94, 186, 133, 0.38); }
.chip--warn { background: rgba(226, 178, 96, 0.2); border-color: rgba(226, 178, 96, 0.4); }
.chip--crit { background: rgba(224, 130, 120, 0.2); border-color: rgba(224, 130, 120, 0.42); }

/* Statuspille på lys flade.
   .chip ovenfor har hvid tekst og er bygget til at ligge oven på en mørk hero —
   den har endda backdrop-filter. Bruges den på et almindeligt hvidt panel, bliver
   det hvid tekst på 20 % gennemsigtig farve, og så forsvinder den næsten.
   Denne bruger temaets lyse status-baggrunde med en mørknet tekstfarve, så
   kontrasten holder WCAG AA (4,5:1). Tallene er efterregnet i tests/kontrastcheck. */
.pil {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0;
    font-size: 0.8rem;
    font-weight: 600;
    white-space: nowrap;
}

/* Prik og ord frem for fyldt pille.
   En række fyldte piller under hinanden bliver til et farvet gardin, hvor ingen enkelt skiller
   sig ud. Prikken bærer farven, ordet bærer betydningen, og fladen forbliver rolig — så er det
   den ENE røde, der springer i øjnene, og ikke alle tredive tilsammen.
   Prikken tegnes med ::before, så ingen markup skal røres. */
.pil::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: currentColor;
    flex-shrink: 0;
}

.pil--good { color: var(--good-ink); }
.pil--warn { color: var(--warn-ink); }
.pil--crit { color: var(--crit-ink); }

/* A mark whose words are data — a customer's name, a time and who set it — and may be wider than a phone.
   It wraps (a long address breaks where it must) instead of pushing the page sideways; the dot stays on the
   first line rather than centring on the whole block, and the lines start next to it — also in a
   right-aligned .kv__val, where a wrapped mark takes the whole width. */
.pil--wrap {
    white-space: normal;
    overflow-wrap: anywhere;
    align-items: flex-start;
    max-width: 100%;
    text-align: left;
}

.pil--wrap::before { margin-top: calc(0.75em - 3.5px); }

/* Neutral = «vi ved det ikke». Den er åben frem for fyldt, fordi et hult mærke læses som et
   fravær af svar, hvor et fyldt læses som et svar. Det er præcis forskellen på «ukendt» og
   de tre andre. */
.pil--neutral { color: var(--muted); }
.pil--neutral::before {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px currentColor;
}

/* ==========================================================================
   Bento grid
   ========================================================================== */

.bento {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 1.15rem;
    margin-bottom: 1.5rem;
}

/* Egne span-klasser — IKKE .col-N: Bootstraps .col-N sætter width:25% o.l.,
   hvilket vinder over grid-column og klemmer felterne sammen. */
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
.span-5 { grid-column: span 5; }
.span-6 { grid-column: span 6; }
.span-7 { grid-column: span 7; }
.span-8 { grid-column: span 8; }
.span-12 { grid-column: span 12; }

/* ==========================================================================
   Panelgitteret (js/gitter.js)
   Siden markerer en beholder med data-gitter og sine paneler med data-gitter-panel.
   Selve placeringen skrives af scriptet som regler i <head> — her står kun det, der
   gælder, uanset om gitteret er aktivt.
   ========================================================================== */

/* Until the script places the panels — and whenever it does not: a container narrower than 880 px,
   a page with a single panel — the container behaves like the .bento the panels used to sit in:
   span-6 side by side, everything else full width, the page's 1.5rem between them. The panels are
   grandchildren of .app__content, so its * + * rhythm does not reach them. Margin 0 at two attribute
   selectors' weight, because .status brings a margin-bottom that a grid would add to the gap. The
   script's own rules start with "html" and outweigh all of this once it takes over. */
[data-gitter] {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 1.5rem;
}

/* Full width by default, at no weight at all: a panel carrying one of the house's .span-N classes keeps that
   width here, and with it the breakpoints further down (span-7 full width under 1180 px, span-6 under 640 px)
   — the same as in the .bento it came from. */
:where([data-gitter]) > * { grid-column: 1 / -1; }
[data-gitter] > [data-gitter-panel] { margin: 0; }

/* A grid container never collapses margins, so an empty one would double the gap around it. */
[data-gitter]:not(:has(> *)) { display: none; }

[data-gitter-bar]:empty { display: none; }

/* Scrolled to from the top bar's layout menu: stop below the sticky top bar, not under it. */
[data-gitter-bar] { scroll-margin-top: 5.5rem; }

/* An empty bar first on the page (the staff front page, where the page header is a panel) would give the grid
   .app__content's * + * margin above the header — the header would sit lower than on every other page.
   Only there: where something comes before the bar (a page header, a status line, a customer picker), that
   margin is the gap between it and the panels. */
[data-gitter-bar]:empty:first-child + [data-gitter] { margin-top: 0; }

.gitter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    justify-content: flex-end;
}

.gitter-bar__valg { width: auto; min-width: 11rem; }

.gitter-bar__hint,
.gitter-bar__besked {
    font-size: 0.8rem;
    color: var(--muted);
}

.gitter-bar__besked { color: var(--ink-2); }
.gitter-bar__besked--fejl { color: var(--crit-ink); }

/* The page header as a panel: its own bottom margin would come on top of the grid's gap. */
[data-gitter] > [data-gitter-panel] > .ph { margin-bottom: 0; }

.gitter-bar__gruppe {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
}

.gitter-bar__etiket { font-size: 0.8rem; color: var(--muted); }

.gitter-bar__navn { width: 14rem; }

/* Hide button on a handle in edit mode — a sibling of the handle in the overlay, placed at its top
   right by the script, because a button inside a role=button element is not allowed. */
.gitter-skjul {
    position: absolute;
    z-index: 1;
    transform: translateX(calc(-100% - 0.5rem));
    padding: 0.1rem 0.6rem;
    border: 1px solid var(--blue-500, #3b6fd8);
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--blue-500, #3b6fd8);
    background: var(--paper);
    cursor: pointer;
}

.gitter-skjul:hover,
.gitter-skjul:focus-visible {
    color: #fff;
    background: var(--blue-500, #3b6fd8);
}

.gitter-overlay {
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    z-index: 40;
}

.gitter-greb {
    position: absolute;
    border-radius: var(--r-lg);
    background: color-mix(in srgb, var(--blue-500, #3b6fd8) 6%, transparent);
    cursor: grab;
    touch-action: none;          /* kun på håndtagene i redigering — ellers ville siden ikke kunne scrolles på en telefon */
}

.gitter-greb:focus-visible { outline: 2px solid var(--blue-500, #3b6fd8); outline-offset: 2px; }

.gitter-greb--aktiv {
    cursor: grabbing;
    background: color-mix(in srgb, var(--blue-500, #3b6fd8) 14%, transparent);
}

.gitter-greb__navn {
    position: absolute;
    top: 0.45rem;
    left: 50%;
    transform: translateX(-50%);
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
    color: #fff;
    background: var(--blue-500, #3b6fd8);
    pointer-events: none;
}

.gitter-hjoerne {
    position: absolute;
    right: 0.3rem;
    bottom: 0.3rem;
    width: 1.1rem;
    height: 1.1rem;
    cursor: nwse-resize;
    border-right: 3px solid var(--blue-500, #3b6fd8);
    border-bottom: 3px solid var(--blue-500, #3b6fd8);
    border-radius: 0 0 4px 0;
}

@media (max-width: 1180px) {
    .span-3, .span-4 { grid-column: span 6; }
    .span-5, .span-7, .span-8 { grid-column: span 12; }
}

@media (max-width: 640px) {
    /* span-6 er store paneler og skal have hele bredden.
       span-3 er nøgletalsfelter — dem beholder vi to og to.

       De stod før i fuld bredde hver for sig, og fire felter fyldte omkring 600 px:
       tre skærmfulde rulning på en telefon, før man overhovedet nåede indholdet. Et
       felt med ét tal har ikke brug for 375 px. */
    .span-6 { grid-column: span 12; }

    /* span-4 manglede. Den blev til span 6 ved 1180 px, og der stoppede den — så
       sidepanelet med sagens detaljer stod i halv bredde på en telefon, med felter
       klemt ned i 160 px. Det så ud som en fejl, fordi det var en. */
    .span-4 { grid-column: span 12; }
}

/* ==========================================================================
   Stat tile
   ========================================================================== */

.stat {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    padding: 1.3rem 1.4rem;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    position: relative;
    min-height: 100%;
    transition: box-shadow 0.16s ease, transform 0.16s ease;
}

.stat:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }

/* A tile that leads to the list behind its number (StatTile Href). */
a.stat--link { color: inherit; text-decoration: none; cursor: pointer; }
a.stat--link:focus-visible { outline: 2px solid var(--blue-500, currentColor); outline-offset: 2px; }

.stat__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.15rem;
}

.stat__label {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

.stat__dot {
    width: 30px;
    height: 30px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    background: var(--blue-50);
    color: var(--navy-700);
    flex-shrink: 0;
}

.stat--good .stat__dot { background: var(--good-bg); color: var(--good); }
.stat--warn .stat__dot { background: var(--warn-bg); color: var(--warn); }
.stat--crit .stat__dot { background: var(--crit-bg); color: var(--crit); }

.stat__value {
    font-size: 2.15rem;
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1.05;
    color: var(--ink);
}

.stat__meta {
    font-size: 0.81rem;
    color: var(--faint);
}

/* A row of stat tiles inside a panel (the device page, device merge). The class never had a rule, so the tiles stood
   in one column at full width - fourteen of them, one under the other, on a device page. As many columns as fit at
   13rem; a long value (a processor, MAC addresses) wraps inside its tile instead of running out of it, at the lean
   tile size (1.6rem) so a model name is two lines, not five. */
.stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
    gap: 1rem;
}

.stat-row .stat__value { font-size: 1.6rem; line-height: 1.15; overflow-wrap: anywhere; }

/* Two by two on a phone, like the key-figure tiles (.span-3): a tile with one number does not need 375 px. */
@media (max-width: 640px) {
    .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
}

/* ==========================================================================
   Meter / progress
   ========================================================================== */

.meter {
    height: 10px;
    border-radius: 999px;
    background: var(--blue-50);
    overflow: hidden;
    box-shadow: inset 0 0 0 1px var(--line);
}

.meter__fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--navy-700), var(--blue-500));
}

.meter__fill--warn { background: linear-gradient(90deg, #a06f28, var(--warn)); }
.meter__fill--crit { background: linear-gradient(90deg, #8f3a33, var(--crit)); }

.bigfig {
    font-size: 2.9rem;
    font-weight: 800;
    letter-spacing: -0.04em;
    line-height: 1;
    color: var(--ink);
}

.bigfig small {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--faint);
    letter-spacing: -0.01em;
}

/* ==========================================================================
   Module list (dashboard)
   ========================================================================== */

.mods { display: flex; flex-direction: column; gap: 0.45rem; }

.mods__row {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--r-sm);
    background: var(--blue-50);
    font-size: 0.87rem;
    font-weight: 600;
    color: var(--ink-2);
}

.mods__row .icon { color: var(--navy-700); flex-shrink: 0; }
.mods__row span { margin-left: auto; font-size: 0.75rem; font-weight: 700; color: var(--good); }

/* ==========================================================================
   Aftalekort
   ========================================================================== */

.agr-list { display: flex; flex-direction: column; gap: 1rem; }

.agr {
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    padding: 1.1rem 1.2rem;
    background: linear-gradient(180deg, var(--blue-50), var(--paper));
}

.agr__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.75rem;
}

.agr__name { font-weight: 700; font-size: 0.98rem; color: var(--ink); }

.agr__bill {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.9rem;
    padding-top: 0.75rem;
    border-top: 1px dashed var(--line-2);
    font-size: 0.83rem;
    color: var(--warn);
}

.agr__outside {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-top: 0.85rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--r-sm);
    background: var(--paper);
    border: 1px dashed var(--line-2);
    font-size: 0.83rem;
    color: var(--ink-2);
}

.agr__outside span { display: flex; flex-direction: column; }
.agr__outside .icon { margin-top: 2px; color: var(--blue-500); }

/* ==========================================================================
   Domænekort (Domænesikkerhed) — grupperet pr. kunde i stedet for én flad tabel,
   så det stadig er overskueligt med flere domæner pr. kunde og flere checks.
   ========================================================================== */

.dgroup {
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow-sm);
    margin-bottom: 1rem;
    overflow: hidden;
}

.dgroup__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1.2rem;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.dgroup__summary::-webkit-details-marker { display: none; }

.dgroup__summary::before {
    content: "";
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--ink-2);
    border-bottom: 2px solid var(--ink-2);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
    margin-right: 0.5rem;
    flex-shrink: 0;
}

.dgroup[open] > .dgroup__summary::before { transform: rotate(45deg); }

.dgroup__name { font-weight: 700; font-size: 0.95rem; }

/* ── Dmarc: the customer table (staff overview, and the mailboxes per customer) ── */
.dm-kunder__row { cursor: pointer; }
.dm-kunder__row:hover { background: var(--blue-50); }
.dm-kunder__row:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.dm-kunder__navn { font-weight: 700; }

/* Den valgte kunde bliver stående markeret, så man kan se hvis postkasse
   panelet nedenunder hører til, mens man arbejder i den. */
.dm-kunder__row.er-valgt { background: var(--blue-50); }
.dm-kunder__row.er-valgt td:first-child { box-shadow: inset 3px 0 0 var(--ink-2); }

.dm-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 0.5rem; background: var(--faint); }
.dm-dot--ok { background: var(--good); }
.dm-dot--warn { background: var(--warn); }
.dm-dot--crit { background: var(--crit); }

/* Ingen rapporter modtaget. Hul frem for fyldt, saa den ikke kan forveksles med en
   maalt tilstand — hverken den groenne eller den roede. */
.dm-dot--tom {
    background: transparent;
    box-shadow: inset 0 0 0 1.5px var(--faint);
}

.dm-rate { font-variant-numeric: tabular-nums; }

.dm-bar {
    display: block;
    width: 80px;
    height: 5px;
    margin-left: auto;
    margin-top: 0.25rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--crit) 55%, transparent);
    overflow: hidden;
}

.dm-bar > i { display: block; height: 100%; background: var(--good); }

.txt-crit { color: var(--crit); }
.txt-warn { color: var(--warn); }
.txt-faint { color: var(--faint); }
.txt-muted { color: var(--muted); }

/* Klik-for-at-rette-markør: prikket understregning, så inline-redigering er synlig som
   redigerbar uden at man skal hovere. Samlet cue for de steder, der før kun havde cursor+title. */
.editcue { cursor: pointer; text-decoration: underline dotted; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.editcue:hover { text-decoration-color: var(--blue-400); }

/* Klikbar række UDEN ugyldig ARIA-nesting. Før var rækken selv role="button" med rigtige
   <button>-handlinger indeni — en knap i en knap. Nu er rækken ikke interaktiv; «hit»-elementet
   (et <a> eller en <button>) dækker hele rækken via ::after (stretched link), og handlingsknapper
   løftes over med z-index, så de stadig kan klikkes hver for sig. Tastatur: hit-elementet er
   tab-stoppet. Bruges på Vidensbase-rækker og notifikationsrækker. */
.stretchrow { position: relative; }
.stretchrow__hit { text-decoration: none; color: inherit; }
.stretchrow__hit::after { content: ""; position: absolute; inset: 0; }
/* Når hit er en <button>: nulstil knap-look, så den ligner den tekst, den dækker. */
button.stretchrow__hit { border: 0; background: transparent; padding: 0; margin: 0; font: inherit; text-align: inherit; cursor: pointer; }
.stretchrow__over { position: relative; z-index: 1; }

/* .muted som alias, ikke som tyve omdøbninger.
   Klassen står 20 steder — Agents, Maintenance, NetworkScan — uden nogensinde at være
   skrevet, så de linjer blev tegnet i fuld brødtekstfarve i stedet for dæmpet. Det er
   værst dér, hvor den bruges til «vi ved det ikke»-sætninger som «adresse ukendt endnu»:
   en usikker oplysning så lige så bestemt ud som en målt. Samme aliasteknik som .tbl. */
.muted { color: var(--muted); }

/* ── Indstillinger ────────────────────────────────────────────────────────
   Kategorier til venstre, tætte rækker til højre, søgning øverst.

   Det afgørende skifte er fra kort til rækker. Et kort pr. indstilling fylder som en
   reklame og gav fire pr. skærm; en række giver tolv. Når man leder efter noget, er
   antallet man kan se på én gang næsten hele oplevelsen. */
.settings__top {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.4rem;
}

.setsearch {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 0.6rem 1rem;
    color: var(--muted);
    min-width: min(24rem, 100%);
}

/* The border is the focus cue: --focus-ring (--blue-300 was 1.9:1 on paper; KC, 6 October 2026). */
.setsearch:focus-within { border-color: var(--focus-ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue-300) 20%, transparent); }

.setsearch__felt {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--ink);
    outline: none;
}

/* Genvejen vises, indtil man skriver — så bliver den til en ryd-knap. Feltet skifter
   altså aldrig bredde, og der er ingen knap, der dukker op og skubber til noget. */
.setsearch__kbd {
    font-size: 0.7rem;
    border: 1px solid var(--line);
    border-radius: 5px;
    padding: 0.05rem 0.35rem;
    color: var(--faint);
}

.setsearch__ryd {
    display: inline-flex;
    border: 0;
    background: none;
    color: var(--muted);
    cursor: pointer;
    padding: 0;
}

.setsearch__ryd:hover { color: var(--ink); }

/* Emne-rækken øverst på en enkelt indstillingsside. Vandret og kompakt: den skal
   kunne skimmes på én linje, ikke konkurrere med sidens indhold om opmærksomheden.
   Ruller vandret på mobil frem for at brække i tre rækker. */
.setnav {
    display: flex;
    gap: 0.3rem;
    overflow-x: auto;
    padding-bottom: 0.4rem;
    margin-bottom: 1.1rem;
    scrollbar-width: thin;
}

/* Emnevælgeren. To udgaver af samme navigation, fordi en vandret fanerække og en
   telefonskærm ikke kan forliges: otte faner fylder 1192 px, og den aktive kan ligge
   helt uden for skærmen. Målt, ikke gættet. */
.setnav-mobil { display: none; margin-bottom: 1.1rem; }
.setnav-mobil label { display: block; margin-bottom: 0.3rem; }

@media (max-width: 700px) {
    .setnav { display: none; }
    .setnav-mobil { display: block; }
}

/* The section's panels (and the customer-contact switch) carry the anchors the settings hub and the palette link to,
   e.g. admin/settings/drift#eskalering, and the page scrolls there itself (todoitShortcuts.reveal, block: start).
   They follow the tab row as its siblings. Stop below the sticky top bar, like the other reveal targets. */
.setnav ~ [id] { scroll-margin-top: 5.5rem; }

.setnav__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex-shrink: 0;
    padding: 0.42rem 0.7rem;
    border-radius: 999px;
    border: 1px solid var(--line);
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
}

.setnav__link:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); }

.setnav__link--aktiv {
    background: color-mix(in srgb, var(--blue-300) 16%, transparent);
    border-color: color-mix(in srgb, var(--blue-300) 45%, transparent);
    color: var(--ink);
}

/* ==========================================================================
   Endpoint-rækker (Driftsovervågning)

   Kort til alt gav 16 enheder samme vægt, uanset om noget var galt. Det, man
   åbner siden for at vide, druknede i det, man ikke spurgte om. Nu: fuld visning
   kun til det, der kræver noget, og tætte rækker til resten — med detaljerne ét
   klik væk via <details>, så det virker uden JavaScript og med tastatur.
   ========================================================================== */

.eptools { display: flex; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; margin-top: 1rem; }

/* «Vis 4 konti» på et sikkerhedsfund. Foldet sammen, fordi anbefalingen er det, man
   skal læse først — navnene er det, man skal bruge bagefter. */
.sscore__hvem { margin-top: 0.5rem; font-size: 0.82rem; }

.sscore__hvem > summary {
    cursor: pointer;
    /* --blue-600 findes ikke; farven faldt derfor tilbage til arvet brødtekst, og
       «Vis 4 konti» så ud som almindelig tekst frem for noget, man kan klikke på.
       --navy-700 er husets linkfarve (--bs-link-color). */
    color: var(--navy-700);
    font-weight: 700;
    list-style: none;
    display: inline-block;
    padding: 0.2rem 0;
}

.sscore__hvem > summary::-webkit-details-marker { display: none; }
.sscore__hvem > summary::before { content: "▸ "; }
.sscore__hvem[open] > summary::before { content: "▾ "; }
.sscore__hvem > summary:hover { text-decoration: underline; }

.sscore__hvem ul {
    margin: 0.4rem 0 0;
    padding-left: 1.1rem;
    line-height: 1.7;
    color: var(--ink-2);
}

/* Et panel uden indhold. Beholder sin overskrift, så strukturen kan ses, men holder op
   med at fylde som om der stod noget i det — årshjulets fire kvartaler brugte ellers
   hele skærmen på fire gange «Intet planlagt». */
.panel--tom {
    padding-bottom: 0;
    background: transparent;
    box-shadow: none;
    border-style: dashed;
}

.panel--tom .panel__head { margin-bottom: 0; padding-bottom: 0.9rem; border-bottom: 0; }
.panel--tom .panel__title { color: var(--muted); }

.epsek { margin-top: 1.4rem; }

.epsek__titel {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.6rem;
}

.epsek__antal {
    font-weight: 600;
    color: var(--faint);
    font-variant-numeric: tabular-nums;
    text-transform: none;
    letter-spacing: 0;
}

.eprows {
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper);
    overflow: hidden;
}

.eprow { border-bottom: 1px solid var(--line); }
.eprow:last-child { border-bottom: 0; }
.eprow[open] { background: color-mix(in srgb, var(--ink) 3%, transparent); }

.eprow__sum {
    display: grid;
    grid-template-columns: 0.6rem minmax(0, 2fr) minmax(0, 1.2fr) 4.5rem 7rem 5rem 4rem;
    align-items: center;
    gap: 0.75rem;
    padding: 0.62rem 0.9rem;
    cursor: pointer;
    list-style: none;
    font-size: 0.86rem;
}

/* Kolonneoverskrifter over de tætte rækker. Samme gitter som .eprow__sum — ellers
   står etiketterne ikke over deres egne kolonner, og så er de værre end ingen. */
.eprows__hoved {
    display: grid;
    grid-template-columns: 0.6rem minmax(0, 2fr) minmax(0, 1.2fr) 4.5rem 7rem 5rem 4rem;
    gap: 0.75rem;
    padding: 0 0.9rem 0.4rem;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--muted);
}

/* Tal højrestilles i rækkerne, så overskrifterne skal følge med. */
.eprows__hoved span:nth-child(5),
.eprows__hoved span:nth-child(6) { text-align: right; }

/* Domænevarianten. Modifier på selve elementet, ikke en efterkommer-selektor: mobil-
   reglen nedenfor rammer .eprow__sum med samme specificitet og skal kunne vinde, fordi
   den står senere. En `.eprows--dom .eprow__sum` ville stille tabe det opgør. */
.eprow__sum--dom { grid-template-columns: 0.6rem minmax(0, 2fr) minmax(0, 1.4fr) 4.5rem 5.5rem; }

.eprow__sum::-webkit-details-marker { display: none; }
.eprow__sum:hover { background: color-mix(in srgb, var(--blue-300) 8%, transparent); }

.eprow__prik { width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--faint); }
.eprow__prik--oppe { background: var(--good); }
.eprow__prik--langsom { background: var(--warn); }
.eprow__prik--nede { background: var(--crit); }
.eprow__prik--kritisk { background: var(--crit); }

.eprow__navn { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eprow__kunde,
.eprow__type,
.eprow__svar,
.eprow__tid { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eprow__score { color: var(--muted); }
.eprow__svar,
.eprow__tid,
.eprow__score { font-variant-numeric: tabular-nums; text-align: right; }

.eprow__krop { padding: 0 0.7rem 0.7rem; }

/* ── The ticket queue ────────────────────────────────────────────────────────────────────
   The same family as .eprow, with one difference: the row is a LINK to the case, not an
   expander. So .eprow and .eprow__sum sit on the SAME element — .eprow contributes only a
   bottom border, and a wrapper per row would be an element with no job.

   Eight columns in the order you triage in: mark, urgency, what, who, which kind, how far,
   when, whose. Category is the first to give up space on a narrow window — it is something you
   filter by, not something you scan. */
.eprow__sum--sag {
    grid-template-columns: 1.1rem 0.6rem minmax(0, 2.2fr) minmax(0, 1.1fr) minmax(0, 0.8fr) 9.2rem 6rem 3.4rem;
}

/* The headings live inside the frame with the rows, not floating above it: a column label
   detached from its column does not read as a heading. The grid must stay identical to
   .eprow__sum--sag above — tests/sagsgittercheck compares the two, because nothing else would
   notice them drifting apart. */
.eprows__hoved--sag {
    grid-template-columns: 1.1rem 0.6rem minmax(0, 2.2fr) minmax(0, 1.1fr) minmax(0, 0.8fr) 9.2rem 6rem 3.4rem;
    padding: 0.45rem 0.9rem;
    border-bottom: 1px solid var(--line);
    background: color-mix(in srgb, var(--ink) 2%, transparent);
    align-items: center;
}

.eprow--sag { text-decoration: none; color: inherit; }
.eprow--sag:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.eprow--sag.tkt--done { opacity: 0.55; }

/* Priority: only High and Critical are drawn. «Normal» on every single row says nothing, and
   the difference between two shades of blue four pixels wide could only be seen by somebody who
   already knew it was there. The same decision the customer-facing list reached first. */
.sagprio {
    width: 4px;
    height: 1.1rem;
    border-radius: 999px;
    align-self: center;
}
.sagprio--hoej { background: var(--warn); }
.sagprio--kritisk { background: var(--crit); }

/* Status: dot plus word. A filled badge per row turned into a curtain of colour — the house's
   own argument sits at the .badge rules. The dot carries the colour, the word the meaning. */
.sagstatus {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--ink-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sagstatus .eprow__prik { flex-shrink: 0; }

.eprow__prik--ny { background: var(--blue-400); }
.eprow__prik--aaben { background: var(--warn); }
.eprow__prik--venter-kunde { background: var(--faint); }
.eprow__prik--venter-lev { background: var(--blue-300); }
.eprow__prik--loest { background: var(--good); }
.eprow__prik--lukket { background: var(--line-2); }

/* Number and title in one cell. The number is muted: it is an address, not information. */
.sagnavn { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 650; }
.sagnavn__nr { color: var(--faint); font-variant-numeric: tabular-nums; font-weight: 600; }
.sagnavn__mail { color: var(--faint); margin-left: 0.3rem; vertical-align: -1px; }

/* Deadline or age. A missed deadline is the one thing in the row that has to be visible without
   reading it — hence colour and not only text. */
.sagtid { font-variant-numeric: tabular-nums; text-align: right; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sagtid--frist { color: var(--ink-2); font-weight: 650; }
.sagtid--over { color: var(--crit-ink, var(--crit)); font-weight: 700; }

/* Initials or «take». The column is deliberately narrow: it is scanned for «is this anybody's?»,
   not read. */
.sagejer { display: flex; justify-content: flex-end; }

/* Domænesikkerhed — kompakt listevisning. Samme tæthed og farvesprog som .eprow, men med
   en statusprik pr. tjek (SPF/DMARC/DKIM/DNSSEC …), så mange domæner kan skimmes på én skærm.
   Rækken foldes ud til det fulde kort ved klik; kun den udfoldede række tegner kortet. */
.dsp-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.55rem 0.9rem;
    border-bottom: 1px solid var(--line);
    cursor: pointer;
    font-size: 0.86rem;
}
.dsp-row:hover { background: color-mix(in srgb, var(--blue-300) 8%, transparent); }
.dsp-row__sev { flex: 0 0 auto; width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--faint); }
.dsp-row__navn { flex: 1 1 38%; min-width: 0; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dsp-row__kunde { flex: 1 1 22%; min-width: 0; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dsp-row__checks { flex: 0 0 auto; display: flex; gap: 0.35rem; }
.dsp-row__score { flex: 0 0 auto; min-width: 2.6rem; text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
.dsp-row__chev { flex: 0 0 auto; width: 1rem; text-align: center; color: var(--muted); }
.dsp-row__krop { padding: 0.3rem 0.5rem 1rem; }

.dsp-dot { flex: 0 0 auto; width: 0.56rem; height: 0.56rem; border-radius: 50%; background: var(--faint); }
.dsp-dot--ok { background: var(--good); }
.dsp-dot--warn { background: var(--warn); }
.dsp-dot--crit { background: var(--crit); }

/* Filterstriben «Mangler pr. type» over listen. */
.dsp-strip { margin: -0.35rem 0 1rem; align-items: center; }
.dsp-strip__label { margin-right: 0.15rem; }

/* Mobil: kundenavnet viger, så domæne + prikker + score bliver på linjen. */
@media (max-width: 700px) {
    .dsp-row__kunde { display: none; }
}

/* Mobil: seks kolonner kan ikke stå ved siden af hinanden på 375 px. Navn og
   tidspunkt bliver på første linje — det er dem, man skanner efter — og kunden
   lægger sig under som én dæmpet linje.

   Placeringen er eksplicit med vilje. Type og svartid skjules her, og skjulte
   celler deltager ikke i auto-placeringen: klokkeslættet endte i prik-kolonnen
   på 0,6 rem og blev klippet til "0", hvilket lignede en måling, ikke et ur. */
@media (max-width: 700px) {
    .eprow__sum {
        grid-template-columns: 0.6rem minmax(0, 1fr) auto;
        row-gap: 0.15rem;
        padding: 0.7rem 0.8rem;
    }

    .eprow__prik { grid-column: 1; grid-row: 1; }
    .eprow__navn { grid-column: 2; grid-row: 1; }
    .eprow__tid { grid-column: 3; grid-row: 1; text-align: right; font-size: 0.78rem; }
    .eprow__kunde { grid-column: 2 / -1; grid-row: 2; font-size: 0.78rem; }

    .eprow__type,
    .eprow__svar,
    .eprow__score { display: none; }

    /* Rækken folder sig til to linjer her, så der findes ingen kolonner at sætte
       overskrifter over. */
    .eprows__hoved { display: none; }
}

.settings__body { display: grid; grid-template-columns: 13rem 1fr; gap: 2rem; align-items: start; }

/* Klæber, så kategorierne følger med ned gennem en lang side. */
.settings__rail { position: sticky; top: 1.5rem; display: flex; flex-direction: column; gap: 0.1rem; }

.settings__raillink {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    border-radius: var(--r-md);
    font-size: 0.84rem;
    font-weight: 700;
    color: var(--ink-2);
    text-decoration: none;
}

.settings__raillink:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); color: var(--ink); }

.settings__railtal { font-size: 0.72rem; font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; }

.setgroup { margin-bottom: 2.2rem; scroll-margin-top: 1.5rem; }
.setgroup__titel { font-size: 1.02rem; font-weight: 800; margin: 0 0 0.15rem; }
.setgroup__sub { font-size: 0.84rem; color: var(--muted); margin: 0 0 0.8rem; max-width: 46rem; }

.setrows {
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    overflow: hidden;
}

.setrow {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.8rem 1rem;
    text-decoration: none;
    color: inherit;
    border-bottom: 1px solid var(--line);
}

.setrow:last-child { border-bottom: 0; }
.setrow:hover { background: color-mix(in srgb, var(--blue-300) 8%, transparent); }

.setrow__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--r-md);
    background: color-mix(in srgb, var(--blue-300) 16%, var(--paper));
    color: var(--ink-2);
    flex-shrink: 0;
}

.setrow__main { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.setrow__titel { font-weight: 700; font-size: 0.9rem; }
.setrow__sub { font-size: 0.8rem; color: var(--muted); }

.setrow__pil { color: var(--faint); font-size: 1.2rem; flex-shrink: 0; }
.setrow:hover .setrow__pil { color: var(--ink-2); }

/* Under 900 px falder kategorilisten væk — der er ikke plads til to spalter, og
   søgefeltet er alligevel den hurtigste vej på en telefon. */
@media (max-width: 900px) {
    .settings__body { grid-template-columns: 1fr; }
    .settings__rail { display: none; }
}

/* Egne SNMP-målinger i redigeringsformularen. */
.oid-liste {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    padding: 0.5rem 0.6rem;
}

.oid-række {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.82rem;
}

.oid-række__navn { font-weight: 700; min-width: 7rem; }

/* OID'er er lange og må gerne klippes — det er navnet, man leder efter. */
.oid-række__oid {
    color: var(--muted);
    font-size: 0.76rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    min-width: 0;
}

/* Kundebilledet på staff-forsiden. Tæt med vilje: den skal kunne skimmes lodret,
   så man ser hvem der kalder, uden at læse hver celle. */
.kb tbody td { padding: 0.55rem 0.9rem; font-size: 0.84rem; white-space: nowrap; }
.kb tbody tr:hover { background: var(--blue-50, rgba(0,0,0,0.02)); }

/* Hele rækken fører ind til kunden. position:relative gør rækken til udgangspunkt
   for det udstrakte link i sidste celle, så klik hvor som helst på linjen åbner. */
.kb__row { position: relative; cursor: pointer; }
.kb__open { font-weight: 600; }
.kb__row:hover .kb__open { text-decoration: underline; }

/* Venstrekant frem for baggrundsfarve på hele rækken: farven skal pege på, hvor
   man skal kigge, ikke overdøve tallene i cellerne. */
.kb--crit td:first-child { box-shadow: inset 3px 0 0 var(--crit); }
.kb--warn td:first-child { box-shadow: inset 3px 0 0 var(--warn); }

.kb__ok { color: var(--good); font-weight: 700; }
.kb__warn { color: var(--warn); font-weight: 700; }
.kb__crit { color: var(--crit); font-weight: 800; }
.kb__mut { color: var(--muted); }

/* ---- overblik: Personalets forside ---- (3 October 2026, docs/arbejde/2026-10-03-overblik2-byg-forside.md)
   The verdict and the six tiles share one grid panel (home.overview); the tiles are links to the page that owns the
   number or down to the panel that lists it. */
[data-gitter="home"] > .panel[id^="home-"] { scroll-margin-top: 5.5rem; }
[data-gitter="home"] > [data-gitter-panel="home.overview"] > .tile-grid { margin-bottom: 0; }
/* ListNote's «show all» is a link here (the page has no circuit): the pill, not an underlined link. */
a.listnote__all, a.listnote__all:hover { text-decoration: none; }
/* The customer table's figures in the text tones, not the fill tones (contrast: --good on paper was 4.2:1, --warn 3.6:1,
   dark --crit 4.0:1 - measured by tests/forsidecheck; the rules above are main's and stay as they were). */
.kb__ok { color: var(--good-ink); }
.kb__warn { color: var(--warn-ink); }
.kb__crit { color: var(--crit-ink); }
/* ---- /overblik: Personalets forside ---- */

/* ── Kundens forside ───────────────────────────────────────────────────────
   Statuslinjen er sidens vigtigste element: den skal kunne læses på et halvt
   sekund fra den anden side af skrivebordet. Derfor stor skrift og farve som
   bærende signal — ikke et tal i et felt. */
/* Status siges med en streg, ikke med et farvet felt.
   Det fyldte felt tog hele sidens bredde og gjorde ét forhold til sidens dominerende flade,
   uanset hvor alvorligt det var — «alt kører» råbte lige så højt som «noget er galt». Nu bærer
   venstrekanten farven, fladen forbliver papir, og tinten er skruet ned til en antydning
   (4 %), der stadig kan ses, men ikke overtager.
   Farven sættes ét sted, --status-farve, så streg, tint, kant og ikon ikke kan komme i utakt. */
.status {
    --status-farve: var(--good);
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 1.15rem 1.3rem;
    border-radius: 4px var(--r-lg) var(--r-lg) 4px;
    border: 1px solid color-mix(in srgb, var(--status-farve) 22%, var(--line));
    border-left: 3px solid var(--status-farve);
    background: color-mix(in srgb, var(--status-farve) 4%, var(--paper));
    margin-bottom: 1.1rem;
}

.status--ok   { --status-farve: var(--good); }
.status--obs  { --status-farve: var(--warn); }
.status--krit { --status-farve: var(--crit); }

/* Tom er ikke det samme som i orden.
   Et bibliotek uden dokumenter, en side uden agenter, en overvågning uden endpoints —
   ingen af dem har noget galt, men ingen af dem gør heller noget. Et grønt flueben dér
   er den fejlklasse, platformen er blevet ramt af flest gange: den ser sund ud uden at
   have udført sit arbejde. Neutral grå siger det rigtige: der er ikke noget endnu. */
/* Tomtilstanden har ingen status at melde og skal derfor heller ikke have en farvet kant —
   den arver ellers den grønne standard og ville sige «alt kører» om ingenting. */
.status--tom { --status-farve: var(--line-2); background: var(--paper); }
.status--tom .status__ikon { color: var(--muted); }

.status__ikon { display: flex; flex-shrink: 0; }
.status--ok .status__ikon { color: var(--good-ink); }
.status--obs .status__ikon { color: var(--warn-ink); }
.status--krit .status__ikon { color: var(--crit-ink); }

.status__linje { font-size: 1.32rem; font-weight: 800; letter-spacing: -0.01em; color: var(--ink); line-height: 1.25; }
/* --ink-2, ikke --muted. Underlinjen bærer selve tallene — hvor mange der er overvåget,
   hvor mange der er i orden — og står på en tonet flade, hvor --muted lander på 3,9:1.
   Målt af kontrastcheck; --ink-2 klarer kravet på alle tre banner-toner. */
.status__under { font-size: 0.82rem; color: var(--ink-2); margin-top: 0.25rem; line-height: 1.4; }

/* På 375 px bryder sætningen i to, og en overskrift på 1,32 rem med brødtekstens
   linjeafstand river de to linjer fra hinanden. Mindre og tættere — den skal stadig
   være det første, øjet lander på, men den skal læses som én sætning. */
@media (max-width: 700px) {
    .status { padding: 1rem 1.05rem; gap: 0.7rem; align-items: flex-start; }
    .status__ikon { margin-top: 0.15rem; }
    .status__linje { font-size: 1.1rem; line-height: 1.3; }
}

/* ==========================================================================
   Tiles - the shared overview tiles (Components/Shared/Tiles), 3 October 2026.
   The control-room wall's idea on normal pages: each tile answers ONE question with an honest number, a picture of the
   denominator and the names when something needs action; the list stays under them. The spec is
   docs/arbejde/2026-10-03-overblik-dom.md. Built on the platform's tokens only, so the dark theme follows from
   :root[data-theme="dark"] (the few new tokens are redefined there). No TV motion: a 0.15 s hover, off under
   prefers-reduced-motion. Measured in tests/feltcheck (light/dark, 1440/390: nothing overflows, nothing clipped,
   contrast of the tones).
   Order on a page: PageHeader -> .status (the one verdict, tone = the worst tile's) -> TileGrid -> ListNote -> the list.
   ========================================================================== */

/* The status line's own buttons (Enhed: «I'm on it», NIS2: the PDF): right of the text, the whole width on a phone. */
.status__body { flex: 1; min-width: 0; }
.status__act { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; margin-left: auto; flex-shrink: 0; }
@media (max-width: 700px) {
    .status:has(.status__act) { flex-wrap: wrap; }
    .status__act { width: 100%; margin-left: 0; }
}

/* ---- TileGrid: 4 (or 3/2) -> 2 -> 1 by the width it GETS, not the window (the menu is 268 or 66 px). ---- */
.tile-grid { container-type: inline-size; container-name: tiles; margin-bottom: 1.1rem; }
.tile-grid__in { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--tile-gap); }
.tile-grid--3 .tile-grid__in { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.tile-grid--2 .tile-grid__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.tile-grid--1 .tile-grid__in { grid-template-columns: minmax(0, 1fr); }
.tile--wide { grid-column: span 2; }
.tile--full { grid-column: 1 / -1; }
@container tiles (max-width: 940px) {
    .tile-grid__in, .tile-grid--3 .tile-grid__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tile--wide { grid-column: 1 / -1; }
}
/* Phone=Stack: one whole tile per row. */
@container tiles (max-width: 540px) {
    .tile-grid__in, .tile-grid--3 .tile-grid__in, .tile-grid--2 .tile-grid__in { grid-template-columns: minmax(0, 1fr); gap: 0.7rem; }
    .tile { --tile-fs-num: 1.8rem; padding: 0.85rem 1rem 0.85rem 1.25rem; }
}
/* Phone=Pairs (the default, the judge's one phone rule): two columns of LEAN tiles - label, number, phrase, and the
   pressed marker or «could not fetch» on a line of their own. Keep = the whole row with everything (the tile with the
   names one acts on; at most two per page), Lone = a lean tile without a partner, Full = always whole. The picture,
   count line, rows and context line are still in the tile's aria-label, so a screen reader loses nothing. */
@container tiles (max-width: 540px) {
    .tile-grid--pairs .tile-grid__in { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; }
    .tile-grid--pairs .tile-grid__in > :is(.tile--keep, .tile--full, .tile--lone) { grid-column: 1 / -1; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) { --tile-fs-num: 1.6rem; padding: 0.75rem 0.8rem 0.75rem 1.05rem; gap: 0.2rem; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) :is(.lamps, .dayband, .minibars, .minibars__cap, .smeter, .tstats,
        .trows, .trows__more, .tile__caption, .tile__fact, .tile__ok, .tile-visual) { display: none; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) .tile__head { flex-wrap: wrap; row-gap: 0.1rem; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) .tile__scope:not(.tile__scope--on):not(.tile__scope--failed) { display: none; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) :is(.tile__scope--on, .tile__scope--failed) { flex-basis: 100%; text-align: left; order: 2; white-space: normal; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) .tile__phrase { font-size: 0.8rem; line-height: 1.3; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) .split { column-gap: 0.75rem; }
    .tile-grid--pairs .tile:not(.tile--keep):not(.tile--full) .split b { font-size: 1.35rem; }
}

/* ---- OverviewTile / FilterTile ---- */
.tile {
    --tone: color-mix(in srgb, var(--good) 72%, transparent);
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    width: 100%;
    margin: 0;
    padding: var(--tile-pad);
    background: var(--paper);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    font: inherit;
    line-height: 1.45;
    text-align: left;
    text-decoration: none;
    overflow: hidden;
}
.tile::before { content: ""; position: absolute; inset: 0 auto 0 0; width: var(--tile-stripe); background: var(--tone); }
.tile--warn { --tone: var(--warn); }
.tile--crit { --tone: var(--crit); background: var(--crit-bg); border-color: color-mix(in srgb, var(--crit) 35%, var(--line)); }
.tile--muted { --tone: var(--line-2); }

/* A tile that goes somewhere (a link) or narrows the list below (a button with aria-pressed). Pressed = border AND an
   inner ring in --ink-2 AND the words in the scope's place - never colour alone. */
a.tile, button.tile { cursor: pointer; transition: border-color 0.15s ease, box-shadow 0.15s ease; }
a.tile:hover, button.tile:hover { border-color: var(--line-2); box-shadow: var(--shadow-sm); color: var(--ink); text-decoration: none; }
a.tile:focus-visible, button.tile:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
button.tile[aria-pressed="true"] { border-color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--ink-2); }

.tile__head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; min-width: 0; }
/* The label never shrinks (the scope gets the ellipsis). */
.tile__label { flex-shrink: 0; max-width: 100%; font-size: var(--tile-fs-label); font-weight: 750; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0; }
a.tile__label--link { color: var(--link); text-decoration: none; }
a.tile__label--link:hover { color: var(--link-hover); text-decoration: underline; }
.tile--crit .tile__label { color: var(--crit-ink); }
.tile__scope { min-width: 0; font-size: var(--tile-fs-meta); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; }
.tile--crit .tile__scope { color: var(--ink-2); }
.tile__scope--failed { color: var(--warn-ink); font-weight: 650; }
.tile--crit .tile__scope--failed { color: var(--crit-ink); }
.tile__scope--on { color: var(--ink); font-weight: 700; }
.tile__go { width: 0.8rem; height: 0.8rem; flex-shrink: 0; margin-left: 0.2rem; vertical-align: -0.1em; color: var(--muted); }

.tile__hero { display: flex; align-items: baseline; flex-wrap: wrap; column-gap: 0.5rem; min-width: 0; }
.tile__num { font-size: var(--tile-fs-num); font-weight: 800; letter-spacing: -0.035em; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); }
.tile__num small { font-size: var(--tile-fs-of); font-weight: 650; letter-spacing: 0; color: var(--muted); }
.tile__num--warn { color: var(--warn-ink); }
.tile__num--crit { color: var(--crit-ink); }
.tile__num--muted { color: var(--muted); font-weight: 650; }
.tile__num--good { color: var(--good-ink); }
.tile__num--word { font-size: calc(var(--tile-fs-num) * 0.72); letter-spacing: -0.015em; white-space: normal; }
.tile__phrase { font-size: var(--tile-fs-text); color: var(--ink-2); min-width: 0; }

.tile__caption { font-size: var(--tile-fs-meta); color: var(--muted); line-height: 1.4; }
.tile__caption b, .tile__fact b { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.tile__caption b.crit, .tile__fact b.crit { color: var(--crit-ink); }
.tile__caption b.warn, .tile__fact b.warn { color: var(--warn-ink); }
.tile__caption b.muted, .tile__fact b.muted { color: var(--muted); }
.tile__fact { margin-top: auto; padding-top: 0.35rem; font-size: var(--tile-fs-meta); color: var(--muted); line-height: 1.4; }
.tile--crit .tile__caption, .tile--crit .tile__fact { color: var(--ink-2); }
.tile__ok { display: inline-flex; align-items: center; gap: 0.4rem; font-size: var(--tile-fs-text); color: var(--good-ink); font-weight: 600; }
.tile__ok::before { content: ""; flex-shrink: 0; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--good); }

/* TileCounts: each part unbreakable, so the line only breaks between parts and never mid-number. */
.tcounts .tcount { white-space: nowrap; }

/* ---- LampGrid: one lamp per real thing, worst first, the map's shapes. ---- */
.lamps { display: flex; flex-wrap: wrap; align-items: center; gap: var(--lamp-gap); margin: 0.35rem 0 0.1rem; }
.lamps i { flex-shrink: 0; width: var(--lamp); height: var(--lamp); border-radius: 3px; background: var(--lamp-ok); }
.lamps i.w { background: var(--warn); border-radius: 0; clip-path: polygon(50% 4%, 100% 96%, 0 96%); transform: scale(1.18); }
.lamps i.c { background: var(--crit); border-radius: 0; clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); transform: scale(1.3); }
.lamps i.u { background: transparent; box-shadow: inset 0 0 0 1.5px var(--lamp-hollow); }
.lamps i.off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--lamp-hollow); border-radius: 50%; }
.lamps--big { --lamp: var(--lamp-big); --lamp-gap: 0.32rem; }
.lamps__more { font-size: var(--tile-fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- DayBand: height carries the state like the pulse strip (in order lowest, down full, not measured hollow). ---- */
.dayband, .dayband__cells, .dayband__ticks { display: block; }
.dayband__cells { display: grid; grid-template-columns: repeat(var(--cells, 48), minmax(0, 1fr)); gap: 2px; height: 1.15rem; align-items: end; margin-top: 0.4rem; }
.dayband__cells i { height: 62%; border-radius: 2px; background: var(--band-ok); }
.dayband__cells i.w { height: 82%; background: var(--warn); }
.dayband__cells i.c { height: 100%; background: var(--crit); }
.dayband__cells i.n { height: 40%; background: transparent; box-shadow: inset 0 0 0 1px var(--line-2); }
.dayband__cells i.now { outline: 1.5px solid var(--ink-2); outline-offset: 1px; }
.dayband--days .dayband__cells { gap: 3px; }
.dayband__ticks { position: relative; height: 1rem; margin-top: 0.25rem; font-size: 0.72rem; color: var(--faint); font-variant-numeric: tabular-nums; }
.dayband__ticks span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.dayband__ticks .dayband__tick--first { transform: none; }
.dayband__ticks .dayband__now { right: 0; transform: none; }

/* ---- MiniBars: drawn on the server; the caption carries the max (the axis rule). ---- */
.minibars { display: grid; grid-template-columns: repeat(var(--bars, 24), minmax(0, 1fr)); gap: 2px; align-items: end; height: 2.4rem; margin-top: 0.45rem; }
.minibars i { background: var(--bar); border-radius: 2px 2px 0 0; min-height: 2px; }
.minibars i.z { height: 2px; background: var(--bar-zero); }
.minibars i.f { height: 2px; background: transparent; border-bottom: 1px dotted var(--line-2); }
.minibars i.now { background: var(--bar-now); }
.minibars__cap { display: flex; justify-content: space-between; gap: 0.6rem; font-size: 0.72rem; color: var(--faint); margin-top: 0.2rem; white-space: nowrap; }

/* ---- ShareMeter: a share of a whole (= .meter, thinner). Neutral = a share without a verdict. ---- */
.smeter { display: block; height: 6px; border-radius: 99px; background: var(--band-none); overflow: hidden; margin-top: 0.5rem; }
.smeter > span { display: block; height: 100%; border-radius: inherit; background: var(--good); }
.smeter--warn > span { background: var(--warn); }
.smeter--crit > span { background: var(--crit); }
.smeter--neutral > span { background: var(--bar-now); }

/* ---- SplitFigures: two or three numbers that belong together. Spans, so they can stand in a button tile. They wrap
        as whole figures when the tile is narrow (a lean tile on a phone); a grid of nowrap labels ran into the next
        figure there (tests/feltcheck, 3 October 2026), so the figures are spaced by a gap, not divided by rules. ---- */
.split { display: flex; flex-wrap: wrap; gap: 0.35rem 1.15rem; margin-top: 0.2rem; }
.split__cell { display: block; flex: 0 0 auto; min-width: 0; }
.split b { display: block; font-size: 1.7rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; font-variant-numeric: tabular-nums; color: var(--ink); }
.split b.zero { color: var(--muted); font-weight: 600; }
.split__label { display: block; font-size: var(--tile-fs-meta); color: var(--muted); line-height: 1.3; white-space: nowrap; }
.tile--crit .split__label { color: var(--ink-2); }

/* ---- TileStats: number + phrase + small note, one line each. ---- */
.tstats { display: grid; gap: 0.28rem; margin-top: 0.35rem; }
.tstats .s { display: grid; grid-template-columns: 1.6rem minmax(0, 1fr); gap: 0.45rem; align-items: baseline; font-size: var(--tile-fs-text); color: var(--ink-2); }
.tstats .s b { font-weight: 800; font-variant-numeric: tabular-nums; text-align: right; color: var(--ink); }
.tstats .s b.warn { color: var(--warn-ink); }
.tstats .s b.crit { color: var(--crit-ink); }
.tstats .s small { color: var(--muted); font-size: var(--tile-fs-meta); }
.tstats .x { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- TileRows: at most two named rows, then «+N more». The glyph is the row's state in the lamp shapes. ---- */
.trows { display: grid; gap: 0.3rem; margin-top: 0.4rem; }
.trows .r { display: grid; grid-template-columns: 0.7rem minmax(0, 1fr) auto; gap: 0.5rem; align-items: baseline; font-size: var(--tile-fs-text); color: var(--ink); text-decoration: none; }
.trows .r::before { content: ""; width: 0.62rem; height: 0.62rem; border-radius: 2px; background: var(--lamp-ok); }
.trows .r[data-s="warn"]::before { background: var(--warn); border-radius: 0; clip-path: polygon(50% 4%, 100% 96%, 0 96%); }
.trows .r[data-s="crit"]::before { background: var(--crit); border-radius: 0; clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.trows .r[data-s="unk"]::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--lamp-hollow); }
.trows .r[data-s="off"]::before { background: transparent; box-shadow: inset 0 0 0 1.5px var(--lamp-hollow); border-radius: 50%; }
.trows .r[data-s="done"]::before { content: "\2713"; width: auto; height: auto; background: none; border-radius: 0; color: var(--good-ink); font-size: 0.75rem; font-weight: 800; line-height: 1; }
.trows .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.trows .t small { color: var(--muted); font-size: var(--tile-fs-meta); }
.tile--crit .trows .t small, .tile--crit .trows .a { color: var(--ink-2); }
.trows .a { font-size: var(--tile-fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
a.r:hover .t, button.r:hover .t { text-decoration: underline; }
button.r { border: 0; background: none; padding: 0; font: inherit; text-align: left; cursor: pointer; width: 100%; }
:is(a.r, button.r):focus-visible { outline: 2px solid var(--link); outline-offset: 2px; border-radius: 3px; }
.trows__more { font-size: var(--tile-fs-meta); color: var(--link); font-weight: 650; margin-top: 0.15rem; }
a.trows__more { text-decoration: none; }
a.trows__more:hover { text-decoration: underline; }
a.trows__more:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }

/* ---- AreaGrid: one cell per area, coloured by its worst control; a cell filters the list. ---- */
.areas { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 0.55rem; margin-top: 0.55rem; }
@container tiles (max-width: 940px) { .areas { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@container tiles (max-width: 540px) {
    .areas { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.45rem; }
    .acell { min-height: 0; gap: 0.35rem; padding: 0.5rem 0.6rem 0.5rem 0.85rem; }
}
.acell {
    --tone: color-mix(in srgb, var(--good) 72%, transparent);
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 0.5rem;
    min-width: 0;
    min-height: 4.7rem;
    margin: 0;
    padding: 0.6rem 0.7rem 0.55rem 0.95rem;
    background: var(--area-bg);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    font: inherit;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.acell::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--tone); }
.acell--warn { --tone: var(--warn); }
.acell--crit { --tone: var(--crit); }
.acell--unk { --tone: var(--line-2); }
.acell:hover { border-color: var(--line-2); box-shadow: var(--shadow-sm); }
.acell:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
.acell[aria-pressed="true"] { border-color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--ink-2); }
.acell__name { font-size: 0.82rem; font-weight: 650; line-height: 1.25; }
.acell__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; min-width: 0; }
.acell__foot .lamps { margin: 0; min-width: 0; }
.acell__n { font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.acell__n b { color: var(--ink-2); }
.acell__on { font-size: 0.72rem; font-weight: 700; color: var(--ink); white-space: nowrap; }

/* ---- CheckMatrix: a real <table>, one row per check, one lamp per thing checked. ---- */
.cmatrix { border-collapse: separate; border-spacing: 0 0.25rem; width: 100%; margin-top: 0.2rem; }
.cmatrix th { font-size: var(--tile-fs-meta); font-weight: 650; color: var(--ink-2); text-align: left; padding: 0 0.8rem 0 0; white-space: nowrap; width: 1%; }
.cmatrix td { padding: 0; width: 1%; }
.cmatrix td .lamps { margin: 0; flex-wrap: nowrap; }
.cmatrix td.n { font-size: var(--tile-fs-meta); color: var(--muted); text-align: left; white-space: nowrap; padding-left: 1rem; width: auto; font-variant-numeric: tabular-nums; }
@container tiles (max-width: 540px) {
    .cmatrix, .cmatrix tbody { display: block; }
    .cmatrix tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; padding: 0.35rem 0; border-top: 1px solid var(--line); }
    .cmatrix th, .cmatrix td { width: auto; }
    .cmatrix td.n { padding-left: 0.6rem; text-align: right; white-space: normal; }
    .cmatrix td:not(.n) { grid-column: 1 / -1; grid-row: 2; padding-top: 0.3rem; }
    .cmatrix td .lamps { flex-wrap: wrap; }
}

/* ---- ListNote: the list says what it shows, and how to get everything back. ---- */
.listnote { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; font-size: 0.82rem; color: var(--ink-2); margin-bottom: 0.75rem; }
.listnote b { color: var(--ink); font-variant-numeric: tabular-nums; }
.listnote__all { border: 1px solid var(--line-2); background: var(--paper); color: var(--link); font: inherit; font-weight: 650; border-radius: 999px; padding: 0.2rem 0.7rem; font-size: 0.78rem; cursor: pointer; }
.listnote__all:hover { border-color: var(--link); }
.listnote__all:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
/* After «show all» the note itself takes the focus (ListNote.ShowAllAsync): a ring for the keyboard, none for a click. */
.listnote:focus { outline: none; }
.listnote:focus-visible { outline: 2px solid var(--link); outline-offset: 3px; border-radius: 4px; }
.listnote__tools { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-left: auto; min-width: 0; }

@media (prefers-reduced-motion: reduce) {
    a.tile, button.tile, .acell { transition: none; }
}

/* "Det har vi lavet for jer" — sætninger, ikke felter.
   To spalter fra 900 px: på en bred skærm står seks korte linjer i én kolonne som en
   halvtom liste, og resten af skærmen er tom. */
.gjort {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem 2rem;
}

@media (min-width: 900px) {
    .gjort { grid-template-columns: 1fr 1fr; }
}

.gjort li {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--ink-2);
}

.gjort li > :first-child { color: var(--good); flex-shrink: 0; margin-top: 0.15rem; }

/* Aftalen: én linje, der kun vokser når den er ved at være brugt op. */
.aftale {
    display: block;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--paper);
    padding: 0.8rem 1rem;
    margin-bottom: 1.1rem;
}

.aftale:hover { border-color: var(--blue-300); }
.aftale--pres { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.aftale--over { border-color: color-mix(in srgb, var(--crit) 45%, var(--line)); }

.aftale__top { display: flex; align-items: baseline; justify-content: space-between; gap: 0.7rem; }
.aftale__tekst { font-size: 0.9rem; color: var(--ink-2); }
.aftale__navn { color: var(--muted); }
.aftale__pct { font-size: 0.85rem; font-weight: 800; color: var(--muted); font-variant-numeric: tabular-nums; }

.aftale__bar {
    display: block;
    height: 6px;
    border-radius: 999px;
    background: var(--line);
    margin-top: 0.55rem;
    overflow: hidden;
}

.aftale__fill { display: block; height: 100%; background: var(--good); border-radius: 999px; }
.aftale--pres .aftale__fill { background: var(--warn); }
.aftale--over .aftale__fill { background: var(--crit); }

.aftale__note { display: block; font-size: 0.82rem; color: var(--ink-2); margin-top: 0.55rem; }

/* Kvittér og udsæt på et enhedskort. Egen række over handlingsknapperne, så det er
   tydeligt, at de hører til alarmen og ikke til enheden. */
.hnd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.8rem;
    padding: 0.5rem 0.6rem;
    border: 1px dashed var(--line);
    border-radius: var(--r-md);
}

.hnd__tekst {
    font-size: 0.78rem;
    color: var(--muted);
}

/* Gruppefilter over enhedskortene. Knapper og ikke en dropdown: antallet pr. gruppe er
   halvdelen af pointen, og det kan man ikke se i en lukket liste. */
.gfilter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.2rem 0 0.9rem;
}

.gchip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink-2);
    padding: 0.32rem 0.75rem;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
}

.gchip:hover { border-color: var(--blue-300); }

/* --accent findes ikke i :root. En var() uden fallback til en ukendt variabel er
   ugyldig efter kaskaden, og outline arves ikke — reglen gav derfor slet INGEN
   fokusring, ikke bare en forkert farve. Den globale :where()-regel kunne ikke
   redde den: :where() tæller nul, så .gchip:focus-visible vandt med tomme hænder.
   Gruppefiltret på kundens driftsovervågning kunne dermed tabbes igennem uden at
   man kunne se hvor man var. */
.gchip:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.gchip--valgt {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
}

/* Fremhæver den gruppe-chip, en enhed pt. trækkes hen over, så det er tydeligt, hvor
   slippet lander. Sættes kun, når slippet faktisk ville flytte enheden (se
   KanSætteGruppe i Noc.razor) — ellers ville en chip love en flytning, der ikke sker. */
.gchip--sigte {
    border-color: var(--blue-400);
    background: color-mix(in srgb, var(--blue-400) 14%, transparent);
    box-shadow: 0 0 0 2px var(--blue-300);
}

.gchip__antal {
    font-weight: 600;
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

/* «+ Ny gruppe» og den netop oprettede, endnu tomme gruppe. Stiplet kant = «her kan der
   komme noget»: knappen inviterer til at oprette en gruppe, den ventende chip til at trække
   en enhed ind. En ventende gruppe lever kun i browseren, til den får sin første enhed —
   så bliver den en almindelig (massiv) chip. Se nyeGrupper i Noc.razor. */
.gchip--ny {
    border-style: dashed;
    background: transparent;
    color: var(--ink-2);
}
.gchip--ny:hover { border-color: var(--blue-400); color: var(--ink); }

.gchip--venter { border-style: dashed; }

/* Lille rund «×» til at fjerne en tom, netop oprettet gruppe. Sidder som søskende lige efter
   sin ventende chip (ikke inde i den — en knap i en knap er ugyldig markup). Negativ venstre-
   margin trækker den ind mod chippen, så de læses som ét. */
.gchip--fjern {
    margin-left: -0.25rem;
    padding: 0.32rem 0.5rem;
    line-height: 1;
    border-style: dashed;
    color: var(--ink-2);
    font-weight: 700;
}
.gchip--fjern:hover { border-color: var(--crit); color: var(--crit-ink); }

.gchip-input {
    border: 1px solid var(--blue-400);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink);
    padding: 0.32rem 0.75rem;
    font-size: 0.78rem;
    font-weight: 700;
    font-family: inherit;
    width: 9.5rem;
    max-width: 45vw;
    outline: none;
}
.gchip-input::placeholder { color: var(--ink-2); font-weight: 500; }
.gchip-input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.dgroup__body {
    padding: 0 1.2rem 1.2rem;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: 0.9rem;

    /* Kortene i samme række bliver lige høje. Uden dette bestemte den enhed med flest
       målinger højden for hele rækken, og naboerne stod med et stort tomrum nedenunder. */
    align-items: stretch;
}

.dcard {
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    padding: 0.95rem 1.05rem;
    background: var(--paper);
    /* Farvet kant i venstre side gør det muligt at skimme hvilke domæner der har problemer. */
    border-left: 3px solid var(--blue-300);

    /* Knapperne nederst skal stå i bund uanset hvor meget indhold der er over dem,
       så "Rediger" og "Slet" sidder samme sted på alle kort i rækken. */
    display: flex;
    flex-direction: column;
}

.dcard .dcard__actions { margin-top: auto; }

/* Målingerne fylder det, der er plads til, og rulles derefter.
   En printer har let femten målinger; uden loftet blev dens kort tre gange så højt
   som naboernes, og hele rækken fulgte med. */
.dmetrics {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    max-height: 12rem;
    overflow-y: auto;
    /* Plads til rullepanelet, så teksten ikke ligger klods op ad det. */
    padding-right: 0.15rem;
}

.dcard--sev0 { border-left-color: var(--good); }
.dcard--sev1 { border-left-color: var(--warn); }
.dcard--sev2 { border-left-color: var(--crit); }

.dcard__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.8rem;
}

.dcard__name { font-weight: 700; font-size: 0.95rem; }

/* Kort "3/5"-score, så man ser sundhedstilstanden uden at læse alle rækker. */
.dcard__score {
    font-size: 0.78rem;
    font-weight: 800;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    flex-shrink: 0;
    background: var(--blue-50);
    color: var(--ink-2);
}

.dcard__score--sev0 { background: var(--good-bg); color: var(--good); }
.dcard__score--sev1 { background: var(--warn-bg); color: var(--warn); }
.dcard__score--sev2 { background: var(--crit-bg); color: var(--crit); }

.dcard__badges {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    margin-bottom: 0.85rem;
}

.dcheck {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.78rem;
    min-width: 0;
}

.dcheck__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--faint);
    flex-shrink: 0;
}

.dcheck--ok .dcheck__dot { background: var(--good); }
.dcheck--warn .dcheck__dot { background: var(--warn); }
.dcheck--crit .dcheck__dot { background: var(--crit); }

/* Bredden er sat efter det længste navn, ikke efter det korteste.
   3,6rem passede til «SPF», «DKIM» og «CAA». Da tjekkene «Registrering»,
   «Navneservere», «Mailmodtagelse» og «Subdomæner» kom til, løb de ud over deres
   plads og landede oven i statussen ved siden af — nøjagtig samme fejl som med
   målingsnavnene et par regler nede, og med kommentaren allerede skrevet.

   nowrap og ellipsis er sikkerhedsnettet: kommer der en dag et endnu længere navn,
   bliver det klippet frem for at vælte rækken. */
.dcheck__name {
    font-weight: 700;
    color: var(--ink-2);
    letter-spacing: 0.02em;
    width: 7.4rem;
    flex-shrink: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Statussen maa heller ikke kunne ombryde. «Ikke tjekket» er to ord og brød til to
   linjer paa smalle kort, hvilket gjorde raekken dobbelt saa hoej og skubbede
   nabolinjen ind under sig. */
.dcheck__status {
    white-space: nowrap;
    flex-shrink: 0;
}

/* Målingsnavne er længere end "Ping" og "Cert.", som den faste bredde ovenfor er sat
   efter. "Toner sort" ombrød til to linjer og gjorde hver række dobbelt så høj, og
   "Printerstatus" løb ud over sin plads og oven i værdien ved siden af. */
.dcheck__name--metric {
    width: 6.4rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Værdien kan være alt fra "32 %" til en hel enhedsbeskrivelse fra en printer.
   Én linje, og resten klippes af — hele teksten står i title. */
.dcheck__status--metric {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dcheck__status { font-weight: 600; color: var(--muted); }
.dcheck--ok .dcheck__status { color: var(--good); }
.dcheck--warn .dcheck__status { color: var(--warn); }
.dcheck--crit .dcheck__status { color: var(--crit); }

/* «Ikke tjekket» skal tegnes dæmpet, fordi vi VÆLGER det — ikke fordi klassen mangler og
   den arver grundfarven. Forskellen er ikke synlig i dag, men den var det: DomainCheckStatus.Fejl
   pegede også på dcheck--muted og blev derfor tegnet som «vi kunne ikke måle», selv om Fejl
   er husets ord for et målt og udnytteligt problem. */
.dcheck--muted .dcheck__dot { background: var(--faint); }
.dcheck--muted .dcheck__status { color: var(--muted); }

.dcheck__detail {
    color: var(--faint);
    font-size: 0.73rem;
    margin-left: auto;
    max-width: 11rem;

    /* Uden den nægter flexbox at lade teksten krympe under sit indhold, og saa
       skubber den navn og status sammen i stedet for selv at blive klippet. */
    min-width: 0;
}

/* Domænekortet specifikt: detaljen flød før helt ud til højre (margin-left:auto) og
   efterlod et stort tomt mellemrum i midten. Giv status en fast kolonnebredde og lad
   detaljen flyde ind lige efter status og fylde resten af rækken — så pladsen bruges,
   og detaljerne flugter under hinanden. Scopet til .dcard__badges, så måle-/NOC-rækkerne,
   der deler .dcheck, er urørte. */
.dcard__badges .dcheck__status { min-width: 5.5rem; }
.dcard__badges .dcheck__detail {
    margin-left: 0;
    flex: 1 1 auto;
    max-width: none;
    text-align: left;
}

/* Tap-to-expand for the per-check help on the domain card. The row is a <details>; its <summary>
   carries the same flex layout the old .dcheck div had, so the inner .dcheck__* spans keep their
   colours and widths. The help text (previously only in the title= hover) drops down below on tap,
   so touch users can read it too. Scoped to .dchk — the .dcheck rows in the metric/NOC modules are
   untouched. */
.dchk { display: block; }
.dchk__sum {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.78rem;
    min-width: 0;
    cursor: pointer;
    list-style: none;
}
.dchk__sum::-webkit-details-marker { display: none; }
.dchk__sum::marker { content: ""; }
.dchk__more {
    margin-left: auto;
    flex: 0 0 auto;
    width: 1.05rem;
    height: 1.05rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--muted);
    border: 1px solid var(--line-2);
}
.dchk[open] .dchk__more { background: var(--ink-2); color: var(--paper); }
.dchk__help {
    font-size: 0.75rem;
    color: var(--muted);
    line-height: 1.4;
    padding: 0.2rem 0 0.5rem 1.15rem;
}
/* Comfortable tap target on touch. */
@media (max-width: 640px) {
    .dchk__more { width: 1.3rem; height: 1.3rem; }
}

.dsp-legend {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.9rem;
    margin: 0.2rem 0 0.7rem;
}
.dsp-legend__intro { margin-right: 0.15rem; }
.dsp-legend__item strong {
    color: var(--ink-2);
    font-weight: 700;
    letter-spacing: 0.02em;
    margin-right: 0.15rem;
}

.dcard__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding-top: 0.7rem;
    border-top: 1px dashed var(--line-2);
}

/* Mini-historik ("sparkline") over de seneste målinger på et endpoint. */
/* Ét sammenhængende bånd, ikke et søjlediagram.
   To px mellemrum fik striben til at læses som 24 selvstændige målinger, man skulle tælle. Det er
   ikke det, den er til for — den er en TIDSLINJE, og den skal kunne aflæses i ét blik. En px er
   nok til, at bjælkerne stadig kan skelnes, hvis man ser efter.

   Højden bliver. Se .spark__bar--up/slow/down: den bærer alvoren sammen med farven, så striben
   også kan læses i gråtoner og af den, der ikke skiller rødt fra grønt — og grøn/gul/rød er
   præcis den akse, det går galt på. Et ensartet fuldhøjt bånd ville se pænere ud og fortælle
   mindre. */
.spark {
    display: flex;
    align-items: flex-end;
    gap: 1px;
    height: 22px;
    margin-bottom: 0.3rem;

    /* Svag bund under båndet: viser hvor langt vinduet rækker, også hvor bjælkerne er lave.
       Uden den svævede en stribe med idel korte bjælker uden nogen linje at hvile på. */
    border-bottom: 1px solid var(--line);
    padding-bottom: 1px;
}

.spark__spænd {
    font-size: 0.72rem;
    color: var(--muted);
    margin-bottom: 0.85rem;
    font-variant-numeric: tabular-nums;
}

.spark__bar {
    flex: 1;
    min-width: 3px;
    border-radius: 2px;
    background: var(--blue-200);
}

/* Højden bærer alvoren sammen med farven, så striben også kan læses i gråtoner og af den,
   der ikke skelner rødt fra grønt. Rækkefølgen er en trappe: oppe lavest, nede højest. */
.spark__bar--up { background: var(--good); height: 55%; }
.spark__bar--slow { background: var(--warn); height: 75%; }
.spark__bar--down { background: var(--crit); height: 100%; }

/* Kritisk er IKKE nede.
   De to var samme farve og samme højde før — men «fuld disk» og «svarer ikke» kræver hver sit
   opkald. Kritisk får derfor sin egen form: fuld højde som nede, men hul i midten, så den
   svarer-men-fejler-tilstand kan ses uden at læse et værktøjstip. */
.spark__bar--critical {
    height: 100%;
    background: linear-gradient(var(--crit) 0 35%, color-mix(in srgb, var(--crit) 30%, var(--paper)) 35% 65%, var(--crit) 65% 100%);
}

/* «Vi kunne ikke måle den» — typisk fordi noget foran den er nede. Hul frem for fyldt: et
   fravær af svar skal se ud som et fravær, ikke som endnu en tilstand. */
.spark__bar--unknown {
    height: 45%;
    background: transparent;
    box-shadow: inset 0 0 0 1px var(--line-2);
}

/* Ingen måling, og ingen tæt nok bagved til at tale for spanden. Den laveste og svageste
   markering på striben — den siger «her ved vi ingenting», og det skal man kunne se. */
.spark__bar--notmeasured {
    height: 18%;
    background: var(--line);
}

/* Båret frem tegnes som alt andet.
   Den havde halv dækkraft, så en enhed målt hver time ikke lignede en målt hvert femte minut.
   Men i det normale tilfælde — alt grønt — gav det en stribe i to grønne, der flimrede uden at
   betyde noget, og som fik folk til at spørge hvad forskellen var. Svaret er ikke noget, man
   skal bruge, når det hele virker.
   Forskellen står stadig i værktøjstippet («målt» kontra «uændret siden sidste måling»), og det
   ene tilfælde, hvor den betyder noget — at vi ikke VED det — har sin egen markering i
   .spark__bar--notmeasured. */

/* Enkeltstående afvigelse — en måling, flapbeskyttelsen slog fra, fordi den ikke gentog
   sig. Værd at kunne se, men den er ikke et nedbrud og skal ikke ligne et.

   To signaler, ikke ét: skravering OG halv højde. Skraveringen alene forsvinder ved
   nedskalering, og højden alene kunne forveksles med "langsom". Sammen er de entydige.

   Rækkefølgen er ikke tilfældig: den skal stå EFTER farvereglerne ovenfor, som bruger
   background-genvejen. Placeret før blev background-image nulstilt af genvejen, og
   skraveringen blev aldrig tegnet — hvilket man ikke kan se på et skærmbillede, kun
   ved at måle den beregnede stil. */
.spark__bar--blip {
    height: 55%;
    background-image: repeating-linear-gradient(
        135deg,
        rgba(255, 255, 255, 0.6) 0 2px,
        rgba(255, 255, 255, 0) 2px 5px);
}

/* Signaturen til pulsstriben.
   Farverne stod indtil nu kun i et værktøjstip pr. bjælke — altså kun for den, der allerede gættede,
   at der var noget at holde musen over, og slet ikke for den på en telefon. Prikkerne genbruger
   bjælkernes former, ikke bare deres farver: den hule «kunne ikke måles» og den gennemskårne
   «kritisk» skal kunne genkendes igen nede i striben. */
.spark-sig {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1.1rem;
    padding: 0.75rem 0.2rem 0.1rem;
    font-size: 0.72rem;
    color: var(--muted);
}

.spark-sig__punkt {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

.spark-sig__prik {
    width: 4px;
    border-radius: 2px;
    flex-shrink: 0;
}

/* Samme trappe som i striben: oppe lavest, nede højest. Så bærer signaturen også højdens
   betydning, uden at skulle skrive den. */
.spark-sig__prik--up { height: 9px; background: var(--good); }
.spark-sig__prik--slow { height: 12px; background: var(--warn); }
.spark-sig__prik--down { height: 16px; background: var(--crit); }

.spark-sig__prik--critical {
    height: 16px;
    background: linear-gradient(var(--crit) 0 35%, color-mix(in srgb, var(--crit) 30%, var(--paper)) 35% 65%, var(--crit) 65% 100%);
}

.spark-sig__prik--unknown {
    height: 8px;
    background: transparent;
    box-shadow: inset 0 0 0 1px var(--line-2);
}

.spark-sig__prik--notmeasured { height: 4px; background: var(--line); }

/* ==========================================================================
   Hurtig tidsregistrering (Alt+T)
   ========================================================================== */

.qte__launch {
    position: fixed;
    right: 1.5rem;
    bottom: 1.5rem;
    z-index: 900;
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.7rem 1.15rem;
    border: 0;
    border-radius: 999px;
    background: var(--navy-800);
    color: #fff;
    font-weight: 700;
    font-size: 0.87rem;
    box-shadow: var(--shadow-md);
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.qte__launch:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); background: var(--navy-950); }

.qte__launch kbd {
    background: rgba(255, 255, 255, 0.16);
    border: 0;
    border-radius: 5px;
    padding: 0.1rem 0.35rem;
    font-size: 0.72rem;
    font-family: inherit;
    font-weight: 700;
    color: #fff;
}

.qte__backdrop {
    position: fixed;
    inset: 0;
    z-index: 950;
    background: rgba(19, 28, 40, 0.42);
    backdrop-filter: blur(2px);
}

/* ==========================================================================
   Dokumentbibliotek
   ========================================================================== */

.doc-search { margin-bottom: 1rem; }

.fgrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 0.5rem;
    margin-bottom: 1.15rem;
}

.fcard {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 0.85rem;
    border-radius: var(--r-md);
    background: var(--clay-100);
    box-shadow: inset 0 0 0 1px var(--line);
    cursor: pointer;
    transition: box-shadow 0.13s ease, transform 0.13s ease;
}

.fcard:hover {
    box-shadow: inset 0 0 0 1px var(--line-2), var(--shadow-sm);
    transform: translateY(-1px);
}

.fcard__icon {
    color: var(--warn);
    display: grid;
    place-items: center;
    flex-shrink: 0;
}

.fcard__main { min-width: 0; flex: 1; }

.fcard__name {
    font-weight: 700;
    font-size: 0.87rem;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Filtype-badge i dokumentlisten — erstatter prioritetsstriben fra ticket-kortene. */
.doc__ext {
    width: 40px;
    flex-shrink: 0;
    align-self: center;
    text-align: center;
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.03em;
    padding: 0.3rem 0;
    border-radius: 6px;
    background: var(--blue-100);
    color: var(--navy-800);
}

.doc__ext--pdf { background: #f6e2e0; color: #96382f; }
.doc__ext--doc { background: #dfe7f5; color: #2f4d80; }
.doc__ext--sheet { background: #dff0e4; color: #2c6b42; }
.doc__ext--img { background: #f1e6f5; color: #6b3d80; }
.doc__ext--zip { background: var(--clay-200); color: #6d4d16; }

/* ==========================================================================
   Tidsforbrug-historik (måned for måned)
   ========================================================================== */

.mhist { display: flex; flex-direction: column; gap: 0.35rem; }

.mhist__month {
    border-radius: var(--r-md);
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
}

.mhist__month[open] { box-shadow: inset 0 0 0 1px var(--line-2); }

.mhist__summary {
    display: grid;
    grid-template-columns: 9rem 1fr 4rem 9rem;
    align-items: center;
    gap: 0.9rem;
    padding: 0.7rem 1rem;
    cursor: pointer;
    list-style: none;
}

.mhist__summary::-webkit-details-marker { display: none; }
.mhist__summary:hover { background: var(--blue-50); border-radius: var(--r-md); }

/* Pil, der viser at rækken kan foldes ud.
   Browserens egen trekant er slået fra ovenfor, og uden en erstatning var der ingen
   antydning overhovedet — en kunde gætter ikke på, at «August 2026» kan klikkes.

   Kun på details-varianten. Microsoft 365-siden genbruger de samme klasser på en
   <div>, der ikke kan foldes ud, og dér ville en pil love noget, der ikke sker. */
/* The hours column is 8rem (it was 4rem): «13 t 45 min.» and «+ 2 t fakturerbart» each fit on one line there. In 4rem
   the small line broke over five (KC, 15 October 2026). Fixed, not auto: every row is its own grid, and the bars only
   compare when their tracks are the same width. */
details.mhist__month > .mhist__summary {
    grid-template-columns: 9rem 1fr 8rem 9rem 1.25rem;
}

details.mhist__month > .mhist__summary::after {
    content: "";
    width: 0.45rem;
    height: 0.45rem;
    border-right: 2px solid var(--ink-3, var(--ink-2));
    border-bottom: 2px solid var(--ink-3, var(--ink-2));
    border-radius: 1px;
    transform: rotate(45deg) translateY(-0.1rem);
    transform-origin: center;
    transition: transform 0.15s ease;
    justify-self: end;
}

details.mhist__month[open] > .mhist__summary::after {
    transform: rotate(-135deg) translateY(-0.1rem);
}

@media (max-width: 900px) {
    /* On a phone the row wraps instead of keeping columns (KC, 15 October 2026): the month and the arrow on top, the bar
       under them, then the hours and the badge — and the badge drops to its own line, right-aligned, when the two do not
       fit side by side. In the grid, the hours (13 t 45 min.) beside a wide badge (3 t 45 min. over) pushed the row past
       its edge at 320 px and squeezed «September 2026» onto two lines. */
    details.mhist__month > .mhist__summary {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        column-gap: 0.75rem;
        row-gap: 0.5rem;
    }

    details.mhist__month > .mhist__summary > .mhist__label { flex: 1 1 0; min-width: 0; }
    details.mhist__month > .mhist__summary::after { order: 1; flex: none; }
    details.mhist__month > .mhist__summary > .mhist__bar { order: 2; flex: 0 0 100%; }
    details.mhist__month > .mhist__summary > .mhist__hours { order: 3; text-align: left; }
    details.mhist__month > .mhist__summary > .mhist__status { order: 4; margin-left: auto; }
}

@media (prefers-reduced-motion: reduce) {
    details.mhist__month > .mhist__summary::after { transition: none; }
}

.mhist__label {
    font-weight: 700;
    font-size: 0.86rem;
    color: var(--ink);
    text-transform: capitalize;
}

.mhist__bar {
    position: relative;
    display: block;
    height: 12px;
    border-radius: 999px;
    background: var(--blue-50);
    overflow: hidden;
}

/* Puljen tegnes som en svag baggrundsmarkering, så man kan se hvor grænsen går. */
.mhist__allowance {
    position: absolute;
    inset: 0 auto 0 0;
    background: var(--clay-200);
    opacity: 0.55;
}

.mhist__fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    background: var(--good);
    border-radius: 999px;
}

.mhist__fill--over { background: var(--warn); }

/* The time usage bar: one pill split into parts, each as wide as its share of the month's hours.
   Green inside the month's own pool, orange only past it, blue billable, grey before the agreement's start. */
.mhist__stack {
    position: absolute;
    inset: 0 auto 0 0;
    display: flex;
    border-radius: 999px;
    overflow: hidden;
}

.mhist__seg { flex: none; }
.mhist__seg--within { background: var(--good); }
.mhist__seg--over { background: var(--warn); }
.mhist__seg--billable { background: var(--blue-400); }

/* Time before the agreement's start: it draws on no pool, and is invoiced only when billable. */
.mhist__seg--before { background: var(--muted); opacity: 0.45; }

.mhist__hours {
    font-weight: 800;
    font-size: 0.86rem;
    color: var(--ink);
    text-align: right;
}

.mhist__num { white-space: nowrap; }

/* The small line under the hours: «+ 2 t fakturerbart». A long one («+ 13 t 45 min. fakturerbart») breaks once,
   after the time. */
.mhist__extra {
    display: block;
    font-size: 0.75rem;
    font-weight: 500;
    line-height: 1.25;
    color: var(--faint);
}

/* The month in progress: under the month's name, since the label column has no room beside it. */
.mhist__now {
    display: block;
    width: fit-content;
    margin-top: 0.15rem;
    padding: 0 0.45rem;
    border: 1px solid var(--line-2);
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: none;
}

/* En måned helt før aftalens start: den står i listen, men grå, og tæller ikke med. */
.mhist__month--before .mhist__label,
.mhist__month--before .mhist__hours { color: var(--muted); }

.mhist__status { text-align: right; }

.mhist__detail {
    padding: 0 1rem 0.9rem;
    border-top: 1px solid var(--line);
    margin-top: 0.15rem;
    padding-top: 0.8rem;
}

.mhist__legend {
    display: flex;
    gap: 1.1rem;
    flex-wrap: wrap;
    margin-top: 1rem;
    font-size: 0.76rem;
    color: var(--muted);
}

.mhist__legend span { display: inline-flex; align-items: center; gap: 0.4rem; }

.mhist__key {
    width: 11px;
    height: 11px;
    border-radius: 3px;
    display: inline-block;
}

.mhist__key--allowance { background: var(--clay-200); }
.mhist__key--used { background: var(--good); }
.mhist__key--over { background: var(--warn); }
.mhist__key--billable { background: var(--blue-400); }
.mhist__key--before { background: var(--muted); opacity: 0.45; }

@media (max-width: 900px) {
    .mhist__summary { grid-template-columns: 1fr auto; row-gap: 0.5rem; }
    .mhist__bar { grid-column: 1 / -1; }
}

/* ==========================================================================
   Tickets
   ========================================================================== */

.tkt-filters { margin-bottom: 1.15rem; }

.tkt-chips { display: flex; gap: 0.4rem; flex-wrap: wrap; }

.tkt-chip {
    border: 0;
    background: var(--blue-50);
    color: var(--ink-2);
    font-size: 0.8rem;
    font-weight: 700;
    padding: 0.4rem 0.85rem;
    border-radius: 999px;
    cursor: pointer;
}

.tkt-chip:hover { background: var(--blue-100); }
.tkt-chip--active { background: var(--navy-800); color: #fff; }
.tkt-chip--active:hover { background: var(--navy-950); color: #fff; }

.tkt-filters__row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.75rem;
}

.tkt-filters__row .form-select { width: auto; }
.tkt-filters__search { flex: 1; min-width: 12rem; }

/* ---- overblik: Sager ---- (3 October 2026, docs/arbejde/2026-10-03-overblik-design-3.md)
   The queue's four tiles (TicketQueueTiles) sit tight between the header and the queue: the page lost two earlier tops
   for pushing the queue below the fold. The panel head went (the view switch and «Opret ticket» moved into the header's
   action slot), the queue's title and the ownership chips lead the filter row, and on a phone the four selects fold
   behind «Flere filtre». The ticket row gets its own two-line phone layout. */
.ph:has(+ [data-tiles="ticket-queue"]) { margin-bottom: 1.15rem; }
[data-tiles="ticket-queue"] { margin-bottom: 1rem; }
.panel--queue { padding-top: 1.15rem; }
.tkt-filters--one .tkt-filters__row { margin-top: 0; align-items: center; }
.tkt-filters--one .tkt-chips { margin-right: 0.35rem; }
.queue-title { margin: 0 0.4rem 0 0; white-space: nowrap; }
.panel--queue .listnote { margin: -0.35rem 0 0.8rem; }
/* The search takes what is left of the one row; at 12rem it was pushed onto a line of its own at 1440 px. */
.tkt-filters--one .tkt-filters__search { min-width: 9rem; }
/* The count in the pressed ownership chip: the muted grey on navy was 2.5:1. */
.tkt-chip--active .epsek__antal { color: inherit; opacity: 0.8; }
/* Dark theme: the chip rule at the top (:root[data-theme="dark"] .tkt-chip) outranks .tkt-chip--active, so the chosen
   chip - Liste/Tavle, Alle/Mine - looked like the others. The pressed one is light, as the links are. */
:root[data-theme="dark"] .tkt-chip--active,
:root[data-theme="dark"] .tkt-chip--active:hover { background: var(--blue-300); color: var(--navy-950); }
/* «Frist / alder ▲» is wider than its 6rem column and broke onto two lines. It stays on one, right-aligned to the dates
   below, and runs into the status column's empty space to its left. */
.eprows__hoved--sag > span:nth-child(7) { direction: rtl; white-space: nowrap; }
.eprows__hoved--sag > span:nth-child(7) > .th-sort { direction: ltr; }

/* «Flere filtre»: only on a phone. A dot when a folded select is narrowing the list, so a hidden filter is never a secret. */
.morefilters { display: none; }
.morefilters__on { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--link); }

@media (max-width: 700px) {
    .queue-title { width: 100%; margin-bottom: 0.1rem; }
    .tkt-filters--one .tkt-chips { margin-right: 0; }
    .tkt-filters--one .tkt-filters__row > .form-select { display: none; }
    .tkt-filters--one.tkt-filters--open .tkt-filters__row > .form-select { display: block; }
    .morefilters {
        display: inline-flex;
        align-items: center;
        gap: 0.4rem;
        font: inherit;
        font-size: 0.8rem;
        font-weight: 700;
        color: var(--ink-2);
        background: var(--paper);
        border: 1px solid var(--line-2);
        border-radius: 999px;
        padding: 0.38rem 0.85rem;
        cursor: pointer;
    }
    .morefilters[aria-expanded="true"] { border-color: var(--ink-2); }
    .morefilters:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
    .panel--queue .listnote { margin-top: 0; }
    .tkt-filters--one .tkt-filters__search { flex: 1 1 100%; }

    /* The ticket row on two lines: title and time, then customer, state and owner. Placed explicitly - the dense rows'
       own phone rule (.eprow__sum, above) is written for the domain rows, and auto-placing the ticket's eight cells into
       its three columns dropped the state word into the 0.6rem column and clipped the date. The checkbox keeps its own
       column beside the priority bar - it is the only way to select cases for the bulk «Tag N» - and the category stays
       on the wider screens. */
    .eprow__sum.eprow__sum--sag {
        grid-template-columns: 4px 1.1rem minmax(0, 1fr) auto auto;
        grid-template-rows: auto auto;
        column-gap: 0.6rem;
        row-gap: 0.12rem;
        padding: 0.6rem 0.75rem;
    }
    .eprow__sum--sag > .form-check-input { grid-column: 2; grid-row: 1 / span 2; align-self: center; margin: 0; }
    .eprow__sum--sag > .eprow__type { display: none; }
    .eprow__sum--sag > .sagrow__prio { grid-column: 1; grid-row: 1 / span 2; height: 2.2rem; }
    .eprow__sum--sag > .sagnavn { grid-column: 3 / 5; grid-row: 1; }
    .eprow__sum--sag > .sagtid { grid-column: 5; grid-row: 1; font-size: 0.78rem; }
    .eprow__sum--sag > .eprow__kunde { grid-column: 3; grid-row: 2; font-size: 0.78rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .eprow__sum--sag > .sagstatus { grid-column: 4; grid-row: 2; font-size: 0.78rem; }
    .eprow__sum--sag > .sagejer { grid-column: 5; grid-row: 2; }
    .eprow__sum--sag .tkt__assignee { width: 22px; height: 22px; font-size: 0.58rem; }
}
/* ---- /overblik: Sager ---- */

.tkt-list { display: flex; flex-direction: column; gap: 0.5rem; }

/* Massevalg-bjælken over triage-listen. Klæber til toppen, så «Tag N» bliver ved med at være
   inden for rækkevidde, mens man ruller gennem en lang liste og vælger flere sager. */
.tktbulk {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.55rem 0.85rem;
    margin-bottom: 0.8rem;
    background: var(--paper);
    border-radius: var(--r-md);
    box-shadow: inset 0 0 0 1px var(--line-2);
    position: sticky;
    /* Below the topbar, which is itself sticky at top:0 with z-index 800. At top:0.5rem this bar
       slid in UNDER it — so «Tag N» disappeared at the moment it was being used. The value tracks
       .topbar's height (0.85rem padding twice plus its content). */
    top: 4.8rem;
    z-index: 3;
}

/* Afkrydsningen sidder først på sagskortet uden at skubbe prioritetsstriben ud af flugt. */
.tkt__check { flex-shrink: 0; margin: 0; cursor: pointer; }

/* Synligt trækhåndtag på kort, der kan omarrangeres (fx årshjulet, plan-skabeloner) — så
   «kan trækkes» ikke kun afsløres af grab-cursoren ved et tilfældigt hover. Dæmpet, men
   tydeligere når man er ved kortet. Hele kortet er stadig trækfladen; grebet er blot cue'en. */
.tkt__grip {
    flex-shrink: 0;
    color: var(--faint);
    font-size: 1.05rem;
    line-height: 1;
    cursor: grab;
    user-select: none;
    opacity: 0.5;
    transition: opacity 0.12s, color 0.12s;
}
.tkt:hover .tkt__grip { opacity: 1; color: var(--muted); }

.tkt {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.85rem 1rem;
    border-radius: var(--r-md);
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
    cursor: pointer;
    /* Mange .tkt-rækker er <a>. Uden dette hånd-tilføjede hvert kaldested style="text-decoration:none"
       (og arvede link-blå på titlen). Sat på basen én gang, så rækkerne ser ens ud som links og ikke. */
    text-decoration: none;
    color: inherit;
    transition: box-shadow 0.13s ease, transform 0.13s ease;
}

/* Tint, not lift. The queue reloads itself every couple of minutes and the mouse travels down eighty
   rows; a 1px hop under the cursor on each one is motion the eye has to discount. The house says so
   itself further down, in the rule about hover on dense rows. */
.tkt:hover {
    box-shadow: inset 0 0 0 1px var(--line-2);
    background: var(--blue-50, color-mix(in srgb, var(--ink) 3%, var(--paper)));
}

/* Rene informationskort er ikke klikbare. Uden denne modifier løftede de sig på hover
   som et ægte klikbart .tkt (kun cursoren var rettet inline), så hover holdt op med at
   betyde «her kan klikkes». Flad hover: behold rammen, drop løftet og den ekstra skygge. */
.tkt--static { cursor: default; }
.tkt--static:hover {
    box-shadow: inset 0 0 0 1px var(--line);
    transform: none;
}

.tkt--done { opacity: 0.62; }

.tkt__prio {
    width: 4px;
    align-self: stretch;
    border-radius: 999px;
    background: var(--blue-300);
    flex-shrink: 0;
}

.tkt__prio--lav { background: var(--blue-200); }
.tkt__prio--normal { background: var(--blue-400); }
.tkt__prio--hoej { background: var(--warn); }
.tkt__prio--kritisk { background: var(--crit); }

.tkt__main { flex: 1; min-width: 0; }

.tkt__title {
    font-weight: 700;
    font-size: 0.92rem;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A card's title row (the annual plan): only the title is cut with an ellipsis; its badges sit beside it and wrap to their
   own line when there is no room. Inside .tkt__title they were clipped with it, and on a phone the DORA mark was gone
   (23 October 2026). */
.tkt__head { display: flex; flex-wrap: wrap; align-items: center; column-gap: 0.45rem; row-gap: 0.2rem; min-width: 0; }
.tkt__head > .tkt__title { flex: 0 1 auto; min-width: 0; }
.tkt__head > .badge,
.tkt__head > .chip { flex-shrink: 0; }

/* Same three as .tkt__title. Without them a long customer name wraps the meta line and that one row
   grows ~18px, so the list looks untidy without anything you can point at. */
.tkt__meta {
    font-size: 0.76rem;
    color: var(--muted);
    margin-top: 0.15rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tkt__side {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-shrink: 0;
}

/* «Kvittér» på en sikkerhedsadvarsel: en diskret pille, der ikke skal tage opmærksomhed
   fra selve advarslen — men bliver tydelig, når man er ved den. */
.tkt__kvit {
    display: inline-flex;
    align-items: center;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    border: 1px solid var(--line-2, var(--line));
    background: transparent;
    color: var(--muted);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: color .12s, background .12s, border-color .12s;
}

.tkt__kvit:hover,
.tkt__kvit:focus-visible {
    color: #fff;
    background: var(--blue-500);
    border-color: var(--blue-500);
    outline: none;
}

/* Modul-adgang som klikbare fliser i stedet for en tabel med knapper. */
.mods-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: 0.5rem;
}

.mtile {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.65rem 0.75rem;
    border: 0;
    border-radius: var(--r-md);
    background: var(--blue-50);
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--muted);
    cursor: pointer;
    text-align: left;
    transition: background-color 0.13s ease, color 0.13s ease, box-shadow 0.13s ease;
}

.mtile:hover { box-shadow: inset 0 0 0 1px var(--line-2); }

.mtile--on {
    background: var(--good-bg);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--good) 28%, transparent);
    color: var(--ink);
}

.mtile__icon { display: grid; place-items: center; flex-shrink: 0; opacity: 0.7; }
.mtile--on .mtile__icon { color: var(--good); opacity: 1; }

.mtile__name {
    flex: 1;
    min-width: 0;
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1.2;
}

.mtile__state {
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    flex-shrink: 0;
}

.mtile--on .mtile__state { color: var(--good); }

/* Tynd forbrugsbjælke under en aftale i listen. */
.agr-bar {
    position: relative;
    height: 5px;
    border-radius: 999px;
    background: var(--blue-50);
    overflow: hidden;
    margin-top: 0.45rem;
    max-width: 22rem;
}

.agr-bar__fill {
    position: absolute;
    inset: 0 auto 0 0;
    background: var(--good);
    border-radius: 999px;
}

.agr-bar__fill--over { background: var(--warn); }

/* Rund avatar i venstre side af et listekort (kunder, medarbejdere). */
.tkt__avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--blue-400), var(--navy-700));
    color: #fff;
    font-size: 0.74rem;
    font-weight: 800;
    display: grid;
    place-items: center;
    flex-shrink: 0;
}

.tkt__assignee {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--blue-400), var(--navy-700));
    color: #fff;
    font-size: 0.66rem;
    font-weight: 800;
    display: grid;
    place-items: center;
}

.tkt-actions {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}

.tkt-actions__spacer { flex: 1; }

/* Samtaletråd */

.thread { display: flex; flex-direction: column; gap: 1rem; }

.thread__item { display: flex; gap: 0.75rem; }

/* Samtalen læses som en samtale: modparten til venstre, én selv til højre — samme
   konvention som enhver beskedapp. Siden afhænger af, hvem der kigger: kunden ser
   sig selv til højre, vi ser os selv til højre. Det er ikke to designs, men det
   samme design set fra hver sin ende, og det er dét, der gør «hvem sagde hvad»
   læsbart uden at læse navnet over hver boble.

   Boblen får et loft på bredden. Uden det ville en lang besked fylde hele linjen,
   og så er der ingen venstre og højre at se forskel på. */
.thread__body { max-width: 78%; flex: 0 1 auto; }

/* Hjørnet nærmest afsenderen er skarpt — den ene kode, enhver beskedapp bruger, og
   den eneste, der stadig virker, når boblen fylder næsten hele bredden. På en telefon
   er forskydningen på 44 px ikke nok til at se forskel, og farven alene er svag, hvis
   begge parter tilfældigvis hedder det samme. Hjørnet peger. */
.thread__item .thread__body { border-bottom-left-radius: 5px; }
.thread__item--mig .thread__body {
    border-bottom-left-radius: var(--r-md);
    border-bottom-right-radius: 5px;
}

/* Den lyse boble ligger på en næsten lige så lys flade. Uden kanten flyder den ud i
   panelet og ligner brødtekst frem for en replik. */
.thread__item .thread__body { box-shadow: inset 0 0 0 1px var(--line); }
.thread__item--mig .thread__body { box-shadow: none; }

.thread__item--mig { flex-direction: row-reverse; }
.thread__item--mig .thread__head { flex-direction: row-reverse; }

.thread__item--mig .thread__body {
    background: var(--navy-800);
    color: #fff;
}

/* Tid og navn i en mørk boble. --muted ville lande på ~2,5:1 mod navy-800; hvid med
   nedsat gennemsigtighed holder sig over kravet og læses stadig som sekundært. */
.thread__item--mig .thread__head .stat__meta,
.thread__item--mig .thread__head strong { color: rgba(255, 255, 255, 0.86); }

/* «Redigér» (og anden btn-link) i den mørke boble: link-farven er valgt til lys baggrund og
   forsvinder næsten på navy-800. Lys, understreget tekst her — mørk/blå alle andre steder. */
.thread__item--mig .thread__body .btn-link {
    color: rgba(255, 255, 255, 0.9);
    text-decoration: underline;
}
.thread__item--mig .thread__body .btn-link:hover { color: #fff; }

.thread__item--mig .thread__avatar {
    background: linear-gradient(140deg, var(--navy-700), var(--navy-950));
}

/* Interne noter er ikke en replik i samtalen — de er noget, vi skriver til os selv
   midt i den. Derfor hverken venstre eller højre, men fuld bredde, så de tydeligt
   ligger uden for det, kunden nogensinde ser. */
.thread__item--internal .thread__body {
    background: var(--warn-bg);
    box-shadow: inset 0 0 0 1px rgba(176, 125, 51, 0.22);
    max-width: 100%;
    flex: 1;
    color: var(--ink);
}

/* Den interne note peger ingen steder hen — den er ikke en replik i samtalen, så
   den beholder runde hjørner hele vejen rundt. */
.thread__item--internal .thread__body {
    border-radius: var(--r-md);
}

.thread__item--internal { flex-direction: row; }
.thread__item--internal .thread__head { flex-direction: row; }
.thread__item--internal .thread__head strong { color: var(--ink); }
.thread__item--internal .thread__head .stat__meta { color: var(--ink-2); }

.thread__item--internal .thread__avatar {
    background: linear-gradient(140deg, var(--blue-400), var(--navy-700));
}


.thread__avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: linear-gradient(140deg, var(--blue-400), var(--navy-700));
    color: #fff;
    font-size: 0.7rem;
    font-weight: 800;
    display: grid;
    place-items: center;
    flex-shrink: 0;
}

.thread__body {
    flex: 1;
    min-width: 0;
    background: var(--blue-50);
    border-radius: var(--r-md);
    padding: 0.7rem 0.9rem;
}

.thread__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.82rem;
}

/* Telefonen. Blokken står her og ikke længere oppe: den skal komme EFTER
   .thread__avatar og .thread__body, ellers vinder grundreglerne på lige specificitet,
   og reglerne herunder ser ud til at virke uden at gøre noget. Første forsøg stod
   ovenfor, og avataren blev pænt stående — målt, ikke antaget. */
@media (max-width: 640px) {
    /* Avataren er 32 px plus 12 px afstand — plads, der er dyr på en smal skærm, og
       den fortæller ikke mere, end boblen gør. Navnet står i hovedet ovenfor. */
    .thread__avatar { display: none; }
    .thread__item { gap: 0; }

    /* Uden avataren skal boblen selv skabe forskydningen. 14 % tomrum i den ene ende
       er nok til at siden kan ses på et øjeblik, uden at teksten bliver en smal søjle. */
    .thread__item--mig { padding-left: 14%; }
    .thread__item:not(.thread__item--mig):not(.thread__item--internal) { padding-right: 14%; }

    .thread__body { max-width: 100%; }

    /* Den interne note er ikke en replik og skal have hele bredden. */
    .thread__item--internal { padding: 0; }
}

/* Svar-boks */

.reply {
    margin-top: 1.25rem;
    padding-top: 1.15rem;
    border-top: 1px solid var(--line);
}

.reply__tabs { display: flex; gap: 0.35rem; margin-bottom: 0.6rem; }

.reply__tab {
    border: 0;
    background: none;
    color: var(--muted);
    font-size: 0.82rem;
    font-weight: 700;
    padding: 0.35rem 0.7rem;
    border-radius: 8px;
    cursor: pointer;
}

.reply__tab:hover { background: var(--blue-50); color: var(--ink); }
.reply__tab--active { background: var(--navy-800); color: #fff; }
.reply__tab--active:hover { background: var(--navy-950); color: #fff; }

.reply__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 0.6rem;
}

/* Fristen på en løst sag. --ink-2 og ikke --muted: teksten står på en tonet flade,
   og --muted rammer 3,9:1 dér — under de 4,5:1, WCAG kræver. Målt, ikke skønnet. */
.reply__loest {
    margin: 0 0 0.7rem;
    padding: 0.6rem 0.75rem;
    border-radius: 10px;
    background: var(--blue-50);
    color: var(--ink-2);
    font-size: 0.85rem;
    line-height: 1.45;
}

/* Henvisningen tilbage til den lukkede sag. Står mellem sidehoved og handlinger,
   hvor den læses før man begynder at svare — ikke nede i en detaljeliste. */
.tkt-opfoelger {
    margin: 0 0 0.9rem;
    padding: 0.55rem 0.8rem;
    border-left: 3px solid var(--navy-800);
    background: var(--blue-50);
    color: var(--ink-2);
    font-size: 0.85rem;
    border-radius: 0 10px 10px 0;
}

.tkt-opfoelger a { color: var(--navy-950); font-weight: 700; }

/* «Hænger sammen med» — de linjer, opgavelistens oprulning lagde ind under en anden, fordi de
   handler om den samme enhed eller forklares af den. Indrykket og dæmpet: rækken ovenover er
   stadig den, der skal læses, men de underordnede beholder hver sit link ind i sit eget modul.
   Kun tokens der selv vender i mørkt tema — ellers ville blokken kræve sin egen dark-regel. */
.tkt-group { display: flex; flex-direction: column; }

/* A task row with its action cell BESIDE the link (19 September 2026). Real buttons cannot sit inside an <a>, so
   the row is a link and the cell next to it holds at most two buttons and one «where to» link — the same place on
   every row. */
.tkt-row { display: flex; align-items: stretch; gap: 0.5rem; }
.tkt-row > .tkt { flex: 1 1 auto; min-width: 0; }
.tkt__acts {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 0.35rem;

    /* A fixed column, drawn on every row: a cell as wide as its own buttons left the cards ending at a different
       place on each row. */
    flex: 0 0 18rem;
}
button.tkt__kvit { font-family: inherit; line-height: 1.4; }
button.tkt__kvit:disabled { opacity: 0.6; cursor: default; }
.tkt__kvit--primary { color: var(--link); border-color: var(--blue-300, var(--line-2)); }
.tkt__hint { font-size: 0.8rem; font-weight: 600; white-space: nowrap; color: var(--link); text-decoration: none; }
.tkt__hint:hover { text-decoration: underline; }
.tkt__note { flex-basis: 100%; font-size: 0.76rem; color: var(--muted); }
.tkt__note--err { color: var(--crit); }
.tkt__note--page { margin-top: 0.75rem; font-size: 0.82rem; }

/* The action column goes under the card when the LIST is narrow, not only the screen: at a small laptop window or a
   split screen the fixed column left the title a few characters. The row's group is the container, so the rule
   follows the width the list actually has, sidebar or not. */
.tkt-group { container-type: inline-size; }

@container (max-width: 800px) {
    .tkt-row { flex-direction: column; }
    .tkt__acts { flex: none; padding-left: 0.5rem; }
    .tkt__acts:empty { display: none; }
}

.tkt-linked {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    margin: 0.3rem 0 0 2.1rem;
    padding: 0.1rem 0 0.1rem 0.75rem;
    border-left: 2px solid var(--line-2);
}

.tkt-linked__label {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.15rem;
}

.tkt-linked__row {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    min-width: 0;
    padding: 0.2rem 0.35rem;
    border-radius: var(--r-sm);
    font-size: 0.8rem;
    color: var(--ink-2);
    text-decoration: none;
}

.tkt-linked__row:hover { background: var(--blue-50); color: var(--ink); }

.tkt-linked__source,
.tkt-linked__detail { flex-shrink: 0; color: var(--muted); font-size: 0.72rem; }

.tkt-linked__source { font-weight: 700; }

.tkt-linked__title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.notif { position: relative; }

.notif__btn {
    position: relative;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, 0.7);
    box-shadow: inset 0 0 0 1px var(--line);
    color: var(--muted);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    cursor: pointer;
}

.notif__btn:hover { background: #fff; color: var(--ink); }

.notif__badge {
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    border-radius: 999px;
    background: var(--crit);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 800;
    display: grid;
    place-items: center;
    line-height: 1;
}

.notif__backdrop {
    position: fixed;
    inset: 0;
    z-index: 950;
}

.notif__panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 951;
    width: 340px;
    max-height: 24rem;
    overflow-y: auto;

    /* Panelet må aldrig kunne rulles sidelæns. Det er ikke pynt: en vandret
       scrollbar nederst spiser en linje af den nederste notifikation og får
       samtidig den lodrette til at se forkert ud. Overskriften var årsagen —
       fem knapper i en space-between uden ombrydning presser indholdet bredere
       end panelet — men hidden her sikrer, at den næste knap, nogen tilføjer,
       ikke gør det samme igen. */
    overflow-x: hidden;
    background: var(--paper);
    color: var(--ink);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-lg);
    padding: 0.75rem;
}

.notif__head {
    display: flex;
    align-items: center;
    justify-content: space-between;

    /* Ombrydning frem for at klemme. Antallet af knapper her afhænger af
       tilstanden — «Markér alle som læst» og «Ryd læste» kommer og går — så
       rækken kan ikke få en bredde, der passer i alle tilfælde. Uden dette
       skubbede den panelet bredere end sig selv. */
    flex-wrap: wrap;
    gap: 0.35rem 0.6rem;

    margin-bottom: 0.5rem;
    font-size: 0.85rem;
}

/* Knapperne må gerne bryde indbyrdes og lægge sig under titlen, når der er
   mange af dem. De holder sammen som gruppe, så «Indstillinger» ikke ender
   alene på en linje for sig. */
.notif__handlinger {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem 0.6rem;
    min-width: 0;
}

/* Bootstrap giver link-knapper en linjehøjde beregnet til en knaprække. Her står
   de som tekst blandt tekst, og uden dette bliver de ombrudte linjer for luftige. */
.notif__handlinger .btn-link {
    line-height: 1.3;
    white-space: nowrap;
}

.notif__item {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.55rem 0.4rem;
    border-radius: 8px;
    cursor: pointer;
    font-size: 0.85rem;
}

.notif__tekst { flex: 1; min-width: 0; }

/* Fjern-krydset. Dæmpet indtil man er ved rækken — det skal kunne findes, men ikke
   konkurrere med selve beskeden om opmærksomheden. */
.notif__ryd {
    flex-shrink: 0;
    border: 0;
    background: none;
    color: var(--faint);
    font-size: 1.15rem;
    line-height: 1;
    padding: 0.15rem 0.3rem;
    border-radius: 6px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.12s, color 0.12s, background 0.12s;
}

.notif__item:hover .notif__ryd,
.notif__ryd:focus-visible { opacity: 1; }

.notif__ryd:hover { color: var(--crit-ink); background: var(--crit-bg); }

/* Touch har ingen hover. Var krydset kun synligt ved musen over, kunne man ikke
   fjerne noget på en telefon overhovedet. */
@media (hover: none) {
    .notif__ryd { opacity: 1; padding: 0.4rem 0.55rem; }
}

.notif__item:hover { background: rgba(60, 110, 180, 0.08); }

.notif__item--unread { font-weight: 700; background: rgba(60, 110, 180, 0.06); }

/* Mobil: bundark i stedet for et hængende panel.
   Panelet var forankret til klokkens højrekant med en fast bredde på 340 px, og klokken
   sidder inde midt i topbaren. Målt ved 375 px lå 109 px uden for skærmen til venstre —
   en tredjedel af hver overskrift var klippet af, så man kunne læse «68.1.50 er oppe
   igen» uden at vide hvilken enhed det var.

   En bundark kan ikke løbe ud over kanten, uanset hvor klokken sidder, og den kræver
   ikke at vi kender topbarens højde — den ændrer sig med safe-area og brugerens
   tekststørrelse. Den ligger samtidig, hvor tommelfingeren er. */
@media (max-width: 700px) {
    .notif__panel {
        position: fixed;
        top: auto;
        right: 0;
        bottom: 0;
        left: 0;
        width: auto;
        max-height: 70vh;
        border-radius: var(--r-lg) var(--r-lg) 0 0;
        padding: 0.9rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
        box-shadow: 0 -12px 32px rgba(19, 28, 40, 0.22);
    }

    .notif__head { font-size: 0.95rem; padding-bottom: 0.35rem; }

    /* Trykmål frem for musemål. */
    .notif__item { padding: 0.8rem 0.5rem; font-size: 0.9rem; }
}

.qte {
    position: fixed;
    z-index: 951;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(520px, calc(100vw - 2rem));
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
    background: var(--paper);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--line);
}

.qte__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 1.35rem 1.5rem 0.9rem;
    border-bottom: 1px solid var(--line);
}

.qte__close {
    border: 0;
    background: none;
    font-size: 1.6rem;
    line-height: 1;
    color: var(--faint);
    cursor: pointer;
    padding: 0 0.25rem;
}

.qte__close:hover { color: var(--ink); }

.qte__body { padding: 1.25rem 1.5rem; display: flex; flex-direction: column; gap: 1rem; }

.qte__row { display: flex; flex-direction: column; gap: 0.35rem; }

.qte__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.9rem; }

/* På en telefon er to kolonner for smalt til datovælger + Område/Type-selects — de blev
   klemt til ~157 px hver. Fald til én kolonne, som alle de andre grids i filen gør. */
@media (max-width: 640px) {
    .qte__grid { grid-template-columns: 1fr; }
}

.qte__grid > div { display: flex; flex-direction: column; gap: 0.35rem; }

/* .preset-row/.preset er den generelle udgave. .qte__* er den oprindelige fra hurtig
   tidsregistrering og deler reglerne, så de to sæt ikke kan komme til at se forskellige ud. */
.qte__presets, .preset-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin-top: -0.4rem;
}

.qte__preset, .preset {
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    border: 1px solid var(--line-2);
    background: var(--paper);
    color: var(--ink-2);
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

.qte__preset:hover, .preset:hover { border-color: var(--blue-400); color: var(--ink); }

.qte__preset--active, .qte__preset--active:hover,
.preset--on, .preset--on:hover {
    background: var(--navy-800);
    border-color: var(--navy-800);
    color: #fff;
}

/* Målerække der kan klikkes for at se forløbet. Skal se ud som de øvrige rækker —
   knappen er en affordance, ikke et nyt formsprog. */
/* A metric row is a <button> (click for the trend). Reset the browser's default button
   chrome — the grey fill + border made the rows look like foreign boxes glued onto the
   card — down to a clean, subtle row that matches the plain rows above it, with only a
   soft hover to say it is clickable. */
.dcheck--btn {
    font: inherit;
    text-align: left;
    cursor: pointer;
    background: transparent;
    border: 0;
    border-radius: 7px;
    padding: 0.3rem 0.4rem;
    width: 100%;
    color: inherit;
    transition: background 0.12s ease;
}

.dcheck--btn:disabled { cursor: default; }

.dcheck--btn:not(:disabled):hover { background: rgba(127, 127, 127, 0.10); }

.dcheck--btn:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 1px;
}

/* Push the value (and its bar) to the right edge, so the rows read "name … value" like
   the plain rows, instead of the value crowding up against the name. */
.dcheck--btn .dcheck__status--metric { margin-left: auto; padding-left: 0.5rem; }

/* Forløbsgraf for én måling. container-type, så højden nedenfor kan følge grafens EGEN bredde: den samme
   graf står både i fuld sidebredde og i en tredjedel, når panelerne er sat op i kolonner. */
.chart { padding: 0.5rem 0 0; container-type: inline-size; }

/* Højden følger grafens egen bredde (cqw), ikke vinduets. Kurven tegnes med preserveAspectRatio="none",
   så X og Y skalerer hver for sig: ved fast højde blev udsvingene fladere, jo bredere siden blev — og med
   vinduet som mål ville en graf i en smal spalte omvendt blive dobbelt så stejl som den samme graf i fuld
   bredde. Gulvet på 180 px er den gamle højde; loftet på 300 px er der, fordi en graf ikke skal fylde en
   halv skærm på en NOC-skærm. */
.chart svg {
    width: 100%;
    height: clamp(180px, 22cqw, 300px);
    display: block;
    overflow: visible;
}

.chart__line {
    fill: none;
    stroke: var(--series-now);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    /* Uden dette skaleres stregtykkelsen med viewBox og bliver tynd på brede skærme. */
    vector-effect: non-scaling-stroke;
}

/* Prikkerne er nul-lange stier med rund ende, ikke cirkler: SVG'en strækkes (preserveAspectRatio none), og en
   cirkel blev en ellipse, så snart grafen var smallere end sin viewBox. En streg med non-scaling-stroke er rund
   uanset bredden. */
.chart__dot,
.chart__pt {
    fill: none;
    stroke: var(--series-now);
    stroke-width: 7;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.chart__pt { stroke-width: 5; }
.chart__dot--prev, .chart__pt--prev { stroke: var(--series-prev); }
.chart__dot--in, .chart__pt--in { stroke: var(--series-in); }
.chart__dot--out, .chart__pt--out { stroke: var(--series-out); }

.chart__limit {
    stroke-width: 1;
    stroke-dasharray: 5 4;
    vector-effect: non-scaling-stroke;
}

.chart__limit--warn { stroke: var(--warn); }
.chart__limit--crit { stroke: var(--crit); }

.chart__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
    margin-top: 0.9rem;
    padding-top: 0.8rem;
    border-top: 1px solid var(--line);
    font-size: 0.8rem;
    color: var(--ink-2);
}

.chart__key::before {
    content: "";
    display: inline-block;
    width: 14px;
    height: 0;
    margin-right: 0.4rem;
    vertical-align: middle;
    border-top: 2px dashed currentColor;
}

.chart__key--warn { color: var(--warn); }
.chart__key--crit { color: var(--crit); }

/* Søgetal (/admin/soegetal): perioden før som en stiplet, dæmpet linje under den fulde — dag mod dag. Nøglerne
   i forklaringen tegner de to linjer, så ingen skal gætte, hvilken der er hvilken. */
.chart__line--prev {
    stroke: var(--series-prev);
    stroke-width: 1.5;
    stroke-dasharray: 5 4;
}

.chart__key--now { color: var(--series-now); }
.chart__key--now::before { border-top-style: solid; }
.chart__key--prev { color: var(--series-prev); }

/* Søjler (logins pr. dag på Demo-interesse). */
.chart__bar { fill: var(--blue-400); }

/* De to retninger på et netværkskort (live-båndbredde). */
.chart__line--in { stroke: var(--series-in); }
.chart__line--out { stroke: var(--series-out); }
.chart__key--in { color: var(--series-in); }
.chart__key--out { color: var(--series-out); }
.chart__key--in::before,
.chart__key--out::before { border-top-style: solid; }

/* ── Akserne (TrendChart.razor) ─────────────────────────────────────────────────────────────
   KC 2/10: «Der mangler noget x/y-akse-skala samt at når man hovrer med musen over, så skal den vise data.»
   SVG'en strækkes til sin spalte (preserveAspectRatio none), så ingen tekst kan stå inde i den uden at blive
   strakt med. Etiketterne er derfor HTML rundt om: tallene i en spalte til venstre, datoerne under, begge placeret
   i procent af de samme koordinater, som stregerne bruger. Spalten til venstre er præcis så bred som den længste
   etiket (en usynlig kopi af den bestemmer bredden). */
.chart__frame {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 0.45rem;
}

.chart__y {
    position: relative;
    font-size: 0.7rem;
    line-height: 1;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.chart__y-sizer {
    display: block;
    height: 0;
    overflow: hidden;
    visibility: hidden;
    white-space: nowrap;
}

.chart__y-mrk {
    position: absolute;
    right: 0;
    transform: translateY(-50%);
    white-space: nowrap;
}

.chart__x {
    grid-column: 2;
    position: relative;
    height: 1.1rem;
    margin-top: 0.3rem;
    font-size: 0.7rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.chart__x-mrk {
    position: absolute;
    top: 0;
    white-space: nowrap;
    transform: translateX(-50%);
}

/* Ved kanten holdes etiketten inde i grafen i stedet for at blive centreret ud over den (ChartAxes.AlignOn). */
.chart__x-mrk--start { transform: none; }
.chart__x-mrk--end { transform: translateX(-100%); }

/* På en smal graf (en telefon, eller et kort i en smal spalte) vises kun hvert n'te mærke — ChartAxes regner ud,
   hvilke der er plads til i den smalleste graf ved 375 px (live-kortet, 281 px), med værdisøjlens egen bredde
   trukket fra. Gitterlinjerne bliver stående. En etiket, telefonen viser anderledes (med årstallet, som naboen
   bar på den brede graf, eller holdt inde ved kanten), er to spans: --wide på den brede, --phone på den smalle. */
.chart__x-mrk--phone { display: none; }

@container (max-width: 519px) {
    .chart__x-mrk--wide { display: none; }
    .chart__x-mrk--phone { display: block; }
}

/* Grafen kan nås med tabulatortasten; piletasterne aflæser punkterne (graf.js). */
.chart svg:focus { outline: none; }
.chart svg:focus-visible {
    outline: 2px solid var(--blue-500);
    outline-offset: 3px;
    border-radius: 2px;
}

/* Live-panelernes graf sidder i et kort: lavere, og falmet når strømmen er gået i stå. */
.chart--compact { padding-top: 0.2rem; }
.chart--compact svg { height: 84px; }
.chart--compact .chart__legend { margin-top: 0.4rem; padding-top: 0.4rem; }
.chart--dim svg { opacity: 0.35; }

/* Søgetal: mulighedslisterne og editorens boks. Lange søgninger og adresser brydes, så intet skubber siden bred på en
   telefon. */
.gsc-opps__title { font-weight: 700; font-size: 0.9rem; color: var(--ink); margin-bottom: 0.5rem; }
.gsc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.gsc-list li { padding-bottom: 0.6rem; border-bottom: 1px solid var(--line); min-width: 0; }
.gsc-list li:last-child { border-bottom: 0; padding-bottom: 0; }
.gsc-list__what { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.gsc-list__meta { font-size: 0.8rem; color: var(--ink-2); overflow-wrap: anywhere; }
.gsc-box__stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.75rem; }
.gsc-box__value { font-size: 1.25rem; font-weight: 700; color: var(--ink); }
.gsc-box-hint { margin: 0 0 0.25rem; }
@media (max-width: 575.98px) {
    .gsc-box__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Skal sætte width — ikke kun max-width — for base-.dlg låser width til min(560px,…),
   så en ren max-width aldrig kunne udvide dialogen (Noc-metrikdialogen stod 160px for smal). */
.dlg--wide { width: min(720px, calc(100vw - 2rem)); }

/* Hændelsesforløb: ét kort pr. hændelse med spor nedenunder. */
.inc {
    padding: 1rem 1.25rem;
    border-top: 1px solid var(--line);
    border-left: 3px solid var(--line-2);
}

/* Kunden på en hændelse. Dæmpet — enhedens navn er stadig overskriften; kunden er
   den oplysning, man skal bruge for at vide, hvem man ringer til. */
.inc__kunde {
    margin-left: 0.5rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--muted);
}

.inc--crit { border-left-color: var(--crit); }
.inc--warn { border-left-color: var(--warn); }

.inc__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    flex-wrap: wrap;
}

.inc__name { font-weight: 700; display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.inc__sub { font-size: 0.82rem; color: var(--ink-2); margin-top: 0.15rem; }
.inc__actions { display: flex; gap: 0.4rem; flex-shrink: 0; }

.inc__tag {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    background: var(--line-2);
    color: var(--ink-2);
}

.inc__tag--ok { background: var(--good); color: #fff; }

/* Sporet. Tallene til venstre gør det læsbart som et forløb frem for en punktliste. */
.inc__trail {
    list-style: none;
    margin: 0.85rem 0 0;
    padding: 0.75rem 0 0;
    border-top: 1px dashed var(--line);
    font-size: 0.82rem;
    color: var(--ink-2);
}

.inc__trail li { display: flex; gap: 0.6rem; padding: 0.15rem 0; }

.inc__time {
    font-variant-numeric: tabular-nums;
    color: var(--ink-3, var(--ink-2));
    flex-shrink: 0;
    min-width: 3.2rem;
}

.inc__by { opacity: 0.75; font-style: italic; }

/* Lille bjælke ved en procentmåling — toner, batteri. Kun visuel: tallet står ved siden
   af, så bjælken behøver ikke kunne aflæses præcist. */
.metric-bar {
    display: inline-block;
    width: 44px;
    height: 5px;
    border-radius: 999px;
    background: var(--line-2);
    overflow: hidden;
    vertical-align: middle;
    margin-left: 0.15rem;
}

.metric-bar__fill {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: currentColor;
    opacity: 0.75;
}

/* Afsnitsoverskrift inde i en dialog. Uden den bliver en lang formular til én
   uafbrudt væg af felter, hvor man ikke kan se hvad der hører sammen. */
.dlg__sect {
    margin: 1.5rem 0 0.85rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--line);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-2);
}

.qte__check {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--line-2);
    border-radius: var(--r-sm);
    cursor: pointer;
    font-size: 0.88rem;
}

.qte__check span { display: flex; flex-direction: column; }

.qte__foot {
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    padding: 1rem 1.5rem 1.35rem;
    border-top: 1px solid var(--line);
}

kbd {
    background: var(--blue-50);
    border: 1px solid var(--line-2);
    border-radius: 5px;
    padding: 0.1rem 0.4rem;
    font-size: 0.78rem;
    font-family: inherit;
    font-weight: 700;
    color: var(--ink-2);
}

/* ==========================================================================
   Generisk modal/dialog (opret/rediger-formularer på tværs af siderne)
   ========================================================================== */

.dlg__backdrop {
    position: fixed;
    inset: 0;
    z-index: 950;
    background: rgba(19, 28, 40, 0.42);
    backdrop-filter: blur(2px);
}

.dlg {
    position: fixed;
    z-index: 951;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(560px, calc(100vw - 2rem));
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
    overflow-x: hidden;
    background: var(--paper);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-lg);
    border: 1px solid var(--line);
    /* .dlg er "position: fixed", men er stadig et DOM-barn af hvor <Modal> bliver brugt — fx en
       tabelcelle med "white-space: nowrap" til handlingsknapper. Uden dette arver dialogen den
       nowrap uanset at den visuelt er løsrevet fra tabellen, og teksten scroller i stedet for at ombryde. */
    white-space: normal;
}

.dlg--lg { width: min(860px, calc(100vw - 2rem)); }

.dlg__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    padding: 1.35rem 1.5rem 0.9rem;
    border-bottom: 1px solid var(--line);
    position: sticky;
    top: 0;
    background: var(--paper);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
}

.dlg__close {
    border: 0;
    background: none;
    font-size: 1.6rem;
    line-height: 1;
    color: var(--faint);
    cursor: pointer;
    padding: 0 0.25rem;
}

.dlg__close:hover { color: var(--ink); }

.dlg__body { padding: 1.25rem 1.5rem; overflow-wrap: break-word; }

/* Fodrækken i en modal — knapperne.
   Den ligger inde i .dlg__body, fordi submit-knapper skal være inde i <EditForm>.
   Derfor sticky mod bunden af selve dialogen, som er det element, der scroller:
   uden det lå Gem og Annullér 192 px under folden på en telefon i «Opret aftale»,
   og man skulle scrolle for at finde ud af, at man overhovedet kunne gemme.

   De negative margener trækker rækken ud over kroppens vandrette luft, så stregen
   går fra kant til kant og baggrunden dækker det, der scroller under den. */
.dlg__foot {
    position: sticky;
    bottom: 0;
    z-index: 1;
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    margin: 1.25rem -1.5rem -1.25rem;
    padding: 1rem 1.5rem 1.25rem;
    border-top: 1px solid var(--line);
    background: var(--paper);
}

/* ==========================================================================
   Kommandopaletten (⌘K / Ctrl+K) — en launcher over hele appen.
   Token-drevet hele vejen, så den følger et kommende mørkt tema af sig selv.
   ========================================================================== */

/* Altid-synligt indgangspunkt: en flydende pille, der ligger lige over
   hjørneknappen (tid/opret sag), så genvejen kan opdages uden at kende den. */
.cmdhint {
    position: fixed;
    right: 1.5rem;
    bottom: calc(1.5rem + 3.6rem);
    z-index: 899;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.85rem;
    border: 1px solid var(--line-2);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink-2);
    font-size: 0.85rem;
    font-weight: 600;
    box-shadow: var(--shadow-md);
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, transform 0.15s, box-shadow 0.15s;
}

.cmdhint:hover {
    color: var(--ink);
    border-color: var(--blue-400);
    transform: translateY(-1px);
    box-shadow: var(--shadow-lg);
}

.cmdhint__kbd {
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--faint);
    background: var(--shell);
    border: 1px solid var(--line);
    border-radius: 6px;
    padding: 0.05rem 0.4rem;
}

.cmd__backdrop {
    position: fixed;
    inset: 0;
    z-index: 970;
    background: rgba(19, 28, 40, 0.46);
    backdrop-filter: blur(2px);
}

.cmd {
    position: fixed;
    z-index: 971;
    top: 10vh;
    left: 50%;
    transform: translateX(-50%);
    width: min(640px, calc(100vw - 2rem));
    max-height: min(72vh, calc(100vh - 4rem));
    display: flex;
    flex-direction: column;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

.cmd__search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.9rem 1.1rem;
    border-bottom: 1px solid var(--line);
    color: var(--muted);
    flex: 0 0 auto;
}

.cmd__input {
    flex: 1 1 auto;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--ink);
    font-size: 1.05rem;
    font-weight: 500;
    padding: 0.15rem 0;
}

.cmd__input::placeholder { color: var(--faint); font-weight: 400; }

.cmd__x {
    border: 0;
    background: none;
    font-size: 1.5rem;
    line-height: 1;
    color: var(--faint);
    cursor: pointer;
    padding: 0 0.2rem;
}

.cmd__x:hover { color: var(--ink); }

.cmd__results {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 0.5rem 0.55rem 0.7rem;
}

.cmd__group { padding: 0.35rem 0 0.15rem; }

.cmd__grouphead {
    padding: 0.35rem 0.6rem 0.3rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--faint);
}

.cmd__row {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.5rem 0.6rem;
    border-radius: var(--r-md, 10px);
    text-decoration: none;
    color: var(--ink);
    scroll-margin: 0.5rem;
}

/* Markering (pil op/ned) og musehover ser ens ud, så tastatur og mus peger på det
   samme sted. Markeringen sættes fra JS (palette.js), hover fra browseren. */
.cmd__row--active,
.cmd__row:hover {
    background: var(--blue-50);
}

.cmd__row--active .cmd__ico,
.cmd__row:hover .cmd__ico { color: var(--brand); }

.cmd__ico {
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--muted);
}

.cmd__main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.cmd__label {
    font-size: 0.92rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cmd__sub {
    font-size: 0.78rem;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cmd__note {
    padding: 0.9rem 0.7rem;
    font-size: 0.88rem;
    color: var(--ink-2);
}

.cmd__note--muted { color: var(--muted); }

.cmd__foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.55rem 1rem;
    border-top: 1px solid var(--line);
    background: var(--shell);
    font-size: 0.75rem;
    color: var(--muted);
}

.cmd__tip { display: inline-flex; align-items: center; gap: 0.3rem; }

.cmd__foot kbd {
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--ink-2);
    background: var(--paper);
    border: 1px solid var(--line-2);
    border-radius: 5px;
    padding: 0.02rem 0.35rem;
    min-width: 1.1rem;
    text-align: center;
}

@media (max-width: 640px) {
    /* På en telefon fylder pillen for meget — vis kun ikonet, som en lille FAB
       lige over hjørneknappen. */
    .cmdhint {
        right: 0.9rem;
        bottom: calc(0.9rem + 3.2rem);
        padding: 0.6rem;
    }
    .cmdhint__txt, .cmdhint__kbd { display: none; }

    .cmd {
        top: 4vh;
        width: calc(100vw - 1.2rem);
        max-height: calc(100vh - 6vh);
    }

    /* Foden med tastatur-hints er ligegyldig uden et tastatur. */
    .cmd__foot { display: none; }
}

/* ==========================================================================
   Chart (Dmarc pass/fail)
   ========================================================================== */

/* Bar-chart-legenden (Dmarc). Egen klasse — den delte .chart__legend ovenfor er linje-grafens,
   og et fælles navn fik de to til at overskrive hinandens gap/farve/kant på kryds. */
.chart__legend--bars {
    display: flex;
    gap: 1.2rem;
    margin-bottom: 1.1rem;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--muted);
}

.chart__legend--bars i {
    width: 10px; height: 10px; border-radius: 3px;
    display: inline-block; margin-right: 0.4rem;
}

.chart__row {
    display: grid;
    grid-template-columns: 6rem 1fr 9.5rem;
    align-items: center;
    gap: 0.9rem;
    padding: 0.35rem 0;
    font-size: 0.85rem;
}

.chart__label { color: var(--ink-2); font-weight: 700; white-space: nowrap; }

.chart__track {
    height: 14px;
    display: flex;
    gap: 2px;
    border-radius: 5px;
    overflow: hidden;
    background: var(--blue-50);
}

.chart__seg { height: 100%; min-width: 3px; }
.chart__seg--good { background: var(--good); }
.chart__seg--crit { background: var(--crit); }

.chart__val {
    color: var(--faint);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
}

.empty {
    padding: 1.75rem 0;
    text-align: center;
    color: var(--faint);
    font-size: 0.9rem;
}

/* Den todelte tomme tilstand: en linje der siger hvad der mangler, og en der siger
   hvad man kan gøre. Begge klasser stod 17 steder uden at være skrevet, så de to
   linjer fik samme størrelse og samme farve — og så var opdelingen usynlig. */
/* De to linjer står centreret i et tomt panel. Uden et loft strækker de sig over hele rammen på en bred
   skærm, og så læser man en enkelt sætning på tværs af halvanden meter skærm. */
.empty__title {
    color: var(--ink-2);
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 0.35rem;
    max-width: 60ch;
    margin-inline: auto;
}

.empty__text {
    color: var(--faint);
    font-size: 0.88rem;
    line-height: 1.6;
    max-width: 60ch;
    margin-inline: auto;
}

/* ==========================================================================
   Bootstrap-komponenter i vores sprog
   ========================================================================== */

.btn {
    font-weight: 600;
    border-radius: var(--r-btn);
    padding: 0.55rem 1.25rem;
    font-size: 0.88rem;
    transition: background 0.13s ease, border-color 0.13s ease, color 0.13s ease;
}

.btn-primary {
    background: var(--navy-800);
    border-color: var(--navy-800);
    color: #fff;
}

/* Ingen løft ved hover.
   translateY(-1px) + voksende skygge fik knappen til at hoppe, og på en side, der opdaterer sig
   selv, er hver bevægelse noget, øjet skal bortse fra. Farven alene er svar nok.
   :focus-visible, not :focus: a clicked button no longer keeps the dark colour after the mouse has
   gone. It stays for the keyboard, or Bootstrap's own .btn:focus-visible would paint #0b5ed7. */
.btn-primary:hover, .btn-primary:focus-visible {
    background: var(--navy-950);
    border-color: var(--navy-950);
    color: #fff;
}

/* A disabled button keeps the house palette and is only dimmed (Bootstrap's own opacity).
   Without this, Bootstrap's .btn:disabled — more specific than the rules above — painted every disabled primary
   button in its default bright blue, so a button that could not be pressed stood out more than one that could. */
.btn-primary:disabled, .btn-primary.disabled, fieldset:disabled .btn-primary {
    background: var(--navy-800);
    border-color: var(--navy-800);
    color: #fff;
}

.btn-outline-primary:disabled, .btn-outline-primary.disabled, fieldset:disabled .btn-outline-primary,
.btn-outline-secondary:disabled, .btn-outline-secondary.disabled, fieldset:disabled .btn-outline-secondary {
    background: var(--paper);
    border-color: var(--line-2);
    color: var(--navy-800);
}

.btn-outline-primary, .btn-outline-secondary {
    background: var(--paper);
    border-color: var(--line-2);
    color: var(--navy-800);
}

.btn-outline-primary:hover, .btn-outline-secondary:hover {
    background: var(--blue-50);
    border-color: var(--blue-300);
    color: var(--navy-950);
}

.btn-sm {
    padding: 0.32rem 0.85rem;
    font-size: 0.79rem;
    white-space: nowrap;
}

.btn-link { font-weight: 700; text-decoration: none; }

/* Trykmål på touch.
   btn-sm er 31 px høj, og målingsrækkerne 30 — fint med en musemarkør, for lidt med en
   tommelfinger. Både Apple og Google anbefaler mindst 44 px, og på Driftsovervågning stod
   der 44 elementer under grænsen på ét kort: Tjek nu, Rediger, Slet og hver enkelt måling.

   pointer: coarse rammer rigtige touch-enheder uanset skærmbredde, og max-width tager
   det smalle vindue på en bærbar. Bredden røres ikke — kun højden, så knapperne ikke
   pludselig fylder linjen op. */
@media (max-width: 720px), (pointer: coarse) {
    .btn-sm {
        min-height: 44px;
        padding-top: 0.6rem;
        padding-bottom: 0.6rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    .btn { min-height: 44px; }

    /* Målingsrækken er også en knap — den åbner forløbet. */
    .dcheck--btn { min-height: 44px; }

    /* Luft mellem knapper, så man ikke rammer naboen. */
    .dcard__actions { gap: 0.55rem; }

    /* Bare tekstlinks i tabelceller — typisk "Åbn" — er 25x16 px. Trykfeltet udvides
       med polstring, og den negative margen trækker layoutet tilbage på plads, så
       rækkerne ikke bliver høje af det. Man rammer altså et større felt end det,
       man kan se, hvilket er præcis meningen. */
    .table td a:not(.btn) {
        display: inline-block;
        padding: 0.75rem 0.6rem;
        margin: -0.75rem -0.6rem;
    }

    /* Filterchips — sagsfiltre og gruppefiltre — står på 32 px. De er blandt de
       hyppigst trykkede elementer på siden og skal derfor være blandt de nemmeste
       at ramme, ikke de sværeste. */
    .tkt-chip,
    .gchip {
        min-height: 44px;
        padding-top: 0.6rem;
        padding-bottom: 0.6rem;
    }
}

/* Fields may show their focus on a click: it tells where you type. The transparent outline is
   invisible in normal colours and becomes a real ring in forced colours (Windows contrast themes),
   where the box-shadow is dropped.
   Checkboxes, radios and switches are not fields: after a click they keep no glow, no Bootstrap blue
   border and no blue knob. Buttons and checks get their ring from :focus-visible in the keyboard
   section at the end (.btn:focus-visible, .form-check-input:focus-visible). The rules after this one
   (.form-check-input:checked, .darker-border-checkbox) still win on the border. */
.form-control:focus, .form-select:focus {
    box-shadow: 0 0 0 3px rgba(92, 127, 168, 0.25);
    outline: 2px solid transparent;
}

.form-check-input:focus { border-color: var(--bs-border-color); box-shadow: none; }

.form-switch .form-check-input:focus:not(:checked) {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");
}

/* No ring on a clicked button, and no Bootstrap focus shadow at all; the keyboard ring is an outline
   (.btn:focus-visible at the end). Before 6 October 2026 this said `.btn:focus { outline: none }`,
   which also beat the keyboard ring: no .btn in the platform showed one. */
.btn:focus, .btn:active:focus { box-shadow: none; }
.btn:focus:not(:focus-visible) { outline: none; }
/* Bootstrap draws the glow again on a chosen, open or pressed button, at (0,3,0)-(0,4,0) - above the rule before: a
   grey 4px glow round a clicked period button (Servicerapport) after any key, and on top of the ring for Tab. */
.btn-check:checked + .btn:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible,
.btn:first-child:active:focus-visible, :not(.btn-check) + .btn:active:focus-visible { box-shadow: none; }

.form-control, .form-select {
    /* background-COLOR, not the background shorthand. The shorthand resets background-image, and that
       is where Bootstrap draws the chevron on a <select> — so every dropdown in the platform lost its
       arrow and read as a text field. The house already knows this trap; it is written out at the
       .spark__bar--blip rule, where the same shorthand erased a hatch pattern. */
    background-color: var(--paper);
    border: 1px solid var(--line-2);
    border-radius: var(--r-sm);
    color: var(--ink);
    padding: 0.55rem 0.85rem;
    font-size: 0.9rem;
}

/* Room for the chevron, so a long option does not run underneath it. */
.form-select { padding-right: 2.25rem; }

/* The -sm variants were dead. app.css loads AFTER bootstrap (App.razor) and the rule above wins on
   equal specificity, so every .form-control-sm in the platform rendered at full size — the ticket
   queue asks for five of them. Restated here, after the rule that was overriding them. */
.form-control-sm, .form-select-sm {
    padding: 0.3rem 0.6rem;
    font-size: 0.82rem;
}

.form-select-sm { padding-right: 1.9rem; }

/* A field's focus border is its keyboard cue (the outline is transparent): --focus-ring, so it holds 3:1 against the
   surface (--blue-400 was 2.87:1 on paper; KC, 6 October 2026). */
.form-control:focus, .form-select:focus { border-color: var(--focus-ring); }
.form-control::placeholder { color: var(--faint); }

/* A disabled or read-only field (e.g. a closed ticket's Status/Priority/Kunde) must stay READABLE. Bootstrap's
   :disabled reverts the background to a light colour, which hides our light text on the dark theme — so the value
   vanished. Keep our own tokens and just dim it to signal it cannot be edited. -webkit-text-fill-color stops
   WebKit from greying out the disabled text on top of that. */
.form-control:disabled, .form-select:disabled,
.form-control[readonly], .form-select[readonly] {
    background-color: var(--paper);
    color: var(--ink);
    -webkit-text-fill-color: var(--ink);
    opacity: 0.6;
    cursor: not-allowed;
}

.form-check-input:checked { background-color: var(--navy-700); border-color: var(--navy-700); }

/* .tbl, .tbl-wrap og .num står som aliasser og ikke som egne regler.
   Femten tabeller rundt om i løsningen bruger de korte navne, men de blev aldrig
   skrevet — så de tabeller stod uden .table-wrap'ens overflow-x og gled hele siden
   sidelæns på en telefon. Aliasser frem for at omdøbe femten steder: én rettelse, og
   ingen af de femten kan glemmes. */
.table,
.tbl {
    --bs-table-bg: transparent;
    --bs-table-color: var(--ink);
    --bs-table-border-color: var(--line);
    --bs-table-hover-bg: var(--blue-50);
    margin: 0;
    vertical-align: middle;
    font-size: 0.89rem;

    /* Bredden kom fra Bootstraps egen .table-regel, som .tbl ikke står i — så de
       femten .tbl-tabeller krympede til indholdsbredde og lå smalt i et bredt panel,
       synligt anderledes end de ~20 .table-tabeller ved siden af. */
    width: 100%;
}

/* Reboot nulstiller cellernes border-width til 0, og den eneste regel, der giver dem
   bredde igen, er Bootstraps '.table > :not(caption) > * > *' — som .tbl heller ikke
   står i. Rækkerne løb derfor sammen uden stregar, selv om .tbl tbody td satte en
   border-color. Beviset for at det ikke var meningen stod på næste regel: en
   sidste-række-undtagelse, der fjernede en kant, som aldrig blev tegnet. */
.tbl > :not(caption) > * > * { border-bottom-width: var(--bs-border-width, 1px); }

/* Taljusteret højrestilling. Tal, der skal sammenlignes lodret, skal stå på samme
   cifferbredde — ellers hopper kolonnen, og man kan ikke se hvilket tal der er størst. */
.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.table thead th,
.tbl thead th {
    color: var(--muted);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--line);
    padding: 0.7rem 0.9rem;
    white-space: nowrap;
}

.table tbody td,
.tbl tbody td { padding: 0.8rem 0.9rem; border-color: var(--line); }

/* A group's heading row inside one table (the finance queue by kind, 24 October 2026): the rows under it until the next. */
.tbl tbody th.tbl__group {
    padding: 0.9rem 0.9rem 0.4rem;
    font-size: 0.85rem;
    font-weight: 700;
    text-align: left;
    color: var(--ink);
    background: var(--surface-2, rgba(0, 0, 0, 0.03));
}

.tbl__group-count { margin-left: 0.4rem; font-weight: 400; color: var(--muted); }
.table tbody tr:last-child td,
.tbl tbody tr:last-child td { border-bottom: 0; }

/* Sorterbar kolonneoverskrift.
   En rigtig <button> og ikke et klikbart <th>: så kan man tabbe hen til den og
   trykke mellemrum, og en skærmlæser fortæller af sig selv, at den kan aktiveres. */
.th-sort {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    color: inherit;
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
}

/* Samme fejl som .gchip ovenfor: hverken --fg eller --accent er erklæret, så
   overskriften skiftede ikke farve ved hover, den aktive sorteringskolonne kunne
   ikke skelnes fra de øvrige, og der var ingen fokusring at tabbe efter. */
.th-sort:hover { color: var(--ink); }
.th-sort:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; border-radius: 3px; }

.th-sort.aktiv { color: var(--ink); }

.table-wrap,
.tbl-wrap { overflow-x: auto; max-width: 100%; border-radius: var(--r-lg); }

/* Lange tekniske værdier (DNS-records o.l.) må ikke sprænge tabelbredden */
.truncate {
    display: block;
    max-width: 13rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* stat__meta bruges også som sekundærlinje i tabelceller */
td .stat__meta { display: block; margin-top: 0.2rem; }

.badge {
    border-radius: 999px;
    font-weight: 800;
    font-size: 0.68rem;
    letter-spacing: 0.05em;
    padding: 0.36em 0.72em;
    border: 1px solid transparent;
}

/* Badges får samme behandling som .pil: lys baggrund og en mørknet tekstfarve.
   Hvid tekst på accentfarverne holdt ikke WCAG AA ved 0,68 rem — hvid på --warn giver
   3,60:1, på --good 4,20:1 og på --muted 4,44:1, hvor kravet er 4,50. Kun bg-danger
   klarede den. Det ene sted, nogen havde forsøgt at rette det med .text-dark, kunne
   ikke virke: .text-dark er (0,1,0) mod .badge.bg-warning (0,2,0), og begge sætter
   !important, så teksten blev hvid alligevel. Badges står bl.a. på den offentlige
   statusside, hvor de er det, en kunde læser først.

   --good-ink / --warn-ink / --crit-ink er de samme efterprøvede værdier som .pil
   bruger; de er regnet igennem i tests/kontrastcheck. */
.badge.bg-success {
    background: var(--good-bg) !important;
    color: var(--good-ink) !important;
    border-color: color-mix(in srgb, var(--good) 28%, transparent) !important;
}

.badge.bg-warning {
    background: var(--warn-bg) !important;
    color: var(--warn-ink) !important;
    border-color: color-mix(in srgb, var(--warn) 30%, transparent) !important;
}

.badge.bg-danger {
    background: var(--crit-bg) !important;
    color: var(--crit-ink) !important;
    border-color: color-mix(in srgb, var(--crit) 30%, transparent) !important;
}

.badge.bg-secondary {
    background: color-mix(in srgb, var(--ink) 6%, transparent) !important;
    color: var(--ink-2) !important;
    border-color: color-mix(in srgb, var(--ink) 14%, transparent) !important;
}

/* Bootstraps egen bg-primary er solid og hvid — den ville stå tilbage som det eneste
   fyldte mærke mellem lutter lyse. */
.badge.bg-primary {
    background: var(--blue-100) !important;
    color: var(--navy-800) !important;
    border-color: color-mix(in srgb, var(--navy-600) 25%, transparent) !important;
}

/* bg-info og bg-dark manglede samme behandling som resten — de faldt tilbage på Bootstraps
   mættede cyan/næsten-sort fyld, som hverken er efterprøvet mod WCAG eller passer paletten.
   «Kundevendt»-mærket (info) og «Arkiveret»-mærket (dark) i Vidensbasen bruger dem. */
.badge.bg-info {
    background: var(--blue-50) !important;
    color: var(--navy-700) !important;
    border-color: color-mix(in srgb, var(--blue-400) 34%, transparent) !important;
}

.badge.bg-dark {
    background: color-mix(in srgb, var(--ink) 10%, transparent) !important;
    color: var(--ink) !important;
    border-color: color-mix(in srgb, var(--ink) 22%, transparent) !important;
}

.alert {
    border-radius: var(--r-md);
    border-width: 1px;
    font-size: 0.9rem;
    padding: 0.85rem 1.1rem;
}

/* Kompakt variant — erstatter de per-side inline padding/font-size-overrides på små infobjælker. */
.alert--sm { padding: 0.5rem 0.75rem; font-size: 0.82rem; }

.alert-info { background: var(--blue-50); border-color: var(--blue-200); color: var(--navy-800); }
/* A link inside an alert reads as a link: underlined, in the alert's own colour (the plain link colour is close to the
   info alert's text, light and dark). */
.alert .alert-link { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
/* Tekst- og kantfarver var hånd-plukkede hex tæt på — men ikke lig med — de efterprøvede
   *-ink-tokens. Bruger nu tokenerne + color-mix-kanter som .badge, så kontrasten er den samme
   validerede værdi ét sted. */
.alert-danger { background: var(--crit-bg); border-color: color-mix(in srgb, var(--crit) 30%, transparent); color: var(--crit-ink); }
.alert-warning { background: var(--warn-bg); border-color: color-mix(in srgb, var(--warn) 30%, transparent); color: var(--warn-ink); }
.alert-success { background: var(--good-bg); border-color: color-mix(in srgb, var(--good) 28%, transparent); color: var(--good-ink); }

.text-secondary { color: var(--muted) !important; }
.text-danger { color: var(--crit) !important; }

/* Validering / Blazor-fejl.
   Only the red frame: a field that fails validation says so. The Blazor template's green frame round
   every field you had edited (.valid.modified) is gone since 6 October 2026 - it stayed until the page
   was left and read as one more frame that would not go away. */
.invalid { outline: 1px solid var(--crit); }
.validation-message { color: var(--crit); font-size: 0.83rem; }

.blazor-error-boundary {
    background: var(--crit);
    padding: 1rem 1.25rem;
    color: #fff;
    border-radius: var(--r-md);
}

.blazor-error-boundary::after { content: "Der opstod en fejl."; }

.darker-border-checkbox.form-check-input { border-color: var(--line-2); }

/* --------------------------------------------------------------------------
   Detaljer om mailopsætning på et domænekort — dybden der før var tænkt som
   selvstændige SPF- og DKIM-moduler. Foldet sammen, så oversigten kan skimmes.
   -------------------------------------------------------------------------- */

.ddetail { margin-top: 0.9rem; border-top: 1px solid var(--line); padding-top: 0.7rem; }

.ddetail > summary {
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--blue-500);
    list-style: none;
}

.ddetail > summary::-webkit-details-marker { display: none; }
.ddetail > summary::before { content: "▸ "; }
.ddetail[open] > summary::before { content: "▾ "; }
.ddetail > summary:hover { color: var(--ink); }

.ddetail__block { margin-top: 0.9rem; }
.ddetail__block + .ddetail__block { padding-top: 0.9rem; border-top: 1px dashed var(--line); }

.ddetail__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--ink);
    margin-bottom: 0.5rem;
}

.ddetail__label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0.7rem 0 0.25rem;
}

/* --wash findes ikke i :root, og background arves ikke — feltet stod derfor helt
   gennemsigtigt, så en DNS-record lå direkte på panelet uden at se ud som en værdi,
   der kan kopieres. --blue-50 er husets lyseste flade. */
.ddetail__code {
    display: block;
    background: var(--blue-50);
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    padding: 0.55rem 0.7rem;
    font-size: 0.8rem;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    color: var(--ink-2);
    /* Lange SPF-poster og DKIM-nøgler må bryde frem for at sprænge kortet. */
    white-space: pre-wrap;
    word-break: break-all;
    margin: 0;
}

/* Udførelsesnote på en årshjuls-aktivitet — dokumentationen, ikke bare et flueben. */
.done-note {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin-top: 0.4rem;
    padding: 0.5rem 0.7rem;
    background: color-mix(in srgb, var(--good) 12%, transparent);
    border-left: 2px solid var(--good);
    border-radius: 0 var(--r-sm) var(--r-sm) 0;
    color: var(--ink-2);
}

.done-note .icon { color: var(--good); flex-shrink: 0; margin-top: 0.1rem; }

/* --------------------------------------------------------------------------
   Periodevælger — perioden skal være det første øjet fanger på en rapport,
   så man aldrig er i tvivl om, hvad tallene dækker.
   -------------------------------------------------------------------------- */

/* Loftet holder de to månedspile sammen om perioden. Uden det havner «‹» og «›» i hver sin ende af et
   panel, der nu kan være 1700 px bredt, og man skal sigte efter dem. */
.period { display: flex; align-items: center; gap: 1.2rem; max-width: 38rem; }

.period__main { flex: 1; text-align: center; }

.period__label {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
}

.period__value {
    font-size: 1.7rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--ink);
    line-height: 1.15;
    /* Måneden kommer fra ToString("MMMM") og starter med lille bogstav på dansk. */
    text-transform: capitalize;
}

.period__range { font-size: 0.85rem; color: var(--muted); margin-top: 0.15rem; }

.period__quick {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--line);
}

.period__quick .btn.active {
    background: var(--navy-800);
    border-color: var(--navy-800);
    color: #fff;
}

@media (max-width: 640px) {
    .period__value { font-size: 1.3rem; }
    .period__quick { flex-wrap: wrap; }
    .period__quick .stat__meta { margin-left: 0 !important; width: 100%; }
}

/* The service report's download menus in the page header (25 October 2026): «Hent PDF» and «CSV», each a small list of
   periods under its button, the shown month first. Built like the M365 row menu (.m365-act). */
.srep-dl { position: relative; display: inline-block; }
.srep-dl__btn { white-space: nowrap; }
.srep-dl__btn::after { content: ""; display: inline-block; margin-left: 0.35rem; vertical-align: 0.15em;
    border-left: 0.28em solid transparent; border-right: 0.28em solid transparent; border-top: 0.32em solid currentColor; }
.srep-dl__backdrop { position: fixed; inset: 0; z-index: 29; }
.srep-dl__menu {
    position: absolute; right: 0; top: calc(100% + 4px); z-index: 30;
    width: min(19rem, calc(100vw - 2rem)); padding: 0.4rem;
    background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-lg);
    text-align: left; white-space: normal;
}
.srep-dl__head { margin: 0.4rem 0.5rem 0.2rem; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.srep-dl__item {
    display: flex; justify-content: space-between; gap: 0.6rem; width: 100%; padding: 0.45rem 0.5rem; border: 0;
    border-radius: var(--r-sm); background: none; color: var(--ink); font-size: 0.88rem; text-align: left; cursor: pointer;
}
.srep-dl__item:hover, .srep-dl__item:focus-visible { background: var(--shell); }
.srep-dl__item:disabled { opacity: 0.6; cursor: default; }
.srep-dl__item--first { font-weight: 700; }
.srep-dl__when { color: var(--muted); font-weight: 400; }
.srep-dl__custom { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; padding: 0.3rem 0.5rem 0.5rem; }
.srep-dl__date { display: grid; gap: 0.15rem; font-size: 0.8rem; color: var(--ink-2); }
.srep-dl__cover { grid-column: 1 / -1; font-size: 0.8rem; color: var(--muted); }
.srep-dl__custom .btn { grid-column: 1 / -1; justify-self: start; }
.srep-dl__error { margin: 0.3rem 0.5rem; font-size: 0.84rem; color: var(--crit-ink); }
.srep-dl__hint { margin: 0.4rem 0.5rem 0.2rem; padding-top: 0.4rem; border-top: 1px solid var(--line); font-size: 0.78rem; color: var(--muted); }

/* On a phone the header's buttons are one row that scrolls sideways (.ph__actions), which would clip an open menu: while
   one is open the row stops scrolling, and the menu takes the row's width under it. */
@media (max-width: 780px) {
    .ph__actions:has(.srep-dl) { position: relative; }
    .ph__actions:has(.srep-dl__menu) { overflow: visible; }
    .srep-dl { position: static; }
    .srep-dl__menu { left: 0; right: 0; width: auto; }
}

/* --------------------------------------------------------------------------
   Vandret måler — bruges til oppetid og tidsfordeling i servicerapporten.
   -------------------------------------------------------------------------- */

.bar {
    height: 8px;
    border-radius: 4px;
    background: var(--line);
    overflow: hidden;
}

.bar__fill {
    height: 100%;
    border-radius: 4px;
    background: var(--blue-500);
    transition: width 0.3s ease;
}

/* --------------------------------------------------------------------------
   Sikkerhedsscore — cirkeldiagram tegnet med conic-gradient, så der ikke
   skal et diagrambibliotek ind for ét enkelt tal.
   -------------------------------------------------------------------------- */

.score { display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; }

.score__dial {
    width: 148px;
    height: 148px;
    border-radius: 50%;
    flex-shrink: 0;
    /* --pct sættes inline af komponenten: 0-100. */
    background: conic-gradient(var(--col) calc(var(--pct) * 1%), var(--line) 0);
    display: grid;
    place-items: center;
}

.score__inner {
    width: 116px;
    height: 116px;
    border-radius: 50%;
    background: var(--paper);
    display: grid;
    place-items: center;
    text-align: center;
    line-height: 1.1;
}

.score__num { font-size: 2.4rem; font-weight: 700; color: var(--ink); letter-spacing: -0.03em; }
.score__of { font-size: 0.78rem; color: var(--muted); }

.score__grade { font-size: 1.25rem; font-weight: 600; color: var(--ink); letter-spacing: -0.02em; }

@media (max-width: 600px) {
    .score { gap: 1.2rem; }
}

/* ---- overblik: Sikkerhedsscore ---- */
/* /modules/security-score as an overview (SecurityScoreOverview.razor + SecurityScoreList.razor, 3 October 2026): the
   status line, the shared tiles (score, biggest gain, one per area), then ONE list of every check, problems first.
   A problem keeps the whole row - badge, finding, recommendation, the accounts, what it gives - with the badge column at
   a fixed width so the titles line up; checks in order or not measured are one line each. Platform tokens only, so the
   dark theme follows. The paper is docs/arbejde/2026-10-03-overblik2-byg-score.md. */
.ss-next { font-weight: 650; letter-spacing: 0.06em; text-transform: uppercase; font-size: 0.68rem; margin-top: 0.15rem; }

.ssv__head { flex-wrap: wrap; row-gap: 0.5rem; }
.ssv__head .listnote { margin-bottom: 0; }
.ssv__grp { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.2rem 0.5rem; margin: 1.2rem 0 0.1rem; font-size: 0.68rem; font-weight: 750; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.ssv__grp b { font-variant-numeric: tabular-nums; color: var(--ink-2); letter-spacing: 0; }
.ssv__hint { text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 0.78rem; color: var(--muted); }
.ssv__rows { display: grid; gap: 0.7rem; margin-top: 0.5rem; }

.ssr {
    display: grid;
    grid-template-columns: 6.6rem minmax(0, 1fr) auto;
    gap: 0.3rem 1rem;
    align-items: start;
    padding: 0.85rem 0.95rem;
    border: 1px solid var(--line);
    border-left: 3px solid var(--warn);
    border-radius: var(--r-md);
    background: var(--paper);
}
.ssr--crit { border-left-color: var(--crit); }
.ssr__mark { justify-self: start; margin-top: 0.15rem; white-space: nowrap; }
.ssr__main { min-width: 0; }
.ssr__title { font-weight: 700; color: var(--ink); }
.ssr__area { font-size: 0.78rem; color: var(--muted); margin-top: 0.1rem; }
/* Free text in a 1fr column: without a cap the lines grow so long that the eye loses its way back. */
.ssr__finding { color: var(--ink-2); font-size: 0.88rem; margin-top: 0.4rem; line-height: 1.5; max-width: 78ch; }
.ssr__rec { color: var(--ink-2); font-size: 0.88rem; margin-top: 0.35rem; line-height: 1.5; max-width: 78ch; }
.ssr__rec strong { color: var(--ink); }
.ssr__side { align-self: start; }
.ssr__gain { font-size: 0.82rem; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* On a phone the badge and the points share the first line; the text takes the full width under them. */
@media (max-width: 640px) {
    .ssr { grid-template-columns: minmax(0, 1fr) auto; gap: 0.45rem 0.75rem; }
    .ssr__mark { grid-row: 1; grid-column: 1; }
    .ssr__side { grid-row: 1; grid-column: 2; justify-self: end; }
    .ssr__main { grid-column: 1 / -1; }
}

.ssv__compact { margin-top: 0.3rem; }
.ssc { display: grid; grid-template-columns: 6.6rem minmax(0, 1fr) minmax(0, 1.25fr) auto; gap: 0.3rem 1rem; align-items: center; padding: 0.6rem 0.2rem 0.6rem 0.95rem; border-top: 1px solid var(--line); font-size: 0.875rem; }
.ssc:first-child { border-top: 0; }
.ssc__title { min-width: 0; font-weight: 650; color: var(--ink); }
.ssc__title small { display: block; font-weight: 500; font-size: 0.78rem; color: var(--muted); }
.ssc__finding { min-width: 0; font-size: 0.82rem; color: var(--ink-2); line-height: 1.4; overflow-wrap: anywhere; }
.ssc__end { white-space: nowrap; text-align: right; }
/* Narrow: badge, name and weight on one line, the result under the name. */
@media (max-width: 760px) {
    .ssc { grid-template-columns: auto minmax(0, 1fr) auto; padding-left: 0.2rem; gap: 0.25rem 0.7rem; }
    .ssc__end { grid-row: 1; grid-column: 3; }
    .ssc__finding { grid-column: 2 / -1; }
}

.ssv__foot { margin-top: 1.1rem; padding-top: 0.8rem; border-top: 1px solid var(--line); font-size: 0.8rem; color: var(--muted); line-height: 1.55; }
.ssv__foot p { margin: 0 0 0.35rem; max-width: 90ch; }
.ssv__foot p:last-child { margin-bottom: 0; }
/* ---- /overblik: Sikkerhedsscore ---- */

/* --------------------------------------------------------------------------
   Min konto
   Identity-siderne kom fra Blazors skabelon med Bootstraps form-floating.
   Vores .form-control har lavere højde og padding end Bootstrap regner med, så
   den svævende label lagde sig oven i placeholderen. Siderne bruger nu i stedet
   platformens eget mønster: label over feltet, som alle andre formularer.
   -------------------------------------------------------------------------- */

.acct { display: grid; grid-template-columns: 232px 1fr; gap: 1.1rem; align-items: start; }

.acct__nav { display: flex; flex-direction: column; gap: 2px; }

.acct__link {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.6rem 0.75rem;
    border-radius: var(--r-sm);
    color: var(--ink-2);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
}

/* Samme udefinerede --wash: menupunktet gav ingen hover-respons overhovedet. */
.acct__link:hover { background: var(--blue-50); color: var(--ink); }

.acct__link.active {
    background: var(--navy-800);
    color: #fff;
}

.acct__link.active .icon { opacity: 1; }
.acct__link .icon { opacity: 0.75; flex-shrink: 0; }

/* Feltgruppe: label, felt, hjælpetekst og fejl som én blok.

   Loftet: Bootstrap giver .form-control bredden 100 %, så hvert felt fulgte panelet. Et navnefelt
   på 1500 px er ikke lettere at udfylde end et på 540 — det er bare sværere at se, hvor det slutter.
   I en dialog er .dlg allerede smallere end loftet, så det binder kun i brede paneler. */
.fld { margin-bottom: 1rem; max-width: 34rem; }

/* Til det felt, hvis indhold LÆSES i fuld bredde bagefter: markdown-kroppen på en vidensbase-artikel
   skrives i samme mål, som den udgives i. */
.fld--bred { max-width: 52rem; }

.fld > label {
    display: block;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 0.35rem;
}

.fld__hint { font-size: 0.82rem; color: var(--muted); margin-top: 0.3rem; }
.fld .validation-message { font-size: 0.82rem; }

/* «hint» — the helper text under a field or beside a choice, written that way in over a
   hundred places across the monitoring pages (and a few others) since they were built.
   The class was never defined, so every one of them rendered as body text, the size of the
   answer it was meant to explain (KC, 3 October 2026). Same look as .fld__hint; under a
   field it gets the same gap. Inline (a span inside a label) it stays inline. */
.hint { font-size: 0.82rem; color: var(--muted); }
.fld > .hint { margin-top: 0.3rem; }
.fld label .hint {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
}

/* Nøgle/værdi-liste til profiloplysninger vi viser men ikke redigerer. */
.kv { display: grid; gap: 0.85rem; }

.kv__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--line);
}

.kv__row:last-child { border-bottom: 0; padding-bottom: 0; }

.kv__key { font-size: 0.85rem; color: var(--muted); }
.kv__val { font-size: 0.92rem; color: var(--ink); font-weight: 500; text-align: right; }

/* Række med en til/fra-indstilling og forklarende undertekst. Loftet: uden det står etiketten i venstre
   kant og kontakten halvanden meter til højre på en bred skærm, og man mister linjen mellem dem. */
.tgl {
    max-width: 52rem;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1.25rem;
    padding: 0.9rem 0;
    border-bottom: 1px solid var(--line);
}

.tgl:last-of-type { border-bottom: 0; }
.tgl__text strong { display: block; font-size: 0.92rem; color: var(--ink); font-weight: 600; }
.tgl__text span { display: block; font-size: 0.83rem; color: var(--muted); margin-top: 0.15rem; max-width: 56ch; }
.tgl__ctl { flex-shrink: 0; padding-top: 0.15rem; }

@media (max-width: 900px) {
    .acct { grid-template-columns: 1fr; }
    .acct__nav { flex-direction: row; flex-wrap: wrap; }
}

/* ==========================================================================
   Indstillinger: kort i grupper
   ========================================================================== */

.setgrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
    gap: 0.75rem;
}

.setcard {
    display: flex;
    align-items: flex-start;
    gap: 0.8rem;
    padding: 0.95rem 1.05rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--paper);
    text-decoration: none;
    color: inherit;
    transition: border-color 0.14s ease, box-shadow 0.14s ease, transform 0.14s ease;
}

.setcard:hover {
    border-color: var(--blue-300);
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}

.setcard__icon {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: 9px;
    background: var(--blue-50);
    color: var(--blue-500);
}

.setcard__main { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }

/* A card's status mark on the self-service hub (25 October 2026): a dot and a word under the description. */
.setcard__mark { align-self: flex-start; margin-top: 0.3rem; }
/* The self-service user list's chips and search, over the table. */
.users-filter { margin: 0 0 0.9rem; align-items: center; }

.setcard__title { font-weight: 700; font-size: 0.93rem; color: var(--ink); }
.setcard__sub { font-size: 0.82rem; color: var(--muted); line-height: 1.5; }

/* Skillelinje mellem SSO-knappen og adgangskodeformularen på login. */
.auth__or {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
    color: var(--muted);
    font-size: 0.78rem;
}

.auth__or::before,
.auth__or::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--line);
}

/* ==========================================================================
   Offentlig driftsstatusside (uden login)
   ========================================================================== */

.pub { min-height: 100vh; padding: 2.5rem 1.25rem 3rem; }
.pub__inner { max-width: 720px; margin: 0 auto; }

.pub__brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-bottom: 1.75rem;
}

.pub__foot {
    margin-top: 2rem;
    text-align: center;
    font-size: 0.82rem;
    color: var(--muted);
}

/* Den samlede status øverst. Farven skal kunne aflæses på et halvt sekund. */
.pub__status { display: flex; align-items: center; gap: 1rem; }

.pub__dot {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    flex-shrink: 0;
    background: var(--blue-300);
}

.pub__status--ok .pub__dot { background: var(--good); box-shadow: 0 0 0 5px rgba(60, 132, 96, 0.16); }
.pub__status--warn .pub__dot { background: var(--warn); box-shadow: 0 0 0 5px rgba(176, 125, 51, 0.18); }
.pub__status--down .pub__dot { background: var(--crit); box-shadow: 0 0 0 5px rgba(176, 60, 60, 0.18); }
.pub__status--unknown .pub__dot { background: var(--blue-300); }

/* Oppetids-historik pr. system (Fase 1): en bjælke pr. dag + oppetids-%, grupperet (Fase 2). */
.pubsys__head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; margin-bottom: 0.9rem; }
.pubsys__gruppe {
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--ink-2);
    margin: 1.3rem 0 0.4rem;
}
.pubsys__row { padding: 0.75rem 0; border-top: 1px solid var(--line); }
.pubsys__row:first-of-type { border-top: none; padding-top: 0.35rem; }
.pubsys__top { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; }
.pubsys__navn { font-weight: 600; display: inline-flex; align-items: center; gap: 0.5rem; min-width: 0; }
.pubsys__dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.pubsys__pct { font-size: 0.8rem; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* overflow-x: auto — så kun bjælke-striben kan scrolle vandret, ikke hele den offentlige side, når
   90 dages bjælker ikke kan krympe under min-width på en smal telefon. */
.pubsys__bars { display: flex; gap: 2px; height: 26px; margin: 0.55rem 0 0.35rem; overflow-x: auto; }
.pubsys__bar { flex: 1 1 0; min-width: 2px; border-radius: 2px; }
.pubsys__status { font-size: 0.8rem; }

/* Blazor-fejlbjælken. Stod før KUN i MainLayout.razor.css, som er SCOPET til MainLayout — så den
   offentlige statusside (PublicLayout) fik ingen «display:none» og viste «Der opstod en uventet fejl»
   PERMANENT, uden at der var en fejl. Global her, så begge layouts skjuler den, og blazor.web.js viser
   den kun ved en faktisk fejl. */
#blazor-error-ui {
    color-scheme: light only;
    background: #fdf3e3;
    color: #7d5720;
    border-top: 1px solid #e8d5b0;
    bottom: 0;
    box-shadow: 0 -6px 20px rgba(19, 28, 40, 0.12);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.75rem 1.4rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
    font-size: 0.9rem;
    font-weight: 600;
}
#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 1rem;
    top: 0.65rem;
}

.pub__notice {
    padding: 0.95rem 1.1rem;
    border-radius: var(--r-md);
    border-left: 4px solid var(--blue-300);
    background: var(--blue-50);
}

.pub__notice + .pub__notice { margin-top: 0.7rem; }
.pub__notice--warn { border-left-color: var(--warn); }
.pub__notice--down { border-left-color: var(--crit); }

.pub__notice-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* Auth-sider (login / 2FA) — centreret kort uden sidebar-tyngde */
.auth {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 2rem 1.25rem;
}

.auth__card {
    width: 100%;
    max-width: 430px;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-lg);
    padding: 2.25rem 2.15rem;
}

/* ==========================================================================
   Responsivt
   ========================================================================== */

/* Mellembredder (typisk halv skærm / mindre laptops): giv indholdet luft ved at
   slanke sidebaren og padding — ellers bliver datatabeller unødigt klemt. */
@media (max-width: 1180px) and (min-width: 901px) {
    :root { --sidebar-w: 214px; }

    .app__content { padding: 1.9rem 1.5rem 3rem; }

    .side__brand { padding: 1.2rem 1rem 1.05rem; }
    .side__nav { padding: 0.4rem 0.6rem 1rem; }
    .side__link { font-size: 0.83rem; padding: 0.55rem 0.6rem; }

    .topbar { padding: 0.75rem 1.5rem 0; }

    .truncate { max-width: 11rem; }
}

@media (max-width: 900px) {
    .app { flex-direction: column; }

    .side {
        width: 100%;
        height: auto;
        position: relative;
    }

    .side__nav { display: none; }

    .side__toggle {
        display: block;
        position: absolute;
        top: 1.15rem;
        right: 1.15rem;
        width: 42px;
        height: 38px;
        appearance: none;
        border: 1px solid rgba(255, 255, 255, 0.2);
        border-radius: 10px;
        background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,0.8%29' stroke-linecap='round' stroke-width='2' d='M5 8h20M5 15h20M5 22h20'/%3e%3c/svg%3e") no-repeat center/1.4rem rgba(255, 255, 255, 0.08);
        cursor: pointer;
    }

    .side__toggle:checked ~ .side__nav { display: block; }

    /* Menu-foden (Rediger genveje + skinne-knap) hører til menuen, ikke til den altid-synlige
       topbjælke. Skjul den som nav'et og vis den kun, når hamburgeren er åben — ellers står
       «Rediger genveje» alene mellem logoet og søgefeltet, hvor den ikke giver mening. */
    .side__foot { display: none; }
    .side__toggle:checked ~ .side__foot { display: block; }

    /* Ikon-skinnen er en skrivebordsting: på mobil er menuen fuld bredde og foldes med
       hamburgeren. Skjul fold-knappen, og annullér en skinne-tilstand der er husket fra
       skrivebordet (nav.js sætter data-rail på <html> uanset skærmbredde), så den fulde
       menu ikke bliver klemt ned til 66px på telefonen. */
    .side__rail { display: none; }
    :root[data-rail="1"] .side { width: 100%; }
    :root[data-rail="1"] .side__brand { justify-content: flex-start; padding-left: 1.35rem; padding-right: 1.35rem; }
    :root[data-rail="1"] .side__wordmark { display: inline; }
    :root[data-rail="1"] .side__label { display: inline; }
    :root[data-rail="1"] .side__section { display: block; }
    :root[data-rail="1"] .side__link { justify-content: flex-start; padding-left: 0.75rem; padding-right: 0.75rem; gap: 0.7rem; }

    /* Fastgør-nålen er en hover-affordance til mus. På touch bliver første tap til «hover» (viser
       nålen) i stedet for at navigere, så man skulle trykke to gange på et menupunkt — skjul den på
       mobil. Uden nålen er der heller ingen grund til at reservere plads til den i højre side af linket. */
    .side__pin { display: none; }
    .side__row .side__link { padding-right: 0.75rem; }

    .topbar { padding: 0.75rem 1.25rem 0; }
    .topbar__who { display: none; }

    /* Søgefeltet får resten af bredden, men skal kunne klemmes sammen ved siden
       af klokke, avatar og log ud. */
    .topsearch { flex: 1 1 auto; min-width: 0; }
    .topsearch__input { font-size: 0.82rem; }

    .app__content { padding: 1.5rem 1.25rem 2.5rem; }

    .hero { padding: 1.5rem 1.35rem; }

    .chart__row { grid-template-columns: 4.5rem 1fr; }
    .chart__val { grid-column: 1 / -1; text-align: left; }
}

/* --------------------------------------------------------------------------
   Telefon (≤ 640px)

   Platformen er bygget på en bred skærm, og datatabellerne er brede af natur.
   Frem for at klemme dem sammen får de lov at scrolle vandret inde i deres eget
   panel — så bliver det tabellen der scroller, ikke hele siden. En side der
   glider sidelæns, er den hurtigste måde at gøre en app ubrugelig på telefonen.
   -------------------------------------------------------------------------- */

@media (max-width: 640px) {
    /* Tabeller: scroll indeni panelet. -webkit-overflow-scrolling giver
       inerti-scroll på iOS, hvor det ellers føles hakkende. */
    .panel table.table,
    .table-wrap {
        display: block;
        max-width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* thead/tbody skal IKKE gøres til hver sin "display: table" — så bliver de to
       uafhængige tabeller, og kolonnerne i hoved og krop holder ikke linje.
       Med display:block på selve tabellen pakkes alle rækker i én anonym tabel,
       og justeringen holder. */

    /* Panel-hoveder har titel til venstre og handlinger til højre. På en telefon
       er der ikke plads til begge dele på én linje. */
    .panel__head {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
    }

    .panel__head > div:last-child,
    .panel__head .d-flex { flex-wrap: wrap; }

    /* Filtre og vælgere sættes med style="width:auto" til desktop; her skal de
       fylde bredden, ellers bliver de for smalle til at ramme med en finger. */
    .panel__head .form-select,
    .panel__head .form-control,
    .tkt-filters .form-select,
    .tkt-filters .form-control { width: 100% !important; min-width: 0; }

    .ph { margin-bottom: 1.3rem; }
    .ph__actions { width: 100%; }
    .ph__actions .btn { flex: 1 1 auto; }

    /* Sider med paneler: giv indholdet lidt mere plads i bredden. */
    .app__content { padding: 1.15rem 0.9rem 2rem; }
    .panel { padding: 1.15rem 1rem; }

    /* Nøgletal side om side bliver ulæselige under ~340px. */
    .stat { padding: 1.05rem 1.1rem; }

    /* Sikkerhedsscore: dial og forklaring under hinanden, dialen lidt mindre. */
    .score { gap: 1.2rem; justify-content: center; }
    .score__dial { width: 124px; height: 124px; }
    .score__text { flex: 1 1 100%; }

    /* Servicerapportens periodevælger: pilene skal blive ved siden af, men
       teksten må gerne fylde resten. */
    .period { gap: 0.6rem; }

    /* Ticket-rækker: badges og tidsstempel under titlen frem for ved siden af. */
    .tkt { flex-wrap: wrap; }
    .tkt__side {
        width: 100%;
        justify-content: flex-start;
        padding-left: 1.9rem;
        flex-wrap: wrap;
    }

    /* Nøgle/værdi-lister: værdien under nøglen når begge er lange. */
    .kv__row { flex-wrap: wrap; gap: 0.2rem; }

    /* Den flydende "Registrér tid"-knap fylder for meget på en lille skærm —
       genvejstasten giver heller ingen mening uden tastatur. */
    .qte__launch { right: 0.9rem; bottom: 0.9rem; padding: 0.65rem 0.95rem; }
    .qte__launch kbd { display: none; }

    /* Dialoger: brug hele bredden og undgå at hovedet æder skærmen. */
    .dlg, .dlg--lg { width: calc(100vw - 1.2rem); max-height: calc(100vh - 1.5rem); }
    .dlg__head { padding: 1.1rem 1.15rem 0.8rem; }
    .dlg__body { padding: 1.1rem 1.15rem; }
    /* Margenerne skal følge .dlg__body's mindre luft, ellers rammer stregen ikke kanten. */
    .dlg__foot { margin: 1.1rem -1.15rem -1.1rem; padding: 0.9rem 1.15rem 1.1rem; flex-wrap: wrap; }
    .dlg__foot .btn { flex: 1 1 auto; }

    /* Lange DNS-records o.l. må gerne bruge hele bredden her. */
    .truncate { max-width: 100%; }
}

/* Fingerstørrelse frem for musestørrelse: på enheder uden præcis pegeenhed
   skal knapper og menupunkter være store nok til at ramme. */
@media (pointer: coarse) {
    .side__link { padding-top: 0.7rem; padding-bottom: 0.7rem; }
    .btn-sm { padding: 0.4rem 0.75rem; }
    .tkt-chip { padding: 0.5rem 0.95rem; }
}

/* ==========================================================================
   Tastatur og fokus

   Alt hvad man kan klikke på, skal også kunne nås med Tab og aktiveres med
   Enter/Mellemrum — og man skal kunne SE hvor man er. Ringen vises kun ved
   :focus-visible, så den dukker op når man tabber, men ikke ved museklik.
   ========================================================================== */

/* The ring's colour is --focus-ring (set per theme at the top: --blue-500 light, --blue-400 dark), which
   holds 3:1 against the surfaces it stands on in both themes (WCAG 1.4.11). */
:where(a, button, .btn, [role="button"], input, select, textarea, summary):focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

/* Klikbare rækker og kort: samme fremhævning som hover, plus ringen. .aftale (kunde-Home's
   aftalekort) er også et klikbart <a> med :hover, men manglede fokus-ringen. */
.tkt:focus-visible, .fcard:focus-visible, .notif__item:focus-visible, .aftale:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
    box-shadow: inset 0 0 0 1px var(--line-2), var(--shadow-sm);
}

/* The sidebar is navy: the blue ring disappears there, so it is white. The top bar is not dark (a light glass
   bar, .topbar::before): its only .btn are the bell panel's, on --paper, where a white ring was 1:1 in the light
   theme. They take --focus-ring like every other .btn (6 October 2026). */
.side__link:focus-visible, .side__brand:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Bootstrap's .btn:focus-visible (outline: 0 and a box-shadow) and .form-check-input:focus (outline: 0) are
   (0,2,0) and beat the :where() ring above, so a .btn and a checkbox had no keyboard ring at all. The same
   ring, said again at (0,2,0). */
.btn:focus-visible, .form-check-input:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

/* Dialog boxes take the focus so a screen reader starts inside them (Modal.razor, the command palette,
   the time dialog, the reconnect dialog). They are not controls: no ring round the whole box (it was the
   browser's own, orange). Their buttons and fields carry the ring. */
.dlg:focus, .cmd:focus, .qte:focus, #components-reconnect-modal:focus {
    outline: none;
}

/* The gate: after a click or a tap the ring is not drawn. focus-modality.js sets data-input="pointer" on
   <html> when a mouse, a pen or a finger presses, and "keyboard" at Tab, at Enter/Space on a control, or
   at a key that moves the focus. So the focus a dialog gives back (shortcuts.js slip), a FocusAsync after
   a click, or an arrow that only scrolls gets no ring, and the next Tab shows it again. Focus itself still
   moves exactly as before (WCAG 2.4.3); a keyboard user never reaches "pointer" (WCAG 2.4.7).
   Text fields keep theirs: it shows where you type. Forced colours and a request for more contrast are
   left to the browser. Rings drawn another way (the map's pins: CustomerMapView.razor.css and the
   kgl-focus layer in customer-map.js) ask for the same thing themselves. The site has the same gate. */
@media (forced-colors: none) and (prefers-contrast: no-preference) {
    :root[data-input="pointer"] :focus-visible:not(input:not([type="button"], [type="submit"], [type="reset"], [type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="image"]), textarea, select, [contenteditable]:not([contenteditable="false"])) {
        outline: none !important;
    }

    /* Rings drawn on a PARENT of the focused element, for a file field hidden inside its visible label or frame.
       The rule above only reaches the focused element itself, and Chromium marks that field :focus-visible at
       any key after a click. Every :has(...:focus-visible) ring in this file is listed here. */
    :root[data-input="pointer"] .atts__pick:has(input:focus-visible),
    :root[data-input="pointer"] .slip:has(.slip__felt:focus-visible) {
        outline: none !important;
    }
}

/* Spring til indhold: usynligt indtil man tabber til det som det første på siden. */
.skiplink {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    background: var(--navy-800);
    color: #fff;
    padding: 0.65rem 1.1rem;
    border-radius: 0 0 var(--r-sm) 0;
    font-weight: 700;
    font-size: 0.88rem;
}

.skiplink:focus {
    left: 0;
    color: #fff;
}

/* Respektér systemets "reducér bevægelse". Vi fjerner ikke fokusringe eller
   farveskift — kun det der faktisk bevæger sig. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }

    .tkt:hover, .fcard:hover, .setcard:hover, .stat:hover, .btn:hover {
        transform: none;
    }
}

/* ==========================================================================
   Indlæsning

   Pladsholderne skal have samme højde og afstand som det rigtige indhold, så
   siden ikke flytter sig når data lander. Glimtet er sat lavt: det skal antyde
   at der sker noget, ikke trække blikket til sig.
   ========================================================================== */

/* Kun for skærmlæsere — bruges til at annoncere "Henter…" uden at vise det. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.skel {
    background: linear-gradient(90deg,
        var(--clay-100) 0%,
        var(--line) 40%,
        var(--clay-100) 80%);
    background-size: 300% 100%;
    border-radius: 6px;
    animation: skel-shimmer 1.4s ease-in-out infinite;
}

@keyframes skel-shimmer {
    0% { background-position: 120% 0; }
    100% { background-position: -60% 0; }
}

.skel--line { height: 0.8rem; margin-bottom: 0.55rem; }
.skel--line-sm { height: 0.65rem; opacity: 0.75; }
.skel--label { height: 0.6rem; width: 45%; margin-bottom: 0.75rem; }
.skel--value { height: 1.9rem; width: 35%; margin-bottom: 0.6rem; }
.skel--meta { height: 0.6rem; width: 60%; }
.skel--block { height: 5.5rem; margin-top: 0.9rem; }
.skel--prik { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; }
.skel--avatar { width: 2.1rem; height: 2.1rem; border-radius: 50%; flex-shrink: 0; }
.skel--pill { width: 4.5rem; height: 1.5rem; border-radius: 999px; flex-shrink: 0; }

/* Samme mål som .stat, så nøgletallene ikke rykker når de kommer. */
.skel-tile {
    background: var(--paper);
    border-radius: var(--r-lg);
    box-shadow: inset 0 0 0 1px var(--line);
    padding: 1.15rem 1.25rem;
}

.skel-rows { display: flex; flex-direction: column; gap: 0.5rem; }

/* Samme mål som .tkt. */
.skel-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.85rem 1rem;
    border-radius: var(--r-md);
    box-shadow: inset 0 0 0 1px var(--line);
}

.skel-row__main { flex: 1; min-width: 0; }
.skel-row__main .skel--line:last-child { margin-bottom: 0; }

.skel-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.9rem;
}

.skel-card {
    padding: 1rem 1.1rem;
    border-radius: var(--r-md);
    box-shadow: inset 0 0 0 1px var(--line);
}

/* Har brugeren bedt om mindre bevægelse, står pladsholderne stille. De virker
   stadig — det er formen og ikke glimtet der holder layoutet på plads. */
@media (prefers-reduced-motion: reduce) {
    .skel { animation: none; background: var(--clay-100); }
}

/* Trin-for-trin-vejledninger (fx installation på hjemmeskærmen). Nummereringen
   skal kunne læses på en telefon, hvor teksten ofte fylder flere linjer. */
.pwa-steps ol, .pwa-steps ul {
    margin: 0;
    padding-left: 1.3rem;
    color: var(--ink);
    font-size: 0.92rem;
    line-height: 1.6;
}

.pwa-steps li { margin-bottom: 0.55rem; }
.pwa-steps li:last-child { margin-bottom: 0; }
.pwa-steps li::marker { color: var(--muted); font-weight: 700; }

/* ==========================================================================
   Vedhæftninger på en sag
   ========================================================================== */

.atts {
    margin: 1.15rem 0;
    padding: 1rem 1.1rem;
    border-radius: var(--r-md);
    background: var(--clay-100);
    box-shadow: inset 0 0 0 1px var(--line);
}

.atts__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.atts__actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }

/* Filvælgeren er skjult inde i knappen: browserens egen <input type=file> kan ikke
   styles, så vi bruger en <label> som knap og lader den udløse inputtet. */
.atts__pick {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    cursor: pointer;
    margin: 0;
}

/* Vedhæftninger valgt under oprettelse, før sagen findes. */
.atts__picks {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.vedhft__liste {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.vedhft__liste li {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.3rem 0.5rem;
    border: 1px solid var(--line);
    border-radius: 8px;
    font-size: 0.85rem;
}

/* Filnavnet skal give plads til størrelsen og Fjern-knappen frem for at skubbe
   dem ud af rækken. Et langt navn fra en telefon er ellers nok til at gøre
   knappen utilgængelig på en smal skærm. */
.vedhft__navn {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.atts__pick input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

/* Tastaturbrugere skal kunne se at knappen har fokus, selvom det er inputtet inden i
   der reelt får det. */
.atts__pick:has(input:focus-visible) {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

.atts__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    gap: 0.65rem;
}

.att {
    position: relative;
    background: var(--paper);
    border-radius: var(--r-sm);
    box-shadow: inset 0 0 0 1px var(--line);
    overflow: hidden;
}

/* Miniaturen er nu en <button> for filer, der kan vises, og et <a> for dem, der kun
   kan hentes. Begge skal se ens ud, så nulstillingen af knappen står her. */
.att__view {
    display: block;
    height: 6.5rem;
    background: var(--clay-100);
    width: 100%;
    padding: 0;
    border: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    text-align: left;
}

.att__view:hover { background: var(--blue-50); }

/* Tastaturbrugere skal kunne se, hvilken fil de står på. Indad, så ringen ikke
   klippes af kortets overflow. */
.att__view:focus-visible {
    outline: 2px solid var(--navy-800);
    outline-offset: -2px;
}

.att__view img { width: 100%; height: 100%; object-fit: cover; display: block; }

.att__file {
    display: grid;
    place-items: center;
    height: 100%;
    color: var(--muted);
}

/* Fremviseren i modalen */

.attview {
    display: grid;
    place-items: center;
    background: var(--clay-100);
    border-radius: 10px;
    overflow: hidden;
}

/* Højden er bundet til vinduet og ikke til billedet. Et portrætfoto fra en telefon
   ville ellers skubbe modalens fodrække langt under skærmkanten. */
.attview__img {
    max-width: 100%;
    max-height: 72vh;
    display: block;
    object-fit: contain;

    /* Der zoomes ved at skalere elementet, så det forstørrede skal blive inde i
       rammen — ellers ville billedet lægge sig hen over modalens kanter. */
    transform-origin: center center;
    will-change: transform;
}

.attview--zoom {
    overflow: hidden;

    /* Så man kan se, at der er noget at gøre, før man prøver. */
    cursor: zoom-in;

    /* Uden det ville et træk på billedet markere det som tekst i stedet for at
       flytte det, og markeringen ville blive hængende bagefter. */
    user-select: none;
    -webkit-user-select: none;
}

.attview--zoom img { -webkit-user-drag: none; }

.attview__zoom { display: flex; gap: 0.3rem; }

/* Knapperne er runde og lige brede, så "−" og "+" ikke hopper i forhold til
   "Tilpas" imellem dem. 40 px er trykmålet fra resten af mobilvisningen. */
.attview__zoom .btn {
    min-width: 40px;
    min-height: 40px;
    font-weight: 700;
}

.attview__pdf {
    width: 100%;
    height: 72vh;
    border: 0;
    display: block;
    background: #fff;
}

.attview__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-top: 0.75rem;
}

/* På en telefon er 72vh for lidt til en PDF — der er ingen sidebar at tage plads fra,
   og en A4-side skal kunne læses uden at zoome på hver linje. */
@media (max-width: 640px) {
    .attview__pdf { height: 78vh; }
    .attview__img { max-height: 68vh; }
}

.att__meta { padding: 0.5rem 0.6rem; }

.att__name {
    display: block;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.att__sub { font-size: 0.74rem; color: var(--muted); }

/* Slet-knappen ligger oven på billedet — den skal kunne læses på både lyse og
   mørke fotos, så den får sin egen baggrund. */
.atts__del {
    position: absolute;
    top: 0.3rem;
    right: 0.3rem;
    background: rgba(255, 255, 255, 0.92);
    border-radius: 6px;
    padding: 0.1rem 0.45rem;
}

/* Tilmeldingsbillet: skal kunne læses højt og tastes af på en boks uden fejl. */
.tokenbox {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-align: center;
    padding: 1.1rem 0.75rem;
    border-radius: var(--r-md);
    background: var(--clay-100);
    box-shadow: inset 0 0 0 1px var(--line-2);
    color: var(--ink);
    user-select: all;
    overflow-wrap: anywhere;
}

/* Godkendelsesfeltet under en ukendt afsender. */
.afs__godkend { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; }
.afs__godkend .form-control { flex: 1; min-width: 11rem; }
.afs__knap { margin-top: 0; }

/* Kvitteringen nederst på Dmarc: kommer der rapporter? Én linje, ikke en liste. */
.dm-kvittering { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; font-size: 0.82rem; color: var(--muted); padding: 0.2rem 0.2rem 0.9rem; }
.dm-kvittering--gammel { color: var(--warn); font-weight: 700; }

/* ── Dmarc: raekkeniveau-drilldown ────────────────────────────────────────
   Bevidst under overblikket. Teknikeren har brug for linjen; alle andre har
   brug for konklusionen, og den staar ovenfor. */
.dm-politik { font-size: 0.84rem; color: var(--ink-2); padding: 0.2rem 0 0.8rem; }
.dm-politik code { background: color-mix(in srgb, var(--ink) 7%, transparent); padding: 0.05rem 0.3rem; border-radius: 4px; }

.dm-linjer__row { cursor: pointer; }
.dm-linjer__row:hover { background: var(--blue-50); }
.dm-linjer__row:focus-visible { outline: 2px solid var(--ink-2); outline-offset: -2px; }
.dm-linjer__navn { font-weight: 700; font-size: 0.84rem; }
.dm-linjer__ip { font-size: 0.72rem; color: var(--faint); font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }

.dm-mrk { font-size: 0.72rem; font-weight: 800; border-radius: 999px; padding: 0.1rem 0.45rem; white-space: nowrap; }
.dm-mrk.er-ok { color: var(--good); background: var(--good-bg); }
.dm-mrk.er-fejl { color: var(--crit); background: var(--crit-bg); }

.dm-linjer__detalje > td { background: var(--shell); }

.dm-detalje { display: grid; grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); gap: 1rem 2rem; padding: 0.5rem 0.2rem; }
.dm-detalje__titel { font-weight: 800; font-size: 0.8rem; margin-bottom: 0.3rem; }
.dm-detalje dl { display: grid; grid-template-columns: auto 1fr; gap: 0.15rem 0.9rem; margin: 0; font-size: 0.78rem; }
.dm-detalje dt { color: var(--muted); }
.dm-detalje dd { margin: 0; color: var(--ink); font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }

/* Forslag fra kundesiden, der endnu ikke er bekraeftet. Roligt, ikke alarmerende:
   det er et svar, ikke et problem. */
.afs__forslag { margin-top: 0.15rem; }
.afs__forslag-navn { font-size: 0.84rem; }
.afs__forslag-af { font-size: 0.74rem; color: var(--faint); margin-top: 0.1rem; }
.afs__forslag-knap { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.45rem; }

/* Periodevaelger i sidehovedet. */
.dm-periode { display: inline-flex; gap: 0.15rem; background: color-mix(in srgb, var(--ink) 5%, transparent); border-radius: 999px; padding: 0.15rem; }
.dm-periode__k { border: 0; background: transparent; font-size: 0.76rem; font-weight: 700; color: var(--muted); border-radius: 999px; padding: 0.25rem 0.6rem; cursor: pointer; }
.dm-periode__k:hover { color: var(--ink); }
.dm-periode__k.er-valgt { background: var(--paper); color: var(--ink); box-shadow: var(--shadow-xs); }

/* SPF-analysen: hvad koster recorden, og hvad bliver ikke brugt. */
.dm-spf__raad { font-size: 0.86rem; color: var(--ink-2); line-height: 1.55; padding: 0.2rem 0 0.8rem; }

/* ── Dmarc: the answer, the work list and the senders (15 October 2026) ─────
   The house pattern (docs/arbejde/2026-10-15-dmarc-ux-spec.md): the status line is the answer, with the ladder
   «Overvåger → Karantæne → Afvist» and ONE next step under it; the cards say what needs fixing and who acts; the
   tiles narrow one table of senders. Tokens only, so the dark theme follows from :root[data-theme="dark"]. Words
   carry the meaning; the dots and the stripes only repeat it. */

/* The status line's body carries three lines more than usual: the ladder, the next step, the fold. */
.dmanswer .status__body { display: flex; flex-direction: column; gap: 0.35rem; }
.dmanswer .status__under a { color: var(--link); font-weight: 650; }

.dml-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.9rem; margin-top: 0.15rem; }
.dml { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.5rem; margin: 0; padding: 0; list-style: none; }
.dml__t { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.82rem; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.dml__t:not(:last-child)::after { content: "→"; margin-left: 0.2rem; color: var(--ink-2); font-weight: 400; }
.dml__dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; box-shadow: inset 0 0 0 1.5px var(--line-2); }
.dml__t.is-reached { color: var(--ink); }
.dml__t.is-reached .dml__dot { background: var(--ink-2); box-shadow: none; }
.dml__t.is-current { font-weight: 800; }
.dml__t.is-current .dml__dot { background: var(--status-farve, var(--ink-2)); box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--status-farve, var(--ink-2)); }
.dml__tag { font-size: 0.7rem; font-weight: 700; color: var(--ink-2); border-radius: 999px; padding: 0.05rem 0.45rem; background: color-mix(in srgb, var(--ink) 6%, var(--paper)); }
.dml__tag--next { background: var(--paper); box-shadow: inset 0 0 0 1px var(--line-2); }

.dmanswer__next { font-size: 0.95rem; color: var(--ink); line-height: 1.4; }
.dmanswer__label { font-weight: 750; }
.dmanswer__how { font-size: 0.86rem; color: var(--ink-2); line-height: 1.55; padding: 0.6rem 0.8rem; border-radius: var(--r-sm); background: var(--paper); box-shadow: inset 0 0 0 1px var(--line); max-width: 48rem; }
.dmanswer__how code { background: color-mix(in srgb, var(--ink) 7%, transparent); padding: 0.05rem 0.3rem; border-radius: 4px; }

/* The ladder in three dots, for the list of domains. */
.dml-mini { display: inline-flex; gap: 3px; vertical-align: middle; margin-right: 0.4rem; }
.dml-mini i { width: 7px; height: 7px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--line-2); }
.dml-mini i.is-reached { background: var(--ink-2); box-shadow: none; }

/* Your domains: one line each, the weakest first (the one the answer is about). */
.dmdomains { margin: -0.35rem 0 1.1rem; padding: 0.7rem 1rem; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); }
.dmdomains__title { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.3rem; }
.dmdomains__list { list-style: none; margin: 0; padding: 0; }
.dmdomains__row { display: grid; grid-template-columns: minmax(9rem, 1.1fr) auto minmax(0, 2fr) auto; gap: 0.25rem 1rem; align-items: center; padding: 0.4rem 0; border-top: 1px solid var(--line); font-size: 0.84rem; }
.dmdomains__row:first-child { border-top: 0; }
.dmdomains__name { font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.dmdomains__step { white-space: nowrap; }
.dmdomains__next { color: var(--ink-2); }

/* What needs fixing: one card per thing. The stripe carries the tone; the surface stays paper. */
.dmfix .panel__head { align-items: baseline; }
.dmfix__count { font-size: 0.85rem; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dmfix__group { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-2); margin: 0.9rem 0 0.45rem; }
.dmfix__group:first-of-type { margin-top: 0.2rem; }

.dmo {
    --dmo-farve: var(--line-2);
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.45rem 1.2rem;
    padding: 0.75rem 0.95rem 0.75rem 1rem;
    margin-bottom: 0.5rem;
    border: 1px solid var(--line);
    border-left: 3px solid var(--dmo-farve);
    border-radius: 4px var(--r-md) var(--r-md) 4px;
    background: var(--paper);
}
.dmo--crit { --dmo-farve: var(--crit); }
.dmo--warn { --dmo-farve: var(--warn); }
.dmo--calm { --dmo-farve: var(--good); }
.dmo__title { font-weight: 750; font-size: 0.95rem; color: var(--ink); overflow-wrap: anywhere; }
.dmo__text { font-size: 0.85rem; color: var(--ink-2); line-height: 1.5; margin-top: 0.15rem; }
.dmo__side { display: flex; flex-direction: column; align-items: flex-end; gap: 0.4rem; text-align: right; }
.dmo__who { font-size: 0.8rem; color: var(--ink-2); }
.dmo__who b { color: var(--ink); font-weight: 750; }
.dmo__wholabel { color: var(--muted); }
.dmo__contact { font-size: 0.82rem; color: var(--ink-2); }
.dmo__tech { grid-column: 1 / -1; font-size: 0.8rem; color: var(--ink-2); line-height: 1.5; }
.dmo__tech > summary { cursor: pointer; color: var(--muted); font-weight: 650; width: fit-content; }
.dmo__tech > summary:hover { color: var(--ink); }
.dmo__tech[open] > summary { margin-bottom: 0.3rem; }
.dmo__tech code { overflow-wrap: anywhere; }
.dmo__point, .dmo__sender { padding: 0.35rem 0 0.35rem 0.6rem; border-left: 2px solid var(--line-2); margin-top: 0.35rem; }
.dmo__point-h, .dmo__sender-name { font-weight: 700; color: var(--ink); }
.dmo__ips { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.74rem; color: var(--faint); overflow-wrap: anywhere; }

/* The senders: one table, grouped worst first, forwarded mail last and apart. A row unfolds the detail under it. */
.dms__note { font-size: 0.78rem; color: var(--muted); margin: -0.4rem 0 0.6rem; }
.dms__head th { background: var(--shell); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-2); padding-top: 0.45rem; padding-bottom: 0.45rem; }
.dms__n { font-weight: 700; margin-left: 0.3rem; font-variant-numeric: tabular-nums; }
.dms__group[data-pile="forwarded"] .dms__head th { border-top: 2px solid var(--line-2); }
.dms td.num { font-variant-numeric: tabular-nums; }
.dms__row { cursor: pointer; }
.dms__row:hover, .dms__row.is-open { background: var(--blue-50); }
/* A card's button scrolls to these (todoitShortcuts.reveal): clear of the sticky top bar. */
.dms, .dms__row, .dmspf, #dkim { scroll-margin-top: 5.5rem; }
.dms__toggle { display: inline-flex; align-items: center; gap: 0.45rem; border: 0; background: transparent; padding: 0; font: inherit; font-weight: 700; color: var(--ink); text-align: left; cursor: pointer; min-height: 2rem; overflow-wrap: anywhere; }
.dms__toggle:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }
.dms__chev { width: 7px; height: 7px; border-right: 2px solid var(--ink-2); border-bottom: 2px solid var(--ink-2); transform: rotate(-45deg); transition: transform 0.15s ease; flex-shrink: 0; }
.dms__row.is-open .dms__chev { transform: rotate(45deg); }
.dms__servers-n { display: block; font-size: 0.74rem; color: var(--muted); margin-left: 1.05rem; }
.dms__leg { font-weight: 800; }
.dms__leg--ok { color: var(--good-ink); }
.dms__leg--no { color: var(--crit-ink); }
.dms__detail > td { background: var(--shell); }
.dms__detail-in { padding: 0.35rem 0.2rem 0.5rem 1.05rem; font-size: 0.84rem; color: var(--ink-2); line-height: 1.5; max-width: 60rem; }
.dms__detail-in p { margin: 0 0 0.4rem; }
.dms__advice { color: var(--ink); }
.dms__diag { border-left: 2px solid var(--line-2); padding-left: 0.6rem; }
.dms__handling { margin: 0.5rem 0; }
.dms__servers { margin-top: 0.5rem; }
.dms__servers-title { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.dms__serverlist { list-style: none; margin: 0.2rem 0 0; padding: 0; columns: 2 18rem; column-gap: 2rem; font-size: 0.78rem; }
.dms__serverlist li { display: flex; flex-wrap: wrap; gap: 0.2rem 0.6rem; justify-content: space-between; padding: 0.15rem 0; break-inside: avoid; }
.dms__ip, .dms__host { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
.dms__host { font-size: 0.74rem; color: var(--faint); margin-top: 0.2rem; overflow-wrap: anywhere; }

/* The details tab: the record, SPF and DKIM per domain. */
.dmrec, .dmspf { padding: 0.75rem 0; border-top: 1px solid var(--line); }
.panel__head + .dmrec, .panel__head + .dmspf { border-top: 0; padding-top: 0.2rem; }
.dmrec__head, .dmspf__head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.75rem; margin-bottom: 0.35rem; }
.dmrec__domain { font-size: 0.95rem; color: var(--ink); overflow-wrap: anywhere; }
.dmrec__tech { font-size: 0.76rem; }
.dmrec__kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.2rem 0.9rem; margin: 0.4rem 0; font-size: 0.82rem; }
.dmrec__kv dt { color: var(--muted); font-weight: 600; }
.dmrec__kv dd { margin: 0; overflow-wrap: anywhere; }
.dmrec__ok { font-size: 0.84rem; color: var(--good-ink); font-weight: 650; }
.dmrec__suggest { margin: 0.3rem 0; }
.dmrec__label { font-size: 0.8rem; font-weight: 700; color: var(--ink-2); }
.dmrec__value { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.2rem; }
.dmrec__value code, .dmdns code { overflow-wrap: anywhere; }
.dmsub { font-size: 0.8rem; font-weight: 800; color: var(--ink-2); margin: 0.6rem 0 0.35rem; }

/* Waiting for the customer's DNS: an empty status, with the two records to put in. */
.dmdns__note { font-size: 0.8rem; color: var(--ink-2); margin-top: 0.5rem; line-height: 1.45; }
.dmdns__table { margin-top: 0.6rem; background: var(--paper); }
.dmlink { margin-left: 0.4rem; font-weight: 650; white-space: nowrap; }
.dmcopy { white-space: nowrap; }

/* The mailboxes per customer: one table, the chosen customer unfolds under its own row. */
.dmsrc__pick { border: 0; background: transparent; padding: 0; font: inherit; color: var(--ink); text-align: left; cursor: pointer; min-height: 2rem; }
.dmsrc__pick:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: 4px; }
.dmsrc__fetch .stat__meta { margin-left: 0.4rem; }
.dmsrc__go { text-align: right; white-space: nowrap; }
.dmsrc__detail > td { background: var(--shell); }
.dmsrc__controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

/* The central mailbox: the reports without a customer, grouped by domain. */
.dmmbx__pick { min-width: 220px; }

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

/* A phone: the period picker fills the width with 44 px buttons, a card stacks, and a sender row becomes two
   lines - name and status, then the numbers with their words. Wide detail tables scroll inside .tbl-wrap. */
@media (max-width: 640px) {
    .dm-periode { display: flex; width: 100%; }
    .dm-periode__k { flex: 1; min-height: 44px; }

    .dmdomains__row { grid-template-columns: minmax(0, 1fr) auto; }
    .dmdomains__next, .dmdomains__row .dsec-stale { grid-column: 1 / -1; }

    .dmo { grid-template-columns: minmax(0, 1fr); }
    .dmo__side { align-items: stretch; text-align: left; }
    .dmo__act .btn { width: 100%; }

    .dms-wrap { overflow-x: visible; }
    .dms, .dms tbody, .dms__head, .dms__head th, .dms__detail, .dms__detail > td { display: block; }
    .dms thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .dms__row { display: grid; grid-template-columns: auto auto auto auto minmax(0, 1fr); column-gap: 0.75rem; row-gap: 0.15rem; align-items: center; padding: 0.5rem 0.25rem; border-bottom: 1px solid var(--line); }
    /* The cell resets name the table's own class twice: «.dms__row > td» alone (0,1,1) lost to «.tbl tbody td»
       (0,1,2), every cell kept its side padding, and the page scrolled sideways on a phone. */
    .tbl.dms .dms__row > td { display: block; padding: 0; border: 0; }
    .dms__row > .dms__name { grid-column: 1 / 5; grid-row: 1; min-width: 0; }
    .dms__row > .dms__state { grid-column: 5; grid-row: 1; justify-self: end; }
    .dms__row > .dms__mails, .dms__row > .dms__fail, .dms__row > .dms__legcell { grid-row: 2; font-size: 0.78rem; text-align: left; white-space: nowrap; }
    .dms__row > td[data-label]::before { content: attr(data-label) " "; color: var(--muted); font-weight: 600; }

    /* The mailboxes per customer: customer and mailbox on line 1, the last fetch on line 2. */
    .dmsrc, .dmsrc tbody, .dmsrc__detail, .dmsrc__detail > td { display: block; }
    .dmsrc thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
    .dmsrc__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 0.75rem; row-gap: 0.1rem; align-items: center; padding: 0.5rem 0.25rem; border-bottom: 1px solid var(--line); }
    .tbl.dmsrc .dmsrc__row > td { display: block; padding: 0; border: 0; }
    .dmsrc__row > .dmsrc__fetch { grid-column: 1; grid-row: 2; }
    .dmsrc__row > .dmsrc__go { grid-column: 2; grid-row: 2; }

    /* The reports without a customer: domain and count on line 1, the customer pick and «assign» on line 2. */
    .dmmbx, .dmmbx tbody, .dmmbx tr { display: block; }
    .dmmbx tr.dmmbx__group { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem 0.6rem; padding: 0.5rem 0.25rem; }
    .table.dmmbx .dmmbx__group > td { display: block; border: 0; padding: 0; }
    .dmmbx__domain { grid-column: 1 / -1; }
    .dmmbx__pick { min-width: 0; }
}

/* Planlagte koersler: platformens eget arbejde. */
.krs__navn { font-weight: 700; font-size: 0.88rem; }
.krs__hvad { font-size: 0.76rem; color: var(--muted); margin-top: 0.1rem; max-width: 34rem; }
.krs__bagud { font-size: 0.74rem; color: var(--crit); font-weight: 700; margin-top: 0.2rem; }
.krs__fejl { font-size: 0.76rem; color: var(--crit-ink); margin-top: 0.2rem; max-width: 34rem; }
.krs__fejl a { color: inherit; text-decoration: underline; }

/* Lyd til/fra i notifikationspanelet */

.notif__lyd {
    display: inline-grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--navy-800);
    cursor: pointer;
}

.notif__lyd:hover { background: var(--blue-50); }

/* Slået fra: dæmpet, men stadig over kontrastkravet for et betjeningselement. */
.notif__lyd--fra { color: var(--ink-2); }

.notif__lyd:focus-visible {
    outline: 2px solid var(--navy-800);
    outline-offset: 1px;
}

/* Sagens sidepanel på en telefon.
   ========================================================================== */

/* To og to. Seks felter under hinanden er seks skærmfulde at rulle forbi; parvis er det tre
   rækker, og status og prioritet kan læses i ét blik.

   Det argument stod skrevet og godkendt her — men kun bag @media (max-width: 640px), altså kun
   på en telefon. Det gælder ordret på en computer: seks felter under hinanden er seks felter
   under hinanden, uanset hvor bred skærmen er, og sidepanelet fyldte ~620 px af en side, hvor
   sagens egen tekst skal kunne læses ved siden af. Løftet ud 1. september 2026. */
.tkt-sidepanel .panel {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 0.7rem;
    align-items: start;
}

/* Overskriften og tidsstemplerne skal stadig have hele bredden. */
.tkt-sidepanel .panel__title,
.tkt-sidepanel .panel > .alert,
.tkt-sidepanel .stat__meta { grid-column: 1 / -1; }

.tkt-sidepanel .fld { margin-bottom: 0.6rem; }

/* The customer's notes on the ticket are a list, not fields side by side: the header and the list keep the whole
   width (review of 27 October 2026 — the two-column grid above put them in half a column each). */
.tkt-sidepanel .cnote-panel--compact { display: block; }

/* Kontaktpersonens navn kan være langt, og en rulleliste, der presses ned i halv bredde, viser
   kun de første par bogstaver. Den får rækken for sig selv. */
.tkt-sidepanel .fld:last-of-type { grid-column: 1 / -1; }

@media (max-width: 640px) {
    /* Op over forløbet. Bento er et grid, så rækkefølgen kan vendes uden at røre
       markuppen — og uden at ændre den på en computer, hvor panelet står i sin
       egen spalte og altid er synligt. */
    .tkt-sidepanel { order: -1; }
}

/* Genåbningstælleren på en sag. Skiller sig ud fra de øvrige tidsstempler, fordi
   den er den ene linje, der siger «her gik noget ikke som planlagt». */
.tkt-genaabnet {
    margin-top: 0.5rem;
    padding: 0.3rem 0.5rem;
    border-radius: 8px;
    background: var(--warn-bg);
    color: var(--ink-2);
    font-weight: 700;
}

/* Lukket uden løsning. Rød-tonet, ikke gul: det er ikke en advarsel om noget
   fremtidigt, men en oplysning om noget, der endte anderledes end planlagt. */
.tkt-lukket {
    margin-top: 0.6rem;
    padding: 0.45rem 0.6rem;
    border-radius: 8px;
    background: var(--crit-bg);
    color: var(--ink-2);
    font-weight: 700;
}

.tkt-lukket__note {
    margin-top: 0.25rem;
    font-weight: 400;
    white-space: pre-wrap;
}

/* Beskeden over svarfeltet på en lukket sag: her kan kun skrives internt. */
.reply__laast {
    margin-bottom: 0.6rem;
    padding: 0.5rem 0.7rem;
    border-radius: 10px;
    background: var(--blue-50);
    color: var(--ink-2);
    font-size: 0.85rem;
    line-height: 1.45;
}

/* Brugermenu i topbaren. Log ud ligger heri frem for som løs knap ved siden af
   burgermenuen, hvor et fejlklik loggede folk af uden fortrydelse (sag #1018). */

.brugermenu { position: relative; }

.brugermenu__knap {
    border: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    gap: 0.55rem;
}

.brugermenu__knap:hover { background: rgba(255, 255, 255, 0.95); }

.brugermenu__knap:focus-visible {
    outline: 2px solid var(--navy-800);
    outline-offset: 2px;
}

/* Fanger klik uden for menuen. Under panelet, over alt andet. */
.brugermenu__baggrund {
    position: fixed;
    inset: 0;
    z-index: 950;
}

.brugermenu__panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 951;
    min-width: 220px;
    padding: 0.35rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: 0 18px 40px -18px rgba(22, 32, 46, 0.45);
}

.brugermenu__form { margin: 0; }

.brugermenu__punkt {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--ink);
    font-size: 0.88rem;
    text-align: left;
    text-decoration: none;
    cursor: pointer;

    /* 40 px trykmål, samme som resten af mobilvisningen. */
    min-height: 40px;
}

.brugermenu__punkt:hover { background: var(--blue-50); color: var(--ink); }

/* Log ud adskilt fra resten: det er den ene handling, man ikke vil ramme ved et uheld. */
.brugermenu__punkt--ud {
    margin-top: 0.35rem;
    border-top: 1px solid var(--line);
    border-radius: 0 0 8px 8px;
    color: var(--crit-ink);
}

.brugermenu__punkt--ud:hover { background: var(--crit-bg); color: var(--crit-ink); }

/* M365 Excel export: a disclosure in the accounts panel head and an inline list under it. Inline rather than a
   floating menu, so it never hangs off the edge on a phone and needs no outside-click handling. */
.xport { flex-shrink: 0; }

.xport__panel {
    margin: 0 0 1rem;
    padding: 0.6rem;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--paper);
}

.xport__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0 0.2rem 0.4rem;
}

.xport__title { font-size: 0.82rem; font-weight: 700; color: var(--muted); }

.xport__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
    gap: 0.35rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.xport__item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    min-height: 2.75rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: none;
    color: var(--ink);
    font-size: 0.9rem;
    text-align: left;
}

.xport__item:hover { background: var(--blue-50); }
.xport__item:focus-visible { outline: 2px solid var(--blue-500); outline-offset: 2px; }
.xport__name { font-weight: 600; }
.xport__count { color: var(--muted); font-size: 0.84rem; white-space: nowrap; }

/* An empty or unmeasured list stays focusable (aria-disabled) so a screen reader hears why; it only looks dimmed. */
.xport__item--tom { cursor: default; }
.xport__item--tom .xport__name { color: var(--muted); font-weight: 500; }
.xport__item--tom:hover { background: none; }

.xport__hint { margin: 0.55rem 0.2rem 0; color: var(--muted); font-size: 0.8rem; }

.xport__status:empty { display: none; }
.xport__status { margin: 0 0 0.9rem; font-size: 0.85rem; color: var(--muted); overflow-wrap: anywhere; }
.xport__status--fejl { color: var(--crit-ink); }

/* ---- overblik: Microsoft 365 ---- */
/* The Microsoft 365 page's own parts around the shared tiles (Components/Shared/Tiles); the build is
   docs/arbejde/2026-10-03-overblik2-byg-m365.md. Everything else on the page is the shared tile language. */

/* The account search stands in the list note's tool row; on a narrow page it takes a line of its own. */
.m365-search { width: auto; min-width: 15rem; }
@media (max-width: 900px) {
    .m365-accounts .listnote__tools { width: 100%; margin-left: 0; }
    .m365-search { flex: 1 1 100%; min-width: 0; }
}
/* ---- /overblik: Microsoft 365 ---- */

/* ---- m365-import: reading a filled-in account list back in (docs/arbejde/2026-10-03-m365-import-byg.md) ---- */
/* The export and import buttons share the accounts panel head; on a narrow screen they wrap rather than squeeze. The
   panel itself reuses the export menu's .xport__panel look. */
.ximport__tools { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: flex-end; }
.ximport__hint { margin: 0 0.2rem 0.6rem; }
.ximport__label { margin: 0 0.2rem 0.25rem; font-size: 0.8rem; }
.ximport__file { max-width: 28rem; }
.ximport__busy { margin: 0.6rem 0.2rem 0; color: var(--muted); font-size: 0.85rem; }
.ximport__preview { margin-top: 0.75rem; padding: 0.6rem 0.75rem; border: 1px solid var(--line); border-radius: 8px; }
.ximport__name { color: var(--muted); font-size: 0.8rem; overflow-wrap: anywhere; }
.ximport__summary { margin: 0.3rem 0 0.4rem; font-size: 0.92rem; }
.ximport__problems-title { margin: 0.4rem 0 0.2rem; color: var(--warn-ink); font-size: 0.85rem; font-weight: 600; }
.ximport__problems { margin: 0 0 0.3rem; padding-left: 1.2rem; font-size: 0.84rem; overflow-wrap: anywhere; }
.ximport__more { margin: 0; color: var(--muted); font-size: 0.8rem; }
.ximport__what { margin: 0.5rem 0; font-size: 0.88rem; }
.ximport__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ximport__actions .btn { min-height: 2.25rem; }
/* ---- /m365-import ---- */

/* ---- m365-knapper: the staff-only actions on the M365 page (docs/arbejde/2026-10-03-m365-knapper-a-byg.md) ---- */
/* The menu per account row: a small button in the row's side, its list opening under it, over the rows below. */
.m365-act { position: relative; display: inline-block; }
.m365-act__btn { white-space: nowrap; }
.m365-act__btn::after { content: ""; display: inline-block; margin-left: 0.35rem; vertical-align: 0.15em;
    border-left: 0.28em solid transparent; border-right: 0.28em solid transparent; border-top: 0.32em solid currentColor; }
.m365-act__menu {
    position: absolute; right: 0; top: calc(100% + 4px); z-index: 30;
    width: min(18rem, calc(100vw - 2rem)); padding: 0.4rem;
    background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); box-shadow: var(--shadow-lg);
    text-align: left;
}
.m365-act__head { margin: 0.5rem 0.5rem 0.2rem; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); }
.m365-act__item {
    display: block; width: 100%; padding: 0.4rem 0.5rem; border: 0; border-radius: var(--r-sm);
    background: none; color: var(--ink); font-size: 0.88rem; text-align: left; cursor: pointer;
}
.m365-act__item:hover, .m365-act__item:focus-visible { background: var(--shell); }
.m365-act__hint { margin: 0.4rem 0.5rem 0.2rem; padding-top: 0.4rem; border-top: 1px solid var(--line); font-size: 0.78rem; color: var(--muted); }

/* The panel: who the customer is to PowerShell, and the tasks made for it. */
.m365-actions__eyebrow { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--brass); }
.m365-actions__who { margin: 0 0 0.8rem; font-size: 0.85rem; color: var(--ink-2); overflow-wrap: anywhere; }
.m365-actions__jobs-head { margin: 0.6rem 0 0.4rem; }
.m365-actions__jobs { list-style: none; margin: 0; padding: 0; }
.m365-actions__job { display: flex; gap: 0.75rem; align-items: flex-start; justify-content: space-between; padding: 0.55rem 0; border-top: 1px solid var(--line); }
.m365-actions__job-main { min-width: 0; }
.m365-actions__job-what { font-size: 0.9rem; color: var(--ink); overflow-wrap: anywhere; }
.m365-actions__job-msg { color: var(--crit-ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.m365-actions__job .pil { flex: none; }

/* The dialog: the customer in a dark strip at the top, the fields, the ticket, the exact command. */
.m365-job__who { margin: -0.25rem 0 0.9rem; padding: 0.7rem 0.9rem; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--navy-900); color: #fff; font-size: 0.88rem; overflow-wrap: anywhere; }
.m365-job__mono { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 0.8rem; color: #d5dbe4; }
.m365-job__pc { color: #f0c98a; }
.m365-job__legend { margin-bottom: 0.35rem; font-size: 0.85rem; font-weight: 600; color: var(--ink); }
.m365-job__choices { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; }
.m365-job__choice, .m365-job__check { display: inline-flex; gap: 0.4rem; align-items: center; font-size: 0.9rem; color: var(--ink); }
/* A switch's label is a sentence, not a field heading: .fld > label's small capitals do not apply. */
.fld > label.m365-job__check { margin: 0; font-size: 0.9rem; font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--ink); }
.m365-job__fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
.m365-job__fld { max-width: none; }
.m365-job__fld--switch { grid-column: 1 / -1; margin-bottom: 0.5rem; }
.m365-job__row2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
.m365-job__problem { margin-top: 0.3rem; font-size: 0.82rem; color: var(--crit-ink); }
.m365-job__cmd {
    margin: 0; padding: 0.7rem 0.85rem; border-radius: var(--r-md); background: var(--navy-950); color: #e8edf3;
    font-size: 0.8rem; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere;
}
.m365-job__foot { flex-wrap: wrap; }
.m365-job__spacer { flex: 1 1 auto; }
@media (max-width: 640px) {
    .m365-job__fields, .m365-job__row2 { grid-template-columns: minmax(0, 1fr); }
}
/* ---- /m365-knapper ---- */

/* ---- overblik: Platform-vitals og Netværksscan ---- */
/* The two pages' own parts around the shared tiles (Components/Shared/Tiles); the build is
   docs/arbejde/2026-10-03-overblik3-byg.md. Everything else on the pages is the shared tile language. */

/* Platform-vitals: the runs section now follows the tiles that filter it. */
.vruns__title { margin-top: 1.6rem; }
.vruns__lead { margin-bottom: 0.9rem; }
/* The runs table's marks in the ink tones: the plain good/crit colours on their pale chips fall under 4.5:1 (3.7:1 light
   for «Kører», 4.4:1 dark for «Stoppet», 4.0:1 dark for «3 timer bagud»). Scoped to this table; .dm-mrk is shared. */
#vitals-runs-list .dm-mrk.er-ok { color: var(--good-ink); }
#vitals-runs-list .dm-mrk.er-fejl { color: var(--crit-ink); }
#vitals-runs-list .krs__bagud { color: var(--crit-ink); }

/* Network scan: the agent cards. One column with a tighter gap than the page's; a closed card is one row. */
.nscards { display: flex; flex-direction: column; gap: 0.75rem; }
.nscard { padding: 0.95rem 1.2rem; }
.nscard__head { display: flex; align-items: center; gap: 0.6rem 1rem; flex-wrap: wrap; }
.nscard__fold {
    flex: 1 1 22rem;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem 1rem;
    flex-wrap: wrap;
    padding: 0.2rem 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
/* The arrow that says the card folds: right when closed, down when open - only on the fold button. */
.nscard__fold::before {
    content: "";
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-right: 2px solid var(--ink-2);
    border-bottom: 2px solid var(--ink-2);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
}
.nscard__fold[aria-expanded="true"]::before { transform: rotate(45deg); }
.nscard__fold:focus-visible { outline: 2px solid var(--blue-500); outline-offset: 3px; border-radius: var(--r-sm); }
.nscard__fold:hover .nscard__name { text-decoration: underline; text-underline-offset: 0.18em; }
.nscard__who { display: flex; flex-direction: column; min-width: 0; flex: 1 1 14rem; }
.nscard__name { font-size: 1.02rem; font-weight: 700; letter-spacing: -0.012em; overflow-wrap: anywhere; }
.nscard__sub { font-size: 0.83rem; color: var(--muted); margin-top: 0.1rem; overflow-wrap: anywhere; }
.nscard__marks { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.nscard__mark {
    font-size: 0.74rem;
    font-weight: 700;
    border-radius: 999px;
    padding: 0.12rem 0.55rem;
    white-space: nowrap;
    color: var(--muted);
    background: color-mix(in srgb, var(--ink) 6%, var(--paper));
}
.nscard__mark[data-s="crit"] { color: var(--crit-ink); background: var(--crit-bg); }
.nscard__mark[data-s="warn"] { color: var(--warn-ink); background: var(--warn-bg); }
.nscard__mark[data-s="ok"] { color: var(--good-ink); background: var(--good-bg); }
.nscard__act { display: flex; gap: 0.4rem; flex-shrink: 0; }
.nscard__body { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--line); }
/* Bootstrap's pink <code> (the addresses and MACs in the tables) is 3.5:1 on the dark card; the card's own ink instead. */
:root[data-theme="dark"] .nscard__body code { color: var(--ink-2); }
@media (prefers-reduced-motion: reduce) { .nscard__fold::before { transition: none; } }
/* ---- /overblik: Platform-vitals og Netværksscan ---- */

/* Plads til den svævende «Registrér tid».
   ==========================================================================

   Knappen er fast i nederste højre hjørne og dækker de nederste ~56 px af skærmen.
   Indholdet havde 32 px bundpolstring på mobil, så det sidste af siden lå under
   knappen, uanset hvor langt man rullede. Meldt ind som sag #1019.

   4rem (64 px) rydder knappen på ~56 px med lidt luft. Var før 6rem, men det efterlod
   et unødigt bånd tomt hvidt rum, man kunne rulle ned i, når indholdet næsten fyldte
   skærmen. Polstringen står til sidst i filen med vilje: den skal vinde over alle
   skærmstørrelses-reglerne ovenfor, som hver især sætter deres egen bund. */
.app__content { padding-bottom: 4rem; }

@media (max-width: 640px) {
    /* Lidt mere på telefonen: der er knappen forholdsvis større, og der er ingen
       plads i siden at læse det dækkede indhold fra. */
    .app__content { padding-bottom: 6.5rem; }
}

/* Forslag fra sprogmodellen.
   ==========================================================================

   Tonet anderledes end resten af formularen med vilje: det er et bud, ikke en
   værdi. Man skal kunne se forskel på «sådan er det» og «sådan tror en maskine
   det er» uden at læse teksten. */
.aiforslag {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin: -0.35rem 0 0.9rem;
    padding: 0.45rem 0.6rem;
    border: 1px dashed var(--line);
    border-radius: 10px;
    background: var(--blue-50);
}

.aiforslag__tekst {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    color: var(--ink-2);
}

.aiforslag__fejl {
    flex-basis: 100%;
    font-size: 0.8rem;
    color: var(--crit-ink);
}

/* «Sådan finder du derhen» under et konfigurationspunkt. Dæmpet, fordi det er en
   vejviser og ikke et fund — men stort nok til at kunne læses højt i telefonen. */
.konfig__sti {
    margin-top: 0.3rem;
    font-size: 0.8rem;
    white-space: normal;
}

.konfig__sti a {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    color: var(--ink-2);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.konfig__sti a:hover { color: var(--blue-600, var(--ink)); }

.konfig__berørte {
    list-style: none;
    margin: 0.3rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    white-space: normal;
}

.konfig__berørte a {
    color: var(--ink-2);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
}

.konfig__berørte a:hover { color: var(--blue-600, var(--ink)); }

/* Maskinskrevet referat over sagsteksten.
   Stiplet kant og samme blå som forslagsstriben, så «det her er modellens ord»
   er den samme visuelle besked overalt i platformen. Den venstre streg gør den
   til et citat frem for til indholdet. */
.airesume {
    margin: 0 0 0.9rem;
    padding: 0.55rem 0.75rem;
    border: 1px dashed var(--line);
    border-left: 3px solid var(--blue-300, var(--line));
    border-radius: 10px;
    background: var(--blue-50);
}

.airesume__mærke {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ink-3, var(--ink-2));
    margin-bottom: 0.3rem;
}

/* Svarudkast over svarfeltet. Samme sprog som resuméet — stiplet kant, blå
   venstrestreg — så «det her er modellens ord» ser ens ud overalt. */
.aiudkast {
    margin: 0 0 0.6rem;
    padding: 0.6rem 0.75rem;
    border: 1px dashed var(--line);
    border-left: 3px solid var(--blue-300, var(--line));
    border-radius: 10px;
    background: var(--blue-50);
}

.aiudkast__mærke {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ink-3, var(--ink-2));
    margin-bottom: 0.35rem;
}

.aiudkast__tekst {
    margin: 0 0 0.5rem;
    font-size: 0.9rem;
    line-height: 1.5;
    white-space: pre-wrap;
    color: var(--ink-1, var(--ink-2));
}

.aiudkast__knapper {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}

.aimangler {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-size: 0.9rem;
    line-height: 1.5;
}

/* Punkttegnet sættes her frem for af modellen. Så ser listen ens ud, uanset om
   modellen huskede at lade være med at skrive en bindestreg foran — og koden
   fjerner den slags i forvejen, netop for at kunne bestemme det her. */
.aimangler li::before {
    content: "· ";
    color: var(--ink-3, var(--ink-2));
    font-weight: 700;
}

/* Sagens tekst og sagsresuméet: den prosa, en tekniker læser på hver eneste sag. Samme læsemål som
   platformens øvrige fritekst — uden loft ville de følge panelet ud i 1000 px lange linjer. */
.sag-tekst { max-width: 78ch; }

.airesume__tekst {
    margin: 0;
    max-width: 78ch;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--ink-1, var(--ink-2));
}

/* Vaerktoejslinjen over fundlisten paa Netvaerksscan: soegning, markering, eksport.
   Wrapper paa smal skaerm frem for at skubbe eksportknappen ud af billedet — den
   sidder yderst til hoejre og ville ellers vaere den foerste, der forsvandt. */
.scanværktøj {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.7rem;
}

.scanværktøj__søg {
    flex: 1 1 18rem;
    max-width: 26rem;
}

/* ms-auto virker ikke, naar raekken wrapper — knappen ville lande alene paa en linje
   med al pladsen foran sig. Under wrap-graensen slaas den fra. */
@media (max-width: 42rem) {
    .scanværktøj .ms-auto {
        margin-left: 0 !important;
    }
}

/* Netvaerksscan udgivelse 2, trin 1: faner pr. agent.
   Et gruppehoved i tabellen skiller "Skiftet adresse" fra "Nye enheder" i Kraever svar-fanen,
   og grundene i arkivfanen — ASCII i klassenavnet, fordi JS'en (netvaerksscan.js) finder
   maalet med querySelector, og et fremmed tegn i en selector er ikke vaerd at risikere. */
.netscan-group td {
    padding: 0.35rem 0.6rem;
    background: var(--line);
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--ink-2);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* En agent uden scanning og uden noget at vise fylder én linje i stedet for et helt panel. */
.netscan-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.65rem 1rem;
}

/* Det dybe link (?agent=&fane=&fund=) sender én bestemt raekke i fokus. */
.netscan-hit {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

/* Slip-felt i dokumentbiblioteket.

   Filfeltet ligger gennemsigtigt hen over hele feltet frem for at vaere en
   haandrullet drop-zone i JavaScript. Browseren fyrer selv change, naar filer
   slippes paa et filfelt, saa klik og slip virker med den samme kode — og
   tastaturbrugere kan tabbe til det. En egen implementering ville skulle holde
   styr paa dragleave over indlejrede elementer og kunne klikkes forbi. */
.slip {
    position: relative;
    border: 2px dashed var(--line-2, #cbd5e1);
    border-radius: 10px;
    padding: 1.1rem;
    margin-bottom: 1rem;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.slip--sigtet {
    border-color: var(--blue-400, #3b82f6);
    background: var(--blue-50);
}

.slip--arbejder {
    border-style: solid;
    opacity: 0.75;
}

.slip__felt {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.slip__felt:disabled {
    cursor: default;
}

/* Fokusringen sidder paa det usynlige felt og ville ikke kunne ses. Den flyttes
   derfor ud paa rammen, saa man kan se hvor man er, naar man tabber rundt.
   The platform's ring (6 October 2026): an outline in --focus-ring, which holds 3:1 (the blue-400 border with a
   glow was 2.87:1 on paper), shows in forced colours, and the gate takes away after a pointer. */
.slip:has(.slip__felt:focus-visible) {
    outline: 2px solid var(--focus-ring);
    outline-offset: 2px;
}

.slip__indhold {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--ink-2, #64748b);
    font-size: 0.9rem;
    pointer-events: none;
}

/* Mappekort som drop-maal. Feltet indsaettes foerst ved traek — laa det der
   altid, ville det spise klikket, og mappen kunne ikke aabnes. */
.fcard--sigtet {
    outline: 2px solid var(--blue-400, #3b82f6);
    outline-offset: 2px;
}

.fcard__slip {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: copy;
}

.fcard {
    position: relative;
}

/* Hjaelpetekst inde i en label maa ikke arve dens versaler.

   .fld label saetter text-transform: uppercase, hvilket er rigtigt for et kort
   feltnavn som «E-MAIL». Laegger man en hel saetning i samme label — fx forklaringen
   under et flueben — bliver den ogsaa til versaler, og en saetning i versaler raaber
   ad laeseren. */
.fld label .fld__hint {
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
}

/* Vidensbase: læsevisning af en artikel. Indholdet er renderet fra Markdown til et sikkert
   HTML-subset (KnowledgebaseMarkdown), så det er almindelige elementer der styles her — ikke
   Blazor-scoped CSS, som ikke når MarkupString-indhold. */
.kb-article {
    max-width: 70ch;
    color: var(--ink-2);
    line-height: 1.65;
}
.kb-article h2, .kb-article h3, .kb-article h4, .kb-article h5, .kb-article h6 {
    color: var(--ink);
    font-weight: 700;
    line-height: 1.3;
    margin: 1.6rem 0 0.6rem;
}
.kb-article h2 { font-size: 1.25rem; }
.kb-article h3 { font-size: 1.1rem; }
.kb-article h4, .kb-article h5, .kb-article h6 { font-size: 1rem; }
.kb-article > :first-child { margin-top: 0; }
.kb-article p { margin: 0 0 0.9rem; }
.kb-article ul, .kb-article ol { margin: 0 0 0.9rem 1.4rem; }
.kb-article li { margin: 0.2rem 0; }
.kb-article a { color: var(--navy-800); text-decoration: underline; }
.kb-article code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.88em;
    background: var(--blue-100);
    color: var(--navy-800);
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
}
.kb-article pre {
    background: var(--blue-100);
    border-radius: 8px;
    padding: 0.9rem 1rem;
    overflow-x: auto;
    margin: 0 0 0.9rem;
}
.kb-article pre code { background: none; padding: 0; }
.kb-article blockquote {
    margin: 0 0 0.9rem;
    padding: 0.2rem 0 0.2rem 1rem;
    border-left: 3px solid var(--blue-100);
    color: var(--ink-2);
}
.kb-article hr { border: 0; border-top: 1px solid var(--blue-100); margin: 1.4rem 0; }

/* Tabeller. Ombryderen er ikke pynt: en tabel med fem kolonner er bredere end en telefon, og
   uden en flade der selv kan rulle, skubber den hele siden sidelæns. */
.kb-tabel { overflow-x: auto; margin: 0 0 1rem; }
.kb-article .kb-tabel { max-width: 100%; }
.kb-article table {
    border-collapse: collapse;
    width: 100%;
    font-size: 0.94rem;
}
.kb-article th, .kb-article td {
    border-bottom: 1px solid var(--blue-100);
    padding: 0.5rem 0.7rem;
    text-align: left;
    vertical-align: top;
}
.kb-article th {
    color: var(--ink);
    font-weight: 700;
    white-space: nowrap;
    border-bottom-width: 2px;
}
.kb-article tbody tr:last-child td { border-bottom: 0; }
/* Tal skal kunne sammenlignes lodret — cifrene skal stå i kolonne, også i en proportional skrift. */
.kb-article td[style*="right"], .kb-article th[style*="right"] { font-variant-numeric: tabular-nums; }

/* Afkrydsningslister. Feltet er låst med vilje — en artikel gemmer ikke noget, og et felt der
   kan klikkes uden at noget sker, lover mere end det holder. Markøren siger det samme. */
.kb-article ul:has(> .kb-opgave) { list-style: none; margin-left: 0; }
.kb-article .kb-opgave { display: flex; align-items: flex-start; gap: 0.5rem; }
.kb-article .kb-opgave input {
    margin: 0.35rem 0 0;
    flex: none;
    cursor: default;
    accent-color: var(--navy-800);
}

/* Billeder må aldrig kunne blive bredere end spalten. */
.kb-article img {
    max-width: 100%;
    height: auto;
    border-radius: 8px;
    margin: 0.3rem 0;
}

.kb-article del { color: var(--ink-3, var(--ink-2)); }

/* ---- NIS2-parathed ------------------------------------------------------ */

.nis-list { display: grid; gap: 0.7rem; margin-top: 0.9rem; }

.nis {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.7rem 0.9rem;
    align-items: start;
    padding: 0.85rem 0.95rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--paper);
}
.nis__mark { align-self: start; margin-top: 0.15rem; white-space: nowrap; }
.nis__main { min-width: 0; }
.nis__title {
    font-weight: 700;
    color: var(--ink);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
/* Fritekst i et 1fr-felt: uden et loft bliver linjerne så lange, at øjet taber linjen på vej tilbage. */
.nis__desc { color: var(--muted); font-size: 0.9rem; margin-top: 0.2rem; line-height: 1.55; max-width: 78ch; }
.nis__finding { color: var(--ink-2); font-size: 0.88rem; margin-top: 0.4rem; line-height: 1.5; max-width: 78ch; }
.nis__evidence {
    display: inline-flex; align-items: center; gap: 0.35rem;
    color: var(--ink-2); font-size: 0.85rem; margin-top: 0.4rem;
}

/* Muted "Automatisk"-markør på lys flade — den hvide .chip-basis dur ikke på et hvidt panel. */
.chip--muted {
    background: var(--line);
    color: var(--muted);
    border-color: var(--line-2);
    backdrop-filter: none;
    padding: 0.16rem 0.55rem;
    font-size: 0.72rem;
    font-weight: 700;
}

.nis__actions { display: flex; gap: 0.5rem; margin-top: 0.6rem; }
.nis__editor {
    margin-top: 0.7rem;
    padding: 0.85rem;
    border: 1px solid var(--line-2);
    border-radius: var(--r-md);
    background: var(--blue-50);
    display: grid;
    gap: 0.6rem;
}
.nis__editor label { display: grid; gap: 0.25rem; font-size: 0.82rem; font-weight: 600; color: var(--ink-2); }
.nis__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
@media (max-width: 640px) {
    .nis__row { grid-template-columns: 1fr; }
    .nis { grid-template-columns: 1fr; }
}

/* ---- overblik: NIS2 ---- */
/* /modules/nis2 as an overview (Nis2Overview.razor, 3 October 2026): the status line with the report on its right,
   the shared tiles and area grid, then ONE list of all controls, problems first. Full rows keep the badge column at a
   fixed width so the titles line up, with the action on the right; met and not-relevant controls are one line each.
   Platform tokens only, so the dark theme follows. The design is docs/arbejde/2026-10-03-overblik-design-5.md. */
.nis-status .status__under b { color: var(--ink); font-variant-numeric: tabular-nums; }
.nis-act { flex-direction: column; align-items: flex-end; gap: 0.25rem; }
.nis-act__hint { font-size: 0.74rem; color: var(--ink-2); }
.nis-act__error { font-size: 0.78rem; font-weight: 650; color: var(--crit-ink); }
@media (max-width: 700px) {
    .nis-act { align-items: flex-start; }
}

.nisv__head { flex-wrap: wrap; row-gap: 0.5rem; }
.nisv__head .listnote { margin-bottom: 0; }
.nisv__frame { margin: 0 0 0.4rem; }
.nisv__grp { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.2rem 0.5rem; margin: 1.2rem 0 0.1rem; font-size: 0.68rem; font-weight: 750; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.nisv__grp b { font-variant-numeric: tabular-nums; color: var(--ink-2); letter-spacing: 0; }
.nisv__hint { text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 0.78rem; color: var(--muted); }
.nisv .nis-list { margin-top: 0.5rem; }
.nisv .nis { grid-template-columns: 6.6rem minmax(0, 1fr) auto; gap: 0.3rem 1rem; }
.nisv .nis__mark { justify-self: start; }
.nisv .nis--crit { border-left: 3px solid var(--crit); }
.nisv .nis--warn { border-left: 3px solid var(--warn); }
.nisv .nis--unk { border-left: 3px solid var(--line-2); }
.nis__area { font-size: 0.78rem; color: var(--muted); margin-top: 0.1rem; }
.nis__when { margin-top: 0.25rem; }
.nis__side { align-self: start; }
.nis__link { font-size: 0.82rem; font-weight: 650; color: var(--link); text-decoration: none; white-space: nowrap; }
.nis__link:hover { text-decoration: underline; }
/* On a phone the area tile keeps its grid but not its scope line (design-5): beside «Område for område» the scope only
   ran out as an ellipsis. The pairs rule leaves Full tiles whole, so this one says it for itself. */
@container tiles (max-width: 540px) {
    .tile[data-tile="nis-areas"] .tile__scope:not(.tile__scope--on):not(.tile__scope--failed) { display: none; }
}
@media (max-width: 640px) {
    .nisv .nis { grid-template-columns: minmax(0, 1fr); gap: 0.45rem; }
    .nis__side { justify-self: start; }
}

.nisc { display: grid; grid-template-columns: 6.6rem minmax(0, 1.25fr) minmax(0, 1fr) auto; gap: 0.3rem 1rem; align-items: center; padding: 0.6rem 0.2rem 0.6rem 0.95rem; border-top: 1px solid var(--line); font-size: 0.875rem; }
.nisc:first-child { border-top: 0; }
.nisc__title { min-width: 0; font-weight: 650; color: var(--ink); }
.nisc__title small { display: block; font-weight: 500; font-size: 0.78rem; color: var(--muted); }
.nisc__ev { display: flex; align-items: flex-start; gap: 0.35rem; min-width: 0; font-size: 0.82rem; color: var(--ink-2); }
.nisc__ev .icon { flex-shrink: 0; }
.nisc__ev span { min-width: 0; overflow-wrap: anywhere; line-height: 1.4; }
.nisc__end { display: flex; align-items: center; justify-content: flex-end; gap: 0.7rem; }
.nisc__end .stat__meta { white-space: nowrap; }
@media (max-width: 760px) {
    .nisc { grid-template-columns: auto minmax(0, 1fr); padding-left: 0.2rem; }
    .nisc__ev, .nisc__end { grid-column: 2; justify-content: flex-start; }
    .nisc__end { flex-wrap: wrap; row-gap: 0.3rem; }
}
/* ---- /overblik: NIS2 ---- */

/* ---- overblik: Cyberforsikring ---- */
/* /modules/cyber-insurance as an overview (CyberInsuranceOverview.razor, 3 October 2026), built like NIS2's: it reuses
   the NIS2 list classes above (.nis-status, .nisv, .nis, .nisc, .nis-act) and the shared tiles. Only what is its own
   is here: the area tile's scope gives way on a phone, as NIS2's does (the pairs rule leaves Full tiles whole). */
@container tiles (max-width: 540px) {
    .tile[data-tile="cyber-areas"] .tile__scope:not(.tile__scope--on):not(.tile__scope--failed) { display: none; }
}
/* ---- /overblik: Cyberforsikring ---- */

/* ---- overview: DORA readiness ---- */
/* /modules/dora (DoraOverview.razor, 21 October 2026), cloned from the cyber insurance overview: it reuses the NIS2 list
   classes (.nis-status, .nisv, .nis, .nisc, .nis-act) and the shared tiles. Only its own area tile is named here, so
   the tile's scope gives way on a phone as the other two do. */
@container tiles (max-width: 540px) {
    .tile[data-tile="dora-areas"] .tile__scope:not(.tile__scope--on):not(.tile__scope--failed) { display: none; }
}
/* ---- /overview: DORA readiness ---- */


/* ---- GDPR-fortegnelse (RoPA) ------------------------------------------- */
.ropa-list { display: grid; gap: 1rem; }
/* A grid item is min-width:auto: one wide table inside a panel (the incident register's deadlines) pushed the whole page
   sideways on a phone instead of scrolling in its own .tbl-wrap. */
.ropa-list > * { min-width: 0; }
.ropa__head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 0.8rem; flex-wrap: wrap; margin-bottom: 0.8rem;
}
.ropa__navn { font-weight: 800; color: var(--ink); font-size: 1.02rem; }
.ropa__meta { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.ropa__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 1.4rem; }

.felt { min-width: 0; }
.felt--bred { grid-column: 1 / -1; }
.felt__etiket { font-size: 0.72rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--muted); font-weight: 700; }
/* GDPR-teksterne er hele afsnit i et 1fr-felt — samme læsemål som de øvrige fritekster. */
.felt__vaerdi { color: var(--ink-2); font-size: 0.92rem; line-height: 1.5; white-space: pre-wrap; max-width: 78ch; }
.felt__vaerdi--tom { color: var(--muted); }

/* Kom-i-gang-skabeloner */
.ropa-forslag { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0.7rem; margin-top: 0.9rem; }
.ropa-forslag__k {
    display: grid; gap: 0.2rem; text-align: left; padding: 0.75rem 0.9rem;
    border: 1px solid var(--line-2); border-radius: var(--r-md); background: var(--blue-50); cursor: pointer;
    transition: box-shadow 0.13s ease, transform 0.13s ease;
}
.ropa-forslag__k:hover { box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.ropa-forslag__k:disabled { opacity: 0.6; cursor: default; transform: none; box-shadow: none; }
.ropa-forslag__navn { font-weight: 700; color: var(--ink); }
.ropa-forslag__hint { font-size: 0.82rem; color: var(--muted); line-height: 1.4; }
.ropa-forslag__plus { font-size: 0.78rem; font-weight: 700; color: var(--blue-500); }

/* Editor-form */
.ropa-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
.ropa-check {
    display: flex; align-items: flex-start; gap: 0.5rem; margin-bottom: 1rem;
    font-size: 0.9rem; color: var(--ink-2); line-height: 1.4;
}
.ropa-check input { margin-top: 0.2rem; }

@media (max-width: 640px) {
    .ropa__grid, .ropa-form__row { grid-template-columns: 1fr; }
}

/* The record's compact list (25 October 2026): one line per activity (name · purpose · legal basis) in one panel, each
   a <details> that folds out to the full card. The arrow is drawn, the browser's own marker hidden. */
.ropa-compact__cols,
.ropa-row__sum { display: grid; grid-template-columns: minmax(10rem, 1.1fr) 2fr minmax(9rem, 1fr); gap: 0.3rem 1.2rem; align-items: baseline; }
.ropa-compact__cols {
    padding: 0 0.4rem 0.5rem 1.6rem;
    font-size: 0.72rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--muted); font-weight: 700;
}
.ropa-row { border-top: 1px solid var(--line); }
.ropa-row__sum { position: relative; padding: 0.7rem 0.4rem 0.7rem 1.6rem; cursor: pointer; list-style: none; border-radius: var(--r-sm); }
.ropa-row__sum::-webkit-details-marker { display: none; }
.ropa-row__sum::before {
    content: ""; position: absolute; left: 0.45rem; top: 1.05rem;
    border-left: 0.34em solid var(--muted); border-top: 0.28em solid transparent; border-bottom: 0.28em solid transparent;
    transition: transform 0.12s ease;
}
.ropa-row[open] > .ropa-row__sum::before { transform: rotate(90deg); }
.ropa-row__sum:hover { background: var(--shell); }
.ropa-row__name { font-weight: 700; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.ropa-row__purpose { color: var(--ink-2); font-size: 0.9rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ropa-row__basis { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; font-size: 0.85rem; color: var(--muted); }
.ropa-row__card { padding: 0.3rem 0.4rem 1.1rem 1.6rem; }

@media (max-width: 640px) {
    .ropa-compact__cols { display: none; }
    .ropa-row__sum { grid-template-columns: 1fr; gap: 0.15rem; }
    .ropa-row__purpose { white-space: normal; }
    .ropa-row__card { padding-left: 0.4rem; }
}

/* ---- DORA register of ICT suppliers (/modules/dora/leverandoerer, 22 October 2026) -------------------------------
   Built on the record of processing's layout above (ropa-list, ropa__head, ropa__grid, felt); only the contract blocks
   inside a supplier, the red edge on a critical contract without an exit plan, and the subcontractor rows are new. */
.dreg__exports { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; margin-top: 1rem; }
/* DORA package 5: the access review's sign-off form under the lists. */
.dacc__form { display: grid; gap: 0.8rem; margin-top: 1rem; max-width: 40rem; }
/* Its own button row: the dialogs' .dlg__foot is sticky with negative margins, made for a modal's body, and outside one its
   rule stopped mid-panel and the row stuck to the bottom of the screen (23 October 2026). */
.dacc__foot { display: flex; justify-content: flex-end; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.4rem; }
.dreg__error { color: var(--crit-ink); margin-top: 0.4rem; }
.dreg__contract { border-top: 1px solid var(--line-2); padding: 0.9rem 0 0.2rem 0.8rem; margin-top: 0.9rem; border-left: 3px solid transparent; }
.dreg__contract--crit { border-left-color: var(--crit); }
.dreg__title { font-weight: 700; color: var(--ink); }
.dreg__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.7rem; }
.dreg__sub { display: grid; grid-template-columns: 2fr 0.6fr 1.4fr auto; gap: 0.5rem; margin: 0.4rem 0; }
/* The register's chips and «mark the selected reviewed» over the suppliers (25 October 2026). */
.dreg__filter { display: grid; gap: 0.6rem; margin-bottom: 1rem; }
.dreg__bulk { display: flex; gap: 0.6rem 1rem; align-items: center; flex-wrap: wrap; }
.dreg__all { display: inline-flex; gap: 0.45rem; align-items: center; font-size: 0.88rem; color: var(--ink-2); cursor: pointer; }
.dreg__all .form-check-input, .dreg__pick { margin: 0; }
.dreg__pick { margin-right: 0.45rem; vertical-align: -0.12em; }

@media (max-width: 640px) {
    .dreg__sub { grid-template-columns: 1fr; }
}

/* ---- DORA incident register (/modules/dora/haendelser, 22 October 2026) -------------------------------------------
   On the same register layout (ropa-list, ropa__head, ropa__grid, felt, dreg__actions): only the red edge on an incident
   with a passed deadline, the decision block, the deadline table and the lists are new. */
.dinc { border-left: 3px solid transparent; }
.dinc--overdue { border-left-color: var(--crit); }
.dinc__desc { margin: 0.6rem 0 0.8rem; color: var(--ink); white-space: pre-line; }
.dinc__decision { border-top: 1px solid var(--line-2); margin-top: 0.9rem; padding-top: 0.7rem; display: grid; gap: 0.25rem; }
.dinc__deadlines { margin-top: 0.9rem; }
/* A status badge in the deadline table may wrap: «Overskredet før omklassificeringen» was cut at the table box on a phone. */
.dinc__deadlines .badge { white-space: normal; text-align: left; }
/* The margin month view's flags wrap too, so the last column stays inside the table on a 1280 screen. */
[data-margin-summary] td .badge { white-space: normal; text-align: left; }
.dinc__hint { margin-top: 0.4rem; }
.dinc__block { border-top: 1px solid var(--line-2); margin-top: 0.9rem; padding-top: 0.7rem; }
.dinc__list { margin: 0.3rem 0 0; padding-left: 1.1rem; display: grid; gap: 0.25rem; }
.dinc__checks { display: flex; flex-wrap: wrap; gap: 0.3rem 1.2rem; }
/* The criteria in their own box: straight under .fld, «.fld > label» made them field headings (grey small capitals). */
.dinc__criteria { display: grid; gap: 0.55rem; }
.dinc__criteria .ropa-check { margin-bottom: 0; }
.dinc__preview { margin: 0.6rem 0; font-weight: 600; color: var(--ink); }

/* ---- Spørg platformen (AI-copilot) ------------------------------------ */
.kop-input { display: flex; gap: 0.6rem; align-items: flex-end; }
.kop-input textarea { flex: 1; resize: vertical; }
.kop-input .btn { flex-shrink: 0; }
.kop-forslag { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.8rem; }
.kop-sp { font-weight: 700; color: var(--ink); margin-bottom: 0.5rem; }
/* Svaret er prosa og læses linje for linje: et loft på læsemålet, uanset hvor bred siden er. */
.kop-tekst { color: var(--ink-2); line-height: 1.65; white-space: pre-wrap; max-width: 78ch; }
.kop-kilder { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.8rem; }
.kop-meta { margin-top: 0.6rem; }
.kop-taenker, .kop-tænker { display: flex; align-items: center; padding: 0.4rem 0; }
.kop-prik {
    width: 7px; height: 7px; border-radius: 999px; background: var(--blue-400);
    margin-right: 4px; display: inline-block; animation: kopblink 1.2s infinite ease-in-out both;
}
.kop-prik:nth-child(2) { animation-delay: 0.2s; }
.kop-prik:nth-child(3) { animation-delay: 0.4s; }
@keyframes kopblink { 0%, 80%, 100% { opacity: 0.25; } 40% { opacity: 1; } }

/* ---- Cockpit (Tillid & efterlevelse) ---------------------------------- */
/* Månedens opsummering er prosa — samme læsemål som de øvrige fritekster. */
.cockpit-narrativ { font-size: 1rem; line-height: 1.7; color: var(--ink-2); margin: 0.4rem 0 0; white-space: pre-wrap; max-width: 78ch; }
.cockpit-tal { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.6rem 1.4rem; margin-top: 1rem; }

/* ---- NOC: mål-først «Tilføj overvågning» ------------------------------ */
/* Mål-vælgeren: klikbare kort i et responsivt gitter. Deler formsprog med
   panelerne (--paper/--line/--r-md/--shadow-sm), så de ikke ser fremmede ud. */
.goalgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 0.7rem;
    margin: 0.2rem 0 0.4rem;
}

.goalcard {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.35rem;
    text-align: left;
    padding: 0.9rem 1rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--paper);
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease;
}

.goalcard:hover {
    border-color: var(--blue-400);
    box-shadow: 0 6px 18px rgba(19, 28, 40, 0.10);
    transform: translateY(-1px);
}

.goalcard:focus-visible { outline: 2px solid var(--blue-500); outline-offset: 2px; }

.goalcard__icon {
    display: inline-flex;
    width: 2.2rem;
    height: 2.2rem;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--line);
    color: var(--ink-2);
}

.goalcard__title { font-weight: 700; color: var(--ink); line-height: 1.25; }
.goalcard__sub { font-size: 0.82rem; color: var(--muted); line-height: 1.35; }

@media (max-width: 640px) {
    .goalgrid { grid-template-columns: 1fr; }
}

/* Mål-linjen i formularen: viser det valgte mål med en diskret «Skift»-genvej,
   i stedet for den kolde 7-vejs type-dropdown. */
.goalline {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--paper);
}

.goalline__val { font-weight: 600; color: var(--ink); }
.goalline__change { font-size: 0.85rem; }

/* Tastemærket i topbarens søgefelt.
   Erstatter den flydende «Søg eller hop til…»-pille, der lå oven på indholdet i hjørnet og fyldte
   hele tiden for en genvej, man lærer én gang. Her koster den ingen plads og står, hvor man i
   forvejen kigger. Skjules på smalle skærme: der er der ingen tastatur, og så er mærket støj. */
.topsearch__kbd {
    flex-shrink: 0;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--faint);
    background: color-mix(in srgb, var(--ink) 5%, transparent);
    border: 1px solid var(--line);
    border-radius: 5px;
    padding: 0.1rem 0.36rem;
    white-space: nowrap;
}

@media (max-width: 900px) {
    .topsearch__kbd { display: none; }
}

/* ==========================================================================
   Problemgrupper på Domænesikkerhed
   --------------------------------------------------------------------------
   Fundene samlet efter PROBLEM frem for efter domæne. Arbejdet foregår sådan:
   man logger ind hos én DNS-udbyder og retter DMARC på fem domæner. Seksten
   domæner gange otte tjek er 128 felter at skimme; fire linjer er en dagsorden.
   Se Domaenedom for reglen bag rækkefølgen.
   ========================================================================== */

.probs { display: flex; flex-direction: column; gap: 0.55rem; }

.prob {
    border: 1px solid var(--line);
    border-radius: 10px;
    overflow: hidden;
    background: var(--paper);
}

/* Hele overskriften er knappen — ikke en lille pil i kanten. Rækken ER handlingen. */
.prob__head {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    width: 100%;
    padding: 0.8rem 1rem;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.prob__head:hover { background: var(--blue-50); }
.prob__head:focus-visible { outline: 2px solid var(--brass); outline-offset: -2px; }

/* Alvoren som en kant i venstre side. Farve OG plads, så den kan ses uden at læse. */
.prob__sev {
    width: 3px;
    align-self: stretch;
    border-radius: 2px;
    background: var(--warn);
    flex-shrink: 0;
}

.prob--krit .prob__sev { background: var(--crit); }
.prob--tapet .prob__sev { background: var(--line-2); }

.prob__n {
    font-size: 1.3rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    min-width: 1.7rem;
    text-align: right;
    flex-shrink: 0;
}

.prob--krit .prob__n { color: var(--crit); }
.prob--tapet .prob__n { color: var(--muted); font-weight: 700; }

.prob__tekst { min-width: 0; flex: 1; }
.prob__t { font-weight: 700; display: block; }
.prob__d { font-size: 0.82rem; color: var(--muted); display: block; margin-top: 0.1rem; }

/* Mærkat for det, der gælder næsten alle. Se Domaenedom.TapetGrænse: et fund på 16 af 16
   er ikke seksten fund — det er en beslutning, vi ikke har truffet, og den skal ikke fylde
   som seksten. */
.prob__mrk {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.1rem 0.45rem;
    border: 1px solid var(--line-2);
    border-radius: 999px;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    vertical-align: 0.1em;
}

.prob__pil {
    width: 7px; height: 7px;
    border-right: 1.5px solid var(--faint);
    border-bottom: 1.5px solid var(--faint);
    transform: rotate(-45deg);
    flex-shrink: 0;
    transition: transform 0.14s ease;
}

.prob__head[aria-expanded="true"] .prob__pil { transform: rotate(45deg); }

.prob__body {
    padding: 0.9rem 1rem 1rem 2.55rem;
    border-top: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.doms { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.dom {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    padding: 0.22rem 0.55rem;
    border: 1px solid var(--line-2);
    border-radius: 6px;
    background: var(--paper);
    color: var(--ink-2);
    cursor: pointer;
}

.dom:hover { border-color: var(--brass); color: var(--ink); }
.dom:focus-visible { outline: 2px solid var(--brass); outline-offset: 1px; }
.dom__kunde { font-family: var(--font); font-size: 0.7rem; color: var(--faint); }

/* Rettelsen. «SPF har 9 opslag» er en diagnose; posten, der skal stå, er et svar. */
.fix {
    background: var(--blue-50);
    border-radius: 8px;
    padding: 0.75rem 0.9rem;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

.fix__t {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--brass);
}

.fix__rec {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    line-height: 1.7;
    color: var(--ink);
    word-break: break-all;
}

.fix__note { font-size: 0.82rem; color: var(--muted); }

@media (max-width: 640px) {
    .prob__head { gap: 0.6rem; padding: 0.7rem 0.8rem; }
    .prob__body { padding-left: 0.8rem; }
    .prob__d { font-size: 0.78rem; }
}

/* ==========================================================================
   Grene i Driftsovervågning: årsagen og det, der står bag den
   --------------------------------------------------------------------------
   Da routeren gik ned, blev det til seks lige store kort: ét nede og fem «kan
   ikke måles». Det er ikke seks problemer — det er ét problem og fem
   konsekvenser. Børnene tegnes derfor som en indrykket, tæt liste og ikke som
   kort: de er ikke fund, man skal undersøge, men OMFANGET af det ene fund
   ovenover. Se Afhaengighedstrae for reglen.
   ========================================================================== */

.grenboern {
    display: flex;
    flex-direction: column;
    margin: -0.35rem 0 0.9rem 1.5rem;
    padding-left: 1rem;

    /* Stregen binder børnene til kortet ovenover. Indrykning alene ligner en
       sorteringsdetalje; stregen siger «de hænger fast i den». */
    border-left: 1px solid var(--line-2);
}

.grenbarn {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    flex-wrap: wrap;
    padding: 0.4rem 0 0.4rem 0.7rem;
    font-size: 0.82rem;
    position: relative;
}

.grenbarn + .grenbarn { border-top: 1px solid var(--line); }

/* Den lille vandrette streg ind til rækken — samme greb som et filtræ. */
.grenbarn::before {
    content: "";
    position: absolute;
    left: -1px;
    top: 1.05em;
    width: 0.55rem;
    border-top: 1px solid var(--line-2);
}

.grenbarn__navn { font-weight: 600; color: var(--ink-2); }

.grenbarn__adr {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.76rem;
    color: var(--muted);
}

/* Årsagen står på HVER række og ikke kun i overskriften: ruller man forbi
   kortet, skal rækken stadig kunne forklare sig selv. */
.grenbarn__aarsag { color: var(--faint); font-size: 0.76rem; margin-left: auto; }

.grenbarn--flere { color: var(--muted); font-size: 0.8rem; }
.grenbarn--flere .grenbarn__navne { color: var(--faint); font-size: 0.76rem; }

@media (max-width: 640px) {
    .grenboern { margin-left: 0.5rem; }
    .grenbarn__aarsag { margin-left: 0; width: 100%; }
}

/* ==========================================================================
   Døgnbåndet på Driftsovervågning
   --------------------------------------------------------------------------
   Pulsstriben findes pr. enhed. Båndet lægger dem oven på hinanden, fordi det
   interessante er, når FLERE striber knækker samme sted: tre enheder med hvert
   sit hak klokken 09.14 er ikke tre uheld, det er én hændelse. Se Driftsbaand.
   ========================================================================== */

.dbaand {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.85rem 1rem;
    margin-bottom: 1rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 10px;
}

.dbaand__hoved { display: flex; align-items: baseline; gap: 0.8rem; flex-wrap: wrap; }

.dbaand__titel {
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--faint);
}

.dbaand__mest { font-size: 0.78rem; color: var(--crit); font-weight: 600; margin-left: auto; }

.dbaand__spor { display: flex; gap: 1px; height: 14px; }

.dbaand__felt {
    flex: 1;
    min-width: 2px;
    border-radius: 1px;

    /* Roligt tegnes SVAGT og ikke grønt. Båndet findes for at vise hakkene; et døgn i fuld
       grøn ville råbe «alt er godt» hen over den ene halve time, hvor det ikke var. */
    background: var(--line-2);
    opacity: 0.55;
}

.dbaand__felt--ned { background: var(--crit); opacity: 1; }

.dbaand__akse {
    display: flex;
    justify-content: space-between;
    font-size: 0.66rem;
    color: var(--faint);
    font-variant-numeric: tabular-nums;
}

/* «Vis de N øvrige» under en foldet sektion. En knap og ikke et link: den gør noget på siden,
   den fører ingen steder hen. */
.epfold {
    display: block;
    width: 100%;
    margin-top: 0.5rem;
    padding: 0.55rem;
    border: 1px dashed var(--line-2);
    border-radius: 8px;
    background: none;
    color: var(--muted);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.epfold:hover { border-color: var(--brass); color: var(--ink-2); }
.epfold:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }

/* Dommen over et domæne — ét ord i stedet for brøken «6/8».
   Brøken var sidens mest fremtrædende tal og det mest misvisende: den vejede DNSSEC lige så tungt
   som DMARC, så 4/8 kunne være fuldt beskyttet og 6/8 kunne lade hvem som helst sende fakturaer i
   kundens navn. Et ord kan ikke lægges sammen, sammenlignes eller jages. Se Domaenedom. */
.domdom {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.72rem;
    font-weight: 700;
    white-space: nowrap;
    letter-spacing: 0.01em;
}

.domdom::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

.domdom--krit { color: var(--crit); }
.domdom--obs { color: var(--warn); }
.domdom--ok { color: var(--good); }
.domdom--ukendt { color: var(--faint); }
.domdom--ukendt::before { background: none; box-shadow: inset 0 0 0 1.5px currentColor; }

/* Pulsstriben inde i den tætte række.
   Den lå før kun i kortet, man skulle folde ud — altså skjult bag et klik pr. enhed. Striben er
   det eneste på siden, der viser et FORLØB, og skjult er den ingenting værd: med den i rækken kan
   fyrre enheder skimmes for «hvem har haft hak i dag» i ét blik. */
.eprow__puls { display: flex; align-items: center; min-width: 0; }

.spark--mini {
    height: 14px;
    width: 100%;
    margin-bottom: 0;
    border-bottom: none;
    padding-bottom: 0;
}

.spark--mini .spark__bar { min-width: 1px; border-radius: 1px; }

@media (max-width: 900px) {
    /* Rækken folder til to linjer på små skærme, og der er ikke plads til striben. Den står
       stadig i kortet, man folder ud — det er ét klik, ikke en manglende oplysning. */
    .eprow__puls { display: none; }
}

/* Gruppeoverskrift inde i den tætte liste. Kundens EGNE grupper — «Hjemmeside», «Servere» —
   ikke tjektype: en gruppe er, hvad kunden selv har kaldt tingene, og det er den inddeling, man
   leder i. Vises kun, når der er mere end én. */
.eprows__grp {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 1rem 0.9rem 0.35rem;
    font-size: 0.62rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--faint);
}

.eprows__grp:first-child { padding-top: 0.2rem; }
.eprows__grpantal { font-size: 0.68rem; letter-spacing: 0; font-weight: 700; color: var(--line-2); }

/* Hvad der er GALT på et domæne — ikke hvor galt.
   Rækken stod før med seks anonyme prikker plus et ord, der var det samme på alle rækker i
   sektionen. Prikkerne skulle afkodes med musen (og kunne slet ikke på en telefon), og ordet
   tilføjede ingenting under en overskrift, der sagde det samme. En kolonne, hvor hver celle siger
   det samme, er død plads. */
.dsp-row__fejl { flex: 1 1 34%; display: flex; flex-wrap: wrap; gap: 0.3rem; min-width: 0; justify-content: flex-end; }

.domfejl {
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0.1rem 0.45rem;
    border-radius: 5px;
    white-space: nowrap;
    border: 1px solid transparent;
}

/* The tone's ink, not its stripe colour: --warn on its own tint measured 3.2:1 (light) and --crit 3.7:1 (dark) in
   tests/domaenesidecheck, 3 October 2026. */
.domfejl--krit { color: var(--crit-ink); background: color-mix(in srgb, var(--crit) 9%, transparent); }
.domfejl--obs { color: var(--warn-ink); background: color-mix(in srgb, var(--warn) 10%, transparent); }
.domfejl--svag { color: var(--muted); border-color: var(--line-2); }
.domfejl--ok { color: var(--good-ink); }

/* ---- overblik: Domænesikkerhed ---- */
/* The Domain security page's own parts around the shared tiles (Components/Shared/Tiles); the design is
   docs/arbejde/2026-10-03-overblik-design-4.md. Everything else on the page is the shared tile language. */

/* The status sub-line when the nightly run has stalled: warm ink, so an old measurement never reads as calm. */
.dsec-stale { color: var(--warn-ink); font-weight: 650; }

/* The search sits in the list note's tool row; on a narrow page it takes a line of its own, last. */
.dsec-search { width: auto; min-width: 14rem; }
@media (max-width: 900px) {
    .listnote__tools { width: 100%; margin-left: 0; }
    .dsec-search { flex: 1 1 100%; min-width: 0; order: 3; }
}

/* «Vis alle N — M mere» at the foot of a section capped in the default view, attached to the rows above it. */
.eprows:has(+ .eprows__more) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.eprows__more {
    display: block;
    width: 100%;
    border: 1px solid var(--line);
    border-top: 0;
    border-radius: 0 0 12px 12px;
    background: color-mix(in srgb, var(--ink) 2%, var(--paper));
    color: var(--link);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 650;
    padding: 0.55rem 0.9rem;
    text-align: left;
    cursor: pointer;
}
.eprows__more:hover { text-decoration: underline; }
.eprows__more:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }

/* The in-order section folded to one line in the default view: it exists, and one click shows it. */
.epsek--fold {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.45rem 0.8rem;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper);
    font-size: 0.86rem;
    color: var(--ink-2);
}
.epsek--fold .epsek__titel { margin: 0; }
.epsek__names { flex: 1 1 12rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.epsek--fold .listnote__all { margin-left: auto; white-space: nowrap; }

/* The affected-customers tile holds buttons (one per customer row, and «+N»): the row the list shows now is marked
   in weight and underline, never colour alone. */
.trows button.r[aria-pressed="true"] .t { font-weight: 750; text-decoration: underline; text-underline-offset: 2px; }
button.trows__more { align-self: flex-start; border: 0; background: none; padding: 0; font: inherit; font-size: var(--tile-fs-meta); color: var(--link); font-weight: 650; cursor: pointer; text-align: left; }
button.trows__more:hover { text-decoration: underline; }
button.trows__more:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }
/* ---- /overblik: Domænesikkerhed ---- */

/* ── Hover-aflæsning på graferne (graf.js) ──────────────────────────────────────────────
   Boksen og trådkorset ligger på <body> og er position:fixed, fordi de skal kunne stå over
   en graf, Blazor gentegner en gang i sekundet. Ét sæt for hele siden, uanset hvor mange
   grafer der er åbne. Ingen pointer-events: de må aldrig spise den bevægelse, der styrer dem. */
.graf-streg {
    position: fixed;
    display: none;
    width: 1px;
    z-index: 1080;
    pointer-events: none;
    background: var(--ink-3);
    opacity: 0.55;
}

.graf-boks {
    position: fixed;
    display: none;
    z-index: 1081;
    pointer-events: none;
    padding: 0.4rem 0.6rem;
    border: 1px solid var(--line-2);
    border-radius: 0.4rem;
    background: var(--paper);
    box-shadow: var(--shadow-md);
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--ink);
    white-space: nowrap;
    /* Tal, der skifter en gang i sekundet, må ikke få boksen til at hoppe i bredden. */
    font-variant-numeric: tabular-nums;
}

.graf-boks__tid {
    color: var(--muted);
    font-size: 0.72rem;
    margin-bottom: 0.1rem;
}

.graf-boks__navn { color: var(--muted); }

/* «ikke målt» er ikke et tal og skal ikke se ud som et. */
.graf-boks__tom {
    color: var(--muted);
    font-style: normal;
}

/* Én række pr. linje i grafen, med linjens egen nøgle foran: fuld, stiplet, ind, ud. */
.graf-boks__rk { display: flex; align-items: center; gap: 0.35rem; }

.graf-boks__swatch {
    display: inline-block;
    flex: none;
    width: 14px;
    height: 0;
    border-top: 2px solid var(--series-now);
}

.graf-boks__swatch--prev { border-top: 2px dashed var(--series-prev); }
.graf-boks__swatch--in { border-top-color: var(--series-in); }
.graf-boks__swatch--out { border-top-color: var(--series-out); }

/* Selve grafen: markér, at der er noget at pege på. pan-y: et lodret stryg ruller stadig siden, et vandret
   træk med fingeren aflæser kurven. */
[data-graf] { cursor: crosshair; touch-action: pan-y; }

/* ── Driftsovervågning på enheden (Enheder.razor) ───────────────────────────────────────
   En enhed er én række, man kan folde ud. Sensorerne ligger indeni, og kanalerne under dem.
   Rækken skal kunne læses på ét blik i en liste på hundrede: prik, navn, hvad der måles,
   puls, tilstand — i den rækkefølge, fordi det er den rækkefølge, øjet spørger i. */
.denhed {
    border-top: 1px solid var(--line);
}

.denhed:first-of-type { border-top: 0; }

/* Kun det, der KRÆVER noget, får en kant. Grøn skal være usynlig — en markering på hver
   række er det samme som ingen markering. */
.denhed--obs { box-shadow: inset 3px 0 0 var(--warn); }

.denhed__hoved {
    display: grid;
    grid-template-columns: 1rem 0.7rem minmax(9rem, 1.5fr) minmax(0, 1.3fr) 4.5rem auto 7rem;
    align-items: center;
    gap: 0.7rem;
    width: 100%;
    padding: 0.6rem 0.4rem;
    background: none;
    border: 0;
    text-align: left;
    color: inherit;
    cursor: pointer;
    font: inherit;
}

.denhed__hoved:hover { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.denhed__hoved:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }

.denhed__pil {
    color: var(--muted);
    font-size: 0.8rem;
}

.denhed__navn { min-width: 0; }

.denhed__sensorer,
.denhed__tilstand {
    color: var(--muted);
    font-size: 0.82rem;
}

.denhed__tilstand {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.dprik {
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    display: inline-block;
    flex: 0 0 auto;
}

.dprik--ok { background: var(--good); }
.dprik--obs { background: var(--warn); }
.dprik--nede { background: var(--crit); }
.dprik--krit { background: var(--crit); }

/* «Ukendt» og «delvis» er ikke grønne og ikke røde. De er huller, og et hul skal ses som et hul
   — en grøn prik over noget, vi ikke har målt, er husets værste fejl i prikform. */
.dprik--ukendt {
    background: repeating-linear-gradient(45deg, var(--muted) 0 2px, transparent 2px 4px);
    border: 1px solid var(--muted);
}

.dprik--delvis {
    background: var(--good);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 60%, transparent);
}

.spark--lille {
    height: 1.1rem;
    min-width: 6rem;
    gap: 1px;
}

.denhed__krop {
    padding: 0.2rem 0.4rem 0.9rem 2.4rem;
}

.dsensor {
    border-left: 2px solid var(--line-2);
    padding: 0.45rem 0 0.45rem 0.7rem;
    margin-bottom: 0.4rem;
}

.dsensor__hoved {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    flex-wrap: wrap;
}

.dsensor__vaerdi {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

/* The expanded row, slimmed (19 September 2026): «check now» at the end of the sensor's line, and its measurements
   counted in one line that leads to the device page, where they are drawn. */
.dsensor__tjek {
    padding: 0 0.25rem;
    line-height: inherit;
}

.dsensor__maalinger {
    margin-top: 0.15rem;
    font-size: 0.82rem;
}

.dsensor__maalinger a {
    color: var(--muted);
    text-decoration: none;
}

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

.dsensor__fejl {
    color: var(--crit-ink, var(--crit));
    font-size: 0.8rem;
    margin-top: 0.25rem;
}

.dmaerke {
    font-size: 0.7rem;
    padding: 0.05rem 0.35rem;
    border-radius: 0.25rem;
    border: 1px solid var(--line-2);
    color: var(--muted);
}

/* Kanalerne: to kolonner, navn til venstre og tal til højre, så de kan læses lodret.
   Tabular-nums, fordi et tal, der skifter en gang i minuttet, ikke må rykke i kolonnen. */
.dkanaler {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 0.1rem 1.5rem;
    margin-top: 0.4rem;
}

.dkanal {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 4.5rem auto;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.82rem;
    padding: 0.12rem 0;
    border-bottom: 1px dotted var(--line);
}

.dkanal__navn { color: var(--muted); }

.dkanal__vaerdi { font-variant-numeric: tabular-nums; }

.dkanal__vaerdi--obs {
    color: var(--warn);
    font-weight: 600;
}

.denhed__handlinger {
    margin-top: 0.5rem;
    padding-top: 0.4rem;
    border-top: 1px dotted var(--line);
}

@media (max-width: 780px) {
    .denhed__hoved {
        grid-template-columns: 1rem 0.7rem 1fr auto;
        row-gap: 0.2rem;
    }

    /* Linje 1: navnet og tilstandsordet.
       Tilstanden faldt før igennem til en linje for sig selv og landede i PILENS kolonne — 16 px
       til «svarer ikke», som så flød ud over sin boks, fordi sporet ikke kunne rumme den. Det er
       det ene ord på rækken, der skal kunne læses. */
    .denhed__tilstand { grid-column: 4; text-align: right; }

    /* Linje 2: sensorerne og tallet — hvor længe den ikke har svaret, eller hvor hurtigt den gør. */
    .denhed__sensorer { grid-column: 3; }
    .denhed__ms { grid-column: 4; display: block; text-align: right; }

    /* Linje 3: 2-timers-striben i fuld bredde.
       Den var skjult her. Men den er det eneste på rækken, der viser FLAPNING — en enhed, der ikke
       er nede nu, men har været det tre gange i dag — og en overvågningsside læses netop på en
       telefon om aftenen. Rækken vokser fra 89 til 115 px; det er prisen for oplysningen. */
    .spark--lille { grid-column: 3 / -1; display: flex; }

    .denhed__krop { padding-left: 1rem; }
}

.dafsnit {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    margin: 1.4rem 0 0.5rem;
    font-weight: 600;
}

.dafsnit:first-of-type { margin-top: 0; }

.dmaerke--obs {
    color: var(--warn-ink); /* the ink, not the stripe colour: 3.6:1 on paper in the light theme (driftsidecheck, 3/10) */
    border-color: color-mix(in srgb, var(--warn) 45%, transparent);
}

.dsensor__live { padding-left: 0; }

.denhed__ms {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--muted);
    font-size: 0.82rem;
}

.denhed__sensorer {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    min-width: 0;
}

.denhed__sensorer > span:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* «Kendes også af» — de andre moduler, der kender den samme maskine. En oplysning om enheden,
   ikke et modul for sig; derfor står den nederst i udfoldningen og ikke øverst. */
.dkendt {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.3rem 0.8rem;
    margin-top: 0.6rem;
    padding-top: 0.5rem;
    border-top: 1px dotted var(--line);
    font-size: 0.8rem;
}

.dkendt__mrk {
    color: var(--muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.dkendt__link { text-decoration: none; }
.dkendt__link:hover { text-decoration: underline; }

/* Forslaget i «Tilføj enhed». Fluebenene skal se ud som beslutninger, ikke som en formular:
   én linje pr. ting, med begrundelsen ovenover og ikke gemt i et værktøjstip. */
.dforslag {
    margin-top: 1rem;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--line-2);
    border-radius: 0.5rem;
    background: color-mix(in srgb, var(--good) 5%, transparent);
}

.dforslag__hoved {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 0.25rem;
}

.dforslag__valg {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    padding: 0.3rem 0;
    cursor: pointer;
}

.dforslag__valg input { margin-top: 0.15rem; }

/* «Flyt til en anden kunde»: hvad der flytter med, én linje pr. slags historik. */
.dflyt__liste {
    margin: 0.3rem 0 0.2rem;
    padding-left: 1.1rem;
}

.dflyt__liste li { padding: 0.1rem 0; }

/* Kurven bag hvert kanaltal. Dæmpet med vilje: den er en BAGGRUND for tallet, ikke en graf i
   sig selv — bliver den lige så tydelig som værdien, kæmper de om øjet, og listen bliver til
   femten diagrammer i stedet for femten aflæsninger. */
.dkanal__kurve {
    width: 4.5rem;
    height: 1.1rem;
    display: block;
    color: var(--muted);
    opacity: 0.65;
}

.dkanal:hover .dkanal__kurve {
    opacity: 1;
    color: var(--brand);
}

/* Kanaler uden kurve — tekstmålinger som «Beskrivelse» — skal ikke få tallet til at hoppe
   ud i en anden kolonne end naboens. Den tomme plads holdes. */
.dkanal > .dkanal__vaerdi:nth-child(2) { grid-column: 3; }

@media (max-width: 780px) {
    .dkanal { grid-template-columns: minmax(0, 1fr) auto; }
    .dkanal__kurve { display: none; }
}

/* Oppetiden i udfoldningen. Tallet stort nok til at læses, teksten under lille nok til ikke at
   konkurrere — og «hvor langt vi har kigget» står altid med, så procenten ikke lover mere end
   den dækker. */
.dopptid {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-top: 0.6rem;
    padding-top: 0.5rem;
    border-top: 1px dotted var(--line);
}

.dopptid__tal {
    font-size: 1.05rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.dmaerke--kvit {
    color: var(--good-ink); /* likewise: 4.2:1 as the stripe colour */
    border-color: color-mix(in srgb, var(--good) 45%, transparent);
}

/* Et tal, der lige har ændret sig. Kort og dæmpet: markeringen skal kunne fanges i øjenkrogen
   på en side, man har stående åben — ikke kræve opmærksomhed som en advarsel. */
@keyframes drift-nyt-blink {
    0%   { background: color-mix(in srgb, var(--brand) 26%, transparent); }
    100% { background: transparent; }
}

.drift-nyt {
    animation: drift-nyt-blink 1.6s ease-out;
    border-radius: 0.2rem;
}

/* En række, der bliver til et problem, glider ind. Den, der har siden stående åben, skal kunne
   se, at der KOM noget — ikke bare at listen ser anderledes ud end sidst man kiggede. */
@keyframes drift-ind {
    from { opacity: 0; transform: translateY(-0.35rem); }
    to   { opacity: 1; transform: none; }
}

.denhed--obs { animation: drift-ind 0.35s ease-out; }

/* Tastaturvalget skal kunne ses tydeligt — ellers er j/k en genvej, man taber undervejs. */
.denhed__hoved:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: -2px;
    background: color-mix(in srgb, var(--brand) 7%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    .drift-nyt, .denhed--obs { animation: none; }
}

/* Portlisten i forslaget. Rulbar, fordi en 48-ports switch ellers skubber knapperne ud af
   dialogen — og den, der ikke kan se «Opret», tror at der mangler noget. */
.dporte {
    margin-top: 0.7rem;
    padding-top: 0.6rem;
    border-top: 1px dotted var(--line-2);
    max-height: 15rem;
    overflow-y: auto;
}

.dporte__hoved {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 0.3rem;
    position: sticky;
    top: 0;
    background: var(--paper);
}

.dport {
    display: grid;
    grid-template-columns: 1.1rem minmax(0, 1fr) 5rem 3rem;
    align-items: center;
    gap: 0.4rem;
    padding: 0.15rem 0;
    font-size: 0.82rem;
    cursor: pointer;
}

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

.dport__fart {
    text-align: right;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.dport__op {
    text-align: right;
    color: var(--muted);
    font-size: 0.75rem;
}

/* «Derfor er den markeret». Står før navne- og gruppefelterne, fordi det er det første spørgsmål —
   og fordi et svar, man skal rulle ned til, er et svar, folk holder op med at lede efter.
   (Sensorlisten står stadig over den; «øverst i udfoldningen» er den altså ikke.) */
.dgrund {
    margin-bottom: 0.6rem;
    padding: 0.5rem 0.7rem;
    border-radius: 0.4rem;
    background: color-mix(in srgb, var(--warn) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn) 28%, transparent);
    font-size: 0.83rem;
}

.dgrund__hoved {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 0.2rem;
}

.dgrund__linje { padding: 0.08rem 0; }

.dkvit {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.6rem;
}

.dkvit__grund { flex: 1 1 18rem; max-width: 26rem; }

/* Gemte visninger. Små og lavmælte: de er genveje, ikke navigation — og skal ikke se ud som
   faner, man SKAL vælge imellem. */
.dvisninger {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    flex-wrap: wrap;
}

.dvisning {
    border: 1px solid var(--line-2);
    background: none;
    color: var(--ink-2);
    border-radius: 1rem;
    padding: 0.1rem 0.6rem;
    font-size: 0.76rem;
    cursor: pointer;
    max-width: 10rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dvisning:hover { border-color: var(--brand); color: var(--brand); }
.dgem { padding-left: 0; padding-right: 0; white-space: nowrap; }

/* The header's add menu (25 October 2026): a native details element, drawn as a small popover under its button - the
   customer list's look (Tenants.razor.css). Here and not in a scoped file: a scoped file would stamp every element of
   the monitoring page, whose tests read its markup. */
.noc-add { position: relative; }
.noc-add__button { list-style: none; display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.noc-add__button::-webkit-details-marker { display: none; }
/* A chevron after the label: the button opens a menu, it does not add by itself. */
.noc-add__button::after {
    content: "";
    width: 0.4rem;
    height: 0.4rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-0.12rem) rotate(45deg);
}
.noc-add[open] > .noc-add__button::after { transform: translateY(0.1rem) rotate(225deg); }
/* The network scan's findings on the button itself: a light pill on the primary button. */
.noc-add__count {
    min-width: 1.3rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    background: var(--paper, #fff);
    color: var(--blue-600, #1d4f86);
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.3rem;
    text-align: center;
}
.noc-add__menu {
    position: absolute;
    right: 0;
    top: calc(100% + 0.3rem);
    z-index: 20;
    min-width: 15rem;
    max-width: calc(100vw - 2rem);
    padding: 0.3rem;
    background: var(--paper, #fff);
    border: 1px solid var(--line-2, rgba(19, 28, 40, 0.16));
    border-radius: var(--r-sm, 10px);
    box-shadow: var(--shadow-md, 0 14px 34px rgba(19, 28, 40, 0.09));
}
/* On a phone the header's actions start at the left edge: a menu anchored to the button's right edge would grow off
   the screen to the left, so there it opens rightwards (as the customer list's menu). */
@media (max-width: 640px) {
    .noc-add__menu { left: 0; right: auto; }
}
.noc-add__item {
    display: block;
    width: 100%;
    min-height: 40px;
    padding: 0.5rem 0.7rem;
    text-align: left;
    background: transparent;
    border: 0;
    border-radius: var(--r-btn, 8px);
    color: var(--ink, #16202e);
    font-size: 0.9rem;
    cursor: pointer;
}
.noc-add__item:hover,
.noc-add__item:focus-visible { background: var(--blue-50, #eff4f9); }

/* ---- overblik: Driftsovervågning ---- */
/* The monitoring list around the shared tiles (3 October 2026, docs/arbejde/2026-10-03-overblik-design-1.md): the
   status line, the tiles and the list note are the shared ones; this is only the seam between them and the list.
   The search and the saved views moved from the status panel into the list note's tool row. */
.listnote .dsoeg { width: 15rem; }
@media (max-width: 900px) {
    .listnote .dsoeg { flex: 1 1 12rem; width: auto; min-width: 0; }
}
.noc-empty { margin: 0.2rem 0 1rem; }

/* Graferne på enhedssiden. Her er kurven IKKE en baggrund for et tal — den er det, man kom
   efter, og får derfor sin fulde højde, sin akse og sine grænselinjer. */
.dgraf {
    padding: 0.8rem 0;
    border-top: 1px solid var(--line);
}

.dgraf:first-of-type { border-top: 0; }

.dgraf__hoved {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    margin-bottom: 0.3rem;
}

.dgraf__nu {
    font-variant-numeric: tabular-nums;
    font-size: 1.05rem;
    font-weight: 600;
}

/* ---- overblik: Enhedssiden ---- */
/* The device page's overview (3 October 2026, docs/arbejde/2026-10-03-overblik-design-2.md): the status line and the
   tiles are the shared ones (the Tiles block); this is only what the lists under them need. */

/* What happened: the state as a lamp in its own narrow column, what is still going on tinted. */
.dhist .dhist__g { width: 1.6rem; padding-right: 0; }
.dhist td.dhist__g .lamps { margin: 0; flex-wrap: nowrap; }
.dhist tr.dhist--open td { background: color-mix(in srgb, var(--crit) 6%, transparent); }
/* Scoped to the device page's two lists: a bare .panel > .listnote also matched the ticket queue's note and undid its margin. */
#device-history > .listnote, #device-software > .listnote { margin-top: 0.2rem; }
.dhist .dmaerke { margin-left: 0.4rem; }

/* Installed software: the search sits in the list note's row; the install date never breaks. On a phone the version
   moves under the name and the version and publisher columns go, so the table does not scroll sideways. */
.dsoft__search { width: 22rem; max-width: 100%; }
.dsoft .dsoft__day { white-space: nowrap; }
.dsoft__ver { display: none; }
.dsoft__more { margin-top: 0.75rem; }

/* The machine: hardware and Intune as fact lists, read down a column. */
.dmachine { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); gap: 1.4rem 2.5rem; }
.dmachine__part { min-width: 0; }
.dmachine__h { font-size: 0.68rem; font-weight: 750; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.35rem; }
.dfacts { margin: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: 1.4rem; font-size: 0.875rem; }
.dfacts dt, .dfacts dd { padding: 0.42rem 0; border-top: 1px solid var(--line); margin: 0; }
.dfacts dt { color: var(--muted); font-weight: 400; }
.dfacts dd { color: var(--ink); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: 0.5rem; }
.dfacts dd .lamps { margin: 0; flex-shrink: 0; align-self: center; }
.dmachine__part > .hint { margin-top: 0.5rem; }

/* The staff panels: a button in a table row may wrap rather than push the table past a phone's width. */
.dstaff .tbl .btn { white-space: normal; text-align: right; }

@media (max-width: 700px) {
    .dsoft .dsoft__wide { display: none; }
    .dsoft__ver { display: block; color: var(--muted); font-size: 0.78rem; margin-top: 0.1rem; }
    .dsoft__search { width: 100%; }
    .dfacts { column-gap: 1rem; }
    /* The history: who acknowledged goes (the tile and the status line name who is on it now), the cells close up. */
    .dhist th:last-child, .dhist td:last-child { display: none; }
    .dhist thead th, .dhist tbody td { padding-left: 0.45rem; padding-right: 0.45rem; }
    .dhist thead th { white-space: normal; }
}
/* ---- end: Enhedssiden ---- */

.dport--fund { grid-template-columns: 1.1rem minmax(0, 1fr) auto; }

.dprofil {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.4rem;
}

/* Det, en handling KOSTER, står med i linjen — ikke i en advarsel bagefter. Gul, fordi det er
   noget man skal vide, ikke noget der er galt. */
.dport__advar {
    color: var(--warn);
    font-size: 0.76rem;
    text-align: right;
}

/* Sensorens verber. Diskrete, fordi de er der hele tiden og kun bruges sjældent — en række
   knapper i fuld styrke ved hver sensor ville tage opmærksomheden fra det, der måles. */
.dhandling {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    flex-wrap: wrap;
    margin-top: 0.35rem;
}

.dhandling .btn-link { padding-left: 0.35rem; padding-right: 0.35rem; }

/* To felter side om side i en dialog. Falder sammen på smal skærm, så et talfelt aldrig bliver
   så smalt, at man ikke kan se, hvad man skriver. */
.drow {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 1rem;
}

@media (max-width: 620px) {
    .drow { grid-template-columns: 1fr; }
}

/* Enhed eller tjeneste. To store valg frem for en rulleliste med ti typer: spørgsmålet er ikke
   «hvilken af ti», det er «hvilken slags ting» — og det har kun to svar. */
.dvalgart {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
    margin-bottom: 1rem;
}

.dvalgart__knap {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    text-align: left;
    padding: 0.7rem 0.8rem;
    border: 1px solid var(--line-2);
    border-radius: 0.5rem;
    background: none;
    color: inherit;
    cursor: pointer;
    font: inherit;
}

.dvalgart__knap span { font-size: 0.78rem; color: var(--muted); }
.dvalgart__knap:hover { border-color: var(--brand); }

.dvalgart__knap--valgt {
    border-color: var(--brand);
    background: color-mix(in srgb, var(--brand) 8%, transparent);
}

@media (max-width: 620px) {
    .dvalgart { grid-template-columns: 1fr; }
}

/* Certifikatets udløb. Ikke en fejl og ikke en måling — en dato, der nærmer sig. Neutral, indtil
   den er tæt nok på at kræve noget. */
.dcert {
    font-size: 0.8rem;
    color: var(--muted);
    margin-top: 0.25rem;
}

.dcert--obs {
    color: var(--warn);
    font-weight: 600;
}

/* Tidsaksens gitterstreger. Meget svage: de er en hjælp til at pege, ikke en del af billedet —
   og et gitter, der er lige så tydeligt som kurven, gør grafen sværere at læse, ikke lettere. */
.chart__grid {
    stroke: var(--line-2);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

/* Bunden af værdiaksen lidt fastere end resten af gitteret: den er det, kurven står på. */
.chart__grid--base { stroke: var(--muted); opacity: 0.6; }

/* Tilbagelink over en sides overskrift. Står før titlen og til venstre, fordi det er dér
   øjet leder efter vejen ud — ikke i knapperækken til højre, som er indstillinger. */
.tilbage {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.6rem;
    color: var(--ink-2);
    font-size: 0.9rem;
    text-decoration: none;
}
.tilbage:hover { color: var(--navy-800); text-decoration: underline; }
.tilbage span { font-size: 1.05em; line-height: 1; }
:root[data-theme="dark"] .tilbage:hover { color: var(--link); }

/* Hvad en sensor tjekker. Dæmpet med vilje: den skal kunne læses, når man er i tvivl, og
   overses, når man ikke er — ellers konkurrerer den med tallet, der er det, man kom for. */
.dsensor__hvad {
    font-size: 0.85rem;
    color: var(--ink-2);
    line-height: 1.5;
    margin: 0.15rem 0 0.35rem;
    max-width: 78ch;
}

/* Ticket tabs — REAL tabs, as in a browser. Rendered by TicketTabs.razor, stored per user (TicketTab).

   KC, 18 September 2026: the tabs were pills that moved about and said nothing. Now the queue is the
   first tab, a tab keeps its place, a dot marks news, and the bar reads as tabs: a baseline the tabs
   stand on, and the current one cut out of it and joined to the page below — the shape everybody knows
   from a browser. It scrolls sideways inside itself on a narrow screen rather than wrapping into a
   second list. */
.ftabs {
    display: flex;
    align-items: flex-end;
    gap: 0.2rem;
    margin: 0 0 1rem;
    padding: 0 0.25rem;
    /* The baseline is drawn INSIDE the bar, not as its border: a scroll container clips its children at the
       padding edge, so a tab could never reach down over a border to join the page. An inset shadow sits
       under the tabs, and the current one simply paints over it. */
    box-shadow: inset 0 -1px 0 var(--line-2);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
}

.ftab {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    max-width: 16.5rem;
    border: 1px solid transparent;
    border-bottom: 0;
    border-radius: 0.55rem 0.55rem 0 0;
    font-size: 0.84rem;
    color: var(--ink-2);
    text-decoration: none;
    background: transparent;
}
.ftab:hover { background: var(--blue-50); color: var(--ink); }

.ftab--queue { padding: 0.45rem 0.85rem; font-weight: 600; }

.ftab__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-width: 0;
    padding: 0.45rem 0.2rem 0.45rem 0.75rem;
    color: inherit;
    text-decoration: none;
}
.ftab__nr { color: var(--muted); font-variant-numeric: tabular-nums; }
.ftab__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The one you are on: part of the page below, not a label above it. */
.ftab--current {
    background: var(--paper);
    border-color: var(--line-2);
    color: var(--ink);
}
.ftab--current .ftab__title { font-weight: 600; }

/* News on a case you have open: a dot, and the title in full strength so it is seen at a glance. */
.ftab__dot {
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--link);
}
.ftab--new { color: var(--ink); }
.ftab--new .ftab__title { font-weight: 600; }

/* An unsent reply waits on the case (TicketReplyDrafts). */
.ftab__draft { flex: 0 0 auto; color: var(--muted); font-size: 0.8rem; }

.ftab__close {
    border: 0;
    background: none;
    color: var(--muted);
    font-size: 1rem;
    line-height: 1;
    padding: 0.25rem 0.5rem 0.25rem 0.3rem;
    cursor: pointer;
    border-radius: 0.35rem;
}
.ftab__close:hover { color: var(--ink); background: var(--line); }

/* Sektionsfaner: én ting set fra flere sider. Bevidst UNDERSTREGET, hvor de åbne sagers
   .ftabs er indrammede browserfaner — to bjælker på samme side må ikke se ens ud, når den ene skifter sag
   og den anden kun skifter afsnit. */
.sectabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.1rem;
    margin: 0 0 0.9rem;
    border-bottom: 1px solid var(--line);
}

.sectab {
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    padding: 0.45rem 0.7rem;
    font: inherit;
    font-size: 0.86rem;
    color: var(--muted);
    cursor: pointer;
    white-space: nowrap;
}

.sectab:hover { color: var(--ink); }

.sectab--current {
    color: var(--ink);
    font-weight: 600;
    border-bottom-color: var(--brand);
}

.sectab__count {
    margin-left: 0.35rem;
    font-size: 0.74rem;
    font-weight: 400;
    color: var(--muted);
}

.sectab--current .sectab__count { color: var(--ink-2); }

/* A thin rule between groups of tabs (SectionTabs.Tab Group): daily, periodic, setup on the finance page. */
.sectabs__sep {
    width: 1px;
    align-self: stretch;
    margin: 0.45rem 0.35rem;
    background: var(--line);
}

/* On a phone the strip wraps, and a rule would start a line; the order still reads daily, periodic, setup. */
@media (max-width: 640px) { .sectabs__sep { display: none; } }

/* CountedSection: a section with its count in the header, collapsed at 0. The whole header is the button. */
.csec { margin: 0 0 0.9rem; }
.csec:last-child { margin-bottom: 0; }

.csec__toggle {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.45rem;
    width: 100%;
    padding: 0.35rem 0;
    background: none;
    border: 0;
    font: inherit;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.csec__toggle:focus-visible { outline: 2px solid var(--blue-500, currentColor); outline-offset: 2px; border-radius: 0.3rem; }

.csec__chev {
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

.csec--open .csec__chev { transform: rotate(45deg); }

.csec__count {
    min-width: 1.5rem;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    background: var(--warn-bg);
    color: var(--warn);
    font-size: 0.75rem;
    font-weight: 700;
    text-align: center;
}

.csec__count--zero { background: var(--line); color: var(--muted); }

.csec__nothing { font-weight: 400; font-size: 0.8rem; color: var(--muted); }

.csec__sub { font-size: 0.8rem; color: var(--muted); margin: 0 0 0.5rem 0.95rem; }

.csec__body { padding-top: 0.35rem; }

/* /admin/time's overview tiles and work lists (24 October 2026; the page's tabs 25 October 2026): tiles that link to
   their tab, two by two on a phone, and rows that wrap their buttons under the text instead of scrolling sideways. */
.tact-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 0.75rem; margin-bottom: 1rem; }
@media (max-width: 640px) { .tact-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.6rem; } }
.tact { list-style: none; margin: 0 0 0.5rem; padding: 0; }
.tact__row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; padding: 0.55rem 0; border-top: 1px solid var(--line); }
.tact__row:first-child { border-top: 0; }
.tact__main { flex: 1 1 16rem; min-width: 0; overflow-wrap: anywhere; }
.tact__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.tact__cust { font-weight: 600; margin: 0.6rem 0 0.15rem; }
/* New parties (24 October 2026): the party's proposed time under it, and the CVR field with its look-up button. */
.tact__sub { list-style: none; margin: 0.25rem 0 0; padding: 0 0 0 0.75rem; border-left: 2px solid var(--line); }
.tact__cvr { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.4rem; }
.tact__cvr .form-control { flex: 0 1 9rem; min-width: 7rem; }

/* The card that holds the proposals or the invoicing (25 October 2026): a column, so a section a link asked for
   (&show=over) can stand first without moving the action panel in the page's tree. */
.tov-work { display: flex; flex-direction: column; }
.tov-work > * { min-width: 0; }
.tov-first { order: -1; }

/* The time proposals per customer: the bulk accept above, one row per proposal — tick, source, day, hours, text, the
   covered/billable choice, the buttons — and the routine's reason under it. On a phone the text and the buttons go to
   lines of their own. */
.tprop-bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.9rem; margin: 0 0 0.9rem; }
.tprop-custbar { display: flex; justify-content: flex-end; margin: 0 0 0.35rem; }
.tprops { list-style: none; margin: 0 0 0.4rem; padding: 0; }
.tprop { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.65rem; padding: 0.45rem 0.4rem; border-top: 1px solid var(--line); font-size: 0.9rem; }
.tprop:first-child { border-top: 0; }
.tprop--judge { background: var(--warn-bg); border-radius: 0.35rem; box-shadow: inset 3px 0 0 var(--warn-ink); }
.tprop__ck { flex: 0 0 auto; margin: 0; }
.tprop__src { display: inline-flex; align-items: center; gap: 0.25rem; flex: 0 0 5.2rem; color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.tprop__date { flex: 0 0 5.4rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tprop__hours { flex: 0 0 3.6rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tprop__desc { flex: 1 1 10rem; min-width: 0; overflow-wrap: anywhere; }
.tprop__bill { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; flex: 0 0 auto; }
.tprop__acts { display: flex; flex-wrap: wrap; gap: 0.3rem; flex: 0 0 auto; margin-left: auto; }
.tprop__why { flex-basis: 100%; padding-left: 1.7rem; font-size: 0.8rem; color: var(--warn-ink); overflow-wrap: anywhere; }
.tprop__fixed,
.tprop__none,
.tprop__judge { font-size: 0.76rem; padding: 0.08rem 0.5rem; border-radius: 999px; white-space: nowrap; }
.tprop__fixed { background: var(--good-bg); color: var(--good-ink); }
.tprop__none { background: var(--crit-bg); color: var(--crit-ink); }
.tprop__judge { font-weight: 700; background: var(--warn-ink); color: var(--paper); }
/* The ticket a mail or meeting proposal belongs to, after its text; the pool a row draws on, when the customer has two. */
.tprop__ticket { margin-left: 0.4rem; font-size: 0.8rem; color: var(--muted); white-space: nowrap; }
.tprop__agr { font-size: 0.76rem; color: var(--muted); white-space: nowrap; }

/* The covered/billable choice on a pool proposal's row: two buttons, one pressed. */
.tseg { display: inline-flex; border: 1px solid var(--line); border-radius: 0.4rem; overflow: hidden; }
.tseg__btn { border: 0; background: none; padding: 0.1rem 0.55rem; font: inherit; font-size: 0.78rem; color: var(--muted); cursor: pointer; white-space: nowrap; }
.tseg__btn + .tseg__btn { border-left: 1px solid var(--line); }
.tseg__btn--on { background: var(--line); color: var(--ink); font-weight: 600; }
.tseg__btn:focus-visible { outline: 2px solid var(--blue-500, currentColor); outline-offset: -2px; }

@media (max-width: 560px) {
    .tprop__src, .tprop__date, .tprop__hours { flex-basis: auto; }
    .tprop__srctext { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .tprop__bill { margin-left: auto; }
    .tprop__desc { order: 5; flex-basis: 100%; padding-left: 1.7rem; }
    .tprop__acts { order: 6; margin-left: 1.4rem; }
    .tprop__why { order: 7; }
    .tov-work { padding: 0.9rem 0.7rem; }
    .tprop { gap: 0.3rem 0.45rem; padding-left: 0.3rem; padding-right: 0.3rem; font-size: 0.86rem; }
    .tseg__btn { padding: 0.1rem 0.4rem; font-size: 0.74rem; }
}


/* A queue's number on a tab (the webshop's strip): grey at 0, as above; a pill in the status colours when something
   waits. Two classes' weight, so it also holds on the current tab. The pairs are the house's own ink-on-background
   ones, already checked in tests/kontrastcheck. */
.sectab__count.sectab__count--warn,
.sectab__count.sectab__count--crit {
    padding: 0.05rem 0.42rem;
    border-radius: 999px;
    font-weight: 600;
}

.sectab__count.sectab__count--warn { background: var(--warn-bg); color: var(--warn-ink); }
.sectab__count.sectab__count--crit { background: var(--crit-bg); color: var(--crit-ink); }

/* The second level of a two-level strip (the webshop's areas, then the area's pages): smaller and closer, so the two
   rows read as one strip and its detail, not as two strips. It wraps like the first, so a phone gets short rows. */
.sectabs--sub {
    margin-top: -0.55rem;
    border-bottom-style: dashed;
}

.sectabs--sub .sectab {
    font-size: 0.8rem;
    padding: 0.35rem 0.6rem;
}

/* A group heading among the tiles of a bento page (the webshop's overview): the eyebrow's quiet capitals. */
.ws-group {
    margin: 0.4rem 0 -0.4rem;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--brass);
}

/* The same heading between stacked panels (the webshop settings' four groups): room above, its line close under it. */
.ws-group--page { margin: 1.6rem 0 0.15rem; }
.ws-group--page:first-of-type { margin-top: 0.2rem; }
.ws-group__text { margin: 0 0 0.7rem; font-size: 0.85rem; color: var(--muted); }

/* Panels one under the other with the house's gap. */
.ws-stack { display: flex; flex-direction: column; gap: 1rem; }
.ws-stack > * { margin-top: 0; min-width: 0; }

/* A row of links or buttons that narrow a page (the settings' groups, the agent's proposal kinds). It wraps, so a phone
   gets two short rows and never a row wider than the screen. */
.ws-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0 0 1rem; }
.ws-chips .badge { margin-left: 0.25rem; }

/* Alderen på en fejlende måling. Dæmpet: den er en oplysning om selve målingen, ikke en del
   af fejlen — men den skal stå DÉR, hvor fejlen står, ikke et andet sted på kortet. */
.dsensor__alder {
    color: var(--muted);
    font-weight: 400;
    white-space: nowrap;
}

/* Oprydningsdialogens liste over, hvad der bliver slettet.
   Den skal kunne rulle: et filter kan ramme mange poster, og en dialog, der vokser ud over
   skærmen, skjuler netop den knap, man skal kunne nå. Tokens frem for faste farver, så den
   følger med i mørkt tema. */
.ryd__liste {
    margin-top: 0.9rem;
    border-top: 1px solid var(--line);
    padding-top: 0.7rem;
}

.ryd__ul {
    list-style: none;
    margin: 0 0 0.4rem;
    padding: 0;
    max-height: 15rem;
    overflow-y: auto;
}

.ryd__ul li {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4rem;
    padding: 0.3rem 0;
    border-bottom: 1px solid var(--line);
}

.ryd__ul li:last-child {
    border-bottom: 0;
}

/* Beskrivelsen er den længste del og må gerne tage resten af linjen; tidspunktet skubbes
   til højre, så øjet kan løbe ned ad datoerne uden at læse resten. */
.ryd__ul li .stat__meta:first-of-type {
    flex: 1 1 12rem;
    min-width: 0;
}

.ryd__ul li .stat__meta:last-of-type {
    margin-left: auto;
    white-space: nowrap;
}

/* ==========================================================================
   The operations wall (/driftsskaerm) - the control room, rebuilt 2 October 2026
   (docs/arbejde/2026-10-02-driftsskaerm-wow-dom.md, sections 5 and 9; markup in Components/Wall).

   One 16:9 canvas sized in rem from ONE root: while the wall is on the page, the root font size is
   the smaller of 1/120 of the width and 1/67.5 of the height - 16 px at 1920x1080, 32 px on a 4K
   TV, 11.4 px at 1366x768. Every size below is in rem, so the picture is the same on all three.
   The rule lives on html:has(.wall) only: the rest of the platform never scales. Without :has the
   root stays 16 px, which is right at 1080p.

   Always dark, whatever the viewer's theme: the dark palette's VALUES are re-declared on .wall, so
   every var() below reads them without touching the site-wide data-theme.

   Calm when green: only the clock and the freshness line change. Unmistakable when critical: a 4 px
   red frame and a breathing lamp (opacity, 2.4 s) while it is unacknowledged, for two minutes at most.
   Light on a weak TV PC: no endless animation in any state,
   prefers-reduced-motion turns every animation off. OLED care: dark shell, quiet static labels, no
   large bright fills, and the whole canvas drifts a few pixels over the hour (--drift-x/--drift-y,
   set by driftsskaerm.js).
   ========================================================================== */

html:has(.wall) {
    font-size: min(calc(100vw / 120), calc(100vh / 67.5));
}

html:has(.wall),
html:has(.wall) body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    background: #10161f;
}

.wall {
    --paper: #1a2431;
    --shell: #10161f;
    --ink: #e8eef5;
    --ink-2: #b4c1d1;
    --muted: #96a5b8;
    --faint: #8494a7;
    --line: rgba(255, 255, 255, 0.10);
    --line-2: rgba(255, 255, 255, 0.19);
    --good: #4c9d6d;   --good-bg: #16241b;  --good-ink: #83cf9f;
    --warn: #cc9a48;   --warn-bg: #26200f;  --warn-ink: #e6bd7c;
    --crit: #cf5f55;   --crit-bg: #291715;  --crit-ink: #ec938a;
    --blue-400: #7c9bc0;
    --blue-300: #a5bcd5;
    --focus-ring: var(--blue-400);
    --wall-sea: #0c121a;
    --wall-fs-display: 2.65rem;
    --wall-fs-h1: 1.5rem;
    --wall-fs-h2: 1.2rem;
    --wall-fs-body: 1.05rem;
    --wall-fs-meta: 0.88rem;
    --wall-fs-small: 0.8rem;
    --drift-x: 0px;
    --drift-y: 0px;

    position: fixed;
    inset: 0;
    box-sizing: border-box;
    color: var(--ink);
    background: var(--shell);
    font-family: var(--font);
    font-size: var(--wall-fs-body);
    line-height: 1.3;
    padding: 0.9rem 1.4rem;
    display: grid;
    grid-template-rows: 4.4rem minmax(0, 1fr) 3.9rem;
    gap: 0.85rem;
    overflow: hidden;
}

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

/* OLED: the content drifts, the frame (and its alert border) stays put. */
.wall > * {
    translate: var(--drift-x) var(--drift-y);
}

.wall h2 {
    margin: 0;
}

.wall b {
    font-weight: 650;
}

/* ---------- Top bar ---------- */
.wall-top {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 1.4rem;
    min-width: 0;
}

.wall-brand { display: flex; align-items: center; gap: 0.8rem; min-width: 0; }
.wall-brand__mark {
    flex-shrink: 0;
    width: 2.6rem; height: 2.6rem; border-radius: 0.6rem;
    display: grid; place-items: center;
    border: 1px solid var(--line-2);
    color: var(--muted); font-weight: 800; font-size: 1.2rem;
}
.wall-brand__text { min-width: 0; }
.wall-brand__name { font-size: var(--wall-fs-h1); font-weight: 700; color: var(--ink-2); letter-spacing: -0.01em; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-brand__sub { font-size: var(--wall-fs-meta); color: var(--muted); margin-top: 0.15rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-brand__view { color: var(--faint); letter-spacing: 0.02em; }

.wall-state {
    justify-self: center;
    display: flex; align-items: center; gap: 1rem;
    max-width: 100%;
    padding: 0.55rem 1.4rem 0.55rem 1.1rem;
    border-radius: 999px;
    border: 1px solid var(--line);
    background: rgba(255, 255, 255, 0.02);
}
.wall-state__lamp { flex-shrink: 0; width: 0.95rem; height: 0.95rem; border-radius: 50%; background: var(--good); box-shadow: 0 0 0 0.3rem rgba(76, 157, 109, 0.16); }
.wall-state__text { font-size: var(--wall-fs-h1); font-weight: 650; white-space: nowrap; }
.wall-state__move { font-size: var(--wall-fs-body); color: var(--muted); white-space: nowrap; padding-left: 1rem; border-left: 1px solid var(--line); }
.wall-state__move b { color: var(--ink-2); }
.wall-state--warn .wall-state__lamp { background: var(--warn); box-shadow: 0 0 0 0.3rem rgba(204, 154, 72, 0.16); }
.wall-state--warn .wall-state__text { color: var(--warn-ink); }
.wall-state--muted .wall-state__lamp { background: var(--muted); box-shadow: none; }
.wall-state--crit { background: var(--crit-bg); border-color: rgba(207, 95, 85, 0.75); }
.wall-state--crit .wall-state__lamp { background: var(--crit-ink); box-shadow: 0 0 0 0.3rem rgba(236, 147, 138, 0.22); }
/* Breathing only while something critical is unacknowledged, and for two minutes at most (50 x 2.4 s): an alert that
   stands for hours must not drive the compositor at 60 fps on a weak TV PC (review TV-4). The frame, the capsule and the
   zone stay red and still. */
.wall--breathe .wall-state--crit .wall-state__lamp { animation: wall-breathe 2.4s ease-in-out 50; }
.wall-state--crit .wall-state__text { color: var(--crit-ink); }
.wall-state--crit .wall-state__move { color: #d9a9a3; border-color: rgba(236, 147, 138, 0.25); }
.wall-state--crit .wall-state__move b { color: var(--crit-ink); }

.wall-meta { justify-self: end; display: flex; align-items: center; gap: 1.2rem; min-width: 0; }
.wall-meta__lines { text-align: right; font-size: var(--wall-fs-meta); color: var(--muted); line-height: 1.45; white-space: nowrap; }
.wall-meta__lines b { color: var(--ink-2); font-weight: 600; }

/* Set by driftsskaerm.js every second: warm past 90 seconds without a fresh answer - the one line that must never sit
   still while it quietly goes stale. */
.wall .wall__freshness--stale { color: var(--warn-ink); font-weight: 700; }

.wall__pill {
    display: inline-flex; align-items: center; gap: 0.45rem;
    padding: 0.32rem 0.8rem; border-radius: 999px;
    font-size: var(--wall-fs-meta); font-weight: 650;
}
.wall__pill::before { content: ""; flex: none; width: 0.55rem; height: 0.55rem; border-radius: 50%; background: currentColor; }
.wall__pill--good { background: var(--good-bg); color: var(--good-ink); }
.wall__pill--warn { background: var(--warn-bg); color: var(--warn-ink); }
.wall__pill--crit { background: var(--crit-bg); color: var(--crit-ink); animation: wall-pulse 1.4s ease-in-out 86; }

.wall-clock { text-align: right; line-height: 1; }
.wall-clock__time { font-size: 2.55rem; font-weight: 650; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; min-width: 5ch; min-height: 1em; }
.wall-clock__date { font-size: var(--wall-fs-meta); color: var(--muted); margin-top: 0.3rem; min-height: 1em; white-space: nowrap; }

/* ---------- Main: the map region and the rail ---------- */
.wall-main {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 45rem;
    gap: 0.85rem;
    min-height: 0;
}

.wall-map {
    position: relative;
    display: grid;
    grid-template-rows: minmax(0, 1fr) auto;
    min-height: 0;
    min-width: 0;
    overflow: hidden;
    border-radius: 1rem;
    border: 1px solid var(--line);
    background:
        radial-gradient(ellipse 70% 60% at 62% 48%, rgba(124, 155, 192, 0.06), transparent 70%),
        var(--wall-sea);
}
.wall-map__box { position: relative; min-height: 0; }
.wall-map__canvas { position: absolute; inset: 0.6rem 0 0 0; }
.wall .wall-map__canvas > svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; max-width: none; margin: 0; }

/* Corner brackets: the scope frame. Low contrast, never bright. */
.wall-corner { position: absolute; z-index: 1; width: 1.4rem; height: 1.4rem; border: 0 solid rgba(165, 188, 213, 0.22); pointer-events: none; }
.wall-corner--tl { top: 0.6rem; left: 0.6rem; border-top-width: 2px; border-left-width: 2px; border-top-left-radius: 0.4rem; }
.wall-corner--tr { top: 0.6rem; right: 0.6rem; border-top-width: 2px; border-right-width: 2px; border-top-right-radius: 0.4rem; }
.wall-corner--bl { bottom: 0.6rem; left: 0.6rem; border-bottom-width: 2px; border-left-width: 2px; border-bottom-left-radius: 0.4rem; }
.wall-corner--br { bottom: 0.6rem; right: 0.6rem; border-bottom-width: 2px; border-right-width: 2px; border-bottom-right-radius: 0.4rem; }

/* The server-drawn maps: land darker than a tile so the pins carry the light. */
.wall-dk__land { fill: #172231; stroke: rgba(165, 188, 213, 0.34); stroke-width: 1.1px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.wall-dk__grat { fill: none; stroke: rgba(255, 255, 255, 0.035); stroke-width: 1px; vector-effect: non-scaling-stroke; }
.wall-dk__gratlabel { fill: rgba(150, 165, 184, 0.35); font-family: var(--font); }
.wall-dk__town { fill: rgba(180, 193, 209, 0.42); font-family: var(--font); font-weight: 500; letter-spacing: 0.02em; }
.wall-dk__towndot { fill: rgba(180, 193, 209, 0.35); }
.wall-dk__dot { fill: var(--blue-300); stroke: var(--wall-sea); stroke-width: 1.6px; vector-effect: non-scaling-stroke; }
.wall-dk__housemark { fill: var(--blue-300); stroke: var(--paper); stroke-width: 1.6px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.wall-dk__houselabel { fill: var(--blue-300); font-family: var(--font); font-weight: 650; }

/* A critical customer's halo; it breathes only while the wall is in alert. A changed customer's ripple, once. */
.wall-halo { fill: none; stroke: var(--crit-ink); stroke-width: 2px; vector-effect: non-scaling-stroke; opacity: 0.55; }
.wall--breathe .wall-halo { animation: wall-halo 2.4s ease-in-out 50; }
.wall-ripple { fill: none; stroke: var(--warn-ink); stroke-width: 2px; vector-effect: non-scaling-stroke; opacity: 0; transform-box: fill-box; transform-origin: center; animation: wall-ripple 2.4s ease-out 2; }

/* Alert callouts, in the map's own units. */
.wall-co__box { fill: rgba(41, 23, 21, 0.95); stroke: rgba(207, 95, 85, 0.85); stroke-width: 1.2px; vector-effect: non-scaling-stroke; }
.wall-co__line { stroke: rgba(236, 147, 138, 0.75); stroke-width: 1.5px; vector-effect: non-scaling-stroke; }
.wall-co__k { fill: var(--crit-ink); font-family: var(--font); font-weight: 700; letter-spacing: 0.12em; }
.wall-co__t { fill: var(--ink); font-family: var(--font); font-weight: 650; }
.wall-co__s { fill: #d9a9a3; font-family: var(--font); }

/* The map's corners: legend top left, the count top right, the guest status bottom left - over the sea, never tied to a
   coordinate. */
.wall-hud { position: absolute; z-index: 2; pointer-events: none; }
.wall-hud--tl { top: 1.3rem; left: 1.5rem; }
.wall-hud--tr { top: 1.3rem; right: 1.5rem; text-align: right; }
.wall-hud--bl { bottom: 0.9rem; left: 1.5rem; }
.wall-hud--note { bottom: 0.9rem; right: 1.5rem; font-size: var(--wall-fs-meta); color: var(--warn-ink); }
.wall-hud__eyebrow { font-size: var(--wall-fs-meta); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.wall-hud__title { font-size: 1.9rem; font-weight: 700; letter-spacing: -0.015em; margin-top: 0.2rem; }
.wall-hud__note { font-size: var(--wall-fs-meta); color: var(--muted); margin-top: 0.25rem; }

.wall-legend { list-style: none; margin: 0.9rem 0 0; padding: 0; display: grid; gap: 0.45rem; }
.wall-legend li { display: grid; grid-template-columns: 1.9rem 2.6rem auto; align-items: center; font-size: var(--wall-fs-body); color: var(--ink-2); }
.wall-legend li > svg { width: 1.6rem; height: 1.6rem; overflow: visible; }
.wall-legend .n { font-weight: 750; font-size: 1.45rem; font-variant-numeric: tabular-nums; color: var(--ink); text-align: right; padding-right: 0.7rem; }
.wall-legend .n.is-zero { color: var(--muted); font-weight: 600; }
.wall-legend li.crit, .wall-legend li.crit .n { color: var(--crit-ink); }
.wall-legend li.quiet { grid-template-columns: 1.9rem auto; color: var(--muted); font-size: var(--wall-fs-meta); }
.wall-legend--grid { grid-template-columns: auto auto; column-gap: 1.2rem; margin-top: 0.5rem; }
.wall-sq { display: inline-block; width: 0.9rem; height: 0.9rem; border-radius: 0.2rem; }
.wall-sq--crit { background: var(--crit-ink); }
.wall-sq--ok { background: var(--good-ink); }
.wall-sq--att { background: var(--warn-ink); }
.wall-sq--unm { background: var(--paper); box-shadow: inset 0 0 0 2px var(--muted); }

/* ---------- The 24 h band ---------- */
.wall-band { position: relative; z-index: 2; padding: 0.55rem 1.5rem 0.8rem; border-top: 1px solid var(--line); background: rgba(16, 22, 31, 0.6); }
.wall-band__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; font-size: var(--wall-fs-meta); color: var(--muted); margin-bottom: 0.4rem; white-space: nowrap; }
.wall-band__head b { color: var(--ink-2); font-size: var(--wall-fs-body); }
.wall-band__failed { color: var(--warn-ink); }
.wall-band__cells { display: grid; grid-template-columns: repeat(48, 1fr); gap: 0.19rem; height: 1.35rem; }
.wall-band__cells i { border-radius: 0.19rem; background: rgba(76, 157, 109, 0.42); }
.wall-band__cells i.w { background: var(--warn); }
.wall-band__cells i.c { background: var(--crit); }
.wall-band__cells i.n { background: rgba(255, 255, 255, 0.07); }
.wall-band__cells i.now { outline: 2px solid var(--ink-2); outline-offset: 1px; }
.wall-band__ticks { position: relative; height: 1.05rem; font-size: 0.8rem; color: var(--faint); margin-top: 0.3rem; font-variant-numeric: tabular-nums; }
.wall-band__ticks span { position: absolute; top: 0; white-space: nowrap; }
.wall-band__ticks .wall-band__now { right: 0; }

/* ---------- Rail ---------- */
.wall-rail { display: grid; grid-template-rows: minmax(0, 1fr) 15.2rem; gap: 0.85rem; min-height: 0; min-width: 0; }
.wall-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(3, minmax(0, 1fr)); gap: 0.7rem; min-height: 0; }

.wall-tile {
    position: relative;
    display: flex; flex-direction: column;
    min-height: 0; min-width: 0;
    overflow: hidden;
    padding: 0.75rem 1rem 0.7rem 1.3rem;
    border-radius: 0.9rem;
    border: 1px solid var(--line);
    background: var(--paper);
}
.wall-tile::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px; background: var(--good); opacity: 0.75; }
.wall-tile--warn::before { background: var(--warn); opacity: 1; }
.wall-tile--crit { background: var(--crit-bg); border-color: rgba(207, 95, 85, 0.65); }
.wall-tile--crit::before { background: var(--crit); opacity: 1; }
.wall-tile--muted::before { background: var(--muted); opacity: 0.5; }
.wall-tile__head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; min-width: 0; }
.wall-tile__head h2 { font-size: var(--wall-fs-meta); letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-tile__head span { font-size: var(--wall-fs-small); color: var(--faint); white-space: nowrap; }
.wall-tile__head .wall-tile__failed { color: var(--warn-ink); }
.wall-tile--crit .wall-tile__head h2 { color: var(--crit-ink); }
.wall-tile__hero { display: flex; align-items: baseline; gap: 0.6rem; margin-top: 0.35rem; min-width: 0; }
.wall-tile__num { font-size: var(--wall-fs-display); font-weight: 750; line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wall-tile__num small { font-size: 1.35rem; color: var(--muted); font-weight: 600; letter-spacing: 0; }
.wall-tile__num--crit { color: var(--crit-ink); }
.wall-tile__num--warn { color: var(--warn-ink); }
.wall-tile__num--muted { color: var(--muted); }
.wall-tile__lbl { font-size: var(--wall-fs-body); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-tile__fact { margin-top: auto; padding-top: 0.3rem; font-size: var(--wall-fs-meta); color: var(--muted); line-height: 1.4; }
.wall-tile__fact--top { margin-top: 0.35rem; padding-top: 0; }
.wall-tile__fact b { color: var(--ink-2); }
.wall-tile__fact b.crit { color: var(--crit-ink); }
.wall-tile__fact b.warn { color: var(--warn-ink); }
.wall-tile--crit .wall-tile__fact { color: #d9b5b0; }
.wall-tile__ok { display: inline-flex; align-items: center; gap: 0.45rem; margin-top: 0.35rem; color: var(--good-ink); font-size: var(--wall-fs-body); }
.wall-tile__ok::before { content: ""; width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--good); }

/* Lamp rows: one lamp per real thing (endpoint, run, agent) - a control panel, name-free by construction. */
.wall-lamps { display: flex; flex-wrap: wrap; align-items: center; gap: 0.32rem; margin-top: 0.55rem; }
.wall-lamps i { width: 0.78rem; height: 0.78rem; border-radius: 0.19rem; background: var(--good); opacity: 0.85; }
.wall-lamps i.w { background: var(--warn-ink); opacity: 1; }
.wall-lamps i.c { background: var(--crit-ink); opacity: 1; }
.wall-lamps i.u { background: transparent; box-shadow: inset 0 0 0 1.5px rgba(150, 165, 184, 0.45); opacity: 1; }
.wall-lamps i.off { background: transparent; box-shadow: inset 0 0 0 1.5px rgba(150, 165, 184, 0.45); opacity: 1; }
.wall-lamps--big i { width: 1.25rem; height: 1.25rem; border-radius: 0.25rem; }
.wall-lamps__more { font-size: var(--wall-fs-small); color: var(--muted); font-variant-numeric: tabular-nums; }
.wall-lamps__cap { font-size: var(--wall-fs-meta); color: var(--muted); margin-top: 0.3rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-lamps__cap b { color: var(--ink-2); }
/* The counts under the endpoint lamps wrap rather than cut: what is wrong comes first, and none of it may hide (TV-1). */
.wall-lamps__cap--counts { white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.35; }
.wall-lamps__cap b.crit { color: var(--crit-ink); }
.wall-lamps__cap b.warn { color: var(--warn-ink); }
.wall-tile--crit .wall-lamps__cap { color: #d9b5b0; }

.wall-split { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.4rem; margin-top: 0.45rem; }
.wall-split div { min-width: 0; border-left: 1px solid var(--line); padding-left: 0.6rem; }
.wall-split div:first-child { border-left: 0; padding-left: 0; }
.wall-split b { display: block; font-size: 2.15rem; font-weight: 750; line-height: 1.05; font-variant-numeric: tabular-nums; }
.wall-split b.zero { color: var(--muted); font-weight: 600; }
.wall-split span { display: block; font-size: var(--wall-fs-meta); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.wall-rows { list-style: none; margin: 0.45rem 0 0; padding: 0; display: grid; gap: 0.32rem; }
.wall-rows li { display: grid; grid-template-columns: 0.6rem minmax(0, 1fr) auto; gap: 0.55rem; align-items: baseline; font-size: 1rem; }
.wall-rows li::before { content: ""; width: 0.55rem; height: 0.55rem; border-radius: 50%; background: var(--crit-ink); }
.wall-rows li.warn::before { background: var(--warn-ink); }
.wall-rows .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-rows .t small { color: var(--muted); font-size: var(--wall-fs-meta); }
.wall-rows .a { font-size: var(--wall-fs-meta); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.wall-rows .a.hot { color: var(--crit-ink); font-weight: 650; }
.wall-more { flex-shrink: 0; font-size: var(--wall-fs-meta); color: var(--muted); margin-top: 0.15rem; }
.wall-more:empty { display: none; }

.wall-stats { display: grid; gap: 0.4rem; margin-top: 0.45rem; }
.wall-stat { display: grid; grid-template-columns: minmax(3.3rem, auto) minmax(0, 1fr); align-items: baseline; column-gap: 0.6rem; }
.wall-stat b { font-size: 1.75rem; font-weight: 750; line-height: 1; text-align: right; font-variant-numeric: tabular-nums; }
.wall-stat b.wall-stat__word { font-size: 1.35rem; }
.wall-stat b.ok { color: var(--good-ink); }
.wall-stat b.warn { color: var(--warn-ink); }
.wall-stat b.crit { color: var(--crit-ink); }
.wall-stat b.zero { color: var(--muted); font-weight: 600; }
.wall-stat span { font-size: var(--wall-fs-body); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-stat small { grid-column: 2; font-size: var(--wall-fs-meta); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Bars drawn on the server; the caption carries the maximum (the axis rule). */
.wall-bars { display: grid; grid-template-columns: repeat(24, 1fr); gap: 2px; align-items: end; height: 2.6rem; margin-top: auto; }
.wall-bars i { background: rgba(165, 188, 213, 0.45); border-radius: 2px 2px 0 0; min-height: 2px; }
.wall-bars i.z { background: rgba(255, 255, 255, 0.08); height: 2px; }
.wall-bars i.future { background: transparent; }
.wall-bars__cap { display: flex; justify-content: space-between; gap: 0.6rem; font-size: 0.78rem; color: var(--faint); margin-top: 0.2rem; white-space: nowrap; }
.wall-bars__cap b { color: var(--ink-2); }
.wall-bars__cap span:first-child { overflow: hidden; text-overflow: ellipsis; }
.wall-bars--days { grid-template-columns: repeat(14, 1fr); gap: 0.25rem; height: 3rem; margin-top: 0.7rem; }
.wall-bars--days i { background: rgba(165, 188, 213, 0.35); }
.wall-bars--days i.today { background: var(--blue-300); }

/* ---------- Key figures (calm, staff): slow, own time, kept out of the freshness line ---------- */
.wall-keys {
    display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 0.55rem;
    min-height: 0;
    padding: 0.8rem 1.15rem 0.85rem;
    border-radius: 0.9rem;
    border: 1px solid var(--line);
    background: linear-gradient(180deg, rgba(26, 36, 49, 0.65), rgba(26, 36, 49, 0.35));
}
.wall-keys__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.wall-keys__head h2 { font-size: var(--wall-fs-meta); letter-spacing: 0.13em; text-transform: uppercase; color: var(--muted); font-weight: 650; white-space: nowrap; }
.wall-keys__head span { font-size: var(--wall-fs-small); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-keys__head span.wall-tile__failed { color: var(--warn-ink); }
.wall-keys__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(2, minmax(0, 1fr)); column-gap: 1.1rem; row-gap: 0.5rem; min-height: 0; }
.wall-key { min-width: 0; border-top: 1px solid var(--line); padding-top: 0.45rem; }
.wall-key__v { font-size: 2.05rem; font-weight: 720; letter-spacing: -0.02em; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-key__v small { font-size: 1.1rem; font-weight: 600; color: var(--muted); letter-spacing: 0; }
.wall-key__v .ok, .wall-key__v .warn, .wall-key__v .crit { font-size: 1.35rem; font-weight: 650; }
.wall-key__v .ok { color: var(--good-ink); }
.wall-key__v .warn { color: var(--warn-ink); }
.wall-key__v .crit { color: var(--crit-ink); }
.wall-key__l { font-size: var(--wall-fs-meta); color: var(--ink-2); margin-top: 0.15rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-key__s { font-size: var(--wall-fs-small); color: var(--faint); margin-top: 0.05rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- The critical zone (staff alert): whole rows, no ellipsis on who and what at 40 characters ---------- */
.wall-alarm {
    position: relative;
    display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 0.5rem;
    min-height: 0;
    overflow: hidden;
    padding: 0.85rem 1.15rem 0.8rem;
    border-radius: 0.9rem;
    border: 1px solid rgba(207, 95, 85, 0.75);
    background: var(--crit-bg);
}
.wall-alarm::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 5px; background: var(--crit); }
.wall-alarm__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.wall-alarm__head h2 { font-size: var(--wall-fs-meta); letter-spacing: 0.13em; text-transform: uppercase; color: var(--crit-ink); font-weight: 700; }
.wall-alarm__head span { font-size: 0.85rem; color: #d9a9a3; white-space: nowrap; }
.wall-alarm__rows { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: minmax(0, 4.1rem); align-content: start; gap: 0.45rem; min-height: 0; }
.wall-alarm__row {
    display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 0.7rem; align-items: center;
    min-height: 0;
    padding: 0.25rem 0.85rem;
    border-radius: 0.6rem;
    border: 1px solid rgba(236, 147, 138, 0.18);
    background: rgba(0, 0, 0, 0.22);
}
.wall-alarm__main { min-width: 0; }
.wall-alarm__what { font-size: 1.1rem; font-weight: 650; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-alarm__sub { font-size: var(--wall-fs-meta); line-height: 1.25; color: #d9b5b0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-badge { font-size: 0.85rem; font-weight: 700; padding: 0.22rem 0.6rem; border-radius: 0.4rem; white-space: nowrap; }
.wall-badge--hot { background: var(--crit); color: #fff; }
.wall-badge--ack { background: rgba(255, 255, 255, 0.07); color: var(--ink-2); font-weight: 600; }
.wall-age { min-width: 3.6rem; text-align: right; line-height: 1; }
.wall-age b { display: block; font-size: 1.65rem; font-weight: 750; color: var(--crit-ink); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; white-space: nowrap; }
.wall-age small { font-size: 0.78rem; color: #d9a9a3; }
.wall-alarm__foot { font-size: 0.82rem; color: #c9a19c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-alarm__foot b { color: var(--crit-ink); }

/* ---------- Guest rail: the operations as numbers, the showcase, the alert card ---------- */
.wall-rail--guest { grid-template-rows: 8.4rem minmax(0, 1fr); }
.wall-now { display: grid; grid-template-rows: auto 1fr; gap: 0.4rem; padding: 0.75rem 1.1rem 0.8rem; border-radius: 0.9rem; border: 1px solid var(--line); background: var(--paper); min-height: 0; }
.wall-now__grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
.wall-now__c { min-width: 0; border-left: 1px solid var(--line); padding: 0.1rem 0 0 0.75rem; }
.wall-now__c:first-child { border-left: 0; padding-left: 0; }
.wall-now__c b { display: block; font-size: 2.05rem; font-weight: 750; line-height: 1.05; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wall-now__c b small { font-size: 1.05rem; color: var(--muted); font-weight: 600; }
.wall-now__c b.zero { color: var(--muted); font-weight: 600; }
.wall-now__c b.ok { color: var(--good-ink); }
.wall-now__c b.warn { color: var(--warn-ink); }
.wall-now__c b.crit { color: var(--crit-ink); }
.wall-now__c b.wall-now__word { font-size: 1.6rem; line-height: 1.3; }
.wall-now__c span { display: block; font-size: var(--wall-fs-meta); color: var(--muted); line-height: 1.25; margin-top: 0.15rem; }
.wall-now__c--crit { background: var(--crit-bg); border-radius: 0.5rem; padding-left: 0.6rem; }

.wall-show { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(3, minmax(0, 1fr)); gap: 0.7rem; min-height: 0; }
.wall-show--alert { grid-template-rows: minmax(0, 2.15fr) minmax(0, 1fr); }
.wall-show--alert .wall-galarm { grid-column: span 2; }

.wall-big { position: relative; display: flex; flex-direction: column; min-height: 0; min-width: 0; overflow: hidden; padding: 0.9rem 1.15rem 0.85rem; border-radius: 0.9rem; border: 1px solid var(--line); background: var(--paper); }
.wall-big h2 { font-size: var(--wall-fs-meta); letter-spacing: 0.13em; text-transform: uppercase; color: var(--muted); font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-big__v { font-size: 3.4rem; font-weight: 750; letter-spacing: -0.025em; line-height: 1; margin-top: 0.55rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.wall-big__v small { font-size: 1.5rem; color: var(--muted); font-weight: 600; letter-spacing: 0; }
.wall-big__l { font-size: var(--wall-fs-body); color: var(--ink-2); margin-top: 0.35rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-big__s { margin-top: auto; font-size: var(--wall-fs-meta); color: var(--faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-big__s--first { margin-top: 0.5rem; }
.wall-big__s--first + .wall-big__s { margin-top: auto; }
.wall-big__s b { color: var(--ink-2); }
.wall-meter { height: 0.55rem; margin-top: 0.6rem; overflow: hidden; border-radius: 99px; background: rgba(255, 255, 255, 0.07); }
.wall-meter i { display: block; height: 100%; border-radius: 99px; background: var(--good); opacity: 0.85; }
.wall-days { display: grid; grid-template-columns: repeat(30, 1fr); gap: 2px; height: 1.1rem; margin-top: 0.7rem; }
.wall-days i { border-radius: 2px; background: rgba(76, 157, 109, 0.55); }
.wall-days i.w { background: var(--warn); }
.wall-days i.c { background: var(--crit); }
.wall-days i.n { background: rgba(255, 255, 255, 0.07); }
.wall-stack { display: flex; gap: 2px; height: 0.9rem; margin-top: 0.7rem; overflow: hidden; border-radius: 0.25rem; }
.wall-stack i { display: block; min-width: 2px; opacity: 0.8; }
.wall-stack__p0 { background: #7c9bc0; }
.wall-stack__p1 { background: #a5bcd5; }
.wall-stack__p2 { background: #5c7fa8; }
.wall-stack__rest { background: #8494a7; }
.wall-stack__cap { display: flex; font-size: 0.78rem; color: var(--faint); margin-top: 0.25rem; white-space: nowrap; }
.wall-stack__cap span { min-width: 3.4rem; overflow: hidden; text-overflow: ellipsis; }
.wall-stack__cap span.rest { text-align: right; min-width: 1.6rem; }
.wall-sup { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: 0.6rem; row-gap: 0.3rem; margin-top: 0.6rem; font-size: var(--wall-fs-body); color: var(--ink-2); }
.wall-sup i { align-self: center; width: 0.6rem; height: 0.6rem; border-radius: 50%; background: var(--good); }
.wall-sup i.w { background: var(--warn); }
.wall-sup i.c { background: var(--crit); }
.wall-sup i.n { background: var(--muted); }
.wall-sup span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wall-sup em { align-self: center; font-style: normal; font-size: var(--wall-fs-meta); color: var(--faint); white-space: nowrap; }

.wall-galarm {
    display: grid; grid-template-rows: auto auto auto minmax(0, 1fr) auto auto; gap: 0.35rem;
    min-height: 0; overflow: hidden;
    padding: 1.1rem 1.4rem 1rem;
    border-radius: 0.9rem;
    border: 1px solid rgba(207, 95, 85, 0.75);
    background: linear-gradient(160deg, #3a1b18 0%, var(--crit-bg) 60%);
}
.wall-galarm__k { font-size: var(--wall-fs-meta); letter-spacing: 0.13em; text-transform: uppercase; color: var(--crit-ink); font-weight: 700; }
.wall-galarm__h { font-size: 2.55rem; font-weight: 750; letter-spacing: -0.02em; line-height: 1.08; }
.wall-galarm__p { font-size: var(--wall-fs-h2); color: var(--ink-2); }
.wall-galarm__foot { font-size: var(--wall-fs-meta); color: #c9a19c; }
.wall-galarm__facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem; }
.wall-galarm__facts div { padding: 0.5rem 0.8rem; border-radius: 0.6rem; background: rgba(0, 0, 0, 0.22); }
.wall-galarm__facts b { display: block; font-size: 1.75rem; font-weight: 750; font-variant-numeric: tabular-nums; }
.wall-galarm__facts span { font-size: var(--wall-fs-meta); color: #d9b5b0; }
.wall-galarm--resolved { grid-template-rows: auto auto auto minmax(0, 1fr) auto; border-color: rgba(76, 157, 109, 0.6); background: linear-gradient(160deg, #183022 0%, var(--good-bg) 60%); }
.wall-tl--resolved .wall-tl__line { background: rgba(131, 207, 159, 0.28); }
.wall-tl--resolved .wall-tl__done { background: var(--good-ink); }
.wall-tl--resolved .wall-tl__pt i { border-color: var(--good-ink); background: var(--good-bg); }
.wall-tl--resolved .wall-tl__pt.now i { border-color: var(--good-ink); background: var(--good-ink); }
.wall-tl--resolved .wall-tl__pt span { color: var(--muted); }
.wall-galarm--resolved .wall-galarm__k { color: var(--good-ink); }
.wall-galarm--resolved .wall-galarm__foot { align-self: end; color: var(--muted); }

.wall-tl { position: relative; align-self: center; height: 6.2rem; margin: 0.4rem 0.6rem 0; }
.wall-tl__line { position: absolute; left: 0; right: 0; top: 2.25rem; height: 3px; border-radius: 2px; background: rgba(236, 147, 138, 0.28); }
.wall-tl__done { position: absolute; left: 0; top: 2.25rem; height: 3px; border-radius: 2px; background: var(--crit-ink); }
.wall-tl__pt { position: absolute; top: 0; transform: translateX(-50%); text-align: center; white-space: nowrap; }
.wall-tl__pt b { display: block; font-size: 1.15rem; font-variant-numeric: tabular-nums; }
.wall-tl__pt i { display: block; width: 0.95rem; height: 0.95rem; margin: 0.45rem auto 0.35rem; border-radius: 50%; border: 3px solid var(--crit-ink); background: var(--crit-bg); }
.wall-tl__pt span { font-size: 0.82rem; color: #d9b5b0; }
.wall-tl__pt.first { transform: none; text-align: left; }
.wall-tl__pt.first i { margin-left: -0.3rem; }
.wall-tl__pt.now { transform: translateX(-100%); text-align: right; }
.wall-tl__pt.now i { margin-right: -0.3rem; margin-left: auto; border-color: var(--ink); background: var(--ink); }
.wall-tl__pt.ack { top: 1.82rem; display: flex; flex-direction: column; align-items: center; }
.wall-tl__pt.ack i { order: -1; margin: 0 auto 0.35rem; border-color: var(--warn-ink); }

/* ---------- Ticker ---------- */
.wall-ticker {
    display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 1.1rem;
    min-width: 0; overflow: hidden;
    padding: 0 1.2rem;
    border-radius: 0.9rem;
    border: 1px solid var(--line);
    background: rgba(26, 36, 49, 0.55);
}
.wall-ticker__label { display: flex; align-items: center; gap: 0.55rem; height: 2rem; padding-right: 1.1rem; border-right: 1px solid var(--line); font-size: var(--wall-fs-meta); letter-spacing: 0.13em; text-transform: uppercase; color: var(--muted); font-weight: 650; }
.wall-ticker__label::before { content: ""; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--good); }
.wall--crit .wall-ticker__label::before { background: var(--crit-ink); }
.wall-ticker__items {
    display: flex; overflow: hidden; white-space: nowrap;
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent);
            mask-image: linear-gradient(90deg, #000 88%, transparent);
}
.wall-ev { display: inline-flex; align-items: baseline; gap: 0.55rem; padding: 0 1.25rem; border-left: 1px solid var(--line); font-size: var(--wall-fs-body); color: var(--ink-2); animation: wall-in 0.6s ease-out both; }
.wall-ev:first-child { border-left: 0; padding-left: 0; }
.wall-ev time { font-size: var(--wall-fs-meta); color: var(--faint); font-variant-numeric: tabular-nums; }
.wall-ev b { color: var(--ink); }
.wall-ev .sep { color: var(--faint); }
.wall-ev--good b { color: var(--good-ink); }
.wall-ev--warn b { color: var(--warn-ink); }
.wall-ev--crit b { color: var(--crit-ink); }
.wall-ev--quiet { color: var(--muted); }

/* ---------- The alert frame: 4 px, inset, never a large bright fill ---------- */
.wall--crit::after {
    content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
    box-shadow: inset 0 0 0 4px rgba(207, 95, 85, 0.85), inset 0 0 6rem rgba(207, 95, 85, 0.10);
}
.wall--crit .wall-map { border-color: rgba(207, 95, 85, 0.45); }

/* ---------- Motion: calm by default, nothing at all when the viewer asks for less ---------- */
@keyframes wall-breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@keyframes wall-halo { 0%, 100% { opacity: 0.25; } 50% { opacity: 0.8; } }
@keyframes wall-ripple { from { opacity: 0.8; transform: scale(0.6); } to { opacity: 0; transform: scale(1.8); } }
@keyframes wall-in { from { opacity: 0; transform: translateX(-0.8rem); } to { opacity: 1; transform: none; } }
@keyframes wall-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

@media (prefers-reduced-motion: reduce) {
    .wall *, .wall *::before, .wall *::after, .wall::after { animation: none !important; transition: none !important; }
    .wall-halo { opacity: 0.7; }
    .wall-ripple { display: none; }
}

/* The DMARC chart's value reads «713 mails: 678 godkendt · 35 ikke godkendt», longer than the shared 9.5rem column,
   and its nowrap pushed the text out of the panel. Above 900px this chart alone gets a wider value column; at 900px
   and below the shared rule already gives the value its own line. The value may wrap either way. */
@media (min-width: 901px) {
    .chart__row.chart__row--dmarc { grid-template-columns: 6rem 1fr 19rem; }
}
.chart__row--dmarc .chart__val { white-space: normal; }

/* Customer notes (24 October 2026): one card per note, its secret fields as label + masked value until revealed. The
   value wraps anywhere, so a long key or URL cannot push the card past a phone's width. */
.cnote-list { display: flex; flex-direction: column; gap: 0.75rem; }
.cnote {
    padding: 0.9rem 1rem;
    border-radius: var(--r-md);
    background: var(--paper);
    box-shadow: inset 0 0 0 1px var(--line);
}
.cnote__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.75rem; flex-wrap: wrap; }
.cnote__title { font-weight: 600; }
.cnote__body { margin-top: 0.6rem; }
.cnote__secrets { margin-top: 0.7rem; padding-top: 0.6rem; border-top: 1px solid var(--line); }
.cnote__secret { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; padding: 0.2rem 0; }
.cnote__label { min-width: 10rem; }
.cnote__value { overflow-wrap: anywhere; word-break: break-all; }
.cnote__value--hidden { color: var(--muted); letter-spacing: 0.1em; }
.cnote__edit-secret { display: grid; grid-template-columns: 9rem 1fr 1fr auto; gap: 0.4rem; margin-bottom: 0.4rem; align-items: center; }
@media (max-width: 640px) {
    .cnote__edit-secret { grid-template-columns: 1fr; }
}

/* The note a search hit or a link opened (27 October 2026): marked by its edge, and stopping below the sticky top bar. */
.cnote--focus { box-shadow: inset 0 0 0 2px var(--focus-ring); scroll-margin-top: 5.5rem; }

/* The compact list on a ticket and on the customer page (27 October 2026): one line per note, the whole line a button
   that opens the note's body in place — easy to hit on a phone. Tint on hover, as the ticket rows. */
.cnote-list--compact { gap: 0.4rem; }
.cnote--compact { padding: 0; }
.cnote__toggle {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
    width: 100%;
    padding: 0.6rem 0.8rem;
    border: 0;
    border-radius: var(--r-md);
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.cnote__toggle:hover { background: var(--blue-50, color-mix(in srgb, var(--ink) 3%, var(--paper))); }
.cnote__toggle:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.cnote__read { padding: 0 0.8rem 0.7rem; }
.cnote__read .cnote__body { margin-top: 0; overflow-wrap: anywhere; }
.cnote__has-secrets { margin: 0.4rem 0 0.2rem; }

/* The staff list of every customer's notes (27 October 2026): the filters wrap under each other on a phone. */
.cnote-filters { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.9rem; }
.cnote-filters .form-control { flex: 1 1 14rem; min-width: 0; }
.cnote-filters .form-select { max-width: 100%; }
