/* ==========================================================================
   TodoIT Platform — designsystem
   Eget layout-sprog (app-shell, sidebar, page-header, bento) oven på en
   minimal Bootstrap-brug. Visuelt slægtskab med EKB-Boligbyg: 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;

    /* 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 (fra EKB) */
    --paper: #ffffff;
    --shell: #f2f5f9;
    --clay-100: #f5efe8;
    --clay-200: #e6d8c8;

    --ink: #16202e;
    --ink-2: #3b4a5d;
    /* 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;

    --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;

    --sidebar-w: 268px;

    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(--navy-700);
    --bs-link-hover-color: var(--navy-950);
    --bs-success: var(--good);
    --bs-warning: var(--warn);
    --bs-danger: var(--crit);
    --bs-secondary: var(--muted);
    --bs-font-sans-serif: var(--font);
}

* { 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(--navy-700); text-decoration: none; }
a:hover { color: var(--navy-950); }

/* ==========================================================================
   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);
}

.app__content {
    max-width: 1360px;
    padding: 2.25rem 2.5rem 3.5rem;
}

/* ==========================================================================
   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);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
}

/* 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;
    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);
}

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

.side__toggle { display: none; }

/* ==========================================================================
   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;
}

.topsearch:focus-within {
    border-color: var(--blue-400);
    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; }

.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.55rem;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--blue-500);
    margin-bottom: 0.6rem;
}

.ph__eyebrow::before {
    content: "";
    width: 26px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    opacity: 0.75;
}

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

.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; }

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

.panel {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    padding: 1.5rem 1.6rem;
}

.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;
    padding: 0.26rem 0.7rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    white-space: nowrap;
    border: 1px solid transparent;
}

.pil--good { background: var(--good-bg); color: var(--good-ink); border-color: color-mix(in srgb, var(--good) 28%, transparent); }
.pil--warn { background: var(--warn-bg); color: var(--warn-ink); border-color: color-mix(in srgb, var(--warn) 30%, transparent); }
.pil--crit { background: var(--crit-bg); color: var(--crit-ink); border-color: color-mix(in srgb, var(--crit) 30%, transparent); }

.pil--neutral {
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    color: var(--ink-2);
    border-color: color-mix(in srgb, var(--ink) 14%, transparent);
}

/* ==========================================================================
   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; }

@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); }

.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);
}

/* ==========================================================================
   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-afsendere ──────────────────────────────────────────────────────
   Tre bunker: fejl på egne systemer, ukendte afsendere, og alt der er i orden.
   Farven bæres af en venstrekant, så alvoren kan skimmes lodret uden at læse. */
.afs-gruppe { margin-top: 1.2rem; }
.afs-gruppe:first-of-type { margin-top: 0.4rem; }

.afs-gruppe__titel { font-weight: 800; font-size: 0.92rem; cursor: default; }
.afs-gruppe__titel--crit { color: var(--crit); }
.afs-gruppe__titel--warn { color: var(--warn); }
.afs-gruppe__titel--ok { color: var(--good); cursor: pointer; }

.afs-gruppe__sub { font-size: 0.82rem; color: var(--muted); margin: 0.15rem 0 0.7rem; max-width: 48rem; }

/* Ét kort pr. SYSTEM, ikke pr. IP. Hviletilstanden er én linje: prik, navn, tal, bjælke.
   Alt andet — råd, serveradresser, godkendelsesknap — hænger under og fylder kun, når
   der faktisk er noget at sige. */
.afs {
    border: 1px solid var(--line);
    border-left: 3px solid var(--line-2);
    border-radius: var(--r-md);
    padding: 0.6rem 0.85rem;
    margin-bottom: 0.4rem;
    background: var(--paper);
}

.afs--crit { border-left-color: var(--crit); }
.afs--warn { border-left-color: var(--warn); }
.afs--ok { border-left-color: var(--good); }

.afs__hd { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.afs__flex { flex: 1 1 2rem; }

.afs__prik { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--faint); }
.afs__prik--crit { background: var(--crit); }
.afs__prik--warn { background: var(--warn); }
.afs__prik--ok { background: var(--good); }

.afs__navn { font-weight: 700; font-size: 0.9rem; }

/* Antallet af servere hører til navnet, ikke til tallene: det forklarer, hvorfor
   der står ét kort, hvor der før stod tyve. */
.afs__badge {
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--muted);
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    border-radius: 999px;
    padding: 0.1rem 0.45rem;
}

.afs__tal { font-size: 0.82rem; white-space: nowrap; }

/* Bjælken gør andelen skimbar. Den er lille med vilje — tallet er svaret, bjælken er formen. */
.afs__bar {
    flex: none;
    width: 72px;
    height: 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--crit) 55%, transparent);
    overflow: hidden;
}

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

/* Rådet er det, siden findes for — derfor mere fremtrædende end tallene. */
.afs__raad { font-size: 0.84rem; color: var(--ink-2); margin-top: 0.4rem; line-height: 1.5; }
.afs__raad code { background: color-mix(in srgb, var(--ink) 7%, transparent); padding: 0.05rem 0.3rem; border-radius: 4px; }

.afs__handling { margin-top: 0.5rem; }
.afs__knap { margin-top: 0; }

/* IP'en sidst og småt: den er dokumentation, ikke svaret. Før stod den som overskrift,
   og så skulle man selv være detektiv. */
.afs__ip { font-size: 0.74rem; color: var(--faint); margin-top: 0.35rem; }

.afs__kilder { margin-top: 0.35rem; }
.afs__kilder > summary { font-size: 0.74rem; color: var(--muted); cursor: pointer; }
.afs__kilder > summary:hover { color: var(--ink-2); }

.afs__kildeliste { margin-top: 0.4rem; border-top: 1px solid var(--line); }

.afs__kilde {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.28rem 0;
    font-size: 0.76rem;
    border-bottom: 1px solid var(--line);
}

.afs__kilde-ip { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; color: var(--ink-2); }
.afs__kilde-tal { white-space: nowrap; }

/* ── Dmarc: kunde-chip og tværgående tabel ────────────────────────────────
   Medarbejderens indgang. Uden kunde-chippen kunne man ikke se, hvis tal man
   stod og kiggede på — og tallene på tværs af kunder er ikke nogens tal. */
.dm-kunde-chip {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 700;
    font-size: 0.88rem;
    color: var(--ink);
    margin-bottom: 0.75rem;
}

.dm-kunde-chip svg { width: 16px; height: 16px; color: var(--muted); }

.dm-kunder__row { cursor: pointer; }
.dm-kunder__row:hover { background: var(--blue-50); }
.dm-kunder__row:focus-visible { outline: 2px solid var(--brand, var(--ink-2)); 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); }

/* .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%);
}

.setsearch:focus-within { border-color: var(--blue-300); 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; }
}

.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.4fr) 5rem 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.4fr) 5rem 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__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; }

/* 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); }

/* ── 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 {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 1.15rem 1.3rem;
    border-radius: var(--r-lg);
    border: 1px solid var(--line);
    margin-bottom: 1.1rem;
}

.status--ok { background: color-mix(in srgb, var(--good) 10%, var(--paper)); border-color: color-mix(in srgb, var(--good) 35%, var(--line)); }
.status--obs { background: color-mix(in srgb, var(--warn) 12%, var(--paper)); border-color: color-mix(in srgb, var(--warn) 40%, var(--line)); }
.status--krit { background: color-mix(in srgb, var(--crit) 10%, var(--paper)); border-color: color-mix(in srgb, var(--crit) 38%, var(--line)); }

/* 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. */
.status--tom { background: color-mix(in srgb, var(--ink) 4%, var(--paper)); border-color: var(--line-2); }
.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; }
}

/* "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(--blue-400); 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: rgba(59, 130, 246, 0.12);
    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(--red-400, #f87171); color: var(--red-500, #dc2626); }

.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(--blue-400); outline-offset: 2px; }

.dgroup__body {
    padding: 0 1.2rem 1.2rem;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 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;
}

.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. */
.spark {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 22px;
    margin-bottom: 0.3rem;
}

.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);
}

.spark__bar--oppe { background: var(--good); height: 60%; }
.spark__bar--langsom { background: var(--warn); height: 80%; }
.spark__bar--nede { background: var(--crit); height: 100%; }
.spark__bar--ukendt { background: var(--blue-200); height: 35%; }

/* 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);
}

/* ==========================================================================
   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. */
details.mhist__month > .mhist__summary {
    grid-template-columns: 9rem 1fr 4rem 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) {
    /* Mobilgitteret er to kolonner. Pilen får sin egen plads i stedet for at
       presse tallene sammen. */
    details.mhist__month > .mhist__summary { grid-template-columns: 1fr auto 1.25rem; }
}

@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); }
.mhist__fill--billable { background: var(--blue-400); }

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

.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); }

@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; }

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

.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;
    transition: box-shadow 0.13s ease, transform 0.13s ease;
}

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

.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;
}

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

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

/* 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 rgba(63, 138, 92, 0.28);
    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); }

.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; }

.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: #e5484d;
    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; }

.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. */
.dcheck--btn {
    font: inherit;
    text-align: left;
    cursor: pointer;
}

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

.dcheck--btn:not(:disabled):hover { border-color: currentColor; }

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

/* Forløbsgraf for én måling. */
.chart { padding: 0.5rem 0 0; }

.chart svg {
    width: 100%;
    height: 180px;
    display: block;
    overflow: visible;
}

.chart__line {
    fill: none;
    stroke: var(--navy-800);
    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;
}

.chart__dot { fill: var(--navy-800); }

.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__axis {
    display: flex;
    justify-content: space-between;
    margin-top: 0.4rem;
    font-size: 0.75rem;
    color: var(--ink-3, var(--ink-2));
}

.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); }

.dlg--wide { max-width: 720px; }

/* 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);
}

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

.chart__legend {
    display: flex;
    gap: 1.2rem;
    margin-bottom: 1.1rem;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--muted);
}

.chart__legend 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. */
.empty__title {
    color: var(--ink-2);
    font-size: 1rem;
    font-weight: 700;
    margin-bottom: 0.35rem;
}

.empty__text {
    color: var(--faint);
    font-size: 0.88rem;
    line-height: 1.6;
}

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

.btn {
    font-weight: 700;
    border-radius: 999px;
    padding: 0.55rem 1.25rem;
    font-size: 0.88rem;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

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

.btn-primary:hover, .btn-primary:focus {
    background: var(--navy-950);
    border-color: var(--navy-950);
    color: #fff;
    transform: translateY(-1px);
    box-shadow: var(--shadow-md);
}

.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;
    }
}

/* Felter må gerne vise ringen ved klik — den fortæller hvor man skriver. Knapper må
   ikke, for så bliver den hængende efter hvert museklik; de får den via :focus-visible
   i tastatur-afsnittet nederst. */
.form-control:focus, .form-select:focus, .form-check-input:focus {
    box-shadow: 0 0 0 3px rgba(92, 127, 168, 0.25);
    outline: none;
}

.btn:focus, .btn:active:focus { outline: none; box-shadow: none; }

.form-control, .form-select {
    background: 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;
}

.form-control:focus, .form-select:focus { border-color: var(--blue-400); }
.form-control::placeholder { color: var(--faint); }

.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); }
.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(--blue-400); 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;
}

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

.alert-info { background: var(--blue-50); border-color: var(--blue-200); color: var(--navy-800); }
.alert-danger { background: var(--crit-bg); border-color: #e6c2bd; color: #82332c; }
.alert-warning { background: var(--warn-bg); border-color: #e8d5b0; color: #7d5720; }
.alert-success { background: var(--good-bg); border-color: #bfdccb; color: #2c6644; }

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

/* Validering / Blazor-fejl */
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--good); }
.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: rgba(94, 186, 133, 0.1);
    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.
   -------------------------------------------------------------------------- */

.period { display: flex; align-items: center; gap: 1.2rem; }

.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%; }
}

/* --------------------------------------------------------------------------
   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; }
}

/* --------------------------------------------------------------------------
   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. */
.fld { margin-bottom: 1rem; }

.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; }

/* 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. */
.tgl {
    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(280px, 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; }

.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; }

    .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.
   ========================================================================== */

:where(a, button, .btn, [role="button"], input, select, textarea, summary):focus-visible {
    outline: 2px solid var(--blue-400);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

/* Klikbare rækker og kort: samme fremhævning som hover, plus ringen. */
.tkt:focus-visible, .fcard:focus-visible, .notif__item:focus-visible {
    outline: 2px solid var(--blue-400);
    outline-offset: 2px;
    box-shadow: inset 0 0 0 1px var(--line-2), var(--shadow-sm);
}

/* Sidebar og topbar ligger på mørk bund — dér forsvinder den blå ring. */
.side__link:focus-visible, .side__brand:focus-visible, .topbar .btn:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* 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(--blue-400);
    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; }

/* 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; }

/* SPF og DKIM som to selvstaendige maerker paa afsenderkortet. */
.afs__ben { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-top: 0.45rem; }
.afs__ben-mærke { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.02em; border-radius: 999px; padding: 0.12rem 0.5rem; }
.afs__ben-mærke.er-ok { color: var(--good); background: var(--good-bg); }
.afs__ben-mærke.er-fejl { color: var(--crit); background: var(--crit-bg); }
.afs__ben-note { font-size: 0.74rem; color: var(--muted); }
.afs__raad--diag { border-left: 2px solid var(--line-2); padding-left: 0.6rem; margin-top: 0.35rem; }

/* ── 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; }

/* ── Dmarc: kan politikken strammes? ──────────────────────────────────────
   Oeverst paa siden, fordi det er konklusionen. Alt andet paa siden er
   argumenterne for den. */
.dm-gate { border-left: 4px solid var(--line-2); }
.dm-gate--ok { border-left-color: var(--good); }
.dm-gate--klar { border-left-color: var(--good); }
.dm-gate--blok { border-left-color: var(--warn); }

.dm-gate__hd { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; justify-content: space-between; }
.dm-gate__nu { font-size: 0.8rem; color: var(--muted); }
.dm-gate__svar { font-size: 1.02rem; font-weight: 800; color: var(--ink); margin-top: 0.15rem; }

.dm-trin { display: flex; align-items: center; gap: 0.35rem; }
.dm-trin__t {
    font-size: 0.72rem; font-weight: 800; border-radius: 999px;
    padding: 0.16rem 0.55rem; color: var(--faint);
    background: color-mix(in srgb, var(--ink) 5%, transparent);
    white-space: nowrap;
}
.dm-trin__t.er-naaet { color: var(--good); background: var(--good-bg); }
.dm-trin__t.er-naeste { color: var(--ink); background: var(--clay-200); }

.dm-gate__liste { margin-top: 0.9rem; }
.dm-gate__titel { font-weight: 800; font-size: 0.82rem; margin-bottom: 0.4rem; }
.dm-gate__titel--blok { color: var(--warn); }

.dm-punkt { padding: 0.4rem 0; border-top: 1px solid var(--line); }
.dm-punkt__h { font-weight: 700; font-size: 0.86rem; }
.dm-punkt__d { font-size: 0.82rem; color: var(--ink-2); line-height: 1.5; margin-top: 0.1rem; }

.dm-gate__raad { margin-top: 0.9rem; font-size: 0.84rem; color: var(--ink-2); line-height: 1.55; }
.dm-gate__raad code { background: color-mix(in srgb, var(--ink) 7%, transparent); padding: 0.05rem 0.3rem; border-radius: 4px; }

/* 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: svaret oeverst, resten bag faner ──────────────────────────────
   Siden voksede ét panel ad gangen og endte med ni sektioner under hinanden.
   Rettelsen er ikke faerre oplysninger, men at de tre spoergsmaal — "er vi i
   maal?", "hvem sender?" og "vis mig linjen" — ikke laengere staar blandet. */
.dmh {
    display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; justify-content: space-between;
    background: var(--paper); border: 1px solid var(--line); border-left: 4px solid var(--line-2);
    border-radius: var(--r-lg); box-shadow: var(--shadow-sm);
    padding: 1.1rem 1.3rem; margin-bottom: 0.9rem;
}
.dmh--ok { border-left-color: var(--good); }
.dmh--klar { border-left-color: var(--good); }
.dmh--blok { border-left-color: var(--warn); }

.dmh__label { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.dmh__svar { font-size: 1.24rem; font-weight: 800; color: var(--ink); line-height: 1.25; margin: 0.15rem 0 0.5rem; max-width: 34rem; }

.dmh__trin { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
.dmh__t {
    font-size: 0.7rem; font-weight: 800; border-radius: 999px; padding: 0.14rem 0.5rem;
    color: var(--faint); background: color-mix(in srgb, var(--ink) 5%, transparent);
}
.dmh__t.er-naaet { color: var(--good); background: var(--good-bg); }
.dmh__t.er-naeste { color: var(--ink); background: var(--clay-200); }
.dmh__klar { font-size: 0.76rem; font-weight: 700; color: var(--good); margin-left: 0.25rem; }
.dmh__blok { font-size: 0.76rem; font-weight: 700; color: var(--warn); margin-left: 0.25rem; }

.dmh__tal { display: flex; flex-wrap: wrap; gap: 1.4rem; }
.dmh__n { display: flex; flex-direction: column; }
.dmh__n > b { font-size: 1.3rem; font-weight: 800; line-height: 1.1; color: var(--ink); font-variant-numeric: tabular-nums; }
.dmh__n > span { font-size: 0.72rem; color: var(--muted); }

.txt-good { color: var(--good); }

/* Faner. Trykmaal paa 44 px hoejde ligger inden for det, mobilreglerne kraever. */
.dmfaner { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--line); margin-bottom: 0.9rem; }
.dmfaner__f {
    border: 0; background: transparent; cursor: pointer;
    font-size: 0.88rem; font-weight: 700; color: var(--muted);
    padding: 0.6rem 0.9rem; border-bottom: 2px solid transparent; margin-bottom: -1px;
    display: inline-flex; align-items: center; gap: 0.4rem; min-height: 44px;
}
.dmfaner__f:hover { color: var(--ink); }
.dmfaner__f.er-valgt { color: var(--ink); border-bottom-color: var(--ink); }
.dmfaner__n {
    font-size: 0.68rem; font-weight: 800; border-radius: 999px; padding: 0.05rem 0.4rem;
    background: color-mix(in srgb, var(--ink) 8%, transparent); color: var(--ink-2);
}
.dmfaner__f.er-valgt .dmfaner__n { background: var(--clay-200); }

/* Filterchips i stedet for syv sektioner under hinanden. */
.afsfilter { display: flex; flex-wrap: wrap; gap: 0.35rem; padding: 0.2rem 0 0.9rem; }
.afsfilter__k {
    border: 1px solid var(--line-2); background: var(--paper); cursor: pointer;
    font-size: 0.78rem; font-weight: 700; color: var(--ink-2);
    border-radius: 999px; padding: 0.28rem 0.7rem;
    display: inline-flex; align-items: center; gap: 0.35rem;
}
.afsfilter__k:hover { border-color: var(--ink-2); }
.afsfilter__k.er-valgt { background: var(--ink); border-color: var(--ink); color: #fff; }
.afsfilter__n { font-size: 0.7rem; opacity: 0.75; }

@media (max-width: 720px), (pointer: coarse) {
    .dmh { padding: 0.9rem 1rem; }
    .dmh__svar { font-size: 1.08rem; }
    .dmh__tal { gap: 1rem; }
    .afsfilter__k { min-height: 36px; }
}

/* Politik pr. domaene i heroen. Vurderingen bygger paa det svageste domaene —
   uden at det staar her, ligner det en fejl, naar kunden ved at hoveddomaenet
   for laengst er paa reject. */
.dmh__dom { display: flex; flex-wrap: wrap; gap: 0.35rem 0.8rem; margin-top: 0.5rem; font-size: 0.74rem; color: var(--muted); }
.dmh__d > b { color: var(--ink-2); font-weight: 800; }
.dmh__d.er-ok > b { color: var(--good); }
.dmh__d.er-fejl > b { color: var(--crit); }

/* 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; }

/* 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.
   ========================================================================== */

@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; }

    /* 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. */
    .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; }

    /* 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; }
}

/* 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); }

/* 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.

   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: 6rem; }

@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;
}

.airesume__tekst {
    margin: 0;
    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;
    }
}

/* 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-050, rgba(59, 130, 246, 0.06));
}

.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. */
.slip:has(.slip__felt:focus-visible) {
    border-color: var(--blue-400, #3b82f6);
    box-shadow: 0 0 0 3px var(--blue-100, rgba(59, 130, 246, 0.25));
}

.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;
}
