/* =====================================================================
   nfoo v3 - designsystem
   Formsproget er hentet fra uniconta-projektet: Outfit til brødtekst,
   Rajdhani til overskrifter og etiketter, mint/blå accenter, animeret
   gitter og roterende ringe i baggrunden.

   Begge temaer er bygget på de samme variabler. Der er derfor ingen
   !important-overstyring - lys og mørk er ligeværdige, ikke et lag oven
   på hinanden.
   ===================================================================== */

/* ---------- Mørkt tema (standard) ---------- */
:root {
    --bg:            #05070d;
    --bg-2:          #0a1020;
    --bg-3:          #05060b;
    --surface:       linear-gradient(140deg, rgba(7, 11, 20, 0.86), rgba(10, 17, 32, 0.78));
    --surface-solid:  rgba(9, 15, 27, 0.84);
    --line:          rgba(118, 182, 255, 0.24);
    --line-strong:   rgba(118, 182, 255, 0.42);
    --text:          #eaf0ff;
    --text-muted:  #9caac6;
    --label:         #cfe0ff;
    --accent:        #4cf5c5;
    --accent-2:      #56a4ff;
    --accent-text:  #d7e7ff;
    --field-bg:       rgba(11, 22, 40, 0.92);
    /* En flade der LIGGER OVEN PAA noget: billedkortet der kommer frem
       naar musen hviler paa et filnavn, radioafspilleren nederst,
       filmklippenes fliser. Uigennemsigtig med vilje - kortet staar hen
       over tabellens raekker, og den roede "det her spiller ikke" skal
       ikke skinne igennem.

       Den blev BRUGT tre steder uden nogensinde at vaere skrevet. En
       var(--panel) der ikke findes, giver ikke en fejl - den giver
       ingen baggrund, og saa var kortet gennemsigtigt. */
    --panel:         #0b1628;
    --glow-1:        rgba(76, 245, 197, 0.12);
    --glow-2:        rgba(86, 164, 255, 0.16);
    --grid-line:        rgba(86, 164, 255, 0.08);
    --ring-1:        rgba(76, 245, 197, 0.20);
    --ring-2:        rgba(86, 164, 255, 0.25);
    --card-shadow:   0 24px 64px rgba(0, 0, 0, 0.45);
    /* Faelles hoejde for sprog- og temavaelger, saa de flugter. */
    --control-h:     36px;
    /* Bane og modrotation SKAL dele varighed. Afviger de, driver
       teksten langsomt rundt og ender med at staa paa hovedet. */
    --orbit-time:    15s;
    --orbit-r:       104px;
    --wire-inner:    rgba(86, 164, 255, 0.34);
    --error-bg:       rgba(255, 92, 92, 0.12);
    --error-line:     rgba(255, 92, 92, 0.45);
    --error-text:    #ffd1d1;
    --ok-bg:         rgba(76, 245, 197, 0.12);
    --ok-line:       rgba(76, 245, 197, 0.45);
    --ok-text:      #b8ffe9;
    color-scheme: dark;
}

/* ---------- Lyst tema ---------- */
html[data-theme="light"] {
    --bg:            #eaf1f8;
    --bg-2:          #f8fbfe;
    --bg-3:          #eef5fa;
    --surface:       linear-gradient(140deg, rgba(255, 255, 255, 0.97), rgba(248, 251, 254, 0.92));
    --surface-solid:  rgba(255, 255, 255, 0.94);
    --line:          rgba(34, 78, 122, 0.22);
    --line-strong:   rgba(34, 78, 122, 0.40);
    --text:          #172e48;
    --text-muted:  #5b7290;
    --label:         #2b4d70;
    --accent:        #0d9b7e;
    --accent-2:      #2b7fc4;
    --accent-text:  #10405f;
    --field-bg:       #ffffff;
    --panel:         #ffffff;
    --glow-1:        rgba(13, 155, 126, 0.10);
    --glow-2:        rgba(43, 127, 196, 0.12);
    --grid-line:        rgba(43, 127, 196, 0.07);
    --ring-1:        rgba(13, 155, 126, 0.16);
    --ring-2:        rgba(43, 127, 196, 0.18);
    --card-shadow:   0 18px 44px rgba(28, 60, 90, 0.14);
    --error-bg:       #fdecec;
    --error-line:     #e4a3a3;
    --error-text:    #9a2b36;
    --ok-bg:         #e2f8f1;
    --ok-line:       #75d9c5;
    --ok-text:      #075f50;
    --wire-inner:   rgba(43, 127, 196, 0.30);
    color-scheme: light;
}

* { box-sizing: border-box; }

/* hidden-attributten skal ALTID vinde.
   Browserens egen regel er [hidden] { display: none }, og den taber til
   enhver display-regel man selv skriver - saa .modal { display: flex }
   goer et skjult element synligt igen. Det ramte bekraeftelsesdialogen:
   den stod aaben ved hver sideindlaesning, og Annuller kunne ikke lukke
   den, fordi el.hidden = true ikke aendrede noget.
   Her staar attributten over alt andet. */
[hidden] { display: none !important; }

html {
    scrollbar-width: thin;
    scrollbar-color: var(--accent) var(--bg-2);
}

body {
    margin: 0;
    min-height: 100vh;
    display: grid;
    place-items: center;
    position: relative;
    overflow-x: hidden;
    padding: 20px;
    color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    background:
        radial-gradient(circle at 15% 5%,  var(--glow-1), transparent 32%),
        radial-gradient(circle at 84% 14%, var(--glow-2), transparent 34%),
        linear-gradient(160deg, var(--bg) 0%, var(--bg-2) 58%, var(--bg-3) 100%);
    background-attachment: fixed;
    transition: color 240ms ease, background-color 240ms ease;
}

/* ---------- Animationer ---------- */
@keyframes drift  { 0%, 100% { transform: translateY(0) translateX(0); } 50% { transform: translateY(-8px) translateX(6px); } }
@keyframes rotate { from { transform: translate(-50%, -50%) rotate(0deg); } to { transform: translate(-50%, -50%) rotate(360deg); } }
@keyframes pulse  { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
@keyframes riseIn { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }
/* Rundturens skygge. En riseIn ville faa laaget til at glide ind
   nedefra, og saa ser man siden blinke frem under det. */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes cubeSpin {
    0%   { transform: rotateX(-24deg) rotateY(0deg)   rotateZ(0deg); }
    25%  { transform: rotateX(10deg)  rotateY(90deg)  rotateZ(5deg); }
    50%  { transform: rotateX(24deg)  rotateY(180deg) rotateZ(0deg); }
    75%  { transform: rotateX(10deg)  rotateY(270deg) rotateZ(-5deg); }
    100% { transform: rotateX(-24deg) rotateY(360deg) rotateZ(0deg); }
}

/* Banen haelder let, saa ringen laeses som en ellipse frem for en streg. */
@keyframes orbitSpin {
    from { transform: rotateX(-16deg) rotateY(0deg); }
    to   { transform: rotateX(-16deg) rotateY(360deg); }
}

/* Modrotationen. Praecis det modsatte af orbitSpin, saa teksten staar
   stille i forhold til skaermen mens den baeres rundt. */
@keyframes orbitFace {
    from { transform: rotateY(0deg); }
    to   { transform: rotateY(-360deg); }
}

/* Svag ind- og udtoning naar et maerkat passerer bag terningen. */
@keyframes orbitDepth {
    0%, 100% { opacity: 0.95; }
    50%      { opacity: 0.35; }
}
@keyframes cubeFloat { 0%, 100% { transform: translateY(0) translateX(0); } 50% { transform: translateY(-9px) translateX(6px); } }
@keyframes spin      { to { transform: rotate(360deg); } }

/* ---------- Baggrundsdekoration ---------- */
.fx-grid {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    opacity: 0.45;
    background-image:
        linear-gradient(var(--grid-line) 1px, transparent 1px),
        linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
    background-size: 56px 56px;
    -webkit-mask-image: radial-gradient(circle at center, black 45%, transparent 95%);
            mask-image: radial-gradient(circle at center, black 45%, transparent 95%);
}

.fx-grid::before,
.fx-grid::after {
    content: "";
    position: absolute;
    width: 70vmax;
    height: 70vmax;
    border: 1px solid var(--ring-1);
    border-radius: 50%;
    top: 50%;
    left: 50%;
    animation: rotate 30s linear infinite;
}

.fx-grid::after {
    width: 42vmax;
    height: 42vmax;
    border-color: var(--ring-2);
    animation-duration: 12s;
    animation-direction: reverse;
}

.deco-scene { position: fixed; inset: 0; pointer-events: none; z-index: 1; will-change: transform; }
.deco-layer { position: absolute; inset: 0; will-change: transform; }

.fx-node {
    position: fixed;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 14px var(--accent);
    pointer-events: none;
    animation: pulse 1000ms ease-in-out infinite, drift 3s ease-in-out infinite;
}
.fx-node.n1 { top: 20%; left: 16%; }
.fx-node.n2 { top: 76%; left: 22%; animation-delay: 450ms; }
.fx-node.n3 { top: 24%; right: 17%; animation-delay: 800ms; background: var(--accent-2); box-shadow: 0 0 14px var(--accent-2); }
.fx-node.n4 { top: 72%; right: 14%; animation-delay: 1200ms; background: var(--accent-2); box-shadow: 0 0 14px var(--accent-2); }

/* Roterende terning - samme motiv som uniconta, men med nfoos to moduler */
.deco-cube-wrap {
    position: fixed;
    right: clamp(18px, 8vw, 120px);
    top: clamp(16px, 10vh, 120px);
    width: min(220px, 34vw);
    aspect-ratio: 1;
    perspective: 900px;
    pointer-events: none;
    display: grid;
    place-items: center;
    animation: cubeFloat 3000ms ease-in-out infinite;
    filter: drop-shadow(0 0 24px var(--glow-2));
}
.deco-cube-wrap::before,
.deco-cube-wrap::after {
    content: "";
    position: absolute;
    inset: 12%;
    border-radius: 50%;
    border: 1px dashed var(--ring-1);
}
.deco-cube-wrap::after { inset: 26%; border-style: solid; border-color: var(--ring-2); }

.deco-cube { position: relative; width: 96px; height: 96px; transform-style: preserve-3d; animation: cubeSpin 11s ease-in-out infinite; }
/* Wireframe: fladerne er gennemsigtige, saa kun kanterne ses.
   Med fyld laa fladerne oven i hinanden og terningen laeste som en
   massiv kasse - rotationen var praktisk talt usynlig.

   Hver flade deles i 3x3 som en Rubiks terning. Nettet tegnes med to
   gentagne gradienter frem for 54 elementer i HTML'en - browseren
   rasteriserer dem sammen med fladens baggrund, saa det koster reelt
   ingenting at animere. */
.deco-cube .face {
    position: absolute; inset: 0;
    border: 1px solid var(--accent-2);
    background-image:
        repeating-linear-gradient(90deg, var(--wire-inner) 0 1px, transparent 1px 33.334%),
        repeating-linear-gradient(0deg,  var(--wire-inner) 0 1px, transparent 1px 33.334%);
    opacity: 0.72;
}
.deco-cube .f1 { transform: translateZ(48px); }
.deco-cube .f2 { transform: rotateY(180deg) translateZ(48px); }
.deco-cube .f3 { transform: rotateY(90deg)  translateZ(48px); }
.deco-cube .f4 { transform: rotateY(-90deg) translateZ(48px); }
.deco-cube .f5 { transform: rotateX(90deg)  translateZ(48px); }
.deco-cube .f6 { transform: rotateX(-90deg) translateZ(48px); }

.deco-orbit {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    transform: rotateX(-16deg);
    animation: orbitSpin var(--orbit-time) linear infinite;
}

/* Hver plads sidder paa ringen. Boksen centreres med margin frem for
   translate, saa transform-egenskaben er fri til rotationen. */
.orbit-slot {
    position: absolute;
    top: 50%;
    left: 50%;
    /* Bred nok til det laengste maerkat, INFOTAINMENT. */
    width: 160px;
    height: 18px;
    margin: -9px 0 0 -80px;
    display: grid;
    place-items: center;
    transform-style: preserve-3d;
    transform: rotateY(var(--angle)) translateZ(var(--orbit-r));
}

/* Ophaever pladsens egen vinkel, saa kun banens rotation staar tilbage
   at modvirke - og modrotationen kan vaere ens for alle maerkater. */
.orbit-unspin {
    transform-style: preserve-3d;
    transform: rotateY(calc(-1 * var(--angle)));
}

.deco-tag {
    display: block;
    white-space: nowrap;
    color: var(--text-muted);
    font-size: 12px;
    letter-spacing: 0.08em;
    font-family: "Rajdhani", "Outfit", sans-serif;
    text-transform: uppercase;
    text-shadow: 0 0 12px var(--glow-2);
    animation: orbitFace var(--orbit-time) linear infinite,
               orbitDepth var(--orbit-time) ease-in-out infinite;
    /* Modrotationen maa ALDRIG forskydes - saa ville teksten skride.
       Kun dybdetoningen faseforskydes, saa hvert maerkat daempes netop
       naar det passerer bag terningen. Vaerdien saettes i login.php,
       fordi CSS ikke kan gange grader med tid. */
    animation-delay: 0s, var(--orbit-delay, 0s);
}

/* ---------- Topbjælke: sprog og tema ---------- */
.top-bar {
    position: fixed;
    top: 18px; right: 18px;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 10px;
}

.lang-switch { position: relative; display: flex; align-items: center; gap: 6px; margin: 0; }

.lang-icon { display: inline-flex; color: var(--text-muted); }
.lang-icon svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; }

.lang-button,
.theme-switch button {
    border: 1px solid var(--line);
    background: var(--surface-solid);
    color: var(--text-muted);
    border-radius: 999px;
    cursor: pointer;
    font-family: "Rajdhani", "Outfit", sans-serif;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    transition: border-color 220ms ease, color 220ms ease, background-color 220ms ease;
}

.lang-button {
    height: var(--control-h);
    padding: 0 14px;
    display: inline-flex;
    align-items: center;
    box-sizing: border-box;
    font-size: 12px;
    font-weight: 600;
}
.lang-button:hover { border-color: var(--accent); color: var(--text); }

.lang-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 132px;
    padding: 5px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: var(--card-shadow);
    display: grid;
    gap: 2px;
    z-index: 4;
}

.lang-option {
    border: 0;
    background: transparent;
    color: var(--text-muted);
    padding: 8px 11px;
    border-radius: 8px;
    text-align: left;
    cursor: pointer;
    font-family: "Outfit", sans-serif;
    font-size: 14px;
}
.lang-option:hover  { background: var(--glow-2); color: var(--text); }
.lang-option.is-active  { color: var(--accent); font-weight: 600; }

.theme-switch {
    height: var(--control-h);
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-solid);
}
.theme-switch button {
    border: 0;
    background: transparent;
    padding: 0;
    /* Trukket fra --control-h, saa knapperne altid passer i sporet:
       36 - 2 (kant) - 6 (polstring) = 28 */
    width: calc(var(--control-h) - 8px);
    height: calc(var(--control-h) - 8px);
    display: grid;
    place-items: center;
}
.theme-switch button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
.theme-switch button:hover { color: var(--text); }
.theme-switch button[aria-pressed="true"] {
    background: var(--glow-2);
    color: var(--accent);
}

/* ---------- Login-kort ---------- */
.card {
    position: relative;
    z-index: 2;
    width: min(430px, 92vw);
    padding: 28px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--surface);
    backdrop-filter: blur(10px);
    box-shadow: var(--card-shadow);
    animation: riseIn 700ms ease-out;
}

.card::before {
    content: "";
    position: absolute;
    inset: -30% auto auto -15%;
    width: 50%; height: 120%;
    background: linear-gradient(120deg, var(--glow-1), transparent);
    transform: rotate(8deg);
    pointer-events: none;
    border-radius: 16px;
}

.brand {
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin-bottom: 4px;
    font-family: "Rajdhani", "Outfit", sans-serif;
}
.brand-name {
    font-size: 30px;
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1;
}
.brand-v3 {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    padding: 3px 9px;
}

.sub {
    margin: 0 0 6px;
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.45;
}

.module-row {
    display: flex;
    gap: 7px;
    margin: 14px 0 20px;
    flex-wrap: wrap;
}
.module-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 11px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--field-bg);
    color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}
.module-chip svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.module-chip.signage { color: var(--accent-2); border-color: var(--accent-2); }
.module-chip.music   { color: var(--accent);   border-color: var(--accent); }

label {
    display: block;
    margin-top: 14px;
    margin-bottom: 7px;
    color: var(--label);
    font-size: 13px;
    letter-spacing: 0.03em;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-weight: 600;
    text-transform: uppercase;
}

input[type="text"],
input[type="password"] {
    width: 100%;
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 11px 12px;
    background: var(--field-bg);
    color: var(--text);
    font-family: inherit;
    /* Mindst 16px. Under det zoomer iOS Safari ind naar feltet faar
       fokus, og brugeren efterlades i en halvskaev visning. */
    font-size: 16px;
    transition: border-color 220ms ease, box-shadow 220ms ease;
}
input[type="text"]:focus,
input[type="password"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--glow-1);
}

.field { position: relative; }
.toggle-password {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    padding: 6px;
    border-radius: 6px;
    display: grid;
    place-items: center;
}
.toggle-password svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.toggle-password:hover { color: var(--accent); }
input[type="password"] + .toggle-password,
.field input { padding-right: 42px; }

.row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 14px;
    font-size: 14px;
    color: var(--text-muted);
}
.row label {
    margin: 0;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: "Outfit", sans-serif;
    font-size: 14px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text-muted);
    cursor: pointer;
}
.row input[type="checkbox"] { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }

button.primary {
    position: relative;
    overflow: hidden;
    margin-top: 20px;
    width: 100%;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    padding: 12px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--accent-text);
    background: var(--glow-2);
    cursor: pointer;
    transition: border-color 260ms ease, box-shadow 280ms ease, transform 260ms ease, background-color 260ms ease;
}
button.primary::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(110deg, transparent, var(--glow-2), transparent);
    transform: translateX(-120%);
    transition: transform 420ms ease;
    pointer-events: none;
}
button.primary:hover:not(:disabled) {
    border-color: var(--accent);
    box-shadow: 0 0 0 1px var(--accent), 0 8px 24px var(--glow-2);
    transform: translateY(-1px);
}
button.primary:hover:not(:disabled)::before { transform: translateX(120%); }
button.primary:disabled { opacity: 0.6; cursor: progress; }

button:focus-visible,
a:focus-visible,
input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.spinner {
    display: none;
    width: 15px; height: 15px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: spin 700ms linear infinite;
    vertical-align: -2px;
    margin-right: 8px;
}
button.primary.is-busy .spinner { display: inline-block; }

.notice {
    margin-top: 16px;
    padding: 11px 13px;
    border-radius: 8px;
    font-size: 14px;
    line-height: 1.45;
}
.notice.error { background: var(--error-bg); border: 1px solid var(--error-line); color: var(--error-text); }
.notice.ok   { background: var(--ok-bg);   border: 1px solid var(--ok-line);   color: var(--ok-text); }


/* ---------- Tilgængelighed og små skærme ---------- */
.visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    /* Dekorationen stoppes ikke helt, men saenkes kraftigt. Samme valg som
       uniconta-projektet. Baggrunden er rent pyntende og ligger i et hjoerne,
       saa en meget langsom bevaegelse er til at leve med - mens et fuldt stop
       gjorde siden helt doed for alle med batterisparetilstand slaaet til,
       fordi browsere ogsaa rapporterer 'reduce' i den situation.

       Bevaegelse i selve graensefladen stoppes derimod helt. */
    .fx-grid::before, .fx-grid::after,
    .fx-node, .deco-cube-wrap, .deco-cube, .deco-layer {
        animation-duration: 90s !important;
        animation-timing-function: linear !important;
    }

    /* Bane og modrotation SKAL fortsat foelges ad, ellers skrider teksten. */
    .deco-orbit, .deco-tag {
        animation-duration: 90s !important;
        animation-timing-function: linear !important;
    }

    .card { animation: none !important; }
    button.primary, button.primary::before { transition-duration: 0ms !important; }
}

@media (max-width: 960px) {
    /* Banen skal krympe sammen med terningen, ellers svaever maerkaterne
       udenfor de stiplede ringe. */
    :root { --orbit-r: 84px; }
    .deco-cube-wrap { width: min(178px, 36vw); right: 4vw; top: 8vh; opacity: 0.7; }
    .deco-tag { font-size: 11px; }
}

@media (max-width: 640px) {
    :root { --control-h: 40px; }      /* stoerre beroeringsmaal */

    body {
        padding: 76px 12px 28px;
        place-items: start center;
    }

    .card {
        width: 100%;
        max-width: 440px;
        padding: 22px 18px;
    }

    .brand-name { font-size: 26px; }

    /* Ingen bevaegelse paa mobil. Terningen, maerkaterne, de pulserende
       punkter og de roterende ringe fjernes helt - baade for et roligere
       login paa en lille skaerm og for at telefonen ikke skal animere
       noget rent pyntende i baggrunden.

       Selve gitteret bliver, da det er et statisk moenster. */
    .deco-scene { display: none; }
    .fx-grid::before,
    .fx-grid::after { display: none; }

    .top-bar {
        top: 12px;
        right: 12px;
        left: 12px;
        justify-content: flex-end;
    }

    /* Fingervenlige maal */
    .toggle-password { padding: 10px; }
    .row input[type="checkbox"] { width: 18px; height: 18px; }
    button.primary { padding: 14px; }
}

/* Meget lave skaerme - fx iPhone SE i landskab */
@media (max-height: 620px) and (max-width: 900px) {
    body { padding-top: 64px; }
    .module-row { margin: 10px 0 14px; }
    .deco-cube-wrap { display: none; }
}

/* =====================================================================
   Dashboard-rammen: kollapsbar sidenavigation og sticky header.

   Bygger på de samme variabler som login-skærmen, så mørkt og lyst tema
   følger med uden en linje ekstra.
   ===================================================================== */

:root {
    --side-w:           248px;
    --side-w-collapsed:  68px;
    --header-h:          64px;
}

body.app {
    display: block;
    place-items: initial;
    padding: 0;
    min-height: 100vh;
}

/* ---------- Sidenavigation ---------- */
.side-nav {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    z-index: 20;
    width: var(--side-w);
    padding: 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    border-right: 1px solid var(--line);
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    transition: width 200ms ease, transform 220ms ease;
    overflow: hidden;
}

html[data-sidebar="collapsed"] .side-nav { width: var(--side-w-collapsed); }

.side-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 6px 14px;
    text-decoration: none;
    color: var(--text);
    font-family: "Rajdhani", "Outfit", sans-serif;
}
.side-brand-mark {
    flex: 0 0 28px;
    width: 28px; height: 28px;
    display: grid; place-items: center;
    border: 1px solid var(--line-strong);
    border-radius: 8px;
    background: var(--glow-2);
    color: var(--accent);
    font-size: 16px; font-weight: 700;
}
.side-brand-text { font-size: 17px; font-weight: 600; white-space: nowrap; }
.side-brand-v3 {
    font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--accent); vertical-align: 2px;
}

.side-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; padding: 0 6px 8px;
}
.side-head-title {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--text-muted);
    white-space: nowrap;
}
.side-collapse {
    flex: 0 0 26px;
    width: 26px; height: 26px;
    display: grid; place-items: center;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: color 180ms ease, border-color 180ms ease, transform 220ms ease;
}
.side-collapse svg {
    width: 15px; height: 15px; fill: none; stroke: currentColor;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.side-collapse:hover { color: var(--text); border-color: var(--accent); }
html[data-sidebar="collapsed"] .side-collapse { transform: rotate(180deg); }

/* Skillelinjen mellem de to systemer. v3 samler signage og musik i én
   menu, og uden en adskillelse ser de ud som om de hører sammen.
   Overskriften er lille og dæmpet: den skal kunne overses af den der
   allerede ved hvor han skal hen. */
.side-group {
    display: flex; align-items: center; gap: 10px;
    margin: 18px 0 6px; padding: 0 14px;
}
.side-group::after {
    content: ""; flex: 1 1 auto;
    height: 1px; background: var(--line);
}
.side-group-label {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--text-muted);
    white-space: nowrap;
}

/* Sammenklappet menu: der er ikke plads til teksten, kun til stregen. */
html[data-sidebar="collapsed"] .side-group { padding: 0 10px; margin: 14px 0 6px; }
html[data-sidebar="collapsed"] .side-group-label { display: none; }

.side-links { display: flex; flex-direction: column; gap: 3px; overflow-y: auto; }

.side-link {
    display: flex; align-items: center; gap: 11px;
    padding: 9px 10px;
    border: 1px solid transparent;
    border-radius: 10px;
    color: var(--text-muted);
    text-decoration: none;
    font-size: 14px;
    white-space: nowrap;
    transition: background-color 160ms ease, color 160ms ease, border-color 160ms ease;
}
.side-link:hover { background: var(--glow-2); color: var(--text); }
.side-link.is-active {
    background: var(--glow-1);
    border-color: var(--accent);
    color: var(--text);
    font-weight: 600;
}
/* Det kunden ikke har koebt.
   Svagere end de oevrige, men ikke usynligt: meningen er at man kan se
   at systemet ogsaa kan det. Ingen markoer og intet hover - der sker
   ingenting hvis man trykker, og musen skal sige det paa forhaand. */
.side-link.is-muted {
    opacity: 0.38;
    cursor: default;
    -webkit-user-select: none;
    user-select: none;
}
.side-link.is-muted:hover { background: none; color: var(--text-muted); }

.side-link.is-super { color: #ffb27a; }
.side-link.is-super.is-active {
    border-color: #ffb27a;
    background: rgba(255, 178, 122, 0.12);
}

.side-link-short {
    flex: 0 0 24px;
    width: 24px;
    text-align: center;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
    opacity: 0.75;
}

/* Sammenklappet: kun initialerne */
html[data-sidebar="collapsed"] .side-brand-text,
html[data-sidebar="collapsed"] .side-head-title,
html[data-sidebar="collapsed"] .side-link-label { display: none; }
html[data-sidebar="collapsed"] .side-head { justify-content: center; }
html[data-sidebar="collapsed"] .side-link { justify-content: center; padding: 10px 4px; }
html[data-sidebar="collapsed"] .side-brand {
    justify-content: center; padding-left: 0; padding-right: 0;
}

/* ---------- Hovedområde ---------- */
.app-main {
    margin-left: var(--side-w);
    min-height: 100vh;
    transition: margin-left 200ms ease;
}
html[data-sidebar="collapsed"] .app-main { margin-left: var(--side-w-collapsed); }

.app-header {
    position: sticky;
    top: 0;
    z-index: 15;
    min-height: var(--header-h);
    display: flex; align-items: center; gap: 16px;
    padding: 10px 20px;
    border-bottom: 1px solid var(--line);
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    flex-wrap: wrap;
}

.side-open {
    display: none;
    width: 36px; height: 36px;
    place-items: center;
    border: 1px solid var(--line); border-radius: 10px;
    background: transparent; color: var(--text-muted); cursor: pointer;
}
.side-open svg {
    width: 18px; height: 18px; fill: none; stroke: currentColor;
    stroke-width: 2; stroke-linecap: round;
}

.app-header-facts {
    display: flex; align-items: center; gap: 18px;
    flex-wrap: wrap; flex: 1 1 auto;
}
.fact { display: flex; align-items: baseline; gap: 7px; font-size: 14px; color: var(--text); }
.fact-label {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--text-muted);
}
.fact-tag {
    padding: 2px 8px;
    border: 1px solid var(--line-strong); border-radius: 999px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--accent);
}
.fact-tag.is-super { color: #ffb27a; border-color: #ffb27a; }

.app-header-tools { display: flex; align-items: center; gap: 10px; }
.signout-form { margin: 0; }
.signout-btn {
    height: var(--control-h);
    padding: 0 14px;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer;
    transition: border-color 200ms ease, color 200ms ease;
}
.signout-btn:hover { border-color: var(--accent); color: var(--text); }

.avatar {
    width: var(--control-h); height: var(--control-h);
    display: grid; place-items: center;
    border: 1px solid var(--line-strong); border-radius: 50%;
    background: var(--glow-2); color: var(--accent);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 13px; font-weight: 700;
}

.app-content { padding: 26px 20px 48px; max-width: 1180px; }
.page-title {
    margin: 0 0 22px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 38px; line-height: 1; letter-spacing: -0.01em;
}

.side-scrim {
    position: fixed; inset: 0; z-index: 18;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}

/* ---------- Kontopanelet ----------
   Den gamle udgave var tre linjer i et <p> med opacity: .6 paa den
   sidste. Den sagde det rigtige, men alt saa lige vigtigt ud - og
   navnet stod to gange, fordi en organisation logger ind som sig selv.

   Nu: hvem man er oeverst med initialerne, det der ligger udenom paa
   raekker, og tallene til supporten nederst. */
.acct { display: flex; align-items: center; gap: 14px; }
.acct-avatar {
    width: 44px; height: 44px; font-size: 15px;
    flex: 0 0 auto;
}
.acct-head { min-width: 0; }
.acct-name {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 21px; font-weight: 700; line-height: 1.1;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acct-sub {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-top: 4px;
}
.acct-login {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12.5px; color: var(--text-muted);
}

.acct-facts {
    display: grid; gap: 10px;
    margin: 18px 0 0; padding-top: 16px;
    border-top: 1px solid var(--line);
}
.acct-facts > div {
    display: grid; grid-template-columns: 132px 1fr; gap: 4px 14px;
    align-items: baseline;
}
@media (max-width: 520px) {
    .acct-facts > div { grid-template-columns: 1fr; }
}
.acct-facts dt {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}
.acct-facts dd {
    margin: 0; min-width: 0;
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
/* Tallene til supporten. Monospace, saa cifrene har samme bredde og
   ikke kan laeses forkert i telefonen. */
.acct-ids {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin-top: 16px; padding-top: 14px;
    border-top: 1px solid var(--line);
}
.acct-id {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--glow-2);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12.5px; color: var(--text);
}
.acct-id-key {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}

/* ---------- Kort på dashboardet ---------- */
.tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 12px;
}
.tile {
    display: block;
    padding: 16px;
    border: 1px solid var(--line);
    border-radius: 13px;
    background: var(--surface);
    color: var(--text);
    text-decoration: none;
    transition: border-color 180ms ease, transform 180ms ease, box-shadow 180ms ease;
}
/* En flise uden side bag sig: den fortæller hvad kontoen har adgang
   til, men den skal ikke invitere til et klik der ikke fører nogen
   steder hen. */
/* Samme tanke som .side-link.is-muted: et andet system end kundens.
   Svagere end "ikke bygget endnu" - den staar der som en oplysning, ikke
   som noget der er paa vej til lige netop dem. */
.tile.is-muted {
    opacity: 0.34;
    cursor: default;
    -webkit-user-select: none;
    user-select: none;
}
.tile.is-muted:hover { transform: none; border-color: var(--line); box-shadow: none; }

.tile:hover {
    border-color: var(--accent);
    transform: translateY(-2px);
    box-shadow: 0 10px 26px var(--glow-2);
}
.tile-icon {
    width: 34px; height: 34px;
    display: grid; place-items: center;
    margin-bottom: 11px;
    border: 1px solid var(--line-strong); border-radius: 10px;
    background: var(--glow-2); color: var(--accent);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
}
.tile-name {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 17px; font-weight: 600;
}
.tile-note { margin-top: 3px; font-size: 13px; color: var(--text-muted); }

.stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 12px;
    margin-bottom: 26px;
}
.stat {
    padding: 14px 16px;
    border: 1px solid var(--line);
    border-radius: 13px;
    background: var(--surface);
}
.stat-value {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 30px; font-weight: 700; line-height: 1;
}
.stat-label {
    margin-top: 5px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}

.panel {
    padding: 18px;
    border: 1px solid var(--line);
    border-radius: 13px;
    background: var(--surface);
    margin-bottom: 22px;
}
/* En formular med tre felter skal ikke være så bred som en tabel - så
   bliver linjerne længere end øjet vil følge. */
.panel-narrow { max-width: 520px; }

.panel-title {
    margin: 0 0 12px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 13px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--label);
}
.panel table { width: 100%; border-collapse: collapse; font-size: 14px; }
.panel th {
    text-align: left; padding: 7px 10px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
    border-bottom: 1px solid var(--line);
}
.panel td { padding: 9px 10px; border-bottom: 1px solid var(--line); }
.panel tr:last-child td { border-bottom: 0; }
.table-wrap { overflow-x: auto; }

/* ---------- Mobil: menuen bliver en skuffe ---------- */
@media (max-width: 900px) {
    .side-nav { transform: translateX(-100%); width: var(--side-w); }
    html[data-drawer="open"] .side-nav { transform: translateX(0); }

    /* Sammenklapning giver ingen mening i en skuffe */
    html[data-sidebar="collapsed"] .side-nav { width: var(--side-w); }
    html[data-sidebar="collapsed"] .side-brand-text,
    html[data-sidebar="collapsed"] .side-head-title,
    html[data-sidebar="collapsed"] .side-link-label { display: initial; }
    html[data-sidebar="collapsed"] .side-link { justify-content: flex-start; padding: 9px 10px; }
    html[data-sidebar="collapsed"] .side-brand { justify-content: flex-start; }
    .side-head { display: none; }

    .app-main,
    html[data-sidebar="collapsed"] .app-main { margin-left: 0; }

    .side-open { display: grid; }
    .app-header { padding: 10px 14px; }
    .app-content { padding: 20px 14px 40px; }
    .page-title { font-size: 30px; }
    .app-header-facts { gap: 12px; }
    .fact { font-size: 13px; }
}

/* =====================================================================
   Kartoteket over organisationer og klienter
   ===================================================================== */

.visually-hidden {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.dir-panel { padding-bottom: 12px; }

.dir-toolbar {
    display: flex; align-items: center; gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.dir-search {
    position: relative;
    flex: 1 1 320px; min-width: 240px;
}
.dir-search-icon {
    position: absolute; left: 13px; top: 50%;
    transform: translateY(-50%);
    width: 16px; height: 16px;
    fill: none; stroke: var(--text-muted); stroke-width: 2; stroke-linecap: round;
    pointer-events: none;
}
.dir-search input {
    width: 100%; height: 42px;
    padding: 0 46px 0 38px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--field-bg); color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 15px;
    transition: border-color 180ms ease, box-shadow 180ms ease;
}
.dir-search input::placeholder { color: var(--text-muted); }
.dir-search input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
/* Krydset i type=search er browserens eget og passer ikke ind. */
.dir-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.dir-key {
    position: absolute; right: 12px; top: 50%;
    transform: translateY(-50%);
    min-width: 20px; padding: 2px 6px;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--glow-2); color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; text-align: center;
    pointer-events: none;
}
.dir-search input:focus ~ .dir-key { opacity: 0; }

.dir-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.dir-filter {
    height: 32px; padding: 0 13px;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer; white-space: nowrap;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.dir-filter:hover { color: var(--text); border-color: var(--line-strong); }
.dir-filter.is-active {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}

.dir-expand {
    height: 32px; padding: 0 13px;
    border: 1px dashed var(--line-strong); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer; white-space: nowrap;
}
.dir-expand:hover { color: var(--text); border-color: var(--accent); }
.dir-expand[aria-pressed="true"] { color: var(--accent); border-style: solid; border-color: var(--accent); }

.dir-recent {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: wrap;
    margin: 0 0 14px;
    padding: 10px 12px;
    border: 1px solid var(--line); border-radius: 11px;
    background: var(--glow-2);
}
.dir-recent-label {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}
.dir-recent-item {
    height: 28px; padding: 0 12px;
    border: 1px solid var(--line-strong); border-radius: 999px;
    background: var(--surface-solid); color: var(--text);
    font-family: "Outfit", sans-serif; font-size: 13px;
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease;
}
.dir-recent-item:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- Tabellen ---------- */
.dir-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.dir-table th {
    text-align: left; padding: 7px 10px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}
.dir-table th.is-sortable { cursor: pointer; user-select: none; }
.dir-table th.is-sortable:hover { color: var(--text); }
.dir-arrow {
    display: inline-block; width: 0; height: 0; margin-left: 6px;
    border-left: 4px solid transparent; border-right: 4px solid transparent;
    border-bottom: 5px solid currentColor;
    opacity: 0; transition: opacity 160ms ease, transform 160ms ease;
}
.dir-table th.is-sorted { color: var(--accent); }
.dir-table th.is-sorted .dir-arrow { opacity: 1; }
.dir-table th.is-desc .dir-arrow { transform: rotate(180deg); }

.dir-table td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--line);
    vertical-align: middle;
}
.dir-row:last-child td { border-bottom: 0; }
.dir-row { transition: background 140ms ease; }
.dir-row:hover { background: var(--glow-2); }
.dir-row.is-child { background: rgba(128, 160, 200, 0.05); }
.dir-row.is-child:hover { background: var(--glow-2); }
.dir-row.is-cursor {
    background: var(--glow-1);
    box-shadow: inset 3px 0 0 var(--accent);
}

/* Indrykningen viser hvem der hører under hvem. */
.dir-name {
    display: flex; align-items: center; gap: 10px;
    padding-left: calc(var(--depth, 0) * 22px);
}
.dir-name-text { display: flex; flex-direction: column; min-width: 0; }
.dir-title {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 16px; font-weight: 600; line-height: 1.2;
}
.dir-sub {
    display: flex; align-items: center; gap: 7px;
    margin-top: 1px;
    font-size: 12px; color: var(--text-muted);
    min-width: 0;
}
.dir-sub-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.dir-twist {
    flex: 0 0 auto;
    width: 22px; height: 22px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 7px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: transform 160ms ease, color 160ms ease, border-color 160ms ease;
}
.dir-twist svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.dir-twist:hover { color: var(--accent); border-color: var(--accent); }
.dir-twist.is-open { transform: rotate(90deg); color: var(--accent); border-color: var(--accent); }
.dir-twist.is-empty { border-color: transparent; cursor: default; }

.pill {
    display: inline-block; padding: 3px 11px;
    border-radius: 999px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; white-space: nowrap;
}
.pill.is-organization {
    border: 1px solid var(--accent-2); color: var(--accent-2);
    background: var(--glow-2);
}
.pill.is-client {
    border: 1px solid var(--accent); color: var(--accent);
    background: var(--glow-1);
}

.chip {
    padding: 2px 8px;
    border-radius: 999px; border: 1px solid currentColor;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; white-space: nowrap;
}
.chip.is-super  { color: #ffb27a; }
.chip.is-off    { color: #ff8f8f; }

/* To raekker med samme navn er ikke to ting. Maerket siger det, saa man
   ikke leder efter en forskel der ikke er. */
.chip.is-dupe { color: #ffb27a; }

/* Sidst paa v3. "Aldrig" daempes: det er normaltilstanden i dag, og
   skal ikke raabe hoejere end de datoer der faktisk siger noget. */
.dir-cell-seen { width: 1%; white-space: nowrap; }
.dir-seen {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 13px; font-weight: 600;
    color: var(--accent);
}
.dir-seen.is-never {
    font-weight: 500;
    color: var(--text-muted);
    opacity: 0.65;
}

.dir-cell-summary { color: var(--text-muted); white-space: nowrap; }
.dir-cell-type,
.dir-cell-action { width: 1%; white-space: nowrap; }
.dir-you {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}

.btn-emulate {
    display: inline-flex; align-items: center; gap: 7px;
    height: 30px; padding: 0 13px;
    border: 1px solid var(--line-strong); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-emulate svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}
.btn-emulate:hover {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}

.dir-empty {
    margin: 18px 0; text-align: center;
    color: var(--text-muted); font-size: 14px;
}
.dir-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
    margin-top: 12px; padding-top: 10px;
    border-top: 1px solid var(--line);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
}

/* =====================================================================
   Emuleringsbjælken

   Ligger fast i bunden. Headeren og sidemenuen sidder allerede fast i
   toppen, og en bjælke dér ville skulle forskyde dem begge - mens en
   bjælke der ruller væk er netop den man glemmer at man har.
   ===================================================================== */
.emulation-bar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    display: flex; align-items: center; gap: 14px;
    padding: 10px 20px;
    border-top: 2px solid #ffb27a;
    background: var(--surface-solid);
    backdrop-filter: blur(14px);
    box-shadow: 0 -12px 34px rgba(0, 0, 0, 0.30);
    animation: riseIn 260ms ease both;
}
.emulation-mark {
    flex: 0 0 auto;
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid #ffb27a; border-radius: 50%;
    color: #ffb27a;
}
.emulation-mark svg {
    width: 16px; height: 16px;
    fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}
.emulation-text {
    flex: 1 1 auto;
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
    font-size: 14px; color: var(--text);
}
.emulation-real {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
}
.emulation-form { margin: 0; }
.emulation-stop {
    height: var(--control-h); padding: 0 16px;
    border: 1px solid #ffb27a; border-radius: 999px;
    background: transparent; color: #ffb27a;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; cursor: pointer;
    transition: background 160ms ease, color 160ms ease;
}
.emulation-stop:hover { background: #ffb27a; color: #17202f; }

/* Plads til bjælken, så det sidste panel ikke gemmer sig bag den. */
body.is-emulating .app-content { padding-bottom: 92px; }

@media (max-width: 900px) {
    .dir-toolbar { gap: 10px; }
    .dir-search { flex: 1 1 100%; }
    .dir-key { display: none; }
    .dir-hint { display: none; }
    .dir-sub { max-width: 42vw; }
    .emulation-bar { padding: 10px 14px; gap: 10px; }
    .emulation-real { display: none; }
}


/* ---------- Slet ---------- */
.dir-actions { display: flex; align-items: center; gap: 6px; justify-content: flex-end; }

/* Slet ligger ved siden af Emulér. Den er bevidst afdæmpet indtil man
   peger på den - en rød knap i 300 rækker ville råbe hele dagen. */
.btn-delete {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-delete svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 1.9;
    stroke-linecap: round; stroke-linejoin: round;
}
.btn-delete:hover,
.btn-delete:focus-visible {
    border-color: #ff8f8f; color: #ff8f8f;
    background: rgba(255, 143, 143, 0.12);
}

/* ---------- Bekræftelsesdialog ---------- */
.modal {
    position: fixed; inset: 0; z-index: 60;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
    background: rgba(3, 8, 16, 0.72);
    backdrop-filter: blur(3px);
    animation: riseIn 160ms ease both;
}

.confirm-card {
    width: min(460px, 94vw);
    padding: 20px;
    border: 1px solid var(--line-strong); border-radius: 16px;
    background: var(--surface);
    box-shadow: 0 22px 54px rgba(0, 0, 0, 0.45);
}

/* HER STOD backdrop-filter: blur(10px).
 *
 * Et element med backdrop-filter bliver SELV udgangspunkt for alt der
 * er position: fixed indeni - og med .edit-card's overflow-y: auto
 * klippede kortet dem ogsaa. Rullelisterne og forslagslisterne er
 * fixed netop for at kunne laegge sig ud over kortets kant; i stedet
 * blev de skaaret af ved bunden, saa der stod to raekker tilbage af
 * elleve. Se v3PlacerListe(), hvor den samme forfader allerede har
 * gjort fortraed een gang.
 *
 * Sloeringen er der stadig. .modal har sin egen - og den er inset: 0
 * uden overflow, saa den klipper ikke noget. To lag sloering oven paa
 * hinanden under en 0,72 moerk overflade var alligevel ikke til at se.
 */
.confirm-card.warning {
    border-color: #ff8f8f;
    box-shadow: 0 0 0 1px rgba(255, 143, 143, 0.18), 0 22px 54px rgba(0, 0, 0, 0.45);
}
.confirm-card h3 {
    margin: 0 0 10px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 26px; line-height: 1;
    /* Overskriften er ikke altid vores egen tekst. Afspilleren saetter
       filnavnet der, og et navn som
       "ASDSAgfdgfdg_dfgfdgfdg_dfgfdgDSAD_ASDSADSAD_..." er EET ord -
       understreger er ikke et sted browseren maa braekke. Uden reglen
       loeb overskriften ud over kortets kant og videre ud over skaermen. */
    overflow-wrap: anywhere;
}

/* Navnet paa det man er ved at gaa i gang med. Kortet er 460px bredt, og
   en reklame kan hedde
   "ASDSADSAD_ASDSADSAD_ASDSAD_SADASDSADSAD_DSHold_avstand_SoMe.mp4" -
   eet ord uden et eneste sted browseren maa braekke det. Uden reglen her
   loeb navnet ud over kortets kant.

   Brudt, ikke klippet af. I listen kan et navn godt klippes - der
   kigger man efter noget. Her skal man vaere sikker paa HVAD man
   sletter, og en ellipse skjuler netop den ende hvor to filer plejer at
   vaere forskellige. */
.confirm-card p > strong { overflow-wrap: anywhere; }
.confirm-card.warning h3 { color: #ff8f8f; }
.confirm-card p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); }
.confirm-card p strong { font-size: 16px; }

.confirm-note {
    margin-top: 10px !important;
    font-size: 12.5px !important;
    color: var(--text-muted) !important;
}

.confirm-actions {
    display: flex; justify-content: flex-end; gap: 10px;
    margin-top: 18px; flex-wrap: wrap;
}
.btn-cancel,
.btn-danger {
    height: var(--control-h); padding: 0 18px;
    border-radius: 999px; cursor: pointer;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-cancel {
    border: 1px solid var(--line); background: transparent; color: var(--text-muted);
}
.btn-cancel:hover { border-color: var(--line-strong); color: var(--text); }
.btn-danger {
    border: 1px solid #ff8f8f; background: rgba(255, 143, 143, 0.14); color: #ff8f8f;
}
.btn-danger:hover { background: #ff8f8f; color: #17202f; }
.btn-cancel:focus-visible,
.btn-danger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Rediger og gendan ---------- */
.btn-edit {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-edit svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 1.9;
    stroke-linecap: round; stroke-linejoin: round;
}
.btn-edit:hover,
.btn-edit:focus-visible {
    border-color: var(--accent-2); color: var(--accent-2);
    background: var(--glow-2);
}

/* En knap der staar for noget der ER slaaet til - lukketider paa en
   player, fx. Man skal kunne se ned over listen og se hvilke skaerme
   der slukker af sig selv, uden at aabne dem een for een. */
.btn-edit.is-on {
    border-color: var(--accent); color: var(--accent);
}

/* En slettet raekke skal kunne ses som slettet paa afstand, men stadig
   kunne laeses - det er dén man leder efter naar man vil fortryde. */
.dir-row.is-gone { opacity: 0.45; }
.dir-row.is-gone:hover { opacity: 0.8; background: var(--glow-2); }
.dir-row.is-gone .dir-title { text-decoration: line-through; }
.chip.is-gone { color: #ff8f8f; }
.dir-filter.is-gone.is-active {
    border-color: #ff8f8f; color: #ff8f8f;
    background: rgba(255, 143, 143, 0.12);
}

.btn-restore {
    display: inline-flex; align-items: center; gap: 7px;
    height: 30px; padding: 0 13px;
    border: 1px solid var(--accent); border-radius: 999px;
    background: var(--glow-1); color: var(--accent);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer;
    transition: background 160ms ease, color 160ms ease;
}
.btn-restore svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}
.btn-restore:hover { background: var(--accent); color: #17202f; }

/* ---------- Redigeringsdialogen ---------- */
.edit-card { width: min(620px, 94vw); max-height: 90vh; overflow-y: auto; }

.edit-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px 14px;
    margin-top: 16px;
}
.field-wide   { grid-column: 1 / -1; }
.field-narrow { max-width: 120px; }

/* margin: 0 er ikke pynt. Login-sidens label-regel giver hver <label>
   14px foroven og 7px forneden, og et .field kan vaere baade en <div>
   og en <label>. Staar de to slags side om side i gitteret - som
   "Hvor hoerer det til?" og "Sekunder paa skaermen" i galleriet -
   sad den ene 14px lavere end den anden. Afstanden mellem raekker
   kommer fra .edit-form's gap, ikke fra labelens margin. */
.field {
    display: flex; flex-direction: column; gap: 5px; min-width: 0;
    margin: 0;
}
.field > span {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}
.field input,
.field select,
.field textarea {
    height: 38px; padding: 0 12px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--field-bg); color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 14px; width: 100%;
    transition: border-color 160ms ease, box-shadow 160ms ease;
}

/* En textarea har brug for hoejde og luft foroven, og den skal ikke
   arve browserens egen graa baggrund - den stod som et fremmedlegeme
   mellem de moerke felter. */
.field textarea {
    height: auto; min-height: 96px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--text-muted); opacity: 0.7; }

/* Overskriften mellem stamdata og login */
.edit-split {
    grid-column: 1 / -1;
    margin-top: 6px; padding-top: 12px;
    border-top: 1px solid var(--line);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--label);
}

.btn-save {
    height: var(--control-h); padding: 0 20px;
    border: 1px solid var(--accent); border-radius: 999px;
    background: var(--glow-1); color: var(--accent);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; cursor: pointer;
    transition: background 160ms ease, color 160ms ease;
}
.btn-save:hover { background: var(--accent); color: #17202f; }
.btn-save:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 620px) {
    .edit-form { grid-template-columns: 1fr; }
    .field-narrow { max-width: none; }
}

/* ---------- Vores egen rulleliste ----------
   En <select> tegner sin åbne liste af styresystemet, og den kan ikke
   styles. Derfor en knap, en liste og et skjult felt. Formsproget er
   lånt fra sprogvælgeren i headeren, så de to ligner hinanden. */
.pick { position: relative; }

.pick-button {
    width: 100%; height: 38px;
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 0 12px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--field-bg); color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 14px; text-align: left; cursor: pointer;
    transition: border-color 160ms ease, box-shadow 160ms ease;
}
.pick-button:hover { border-color: var(--line-strong); }
.pick-button:focus-visible,
.pick-button[aria-expanded="true"] {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
.pick-button svg {
    flex: 0 0 auto;
    width: 14px; height: 14px;
    fill: none; stroke: var(--text-muted); stroke-width: 2.4;
    stroke-linecap: round; stroke-linejoin: round;
    transform: rotate(90deg);
    transition: transform 160ms ease;
}
.pick-button[aria-expanded="true"] svg { transform: rotate(-90deg); stroke: var(--accent); }

/* Fast placering, ikke absolut. En .table-wrap har overflow-x: auto, og
   saa klipper den ogsaa lodret - menuen havde ingen chance for at folde
   sig ud af tabellen. Med fixed maales koordinaterne i JavaScript, og
   ingen beholder kan klippe den. */
.pick-menu {
    position: fixed;
    z-index: 60;
    display: grid; gap: 2px;
    padding: 5px;
    /* Hoej nok til at musikkategorierne staar der alle ni. Ruller
       stadig for de lange lister - kaedevalget har over 300. */
    max-height: 340px; overflow-y: auto;
    border: 1px solid var(--line-strong); border-radius: 12px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: var(--card-shadow);
    animation: riseIn 140ms ease both;
}
/* Retningen afgoeres i JavaScript sammen med koordinaterne. */

.pick-option {
    padding: 8px 11px;
    border: 0; border-radius: 8px;
    background: transparent; color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 14px; text-align: left; cursor: pointer;
    transition: background 140ms ease, color 140ms ease;
}
.pick-option:hover { background: var(--glow-2); }

/* Fritekst med forslag. Feltet er et almindeligt tekstfelt; listen er
   den samme som rullelistens, saa de to ser ens ud. */
.suggest { position: relative; }

/* Plads til knappen. .field input giver i forvejen 42px til hoejre for
   oejet paa adgangskodefeltet - det passer. */
.suggest-toggle {
    position: absolute; right: 1px; top: 1px; bottom: 1px; width: 38px;
    display: grid; place-items: center;
    border: 0; background: none; padding: 0;
    color: var(--text-muted); cursor: pointer;
    border-radius: 0 9px 9px 0;
}
.suggest-toggle svg {
    width: 16px; height: 16px; fill: none; stroke: currentColor;
    stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
    transform: rotate(90deg); transition: transform 160ms ease;
}
.suggest-toggle:hover { color: var(--accent); }
.suggest input[aria-expanded="true"] + .suggest-toggle svg {
    transform: rotate(-90deg); stroke: var(--accent);
}

.suggest-menu { padding: 4px; }
.suggest-menu .pick-option { font-size: 13.5px; }

/* Den del af navnet man har skrevet. Uden den skal man selv finde ud af
   hvorfor netop de her tredive navne staar der. */
.suggest-hit { color: var(--accent); font-weight: 600; }

.suggest-more {
    margin: 2px 0 0; padding: 7px 12px;
    font-size: 12px; color: var(--text-muted);
    border-top: 1px solid var(--line);
}

/* En overskrift i en lang liste. 26 opdelinger i een raekke kan man
   ikke finde rundt i; fire grupper kan man. */
.pick-group {
    margin: 6px 0 2px; padding: 6px 12px 2px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--text-muted);
    border-top: 1px solid var(--line);
}
.pick-menu > .pick-group:first-of-type { border-top: 0; margin-top: 0; }
.pick-option:focus-visible {
    outline: none;
    background: var(--glow-2);
    box-shadow: inset 0 0 0 1px var(--accent);
}
.pick-option.is-active { color: var(--accent); font-weight: 600; }
.pick-option.is-active::after { content: " ✓"; opacity: 0.8; }

/* Etiketten over vælgeren skal flugte med de andre feltetiketter */
.field-label {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}

/* Fejl i redigeringsdialogen.
   Den skal ses. Den gamle udgave var grå brødtekst nederst i formularen
   og lignede en fodnote - man kunne trykke Gem to gange uden at opdage
   hvorfor der ikke skete noget. */
.edit-error {
    display: flex; align-items: flex-start; gap: 9px;
    margin: 4px 0 0 !important;
    padding: 11px 13px;
    border: 1px solid #ff8f8f; border-radius: 10px;
    background: rgba(255, 143, 143, 0.12);
    color: #ffc9c9;
    font-size: 13.5px; line-height: 1.45;
    animation: riseIn 160ms ease both;
}
.edit-error svg {
    flex: 0 0 auto;
    width: 17px; height: 17px; margin-top: 1px;
    fill: none; stroke: #ff8f8f; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}

/* Feltet der er noget galt med */
.field input.has-error,
.pick-button.has-error {
    border-color: #ff8f8f;
    background: rgba(255, 143, 143, 0.08);
}
.field input.has-error:focus,
.pick-button.has-error:focus-visible {
    border-color: #ff8f8f;
    box-shadow: 0 0 0 3px rgba(255, 143, 143, 0.22);
}

html[data-theme="light"] .edit-error { color: #9a2b36; background: #fdecec; }

/* ---------- Opret-siden ---------- */
.create-intro {
    margin: 0 0 4px;
    font-size: 14px; line-height: 1.5; color: var(--text-muted);
    max-width: 62ch;
}
.create-intro + .edit-form { margin-top: 18px; }

/* Fejl under et enkelt felt, på den side hvor der ikke er en dialog */
.field-error {
    font-size: 12.5px; line-height: 1.4; color: #ff8f8f;
}


/* Annullér er et link her, ikke en knap - men skal se ens ud */
a.btn-cancel {
    display: inline-flex; align-items: center;
    text-decoration: none;
}

/* ---------- Kvittering efter oprettelse ---------- */
.created-card { width: min(480px, 94vw); text-align: left; }

.created-mark {
    width: 44px; height: 44px;
    display: grid; place-items: center;
    margin-bottom: 14px;
    border: 1px solid var(--accent); border-radius: 50%;
    background: var(--glow-1); color: var(--accent);
}
.created-mark svg {
    width: 22px; height: 22px;
    fill: none; stroke: currentColor; stroke-width: 2.6;
    stroke-linecap: round; stroke-linejoin: round;
}

.created-list {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 9px 16px;
    margin: 18px 0 0;
    align-items: baseline;
}
.created-list dt {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
    white-space: nowrap;
}
.created-list dd { margin: 0; font-size: 14.5px; color: var(--text); }
.created-list code {
    padding: 2px 8px;
    border: 1px solid var(--line); border-radius: 7px;
    background: var(--field-bg);
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 13.5px;
    user-select: all;          /* ét klik markerer hele værdien */
}
.created-hint {
    display: block; margin-top: 3px;
    font-size: 12px; color: var(--text-muted);
}
a.btn-save { display: inline-flex; align-items: center; text-decoration: none; }

/* ---------- Indstillinger ---------- */
.btn-settings {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-settings svg {
    width: 15px; height: 15px;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round;
}
.btn-settings:hover,
.btn-settings:focus-visible {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}

.settings-card { width: min(540px, 94vw); max-height: 90vh; overflow-y: auto; }
.settings-for {
    margin: 0 0 4px !important;
    font-size: 15px; color: var(--text-muted);
}
.settings-for strong { color: var(--text); font-size: 16px; }
.settings-form { display: grid; gap: 2px; margin-top: 16px; }

/* Afkrydsning. Hele linjen er klikbar - en 13px boks er et lille mål. */
.check {
    display: flex; align-items: flex-start; gap: 11px;
    padding: 9px 11px;
    border-radius: 9px;
    cursor: pointer;
    transition: background 140ms ease;
}
.check:hover { background: var(--glow-2); }
.check input {
    flex: 0 0 auto;
    width: 18px; height: 18px; margin: 1px 0 0;
    accent-color: var(--accent);
    cursor: pointer;
}
.check span { font-size: 14px; line-height: 1.4; color: var(--text); }
.check:has(input:checked) span { color: var(--text); }
.check:has(input:focus-visible) { box-shadow: 0 0 0 2px var(--accent); }

/* ---------- Aflyt lukkespeaks ---------- */
.speaks {
    margin-top: 16px; padding-top: 16px;
    border-top: 1px solid var(--line);
}
.speaks-head {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--label);
}
.speaks-note {
    margin: 5px 0 12px !important;
    font-size: 12.5px !important; color: var(--text-muted) !important;
}
.speaks-row {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.speaks-pick { display: flex; gap: 4px; }
.speaks-btn {
    height: 32px; padding: 0 14px;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer; white-space: nowrap;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.speaks-btn:hover { color: var(--text); border-color: var(--line-strong); }
.speaks-btn.is-active {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}
.speaks-row audio { height: 36px; flex: 1 1 220px; min-width: 200px; }

/* ---------- Musetips ----------
   Ét delt element, placeret med position: fixed. Så kan det ikke blive
   klippet af et kort med overflow, som en tooltip inde i rækken ville. */
.tip {
    position: fixed; z-index: 80;
    max-width: 280px;
    padding: 7px 11px;
    border: 1px solid var(--line-strong); border-radius: 9px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
    color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 12.5px; line-height: 1.4;
    /* Et filnavn som NEW_PROGRAM_RELEASE_BODYATTACK_TRAILER_16x9.mp4 har
       ingen steder at brydes, så boksen voksede forbi sin egen max-width
       og ud over kanten. Nu brydes det hvor det skal. */
    overflow-wrap: anywhere;
    pointer-events: none;          /* må aldrig stjæle musen fra knappen */
    animation: tipIn 120ms ease both;
}

/* Spidsen. Et roteret kvadrat med to kanter - så den følger rammen. */
.tip::after {
    content: "";
    position: absolute; left: var(--tip-arrow, 50%); bottom: -5px;
    width: 8px; height: 8px;
    margin-left: -4px;
    transform: rotate(45deg);
    background: var(--surface-solid);
    border-right: 1px solid var(--line-strong);
    border-bottom: 1px solid var(--line-strong);
}
.tip.is-under::after {
    bottom: auto; top: -5px;
    border: 0;
    border-left: 1px solid var(--line-strong);
    border-top: 1px solid var(--line-strong);
}

@keyframes tipIn {
    from { opacity: 0; transform: translateY(3px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Røres ikke af musen på berøringsskærme - der er ingen hover */
@media (hover: none) {
    .tip { display: none !important; }
}

/* ---------- Sporet i emuleringsbjælken ----------
   Hvert trin er en knap tilbage til dét lag. Så kan man gå ud af en
   klient og blive i organisationen, i stedet for hele vejen hjem. */
.emulation-trail {
    flex: 1 1 auto; margin: 0;
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    font-size: 14px;
}
.emulation-step {
    padding: 3px 10px;
    border: 1px solid transparent; border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 13.5px; cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.emulation-step:hover,
.emulation-step:focus-visible {
    border-color: #ffb27a; color: #ffb27a;
    background: rgba(255, 178, 122, 0.12);
    outline: none;
}
.emulation-arrow { color: var(--text-muted); opacity: 0.5; }
.emulation-now {
    padding: 3px 10px;
    border: 1px solid #ffb27a; border-radius: 999px;
    background: rgba(255, 178, 122, 0.16);
    color: #ffe0b0; font-weight: 600;
}

/* ---------- Brugere ---------- */
.users-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    margin-bottom: 16px;
}
.users-head .note { margin: 0; max-width: 58ch; }

/* De satte rettigheder som små mærkater i tabellen */
.chip.is-right {
    color: var(--accent-2);
    margin-right: 4px;
}

.settings-note {
    margin: 0 0 12px !important;
    font-size: 12.5px !important; color: var(--text-muted) !important;
}

/* Lokationslisten kan blive lang - lad den rulle i stedet for at
   skubbe knapperne ud af dialogen */
.group-list {
    max-height: 46vh; overflow-y: auto;
    margin: 0 -4px; padding: 0 4px;
}
.group-type {
    margin-left: 7px;
    font-style: normal;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
}

/* ---------- Players ---------- */

/* Livstegnet som en prik. En player der har været stille i mere end et
   døgn er ikke nødvendigvis død - men det er dét man leder efter. */
.live-dot {
    flex: 0 0 auto;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--text-muted); opacity: 0.4;
}
.live-dot.is-live {
    background: var(--accent); opacity: 1;
    box-shadow: 0 0 0 3px var(--glow-1);
}
.dir-row.is-quiet .dir-title { color: var(--text-muted); }

/* Gamle og demo-enheder (playerstatus <> 1). De skal kunne læses - de
   er stadig en del af historikken - men ikke forveksles med noget der
   kører. Ikke gennemstreget som en slettet række: de er ikke slettet. */
.dir-row.is-retired { opacity: 0.45; }
.dir-row.is-retired:hover { opacity: 0.85; background: var(--glow-2); }
.chip.is-retired { color: var(--text-muted); }

/* identitetid er nøglen vi beder brugeren om i telefonen. Monospace så
   cifrene ikke kan forveksles, og user-select: all så ét klik markerer
   hele tallet. */
/* MAC-adressen står på sin egen linje under sted og lokation. Samlet
   blev linjen for lang, og en MAC læses tegn for tegn - ikke i
   forbifarten - så den har godt af monospace og sin egen plads. */
.player-mac {
    display: block;
    margin-top: 3px;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 11px; letter-spacing: 0.04em;
    color: var(--text-muted);
    user-select: all;
}

/* Panelets hoved: en forklaring til venstre, en handling til hoejre. */
.panel-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 20px; flex-wrap: wrap;
    margin-bottom: 16px;
}

/* Et arvet ban kommer fra organisationen og kan ikke fjernes her. */
.chip.is-inherited { color: var(--accent); }
.chip.is-explicit  { color: #ff8f8f; }

/* Format: en mp3 spilles gennem hoejttalerne, en video fylder skaermen.
   Det er to forskellige ting at banne, saa det skal kunne skimmes. */
.chip.is-mp3   { color: #7fd1ff; }
.chip.is-video { color: #c9a7ff; }

/* Dialogen har en fast mindstehoejde. Uden den var kortet saa lavt naar
   man aabnede det, at kategorilisten foldede sig OP og daekkede
   overskriften. Nu er der plads nedenunder, og hoejden hopper heller
   ikke naar de foerste resultater kommer. */
.ban-card { min-height: 560px; }

/* Soegning i katalaget. To felter side om side naar der er plads. */
.ban-search { display: grid; grid-template-columns: 1fr 200px; gap: 14px; margin: 18px 0 6px; }
@media (max-width: 560px) { .ban-search { grid-template-columns: 1fr; } }

.ban-note {
    margin: 8px 2px 10px; min-height: 18px;
    font-size: 12.5px; color: var(--text-muted);
}

/* Resultatlisten har sin egen hoejde og ruller for sig selv - dialogen
   skal ikke vokse ud af skaermen fordi en soegning gav 60 numre. */
.ban-results {
    max-height: 320px; overflow-y: auto;
    margin: 12px 0 4px;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--surface-2, transparent);
}
.ban-results:empty { display: none; }

/* En tom liste er én sætning i en kasse. Uden polstring klæber den til
   kanten, og uden luft nedenunder løber den ind i næste overskrift. */
.ban-results > .note {
    margin: 0;
    padding: 16px 14px;
}

/* En overskrift lige efter en kasse har brug for mere end sine sædvanlige
   seks pixels - ellers ligger stregen oven i kassens kant. */
.ban-results + .edit-split { margin-top: 20px; }

.ban-hit {
    display: flex; align-items: center; gap: 14px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line);
}
.ban-hit:last-child { border-bottom: 0; }
.ban-hit-text { flex: 1 1 auto; min-width: 0; }
.ban-hit-title {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 15px; font-weight: 600; line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ban-hit-sub {
    display: flex; align-items: center; gap: 7px;
    margin-top: 3px; font-size: 12px; color: var(--text-muted);
    min-width: 0;
}
.ban-hit-sub > span:first-child {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ban-hit.is-banned { opacity: 0.5; }
.ban-hit-done {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted); white-space: nowrap;
}

/* TeamViewer-id'et som knap. Det skal se ud som det tal det er - ikke
   som et link - men det skal kunne ses at man kan trykke. */
.tv-link {
    padding: 0; border: 0; background: none;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 13px; font-weight: 600;
    color: var(--accent);
    cursor: pointer;
    border-bottom: 1px dashed currentColor;
}
.tv-link:hover { color: var(--text); }
.tv-link:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--glow-1);
    border-radius: 3px;
}

/* Denne dialog har mere at læse end de andre, så den får mere luft. */
.tv-card { padding: 26px 28px 22px; }
.tv-card h3 { margin-bottom: 4px; }
.tv-card > p:first-of-type { margin: 0 0 4px; }

/* Id og adgangskode i dialogen: store nok til at læse højt i telefonen. */
.tv-keys {
    display: grid; grid-template-columns: auto 1fr;
    gap: 16px 22px; align-items: center;
    margin: 26px 2px 24px;
}
.tv-keys dt {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-muted);
}
.tv-keys dd { margin: 0; display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.tv-key {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 17px; font-weight: 600; letter-spacing: 0.04em;
    color: var(--text);
    user-select: all;
}
.tv-key.is-unknown { color: var(--text-muted); letter-spacing: 0.12em; }

.tv-copy {
    height: 24px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 999px;
    background: none; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
    text-transform: uppercase; cursor: pointer;
    white-space: nowrap;
}
.tv-copy:hover { color: var(--accent); border-color: var(--accent); }

.tv-card .confirm-note { margin-top: 18px !important; line-height: 1.55; }
.tv-card .confirm-actions { margin-top: 26px; }

/* Standardadgangskoden rettes på stedet. Den er skilt fra med en linje,
   fordi den hører til v3 og ikke til den player dialogen handler om. */
.tv-standard {
    margin-top: 22px; padding-top: 20px;
    border-top: 1px solid var(--line);
}
.tv-standard .note { margin: 8px 0 0; font-size: 12px; color: var(--text-muted); }
.tv-standard .confirm-actions { margin-top: 18px; }


/* Id'et er en knap med en stiplet streg under - samme greb som
   TeamViewer-id'et, saa det kan ses at der er mere bag tallet. Farven
   paa stregen er maskinens alder: 523 af de 981 players er fem aar
   eller mere. */
[data-hover] {
    border: 0; background: none; padding: 0;
    cursor: help;
    border-bottom: 1px dashed currentColor;
    color: inherit; font: inherit;
}
[data-hover].is-new     { color: var(--text-muted); }
[data-hover].is-unknown { color: var(--text-muted); border-bottom-style: dotted; }
[data-hover].is-mid     { color: #ffb27a; }
[data-hover].is-old     { color: #ff8f8f; }
[data-hover]:hover,
[data-hover]:focus-visible { color: var(--text); }
[data-hover]:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--glow-1); }

/* Playertallet og maerkerne paa deres egen linje under login, by og
   kundenummer. Alt paa een linje blev for taet til at skimme - og det
   er netop en liste man skimmer. */
.dir-meta {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    margin-top: 5px;
}
.dir-meta [data-hover] { font-size: 12px; color: var(--accent); white-space: nowrap; }
.dir-meta [data-hover].is-old { color: #ff8f8f; }
.dir-meta [data-hover]:hover,
.dir-meta [data-hover]:focus-visible { color: var(--text); }

/* Kortet der kommer frem naar musen holdes paa noget stiplet. Fast
   placeret, saa tabellens egen rulning ikke klipper det. Deles af
   playerens alder og af kartotekets playertal. */
.hovercard {
    position: fixed; z-index: 70;
    width: 260px; padding: 12px 14px;
    border: 1px solid var(--line-strong); border-radius: 12px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: var(--card-shadow);
    pointer-events: none;
    animation: riseIn 120ms ease both;
}
.hovercard.is-measuring { animation: none; }
.hovercard-title {
    margin: 0; font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 14px; font-weight: 600; line-height: 1.2;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hovercard-lead {
    margin: 2px 0 8px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 17px; font-weight: 700; line-height: 1.15;
}
.hovercard.is-mid .hovercard-lead { color: #ffb27a; }
.hovercard.is-old .hovercard-lead { color: #ff8f8f; }
.hovercard.is-unknown .hovercard-lead { color: var(--text-muted); }

.hovercard-facts {
    display: grid; grid-template-columns: auto 1fr; gap: 3px 10px;
    margin: 0; font-size: 12px;
}
.hovercard-facts dt {
    color: var(--text-muted); white-space: nowrap;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; padding-top: 1px;
}
.hovercard-facts dd {
    margin: 0; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hovercard-note {
    margin: 9px 0 0; padding-top: 8px;
    border-top: 1px solid var(--line);
    font-size: 12px; line-height: 1.4; color: var(--text-muted);
}

.player-id {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 14px; font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text);
    user-select: all;
}

/* Diskforbrug: tal og bjælke. Bjælken er der for at kunne skimme en
   lang liste uden at læse procenter. */
.disk { min-width: 132px; }
.disk-text {
    display: block;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 14px; font-weight: 600; color: var(--text);
}
.disk-of {
    font-weight: 500; font-size: 12px; color: var(--text-muted);
    letter-spacing: 0;
}
.disk-bar {
    display: block; margin-top: 4px;
    height: 5px; border-radius: 999px;
    background: var(--glow-2);
    overflow: hidden;
}
.disk-bar > span {
    display: block; height: 100%;
    background: var(--accent);
    border-radius: 999px;
}
.disk-bar.is-full > span { background: #ff8f8f; }

/* Forbindelse: to linjer med etiket og værdi */
.conn-line { display: block; line-height: 1.7; white-space: nowrap; }
.conn-label {
    display: inline-block; min-width: 74px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}
.conn-line code {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 12.5px; color: var(--text);
    user-select: all;
}

/* Beta-knappen ligner genstart, men lyser gult i stedet for rødt: den
   er ikke destruktiv, den er bare ikke noget man gør i en fart. */
.btn-beta {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-beta svg {
    width: 15px; height: 15px;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}
.btn-beta:hover,
.btn-beta:focus-visible {
    border-color: #ffd479; color: #ffd479;
    background: rgba(255, 212, 121, 0.12);
}

.btn-reboot {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-reboot svg {
    width: 15px; height: 15px;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round;
}
.btn-reboot:hover,
.btn-reboot:focus-visible {
    border-color: #ff8f8f; color: #ff8f8f;
    background: rgba(255, 143, 143, 0.12);
}

/* Oplysninger playeren selv har meldt - kan ikke rettes */
.created-list dd.is-unknown::after {
    content: "–";
    color: var(--text-muted);
}

/* ---------------------------------------------------------------------
   Reklamer
   --------------------------------------------------------------------- */

/* Miniaturen er lille med vilje: den er til at genkende filen på, ikke
   til at vurdere den. En reklame er tit 1920x1080. */
.ad-cell-thumb { width: 78px; padding-right: 0; }

/* Reklamernes filnavne er lange. Eet af dem fylder 99 tegn:
   "154842_131097742415121157_NORWAY_ACTIC_15SEC_ATC_25Mbps_H264_..." -
   uden faste spalter skubber saadan et navn tabellen ud over sin egen
   kant, eller braekker over i to linjer saa raekkerne bliver ulige hoeje.

   Klippet af med en ellipse. Hele navnet staar i title, saa det kan
   laeses ved at holde musen stille - og det staar ogsaa i
   redigeringsdialogen. */
.ad-table { table-layout: fixed; }
.ad-table td { overflow: hidden; }
.ad-table .dir-title {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ad-table .dir-sub-text { max-width: 100%; }
.ad-table th:nth-child(2) { width: auto; }
.ad-table th:nth-child(3) { width: 22%; }
.ad-table th.dir-cell-action { width: 164px; }

/* Lydstyrken. Tallet er kort og skal staa paa een linje - "-24,0 LUFS"
   maa ikke braekke midt over. */
.ad-cell-lufs { width: 118px; white-space: nowrap; }

.ad-lufs {
    display: inline-block;
    font-size: 12px; font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

/* Paa plads: det er meningen at det ikke springer i oejnene. Ved siden
   af: det skal kunne ses paa tvaers af en lang liste, uden at ligne en
   fejl - reklamen spiller udmaerket, den spiller bare for hoejt. */
.ad-lufs.is-level-ok  { color: var(--accent); }
.ad-lufs.is-level-off { color: #ffc46b; }
.ad-lufs.is-unmeasured,
.ad-lufs.is-silent,
.ad-lufs.is-none      { color: var(--text-muted); }
.ad-lufs.is-working   { color: var(--accent); }
.ad-thumb {
    display: grid; place-items: center;
    width: 62px; height: 36px;
    border-radius: 6px; border: 1px solid var(--line);
    object-fit: cover; background: var(--glow-2);
    color: var(--text-muted); font-size: 15px;
}

/* Serveren ved allerede at filen ikke er der - ads.php bygger klassen
   som "is-<?= video ? 'video' : 'missing' ?>", saa navnet staar ikke
   samlet noget sted i koden. Jeg naaede at slette reglen her en gang
   fordi en soegning efter "is-missing" ikke fandt den. */
.ad-thumb.is-missing { color: #ff8f8f; border-color: rgba(255, 143, 143, 0.4); }

.ad-plays { display: block; }
.ad-plays-sub { display: block; margin-top: 2px; font-size: 12px; color: var(--text-muted); }

/* Uploadens fremdrift. Den fylder intet indtil der sker noget. */
.ad-progress { margin: 14px 0 4px; }
.ad-progress-name { font-size: 12.5px; color: var(--text-muted); margin-bottom: 6px; }
.ad-progress-bar {
    height: 6px; border-radius: 999px; overflow: hidden;
    background: var(--glow-2);
}
.ad-progress-bar > span {
    display: block; height: 100%; width: 0;
    background: var(--accent);
    transition: width 180ms ease;
}

/* Planlægningsdialogen har mest indhold af alle - den får sin egen
   bredde og lov til at rulle. */
.adplan-card { width: min(680px, 94vw); max-height: 88vh; overflow-y: auto; }

.adplan-plans { margin: 16px 0 4px; display: grid; gap: 10px; }
.adplan-item {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 14px;
    border: 1px solid var(--line); border-radius: 12px;
}
.adplan-item.is-paused { opacity: 0.6; }
.adplan-item-text { flex: 1 1 auto; min-width: 0; }
.adplan-item-title {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 15px; font-weight: 600; line-height: 1.25;
}
.adplan-item-sub { margin-top: 2px; font-size: 12px; color: var(--text-muted); }

/* Flueben i kolonner - en klient kan have tredive kalendre. */
.adplan-boxes {
    display: grid; gap: 8px 18px;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    margin: 4px 0 10px;
}
.adplan-box {
    display: flex; align-items: center; gap: 9px;
    font-size: 13.5px; cursor: pointer;
}
.adplan-box input { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

.adplan-dates { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 520px) { .adplan-dates { grid-template-columns: 1fr; } }

/* Syv dage, to felter hver. /v2 har fire rullelister pr. dag - 28 felter
   at klikke sig igennem. Her er der 14, og de er klokkefelter. */
.adplan-days { display: grid; gap: 8px; margin-top: 10px; }
.adplan-day { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.adplan-day-name {
    width: 84px; flex: 0 0 auto;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 13px; font-weight: 600; color: var(--text-muted);
}
.adplan-day-dash { color: var(--text-muted); }
.adplan-day input[type="time"] {
    height: 34px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13.5px;
    color-scheme: dark;
}
.adplan-day input[type="time"]:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
.adplan-schedule { margin-top: 6px; }

/* En bemaerkning UNDER dagene skal have luft. Uden den klaeber
   "Playeren spoerger efter sine tider ..." sig til soendag og ligner
   en ottende dag. */
.adplan-days + .note { margin-top: 16px; }

/* En advarsel, ikke en bemaerkning. Staar der ikke et tidsrum paa en
   eneste dag, vises indslaget aldrig - og det skal man opdage mens man
   udfylder, ikke naar skaermen har staaet tom en uge. */
.note.is-warn { color: #ffc46b; }

/* ---------------------------------------------------------------------
   Datovælger

   Samme opbygning som rullelisten: en knap, et panel, et skjult felt.
   En <input type="date"> tegner sit panel af styresystemet, og det kan
   ikke styles - i en mørk dialog ser det ud som et andet program.
   --------------------------------------------------------------------- */
.dp { position: relative; }

.dp-button {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    width: 100%; height: var(--control-h);
    padding: 0 14px;
    border: 1px solid var(--line); border-radius: 11px;
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 14px; text-align: left;
    cursor: pointer;
}
.dp-button svg {
    width: 16px; height: 16px; flex: 0 0 auto;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-muted);
}
.dp-button:hover { border-color: var(--line-strong); }
.dp-button:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
/* Uden en dato står etiketten dæmpet - det er en opfordring, ikke en værdi. */
.dp.is-empty .dp-button { color: var(--text-muted); }

.dp-panel {
    position: absolute; left: 0; top: calc(100% + 6px);
    z-index: 6; width: 268px;
    padding: 12px;
    border: 1px solid var(--line-strong); border-radius: 14px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: var(--card-shadow);
    overflow-y: auto;
    animation: riseIn 140ms ease both;
}
.dp.is-up .dp-panel { top: auto; bottom: calc(100% + 6px); }

.dp-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 10px;
}
.dp-title {
    flex: 1 1 auto; text-align: center;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 14px; font-weight: 600; letter-spacing: 0.02em;
    text-transform: capitalize;
}
.dp-nav {
    width: 28px; height: 28px; flex: 0 0 auto;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 8px;
    background: none; color: var(--text-muted); cursor: pointer;
}
.dp-nav svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.dp-nav:hover { color: var(--accent); border-color: var(--accent); }

.dp-week, .dp-grid {
    display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
}
.dp-wd {
    display: grid; place-items: center; height: 24px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--text-muted);
}
.dp-day {
    height: 32px;
    display: grid; place-items: center;
    border: 1px solid transparent; border-radius: 8px;
    background: none; color: var(--text);
    font-family: inherit; font-size: 13px;
    cursor: pointer;
}
.dp-day:hover { background: var(--glow-2); }
/* I dag markeres med en ring, den valgte med fyld - så kan man se begge. */
.dp-day.is-today { border-color: var(--line-strong); }
.dp-day.is-chosen {
    background: var(--accent); color: #06121a; font-weight: 700;
    border-color: var(--accent);
}
.dp-day:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--glow-1); }

.dp-foot {
    display: flex; justify-content: space-between;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--line);
}
.dp-text {
    border: 0; background: none; padding: 2px 6px;
    color: var(--text-muted); cursor: pointer;
    font-family: inherit; font-size: 12.5px;
    border-radius: 6px;
}
.dp-text:hover { color: var(--accent); }
.dp-text:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--glow-1); }

/* ---------------------------------------------------------------------
   Tidsvælger

   To ruller frem for runde spring: basen har tidspunkter som 13:01 og
   07:07, og en vælger der kun kunne ramme hvert femte minut ville flytte
   dem uden at nogen bad om det.
   --------------------------------------------------------------------- */
.tp { position: relative; }

.tp-button {
    width: 92px; height: 34px;
    padding: 0 10px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); color: var(--text);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 13.5px; text-align: center;
    cursor: pointer;
}
.tp-button:hover { border-color: var(--line-strong); }
.tp-button:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
/* Tom betyder hele døgnet - det skal læses som en oplysning, ikke som
   et felt der mangler at blive udfyldt. */
.tp.is-empty .tp-button {
    color: var(--text-muted);
    font-family: inherit; font-size: 12px;
}

.tp-panel {
    position: absolute; left: 0; top: calc(100% + 6px);
    z-index: 7; width: 156px;
    padding: 8px;
    border: 1px solid var(--line-strong); border-radius: 12px;
    background: var(--surface-solid);
    backdrop-filter: blur(12px);
    box-shadow: var(--card-shadow);
    animation: riseIn 140ms ease both;
}
.tp.is-up .tp-panel { top: auto; bottom: calc(100% + 6px); }

.tp-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.tp-col {
    max-height: 188px; overflow-y: auto;
    display: grid; gap: 2px;
    scrollbar-width: thin;
}
.tp-cell {
    height: 28px;
    display: grid; place-items: center;
    border: 1px solid transparent; border-radius: 7px;
    background: none; color: var(--text);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12.5px; cursor: pointer;
}
.tp-cell:hover { background: var(--glow-2); }
.tp-cell.is-chosen {
    background: var(--accent); color: #06121a; font-weight: 700;
    border-color: var(--accent);
}
.tp-cell:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--glow-1); }

.tp-foot {
    display: flex; justify-content: flex-end;
    margin-top: 8px; padding-top: 8px;
    border-top: 1px solid var(--line);
}

/* ---------------------------------------------------------------------
   Nyhedsbjælken
   --------------------------------------------------------------------- */

/* Kilderne er et gitter af flueben: en række pr. sted, en søjle pr.
   kilde. Så kan man se på én gang hvad der ruller hvor. */
.news-src-col { width: 116px; text-align: center; }
.news-sources td.news-src-col { text-align: center; }

.news-toggle {
    display: inline-grid; place-items: center;
    cursor: pointer;
}
.news-toggle input {
    width: 18px; height: 18px;
    accent-color: var(--accent);
    cursor: pointer;
}
.news-toggle input:disabled { opacity: 0.5; cursor: default; }

/* Beskedens tekst må gerne fylde lidt - man skriver mere end en titel. */
[data-news-text] { min-height: 110px; }

/* Gruppevalget i playerlisten: bredt nok til et gruppenavn, ikke bredere. */
.group-pick-col { width: 240px; }

/* ---------------------------------------------------------------------
   Afspilning
   --------------------------------------------------------------------- */
.play-card { width: min(620px, 94vw); }
.play-card h3 {
    margin-bottom: 2px;
    /* Et filnavn er ikke en overskrift. 26px over tre linjer ville fylde
       mere end det billede man kom for at se. */
    font-size: 18px; line-height: 1.2;
}
.play-card .note { margin: 0 0 14px; }

/* Rammen holder pladsen mens filen hentes, så dialogen ikke hopper. En
   mp3 har intet billede - så er rammen bare en mørk flade med kontroller. */
.play-frame {
    position: relative;
    aspect-ratio: 16 / 9;
    border-radius: 12px; overflow: hidden;
    background: #05090d;
    border: 1px solid var(--line);
}
.play-frame video { width: 100%; height: 100%; display: block; }

.btn-play {
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    cursor: pointer;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-play svg { width: 15px; height: 15px; fill: currentColor; stroke: none; }
.btn-play:hover,
.btn-play:focus-visible {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}

/* ---------------------------------------------------------------------
   Skydere og musikafsnittet på en gruppe
   --------------------------------------------------------------------- */

/* Overskriften bærer en chip, så en kunde med både musik og signage kan
   se hvad afsnittet hører til. 178 kunder har begge dele. */
.music-split { display: flex; align-items: center; gap: 10px; }
.music-block { margin-top: 4px; }

.slider-field .slider-row {
    display: flex; align-items: center; gap: 14px;
}
.slider-value {
    min-width: 52px; text-align: right;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 13px; font-weight: 600; color: var(--accent);
}

input[type="range"] {
    flex: 1 1 auto;
    height: 22px; width: 100%;
    background: none; cursor: pointer;
    -webkit-appearance: none; appearance: none;
}
input[type="range"]::-webkit-slider-runnable-track {
    height: 4px; border-radius: 999px;
    background: var(--line-strong);
}
input[type="range"]::-moz-range-track {
    height: 4px; border-radius: 999px;
    background: var(--line-strong);
}
input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 16px; height: 16px; margin-top: -6px;
    border-radius: 999px; border: 0;
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--glow-1);
}
input[type="range"]::-moz-range-thumb {
    width: 16px; height: 16px;
    border-radius: 999px; border: 0;
    background: var(--accent);
    box-shadow: 0 0 0 4px var(--glow-1);
}
input[type="range"]:focus-visible { outline: none; }
input[type="range"]:focus-visible::-webkit-slider-thumb {
    box-shadow: 0 0 0 6px var(--glow-1);
}

/* Afsnittet er langt - overskrift, forklaring og syv dagsraekker. Uden
   luft omkring hver del loeber de sammen til een graa blok. */
.music-block .edit-split { margin-top: 22px; padding-top: 16px; }
.music-block > .edit-split:first-child { margin-top: 10px; }
.music-block .music-note { margin: 6px 0 0; }
.music-block .adplan-days { margin-top: 16px; gap: 12px; }
.music-block .slider-field { margin-top: 14px; }
.music-block .slider-field .note { margin: 8px 0 0; }

/* ---------------------------------------------------------------------
   Musikkalenderen

   Ugen er et gitter: en smal timekolonne og syv dagsspalter. Blokkene
   ligger absolut placeret i deres spalte, hvor top og hoejde er procent
   af doegnet - saa er et klokkeslaet det samme som en position, og der
   skal ikke regnes om nogen steder.
   --------------------------------------------------------------------- */

.cal-head { margin-bottom: 18px; }
.cal-back {
    display: inline-flex; align-items: center; gap: 6px;
    color: var(--text-muted); text-decoration: none;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase;
}
.cal-back:hover { color: var(--accent); }
.cal-back svg {
    width: 14px; height: 14px; transform: rotate(90deg);
    fill: none; stroke: currentColor; stroke-width: 2;
}
.cal-title {
    display: flex; align-items: center; gap: 10px;
    margin: 8px 0 0; font-size: 22px;
}

.cal-layout {
    display: grid; grid-template-columns: 240px minmax(0, 1fr);
    gap: 18px; margin-top: 16px;

    /* Een hoejde for begge spalter. Stod den to steder, ville de
       drive fra hinanden foerste gang nogen rettede den ene.

       Den foelger skaermen. Fast paa 620px kom rullebjaelken frem
       allerede ved de ti faste blokke: en kilde fylder ca. 66px med
       sin forklaring, saa ti plus mellemrum er omkring 714px. Paa en
       almindelig skaerm er 74vh rigeligt til dem, og paa en lille
       ruller listen - som den skal. */
    --cal-h: clamp(520px, 74vh, 820px);
}
@media (max-width: 900px) {
    .cal-layout { grid-template-columns: 1fr; }
}

/* ---------- Venstre kolonne ---------- */
.cal-tabs { display: flex; gap: 6px; margin-bottom: 10px; }
.cal-tab {
    flex: 1 1 0; height: 30px; padding: 0 8px;
    border: 1px solid var(--line); border-radius: 999px;
    background: none; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; cursor: pointer;
}
.cal-tab.is-on {
    border-color: var(--accent); color: var(--accent);
    background: var(--glow-1);
}

/* Kildelisten fylder den hoejde der er, i stedet for en fast en.
   Med et loft paa 420px kom rullebjaelken frem allerede ved de ti
   faste blokke, selv om der var plads nok ved siden af. Nu ruller den
   foerst naar der faktisk er for mange - typisk fordi kunden har
   bygget en stak playlister. */
.cal-rail {
    display: flex; flex-direction: column;
    min-height: 0; max-height: var(--cal-h);
}
.cal-sources {
    display: grid; gap: 6px; align-content: start;
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
.cal-source {
    padding: 8px 10px;
    border: 1px solid var(--line); border-left: 3px solid var(--accent);
    border-radius: 8px; background: var(--field-bg);
    cursor: grab; touch-action: none; user-select: none;
}
.cal-source:hover, .cal-source:focus-visible {
    border-color: var(--accent); background: var(--glow-1); outline: none;
}
.cal-source.is-playlist { border-left-color: #7fd1ff; }
.cal-source-name {
    display: block; font-size: 13px; font-weight: 600; color: var(--text);
}
/* Hoejst to linjer. En lang playlistetitel maa ikke kunne skubbe
   raekken op i hoejden og presse resten ud i rullebjaelken. */
.cal-source-note {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden;
    margin-top: 2px;
    font-size: 11px; line-height: 1.4; color: var(--text-muted);
}

/* ---------- Gitteret ---------- */
.cal-grid-wrap {
    max-height: var(--cal-h); overflow: auto;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--field-bg);
}
.cal-grid {
    display: grid;
    grid-template-columns: 44px repeat(7, minmax(0, 1fr));
    grid-template-rows: auto 1200px;
}
.cal-corner, .cal-dayhead {
    position: sticky; top: 0; z-index: 3;
    padding: 8px 4px;
    border-bottom: 1px solid var(--line-strong);
    background: var(--surface-solid);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; text-align: center; color: var(--label);
}
.cal-dayhead + .cal-dayhead, .cal-dayhead { border-left: 1px solid var(--line); }

.cal-hours { position: relative; }
.cal-hour {
    height: calc(100% / 24);
    border-bottom: 1px solid transparent;
}
.cal-hour span {
    display: block; transform: translateY(-6px);
    padding-right: 6px; text-align: right;
    font-size: 10px; color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.cal-day {
    position: relative;
    border-left: 1px solid var(--line);
}
.cal-day.is-target { background: var(--glow-1); }
.cal-line {
    position: absolute; left: 0; right: 0;
    border-top: 1px solid var(--line);
    pointer-events: none;
}
/* Hver tredje streg staerkere, saa 06, 12 og 18 kan ses paa afstand. */
.cal-line:nth-child(6n) { border-top-color: var(--line-strong); }

/* ---------- Blokkene ---------- */
.cal-block {
    position: absolute; overflow: hidden;
    padding: 4px 6px;
    border: 1px solid var(--accent); border-radius: 6px;
    background: color-mix(in srgb, var(--accent) 18%, transparent);
    color: var(--text);
    cursor: grab; touch-action: none; user-select: none;
}
.cal-block:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cal-block.is-shared { border-style: dashed; }
.cal-block-name {
    display: block; font-size: 11px; font-weight: 600; line-height: 1.25;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-block-time {
    display: block; margin-top: 1px;
    font-size: 10px; color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.cal-block-share {
    position: absolute; top: 3px; right: 4px;
    padding: 0 4px; border-radius: 999px;
    background: var(--accent); color: var(--bg);
    font-size: 9px; font-weight: 700; line-height: 14px;
}
.cal-resize {
    position: absolute; left: 0; right: 0; bottom: 0;
    height: 7px; cursor: ns-resize;
}
.cal-resize::after {
    content: ""; display: block;
    width: 22px; height: 2px; margin: 2px auto 0;
    border-radius: 2px; background: var(--accent); opacity: 0.5;
}

/* Skyggen der foelger musen mens man traekker en kilde ind. */
.cal-ghost {
    position: fixed; z-index: 60; pointer-events: none;
    transform: translate(10px, 10px);
    padding: 4px 8px;
    border: 1px solid var(--accent); border-radius: 6px;
    background: var(--surface-solid); color: var(--text);
    font-size: 11px; font-weight: 600;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}

.cal-spacer { flex: 1 1 auto; }

/* En linje der oplyser om noget man skal vide, uden at raabe.
   Skemaet der rinder ud; en kaede der bestemmer tidszonen. */
.warn-line {
    display: flex; align-items: center; gap: 8px;
    margin: 0 0 14px; padding: 9px 12px;
    border: 1px solid var(--line-strong); border-radius: 9px;
    background: var(--glow-2); color: var(--label);
    font-size: 12px;
}
.warn-line svg {
    flex: 0 0 auto; width: 16px; height: 16px;
    fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round;
}

/* Blokdialogen skal have plads under klokkefelterne.
   Uden en mindstehoejde er kortet saa lavt, at tidsvaelgerens panel -
   240 px med 24 timer og 60 minutter - foldede sig op over dagsfeltet
   og overskriften. Samme greb som .ban-card. */
.calblock-card { min-height: 470px; }

/* "Ryd" betyder "hele doegnet" i reklamernes skema. I en kalenderblok
   findes den betydning ikke: en blok har altid et fra og et til. */
.calblock-card .tp-foot { display: none; }

/* Fjern staar til venstre for Annullér og Færdig, ikke klemt ind imellem. */
.calblock-card .confirm-actions { justify-content: flex-start; }

/* Tre linjer forklaring i stedet for een - de skal staa som et afsnit
   og ikke skubbe Gem-knappen ned. */
.cal-intro { max-width: 62ch; }
.cal-intro .note { margin: 0 0 6px; }
.cal-intro .note:last-child { margin-bottom: 0; }

/* Listen glider ind fra 18px nede. Naar dens plads skal regnes ud, maa
   den forskydning ikke maales med - saa lander listen 18px for hoejt. */
.pick-menu.is-measuring { animation: none; }

/* ---------------------------------------------------------------------
   Playerlicenser
   --------------------------------------------------------------------- */

/* Noeglen skal kunne laeses op i telefonen og tastes af en installatoer.
   Derfor monospace med luft mellem tegnene - og et klik kopierer den. */
.lic-key {
    padding: 4px 9px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--field-bg); color: var(--accent);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 13.5px; font-weight: 600; letter-spacing: 0.06em;
    cursor: pointer;
    transition: border-color 160ms ease, background 160ms ease, color 160ms ease;
}
.lic-key:hover, .lic-key:focus-visible {
    border-color: var(--accent); background: var(--glow-1); outline: none;
}
.lic-key.is-copied { background: var(--accent); color: var(--bg); border-color: var(--accent); }

.lic-key-line {
    display: flex; align-items: baseline; gap: 10px;
    margin: 0 0 6px !important;
}
.lic-key-line strong {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 17px; letter-spacing: 0.08em; color: var(--accent);
}

/* Otte felter i to spalter. Uden en mindstehoejde folder dato- og
   klientvaelgeren sig op over overskriften - samme sag som .ban-card. */
.lic-card { min-height: 560px; }

/* Soegefeltet i en lang rulleliste. Klientvaelgeren har 210 punkter. */
.pick-search {
    width: 100%; height: 32px; margin-bottom: 4px;
    padding: 0 10px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--field-bg); color: var(--text);
    font: inherit; font-size: 13px;
}
.pick-search:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
.pick-none {
    margin: 6px 4px; font-size: 12px; color: var(--text-muted);
}

/* Tidszonedialogen. Eet felt, men vaelgeren har 137 punkter og et
   soegefelt - den skal have plads at folde sig ud i. */
.tz-card { min-height: 420px; }

/* "Kun os" paa de felter der kom fra player vieweren. Samme farve som
   resten af det super admin har for sig selv. */
.chip.is-super { color: #ffb27a; }

/* ---------------------------------------------------------------------
   Galleriet
   --------------------------------------------------------------------- */

/* Billeder staar som billeder. Man leder efter et motiv, ikke efter et
   filnavn - derfor et gitter og ikke en tabel. */
.gal-split { display: flex; align-items: center; gap: 10px; }
.gal-count {
    margin-left: auto;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12px; color: var(--text-muted);
}

.gal-grid {
    display: grid; gap: 14px; margin: 14px 0 4px;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}

.gal-item {
    margin: 0;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--field-bg); overflow: hidden;
    transition: border-color 160ms ease;
}
.gal-item:hover { border-color: var(--line-strong); }
/* Et skjult billede skal kunne ses som skjult uden at laese teksten. */
.gal-item.is-off { opacity: 0.55; }

.gal-shot {
    position: relative; display: block;
    width: 100%; aspect-ratio: 16 / 9;
    padding: 0; border: 0; border-bottom: 1px solid var(--line);
    background: #05070d; cursor: zoom-in;
}
.gal-shot img { width: 100%; height: 100%; object-fit: contain; display: block; }
.gal-zoom {
    position: absolute; right: 8px; bottom: 8px;
    display: grid; place-items: center;
    width: 28px; height: 28px; border-radius: 999px;
    background: rgba(3, 8, 16, 0.72); color: var(--accent);
    opacity: 0; transition: opacity 160ms ease;
}
.gal-zoom svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; }
.gal-shot:hover .gal-zoom, .gal-shot:focus-visible .gal-zoom { opacity: 1; }

/* Et billede der ikke kunne hentes.
   Browserens eget ikon for en oedelagt fil er en lille graa firkant med
   filnavnet ved siden af - den ligner en fejl i SIDEN, ikke en fil der
   mangler. Og den ser ens ud uanset hvorfor: en fil der er slettet paa
   serveren kan ikke skelnes fra en udviklingsmaskine der slet ikke har
   mapperne. Flisen her siger hvad der er galt. */
.img-gone {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 8px;
    padding: 12px; text-align: center;
    background:
        repeating-linear-gradient(135deg,
            transparent 0 9px, var(--glow-2) 9px 10px),
        var(--field-bg);
    color: var(--text-muted);
}
.img-gone svg {
    width: 26px; height: 26px; flex: 0 0 auto;
    fill: none; stroke: currentColor; stroke-width: 1.5;
    stroke-linecap: round; stroke-linejoin: round;
    opacity: 0.75;
}
.img-gone-text {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; line-height: 1.35;
}

/* I den store visning er der ingen ramme at fylde ud - kortet er saa
   stort som billedet. Flisen faar sin egen stoerrelse i stedet. */
.gal-big-inner .img-gone {
    position: static;
    width: min(480px, 80vw); aspect-ratio: 16 / 9;
    border: 1px solid var(--line); border-radius: 10px;
}

/* I reklamelisten er miniaturen 62x36 - der er ikke plads til ord. */
.ad-thumb-wrap {
    position: relative; display: inline-block;
    width: 62px; height: 36px; border-radius: 6px; overflow: hidden;
}

/* Miniaturen er en knap: et tryk viser reklamen i stor udgave. Et
   filnavn som "7764683_131871103412401713_SCEN7_1280x720_4500.mp4"
   siger ingenting om hvad der staar paa skaermen. */
.ad-thumb-open {
    padding: 0; border: 0; cursor: zoom-in;
    background: none;
}
button.ad-thumb-open.ad-thumb { background: var(--glow-2); }
.ad-thumb-open:hover { border-color: var(--accent); }
.ad-thumb-open:focus-visible {
    outline: none; box-shadow: 0 0 0 3px var(--glow-1);
}
.ad-thumb-open .ad-thumb { border: 0; width: 100%; height: 100%; }

/* Billedet i den store visning. Videoen har sine egne maal. */
.play-frame img {
    display: block; max-width: 100%; max-height: 70vh;
    margin: 0 auto; border-radius: 8px;
}
.ad-thumb-wrap .img-gone { padding: 4px; }
.ad-thumb-wrap .img-gone-text { display: none; }
.ad-thumb-wrap .img-gone svg { width: 18px; height: 18px; }

.gal-body { padding: 10px 12px 12px; }
.gal-name {
    font-size: 13px; font-weight: 600; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gal-facts {
    display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
    margin-top: 5px; font-size: 11px; color: var(--text-muted);
}
.gal-state.is-on { color: var(--accent); }
.gal-sec { font-variant-numeric: tabular-nums; }
.chip.is-planned { color: #c9a7ff; }
.gal-actions { display: flex; gap: 8px; margin-top: 10px; }

.gal-progress {
    margin: 6px 0 0; font-size: 12px; color: var(--text-muted);
}

/* Billedet i stort: ingen ramme om det. Motivet er hele pointen, og en
   kant stjaeler plads fra det. */
.modal.gal-big { padding: 32px; cursor: zoom-out; }
.gal-big-inner {
    margin: 0; max-width: 100%; max-height: 100%;
    display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.gal-big-inner img {
    max-width: 100%; max-height: calc(100vh - 110px);
    border-radius: 10px; box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
}
.gal-big-inner figcaption {
    font-size: 13px; color: var(--label);
}
.gal-close {
    position: fixed; top: 16px; right: 20px;
    width: 38px; height: 38px;
    border: 1px solid var(--line-strong); border-radius: 999px;
    background: var(--surface-solid); color: var(--text);
    font-size: 22px; line-height: 1; cursor: pointer;
}
.gal-close:hover { border-color: var(--accent); color: var(--accent); }

/* De byggede moduler hoerer sammen: de er musikkundens redskaber. */
.tiles-lead {
    display: flex; align-items: center; gap: 10px;
    margin: 0 0 12px; font-size: 12.5px; color: var(--text-muted);
}
.tile { position: relative; }
.tile.is-music { border-color: rgba(127, 209, 255, 0.4); }
.tile.is-music:hover { border-color: #7fd1ff; }
.tile-tag {
    position: absolute; top: 10px; right: 12px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 10px; font-weight: 700; letter-spacing: 0.14em;
    text-transform: uppercase; color: #7fd1ff;
}

/* Browserens egen filknap kan ikke styles. Den gemmes med
   .visually-hidden, og en rigtig knap staar i stedet - med navnene paa
   det man har valgt ved siden af. */
/* Upload og normalisering.
   Fremdriften er to ting i eet felt: browseren sender bidderne, og
   bagefter arbejder serveren. Den anden del har ingen procent - man ved
   ikke hvor laenge ffmpeg er om en fil - saa bjaelken staar fuld og
   teksten siger hvad der sker. */
.enc-progress { margin-top: 16px; }
.enc-bar {
    height: 6px; border-radius: 999px;
    background: var(--glow-2); overflow: hidden;
}
.enc-bar span {
    display: block; height: 100%; width: 0;
    background: var(--accent);
    transition: width 180ms ease;
}
.enc-progress .note { margin: 8px 0 0; }

.enc-table td { vertical-align: middle; }
.enc-lufs {
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 12.5px; white-space: nowrap;
}
.enc-lufs-arrow { color: var(--text-muted); margin: 0 4px; }
.enc-lufs-out { color: var(--accent); font-weight: 600; }

/* Et stadie der er i gang skal kunne ses paa afstand. */
.enc-state { display: inline-flex; align-items: center; gap: 8px; }
.enc-spin {
    width: 12px; height: 12px; flex: 0 0 auto;
    border: 2px solid var(--line-strong); border-top-color: var(--accent);
    border-radius: 50%;
    animation: encSpin 700ms linear infinite;
}
@keyframes encSpin { to { transform: rotate(360deg); } }
.enc-state.is-done  { color: var(--accent); }
.enc-state.is-failed { color: #ff8f8f; }
.enc-fejl {
    display: block; margin-top: 3px;
    font-size: 12px; color: #ff8f8f;
    overflow-wrap: anywhere;
}

.filepick.is-off { opacity: 0.5; pointer-events: none; }

.filepick {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 8px 10px;
    border: 1px dashed var(--line-strong); border-radius: 10px;
    background: var(--field-bg);
}
.filepick-name {
    flex: 1 1 0; min-width: 0;
    font-size: 12.5px; color: var(--text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Har man ingen playlister, er der en vej videre - ikke en fodnote. */
.cal-empty {
    display: grid; justify-items: start; gap: 10px;
    padding: 14px 12px;
    border: 1px dashed var(--line); border-radius: 10px;
}
.cal-empty .note { margin: 0; }

/* Soegning i en opslagsliste. Kunstnere er 3.667 - man leder, man
   bladrer ikke. */
.cat-search {
    display: flex; align-items: flex-end; gap: 10px;
    margin: 14px 0 4px; flex-wrap: wrap;
}
.cat-search .field { flex: 1 1 240px; }
.cat-search .btn-cancel { display: inline-flex; align-items: center; text-decoration: none; }

/* Antallet af numre er en knap. Det skal se ud som det tal det er, men
   det skal kunne ses at der er mere bag det - samme greb som TeamViewer-
   id'et. */
.cat-count { font-family: inherit; font-size: 13.5px; }

/* Et tal der taeller noget der skal ryddes op. Det skal kunne ses paa
   afstand at det ikke er et tal som de andre. */
.stat.is-warn { border-color: rgba(255, 178, 122, 0.5); }
.stat.is-warn .stat-value { color: #ffb27a; }

/* Navnet og et eventuelt maerke staar paa linje. Egen beholder: den
   .dir-name-text de ligger i, deles med ni andre sider, hvor den er en
   soejle med navn og undertekst. */
.cat-name { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cat-name .dir-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Et navn der ikke er der. Kursiv og daempet, saa raekken laeses som
   noget der mangler frem for noget der er gaaet galt i tegningen. */
.dir-title.is-blank,
.ban-hit-title.is-blank { font-style: italic; color: var(--text-muted); }

/* Numrene bag et tal. Listen er det dialogen handler om, saa den faar
   mere hoejde end soegeresultatet i banlisten. */
.cattracks-card { width: min(560px, 92vw); }
.cattracks-card .ban-results { max-height: 46vh; }

/* Musikbibliotekets filtre. Soegefeltet faar hele foerste linje; resten
   staar side om side og brydes selv naar der ikke er plads. */
.lib-filters {
    display: grid; gap: 12px;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    margin: 16px 0 6px;
}
.lib-filters .field-wide { grid-column: 1 / -1; }
.lib-filter-actions {
    display: flex; align-items: flex-end; gap: 10px;
    grid-column: 1 / -1;
}
.lib-filter-actions .btn-cancel {
    display: inline-flex; align-items: center; text-decoration: none;
}

/* Titel og maerker paa linje. Egen beholder: .dir-name-text er en
   soejle med navn og undertekst, og den deles med de andre lister. */
.lib-title { display: flex; align-items: center; gap: 8px; min-width: 0; }

/* Titler og kunstnernavne bliver LANGE. "Adam Port, Keinemusik, Camila
   Cabello, Orso, Stryv, Malachiii" er EET kunstnerfelt.

   Foerst skubbede det hele tabellen ud over sin egen kant. Faste
   spaltebredder loeste det - men .dir-cell-summary har white-space:
   nowrap, saa teksten kunne ikke brydes og floed i stedet ind over
   nabospalten. Den manglende halvdel var overflow: hidden.

   Klippet af med ellipse, ikke brudt over flere linjer: raekkerne skal
   have samme hoejde, saa listen kan skimmes. Hele navnet staar i
   title-attributten, saa det kan laeses ved at holde musen stille. */
/* Spalteoverskrifter man kan sortere paa.
   Pilen har sin egen plads, ogsaa naar den er tom - ellers hopper
   overskrifterne en anelse sidelaens hver gang man skifter spalte. */
.lib-sort {
    display: inline-flex; align-items: center; gap: 6px;
    color: inherit; text-decoration: none;
}
.lib-sort:hover { color: var(--text); }
.lib-sort.is-on { color: var(--accent); }
.lib-arrow { display: inline-block; min-width: 9px; font-size: 11px; }

.lib-table { table-layout: fixed; }
.lib-table td { overflow: hidden; }
.lib-table .dir-cell-summary { text-overflow: ellipsis; }
.lib-table .dir-title {
    line-height: 1.25;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lib-table th:nth-child(1) { width: 30%; }
.lib-table th:nth-child(2) { width: 25%; }
.lib-table th:nth-child(3) { width: 17%; }
.lib-table th:nth-child(4) { width: 14%; }
.lib-table th.dir-cell-action { width: 104px; }

/* Et nummer der ikke spilles skal kunne ses uden at laese maerket. */
.dir-row.is-off .dir-title,
.dir-row.is-off .dir-cell-summary { opacity: 0.55; }

.lib-pages {
    display: flex; align-items: center; justify-content: center; gap: 16px;
    margin-top: 18px;
}
.lib-pages .btn-cancel { display: inline-flex; align-items: center; text-decoration: none; }
.lib-pages .note { margin: 0; }

/* Nummerets oplysninger. Der er 31 afkrydsninger, saa dialogen er
   bredere end de andre og ruller for sig selv. */
.track-card { width: min(760px, 94vw); max-height: 88vh; overflow-y: auto; }

.track-group { gap: 8px; }
.track-group-title {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 11px; font-weight: 700; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-muted);
}
.track-checks {
    display: grid; gap: 6px 16px;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.track-check {
    display: flex; align-items: flex-start; gap: 9px;
    margin: 0; font-size: 13px; line-height: 1.35; cursor: pointer;
}

/* .field input giver hvert felt height 38px, padding og width 100%.
   Det gaelder ogsaa en afkrydsning, og saa blev hvert kryds en graa
   plade paa 38px i fuld spaltebredde med teksten maset ud til siden -
   eet ord pr. linje. Afkrydsningerne er ikke tekstfelter. */
.track-check input[type="checkbox"] {
    width: 17px; height: 17px; min-width: 17px;
    margin: 1px 0 0; padding: 0; flex: 0 0 auto;
    accent-color: var(--accent);
    border-radius: 4px;
}
.track-check input[type="checkbox"]:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: none;
}
.track-check > span {
    /* Ikke en feltetiket - .field > span ville goere den til versaler. */
    font: inherit; letter-spacing: normal; text-transform: none;
    color: var(--text); min-width: 0;
}

/* De to der handler om nummeret selv staar for sig, over opdelingen. */
.track-marks {
    gap: 8px; padding: 12px 14px;
    border: 1px solid var(--line); border-radius: 12px;
}

/* Dialogen ruller lodret. Vandret maa den ikke - saa gemmer knapperne
   sig ude til hoejre, og man kan ikke gemme. */
.track-card { overflow-x: hidden; }

/* KODA-rapporten: eet valg og en knap. */
.koda-form {
    display: flex; align-items: flex-end; gap: 14px;
    margin: 18px 0 4px; flex-wrap: wrap;
}
.koda-form .field { min-width: 220px; }
.koda-busy { margin: 10px 0 0; }

/* =====================================================================
   Signage: sløjfen

   Striben er hele idéen. Bredden af en blok ER varigheden, så man kan se
   at én hjemmeside på 60 sekunder fylder lige så meget som fire billeder
   på 15. flex-grow gør regnestykket - vi behøver ikke regne procenter,
   og striben passer sig selv når vinduet skifter bredde.
   ===================================================================== */
.loop-strip {
    display: flex; gap: 2px;
    height: 34px;
    margin: 18px 0 8px;
    border-radius: 8px;
    overflow: hidden;
    background: var(--line);
}
.loop-seg {
    /* flex-basis 0 saa det KUN er grow der bestemmer - ellers ville en
       blok med et langt navn faa sin egen bredde med i regnestykket. */
    flex-basis: 0;
    min-width: 3px;
    background: var(--glow-2);
    transition: filter 120ms ease;
}
.loop-seg:hover { filter: brightness(1.45); }

/* Typefarverne. Samme fem som i listens mærkater, saa striben og
   tabellen kan laeses sammen. */
.loop-seg.is-image { background: #4fbf8b; }
.loop-seg.is-video { background: #b98cff; }
.loop-seg.is-page  { background: #ffab5c; }
.loop-seg.is-web   { background: #7fd1ff; }
.loop-seg.is-slide { background: #ff8fb1; }
.loop-seg.is-feed  { background: #d7d24f; }

.loop-legend {
    margin: 0 0 4px; font-size: 12px; color: var(--text-muted);
}

.chip.is-image { color: #4fbf8b; border-color: rgba(79, 191, 139, 0.45); }
.chip.is-page  { color: #ffab5c; border-color: rgba(255, 171, 92, 0.45); }
.chip.is-web   { color: #7fd1ff; border-color: rgba(127, 209, 255, 0.45); }
.chip.is-slide { color: #ff8fb1; border-color: rgba(255, 143, 177, 0.45); }
.chip.is-feed  { color: #d7d24f; border-color: rgba(215, 210, 79, 0.45); }

.sig-cell-nr {
    width: 42px; text-align: right; padding-right: 12px;
    color: var(--text-muted); font-variant-numeric: tabular-nums;
}

/* En raekke der ikke spiller. Den staar der, men den skal ikke tage
   opmaerksomhed fra de 20% der faktisk koerer. */
.dir-row.is-off { opacity: 0.45; }

.sig-warn { color: #ff9b9b; }
.sig-own  { color: var(--text-muted); font-style: italic; }
.sig-group { color: var(--accent); }
.sig-more { margin: 14px 0 0; font-size: 13px; }

/* Stiplet streg under noget der gemmer mere.
   Samme greb som [data-hover] bruger paa players - en streg der siger
   "her er mere" uden at ligne en knap. */
.dotted {
    border-bottom: 1px dashed currentColor;
    text-decoration: none;
    color: inherit;
}
a.dotted:hover { color: var(--accent); }

/*
 * Sker der noget ved et klik, saa sig det.
 *
 * Her stod foer kun en regel om, at et billede fik "help" - et
 * spoergsmaalstegn lover en forklaring, ikke en handling, og det var
 * aerligt saa laenge et klik ikke gjorde noget. Filmklippet KUNNE
 * klikkes, men havde ingen regel overhovedet, saa markoeren var en
 * tekstmarkoer. Det eneste der sagde det, var et vaerktoejstip man
 * skulle vente paa.
 *
 * [data-play] er hver eneste ting der aabner afspilleren - sloejfen,
 * reklamerne, musikken, filmsiden. Een regel daekker dem alle.
 */
[data-play] { cursor: pointer; }

/* Grebet man traekker i. Altid synligt, men svagt - man skal kunne se at
   raekkerne KAN flyttes uden at det stjaeler opmaerksomhed fra indholdet. */
.sig-cell-nr { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
.sig-nr { min-width: 18px; text-align: right; }
.sig-grip {
    display: inline-flex; align-items: center;
    width: 12px; opacity: 0.35;
    cursor: grab;
    transition: opacity 140ms ease;
}
.sig-grip svg { width: 10px; height: 16px; fill: currentColor; stroke: none; }
.dir-row:hover .sig-grip { opacity: 0.85; }
.dir-row.is-dragging .sig-grip { cursor: grabbing; }

.dir-row.is-dragging {
    background: var(--glow-2);
    opacity: 0.9;
}
/* Mens der traekkes maa musen ikke markere tekst - saa bliver hele
   tabellen blaa naar man foerer den hen over raekkerne. */
body.sig-dragging { user-select: none; -webkit-user-select: none; cursor: grabbing; }
body.sig-dragging .dotted { pointer-events: none; }

.dir-table.is-saving { opacity: 0.7; }

/* Billedet bag filnavnet. position: fixed, saa det ikke klippes af
   tabellens overflow - v3PlacerListe finder koordinaterne. */
.imgcard {
    position: fixed; z-index: 70;
    max-width: 340px;
    padding: 8px;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--panel);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
    pointer-events: none;
}
.imgcard img {
    display: block; max-width: 100%; max-height: 240px;
    border-radius: 7px;
}
.imgcard.is-broken img { display: none; }
.imgcard.is-broken::before {
    content: attr(data-missing);
    display: block; padding: 18px 10px;
    color: var(--text-muted); font-size: 13px;
}
.imgcard-name {
    margin: 7px 2px 1px;
    font-size: 12px; color: var(--text-muted);
    overflow-wrap: anywhere;
}

/* Skillelinjen mellem den globale del og gruppens. */
.sig-sep td {
    padding: 14px 0 6px;
    border-bottom: 1px solid var(--line);
}
.sig-sep-label {
    font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-muted);
}
.sig-fold {
    display: inline-flex; align-items: center; gap: 8px;
    border: 0; background: none; padding: 0;
    color: var(--text-muted); cursor: pointer;
    font: inherit;
    font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
}
.sig-fold:hover { color: var(--text); }
.sig-fold svg {
    width: 13px; height: 13px;
    fill: none; stroke: currentColor; stroke-width: 2.4;
    stroke-linecap: round; stroke-linejoin: round;
    transition: transform 140ms ease;
}
.sig-fold[aria-expanded="true"] svg { transform: rotate(90deg); }
.sig-sep-time {
    color: var(--text-muted); opacity: 0.7;
    font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0;
}

/* En sammenfoldet raekke. display:none frem for hidden, saa en <tr>
   ikke skifter display-type og braekker tabellen. */
.dir-row.is-folded { display: none; }

/* =====================================================================
   Netradio
   ===================================================================== */
.radio-list {
    display: grid; gap: 2px;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    margin: 18px 0 6px;
}
.radio-row {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px;
    border: 1px solid transparent; border-radius: 9px;
    cursor: pointer;
}
.radio-row:hover { background: var(--glow-2); }
.radio-row input[type="radio"] { width: 16px; height: 16px; accent-color: var(--accent); }
.radio-name { flex: 1; }

/* Lyt-knappen skal ikke fylde foer man har brug for den. */
.radio-listen { opacity: 0.4; transition: opacity 140ms ease; }
.radio-row:hover .radio-listen,
.radio-listen.is-playing { opacity: 1; }
.radio-listen.is-playing { color: var(--accent); }

/* Feltet til en egen adresse. grid-column: 1/-1 saa det ligger under
   hele listen og ikke klemmes ind i en kolonne. */
.radio-own { grid-column: 1 / -1; margin: 6px 0 2px; max-width: 520px; }
.radio-own[hidden] { display: none; }

/* Afspilleren. Fast i bunden, saa den ikke forsvinder naar man ruller
   ned i oversigten over hvert sted. */
.nr-player {
    position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
    z-index: 60;
    display: flex; align-items: center; gap: 12px;
    padding: 9px 16px 9px 10px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--panel);
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5);
}
.nr-player[hidden] { display: none; }
.nr-player-name { font-weight: 600; }
.nr-player-state { color: var(--text-muted); font-size: 13px; }

.nr-station { font-weight: 600; }

/* =====================================================================
   Egne filmklip

   Galleriets gitter, men et filmklip har ingen miniature - der er ikke
   noget billede at vise foer man har set det. Feltet er derfor en stor
   afspilknap med laengden i hjoernet.
   ===================================================================== */
.film-grid {
    display: grid; gap: 14px;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    margin: 10px 0 18px;
}
.film-item {
    display: flex; flex-direction: column;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--panel-2, var(--panel));
    overflow: hidden;
}
.film-item.is-off { opacity: 0.55; }

/*
   Pladsholderen for et klip uden miniature.

   Den var ét fladt forloeb i de samme to farver for hvert eneste klip -
   et gitter med tredive ens felter, hvor man laeste filnavne hver gang
   for at finde sit eget. Nu faar hvert klip sin egen tone, regnet ud af
   navnet (v3_film_hue), saa den er den samme hver gang. Man faar et
   sted at kigge: "min er den groenne".

   Perforeringen langs kanterne er en filmstrimmel. Den siger "video"
   uden et ord og uden et ikon mere - og den er ren CSS, saa den koster
   ingen hentninger paa en side med halvfjerds klip.
*/
.film-shot {
    position: relative; overflow: hidden;
    display: flex; align-items: center; justify-content: center;
    width: 100%; aspect-ratio: 16 / 9;
    border: 0; border-bottom: 1px solid var(--line);
    cursor: pointer;
    --h: 210;
    background:
        radial-gradient(120% 90% at 22% 12%,
            hsl(var(--h) 70% 34% / 0.55), transparent 62%),
        radial-gradient(110% 80% at 82% 88%,
            hsl(calc(var(--h) + 48) 65% 30% / 0.5), transparent 58%),
        linear-gradient(155deg, #0e1726, #121c2e);
}

/* Filmstrimlens huller. To baand, oeverst og nederst. */
.film-shot::before,
.film-shot::after {
    content: ""; position: absolute; left: 0; right: 0; height: 13px;
    background:
        repeating-linear-gradient(to right,
            transparent 0 7px,
            rgba(255, 255, 255, 0.13) 7px 15px,
            transparent 15px 22px);
    opacity: 0.55;
    pointer-events: none;
}
.film-shot::before { top: 0; }
.film-shot::after  { bottom: 0; }

/* Et strejf lys der vandrer hen over feltet naar musen er over. Kort og
   diskret - det skal antyde at der ER noget at afspille, ikke blinke. */
.film-shot:hover { --lys: 1; }
.film-shot:hover::before,
.film-shot:hover::after { opacity: 0.8; }

.film-shot.is-missing {
    cursor: default;
    background: linear-gradient(155deg, #141a24, #10151d);
}
.film-shot.is-missing::before,
.film-shot.is-missing::after { opacity: 0.18; }

.film-play {
    display: flex; align-items: center; justify-content: center;
    width: 46px; height: 46px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    /* En tynd ring, saa knappen staar frit uanset hvilken tone feltet
       har faaet. Uden den forsvinder den i de lyse toner. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22),
                0 6px 18px rgba(0, 0, 0, 0.35);
    transition: transform 140ms ease, background-color 140ms ease;
}
.film-play svg { width: 22px; height: 22px; fill: #fff; stroke: none; }
.film-shot:hover .film-play { transform: scale(1.12); background: rgba(0, 0, 0, 0.65); }

/* Laengden i hjoernet, som paa en videotjeneste. */
.film-len {
    position: absolute; right: 8px; bottom: 7px;
    padding: 2px 7px;
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.62);
    color: #fff; font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.film-gone { color: #ff9b9b; font-size: 13px; }

.film-body { padding: 10px 12px 11px; display: grid; gap: 7px; }
.film-name {
    font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.film-facts {
    display: flex; flex-wrap: wrap; gap: 10px;
    font-size: 13px; color: var(--text-muted);
}
.film-sec, .film-size { font-variant-numeric: tabular-nums; }

/* Faerdigt indhold: miniaturen ER knappen. */
.rm-shot { padding: 0; overflow: hidden; }
.rm-shot img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover;
}
.rm-shot .film-play, .rm-shot .film-len { position: relative; z-index: 1; }
.rm-shot .film-len { position: absolute; right: 8px; bottom: 7px; }

/* Et indslag der allerede er taget i brug. Det bliver staaende, saa man
   kan se HELE samlingen - men det skal ikke se ud som et tilbud. */
.film-item.is-taken { opacity: 0.62; }
.film-item.is-taken .rm-shot { filter: grayscale(0.35); }
.chip.is-image { color: #4fbf8b; border-color: rgba(79, 191, 139, 0.45); }

/* Det faelles bibliotek: brugstallet skal kunne ses paa afstand - det
   er dét der afgoer om noget kan fjernes. */
.sl-used { font-weight: 600; color: var(--accent); }

/* Nyhedskontakten paa sloejfesiden.
   Den staar i selve panelet frem for paa en side for sig: det er her man
   bestemmer hvad der koerer, og eet afkrydsningsfelt fortjener ikke sit
   eget menupunkt. */
.news-switch {
    display: flex; align-items: center; gap: 13px;
    margin: 16px 0 4px;
    padding: 12px 14px;
    border: 1px solid var(--line); border-radius: 11px;
    cursor: pointer;
}
.news-switch:hover { border-color: var(--accent); }
.news-switch input[type="checkbox"] {
    width: 18px; height: 18px; accent-color: var(--accent); flex: none;
}
.news-text { display: grid; gap: 2px; flex: 1; }
.news-title { font-weight: 600; }
.news-note { font-size: 13px; color: var(--text-muted); }
.news-state {
    font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-muted);
}
.news-state.is-on { color: var(--accent); }

/* =====================================================================
   Egne sider - editoren

   Lærredet til venstre, indstillingerne til højre. På en smal skærm
   lægger de sig over hinanden med lærredet øverst: det er dét man skal
   kunne se mens man skriver.
   ===================================================================== */
.pe-split {
    display: grid; gap: 20px; margin-top: 16px;
    grid-template-columns: minmax(0, 1fr) 340px;
    align-items: start;
}

@media (max-width: 900px) {
    .pe-split { grid-template-columns: minmax(0, 1fr); }
}

.pe-stage { min-width: 0; }

/* Laerredet er 1920x1080 indeni. Her skaleres det ned til den plads der
   er - de pixels der sendes, er de samme uanset skaermen. */
.pe-stage canvas {
    display: block; width: 100%; height: auto;
    aspect-ratio: 16 / 9;
    border: 1px solid var(--line); border-radius: 12px;
    background: #05070d;
}

.pe-hint { margin: 8px 0 0; }

.pe-side {
    display: flex; flex-direction: column; gap: 12px;
    min-width: 0;
}

/* Luft over raekken. Et tekstfelt der kan traekkes stoerre, og to
   smaa versaloverskrifter lige under dets nederste kant, staar for
   taet - de ser ud som om de hoerer til feltet. */
.pe-row { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 6px; }
.pe-row > .field { flex: 1 1 140px; min-width: 0; }
/* Farvevaelgeren viser en prik, koden og en pil. 90px klippede den. */
.pe-narrow { flex: 0 0 138px; }

/* Valg der udelukker hinanden: skrift og placering. */
.pe-choice { display: flex; gap: 6px; flex-wrap: wrap; }

.pe-pill {
    padding: 6px 11px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--field-bg); color: var(--text-muted);
    font-size: 12px; cursor: pointer;
    transition: border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.pe-pill:hover { border-color: var(--line-strong); color: var(--text); }
.pe-pill.is-on {
    border-color: var(--accent); color: var(--accent);
    background: var(--ok-bg);
}

/* "Gemt" staar kun et par sekunder. Uden den ved man ikke om knappen
   gjorde noget - billedet paa laerredet ser jo ens ud foer og efter. */
.pe-saved {
    margin-left: auto; margin-right: 10px;
    color: var(--ok-text); font-size: 13px;
}

.pe-panel .panel-head { align-items: center; }

/* Listen over tekstfelter. Navnet er feltets første linje - "Tekstfelt
   2" siger ingenting når der er fem af dem. */
.pe-layers {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 4px;
}

.pe-layer {
    display: flex; align-items: stretch; gap: 4px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--field-bg);
    transition: border-color 140ms ease;
}
.pe-layer:hover { border-color: var(--line-strong); }
.pe-layer.is-on { border-color: var(--accent); background: var(--ok-bg); }

.pe-layer-name {
    flex: 1 1 auto; min-width: 0;
    padding: 7px 10px; border: 0; background: none;
    color: var(--text); font-size: 13px; text-align: left;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    cursor: pointer;
}
/* Et felt uden tekst er ikke en fejl - man har lige lavet det - men det
   skal kunne ses at der ikke staar noget i det endnu. */
.pe-layer-name.is-empty { color: var(--text-muted); font-style: italic; }

.pe-layer-del {
    flex: 0 0 auto; width: 30px;
    border: 0; border-left: 1px solid var(--line);
    background: none; color: var(--text-muted);
    font-size: 17px; line-height: 1; cursor: pointer;
    transition: color 140ms ease;
}
.pe-layer-del:hover { color: var(--error-text); }

.pe-add { align-self: flex-start; }
.pe-add:disabled { opacity: 0.5; cursor: default; }

/* Laerredet kan trækkes i. Uden det ville markøren sige "tekst" over
   et felt man kan flytte. */
.pe-stage canvas { cursor: default; touch-action: none; }
.pe-stage canvas:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Et billedlag i listen kendes fra et tekstfelt. Uden det ville
   "logo.png" og en linje tekst se ens ud. */
.pe-layer-name.is-image::before {
    content: '▣'; margin-right: 6px; color: var(--accent);
}

.pe-adders { display: flex; gap: 8px; }
.pe-order { margin-top: 2px; }
.pe-order .pe-pill:disabled { opacity: 0.4; cursor: default; }

.pe-imgnote { line-height: 1.5; }

/* --- Billedvælgeren -------------------------------------------------- */
.pe-picker { max-width: 720px; width: 92vw; }

.pe-picker-head {
    display: flex; align-items: center; gap: 14px;
    flex-wrap: wrap; margin-bottom: 12px;
}
.pe-picker-head .note { flex: 1 1 260px; }

/* Et <input type=file> kan ikke styles. Knappen er derfor en <label>
   med feltet gemt indeni - et klik på den åbner filvælgeren. */
.pe-upload { cursor: pointer; }

.pe-picker-grid { max-height: 52vh; overflow-y: auto; }

/* --- Gitteret med de faelles baggrunde --------------------------------

   Samme kort som billedvaelgeren, men med overskrifter: 91 motiver i
   elleve kategorier er kun til at finde rundt i fordi de er delt op.
   Det var saadan det gamle system viste dem. */
.pe-biblio { margin-top: 10px; }
.pe-bib-body { max-height: 58vh; overflow-y: auto; padding-right: 4px; }
.pe-bib-group + .pe-bib-group { margin-top: 4px; }
.pe-bib-group .edit-split:first-child { margin-top: 14px; }
.pe-bib-group:first-child .edit-split { margin-top: 0; }
.pe-bib-search { flex: 1 1 200px; }

/* Baggrunde er 16:9. Med billedvaelgerens 4:3 ville hvert kort have en
   sort bjaelke foroven og forneden. */
.pe-bib-group .pe-pic-shot { aspect-ratio: 16 / 9; }
.pe-bib-group .pe-pic-shot img { object-fit: cover; }

.pe-pic-head:first-child { margin-top: 0; }

.pe-pic-row {
    display: grid; gap: 10px; margin: 10px 0 4px;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}

.pe-pic {
    position: relative; margin: 0;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--field-bg); overflow: hidden;
}
.pe-pic:hover { border-color: var(--line-strong); }

.pe-pic-shot {
    display: block; width: 100%; aspect-ratio: 4 / 3;
    padding: 0; border: 0; border-bottom: 1px solid var(--line);
    /* Ternet bund, saa en gennemsigtig PNG kan ses som gennemsigtig og
       ikke som et hvidt billede. */
    background-color: #1b2433;
    background-image:
        linear-gradient(45deg, rgba(255,255,255,0.05) 25%, transparent 25%),
        linear-gradient(-45deg, rgba(255,255,255,0.05) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, rgba(255,255,255,0.05) 75%),
        linear-gradient(-45deg, transparent 75%, rgba(255,255,255,0.05) 75%);
    background-size: 14px 14px;
    background-position: 0 0, 0 7px, 7px -7px, -7px 0;
    cursor: pointer;
}
.pe-pic-shot img { width: 100%; height: 100%; object-fit: contain; display: block; }

.pe-pic-name {
    padding: 6px 8px; font-size: 11px; color: var(--text-muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.pe-pic-del {
    position: absolute; top: 5px; right: 5px;
    width: 22px; height: 22px; padding: 0;
    border: 0; border-radius: 999px;
    background: rgba(3, 8, 16, 0.78); color: var(--text-muted);
    font-size: 15px; line-height: 1; cursor: pointer;
    opacity: 0; transition: opacity 140ms ease, color 140ms ease;
}
.pe-pic:hover .pe-pic-del, .pe-pic-del:focus-visible { opacity: 1; }
.pe-pic-del:hover { color: var(--error-text); }

/* "dine billeder" bag et filnavn i baggrundslisten. En fil maa hedde
   det samme i banken og i galleriet, og saa skal man kunne se hvilken
   af dem man vaelger. */
.pe-from { color: var(--text-muted); font-size: 11px; }


/* =====================================================================
   Den stille knap

   Samme form som .btn-cancel, men den skal ogsaa kunne vaere et <a> -
   tilbagelinket i editoren er et link, ikke en knap. Derfor
   inline-flex og ingen understregning.
   ===================================================================== */
.btn-ghost {
    display: inline-flex; align-items: center; gap: 6px;
    height: var(--control-h); padding: 0 15px;
    border: 1px solid var(--line); border-radius: 999px;
    background: transparent; color: var(--text-muted);
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; text-decoration: none;
    cursor: pointer; white-space: nowrap;
    transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.btn-ghost svg {
    width: 14px; height: 14px;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}
.btn-ghost:hover { border-color: var(--line-strong); color: var(--text); }
.btn-ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-ghost:disabled { opacity: 0.45; cursor: default; }
.btn-ghost:disabled:hover { border-color: var(--line); color: var(--text-muted); }

/* =====================================================================
   Farvevaelgeren

   Samme form som rullelisten [data-pick]: en knap, en menu og et
   skjult felt. Browserens egen <input type="color"> tegner sin knap
   selv og kan ikke styles - den bor derfor inde i menuen, hvor den
   ikke skal passe ind i noget.
   ===================================================================== */
.hue { position: relative; }

.hue-button {
    display: flex; align-items: center; gap: 9px;
    width: 100%; height: 38px; padding: 0 12px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--field-bg); color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 14px; text-align: left; cursor: pointer;
    transition: border-color 160ms ease, box-shadow 160ms ease;
}
.hue-button:hover { border-color: var(--line-strong); }
.hue-button:focus-visible {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
.hue-button > svg {
    width: 16px; height: 16px; margin-left: auto;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
    color: var(--text-muted);
}

/* Selve farven. Ternet bund bagved, saa en lys farve kan ses som lys
   og ikke forsvinder i feltet. */
.hue-dot {
    flex: 0 0 auto; width: 20px; height: 20px; border-radius: 6px;
    border: 1px solid var(--line-strong);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}
.hue-name {
    font-variant-numeric: tabular-nums; letter-spacing: 0.04em;
    color: var(--text-muted); font-size: 13px;
}

.hue-menu {
    position: absolute; z-index: 40; top: calc(100% + 6px); left: 0;
    min-width: 100%; padding: 10px;
    border: 1px solid var(--line-strong); border-radius: 12px;
    background: var(--surface-solid);
    box-shadow: var(--card-shadow);
    backdrop-filter: blur(8px);
}

.hue-grid {
    display: grid; gap: 6px;
    grid-template-columns: repeat(5, 1fr);
}

.hue-chip {
    width: 30px; height: 30px; padding: 0;
    border: 1px solid var(--line-strong); border-radius: 8px;
    cursor: pointer;
    transition: transform 120ms ease, box-shadow 120ms ease;
}
.hue-chip:hover { transform: scale(1.1); }
.hue-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.hue-chip.is-on { box-shadow: 0 0 0 2px var(--accent); }

.hue-own {
    display: flex; align-items: center; gap: 8px;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--line);
}

/* Systemets egen vaelger, gemt bag en rund knap. Feltet selv fylder
   mere end knappen, saa hele fladen kan trykkes. */
.hue-native {
    position: relative; overflow: hidden;
    flex: 0 0 auto; width: 30px; height: 30px;
    border: 1px solid var(--line-strong); border-radius: 8px;
    display: grid; place-items: center; cursor: pointer;
    background:
        conic-gradient(#ff8f8f, #ffd60a, #4cf5c5, #56a4ff, #7c3aed, #ff8f8f);
}
.hue-native input[type="color"] {
    position: absolute; inset: -6px;
    width: 44px; height: 44px; padding: 0; border: 0;
    opacity: 0; cursor: pointer;
}

.hue-hex {
    flex: 1 1 auto; min-width: 0; height: 30px; padding: 0 9px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--field-bg); color: var(--text);
    font-family: "Outfit", "Segoe UI", system-ui, sans-serif;
    font-size: 13px; letter-spacing: 0.04em;
}
.hue-hex:focus {
    outline: none; border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--glow-1);
}
/* En kode der ikke er en farve. Feltet siger det, frem for at rette
   den til noget brugeren ikke bad om. */
.hue-hex.is-bad { border-color: #ff8f8f; }

/* En advarsel OVEN PAA billedvaelgeren, som selv er en modal. Uden en
   hoejere z-index ville den ligge bag den den advarer om. */
.modal.modal-over { z-index: 70; }

/* Sidernes navne i advarslen. Kun et par stykker - er der mange, siger
   tallet det, og listen ruller. */
.pe-used {
    margin: 8px 0 0; padding: 0 0 0 18px;
    max-height: 130px; overflow-y: auto;
    color: var(--text-muted); font-size: 13px; line-height: 1.6;
}

/* Tallet paa kortet: hvor mange sider der bruger billedet. Saa opdager
   man det foer man traekker i krydset, ikke bagefter. */
.pe-pic-used {
    position: absolute; top: 5px; left: 5px;
    min-width: 20px; height: 20px; padding: 0 6px;
    display: grid; place-items: center;
    border-radius: 999px;
    background: rgba(3, 8, 16, 0.78); color: var(--accent);
    font-size: 11px; font-weight: 700;
}

/* =====================================================================
   Nyhedsbjælken pr. indslag

   En smal kolonne med en afkrydsning. Overskriften er kort, fordi
   kolonnen skal fylde så lidt som muligt - forklaringen står på musen.
   ===================================================================== */
.sig-cell-rss { width: 86px; text-align: center; white-space: nowrap; }

.sig-rss {
    display: inline-grid; place-items: center;
    width: 30px; height: 30px; margin: 0;
    border-radius: 8px; cursor: pointer;
    transition: background 140ms ease;
}
.sig-rss:hover { background: var(--glow-1); }
.sig-rss input { width: 16px; height: 16px; margin: 0; cursor: pointer; accent-color: var(--accent); }
.sig-rss input:disabled { cursor: default; opacity: 0.5; }

/* Har klienten intet feed, sker der ingenting paa skaermen uanset hvad
   der er krydset af. Linjen siger det, saa ingen leder efter aarsagen. */
.sig-nofeed {
    display: flex; align-items: flex-start; gap: 8px;
    margin: 12px 0 0;
}
.sig-nofeed svg {
    flex: 0 0 auto; width: 15px; height: 15px; margin-top: 2px;
    fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round;
}

/* =====================================================================
   Nyheder
   ===================================================================== */
.rel-list { list-style: none; margin: 14px 0 0; padding: 0; }

.rel-item {
    padding: 16px 18px; margin-bottom: 12px;
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--field-bg);
}
/* En der ikke er laest, skal kunne ses uden at laese datoen. */
.rel-item.is-new { border-color: var(--accent); background: var(--ok-bg); }

.rel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }

.rel-date {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 600; letter-spacing: 0.08em;
    color: var(--text-muted);
}

.rel-title {
    margin: 0 0 8px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 20px; line-height: 1.2; color: var(--text);
}

.rel-points { margin: 0; padding-left: 20px; line-height: 1.65; }
.rel-points li { margin-bottom: 5px; }
.rel-points li:last-child { margin-bottom: 0; }

/* Beskeden ved login. Den kan blive lang, saa den ruller indeni frem
   for at vokse ud over skaermen. */
.relpop { width: min(620px, 94vw); }
.relpop-list { max-height: 56vh; overflow-y: auto; margin-top: 10px; }
.relpop-list .rel-item { background: none; border-color: var(--line); }

/* Tallet paa menupunktet. Det staar ogsaa naar menuen er smal - det er
   dér man ellers ville gaa glip af det. */
.side-badge {
    margin-left: auto;
    min-width: 19px; height: 19px; padding: 0 6px;
    display: grid; place-items: center;
    border-radius: 999px;
    background: var(--accent); color: #17202f;
    font-size: 11px; font-weight: 700; line-height: 1;
}
.side-link { position: relative; }

/* Smal menu: etiketten er skjult, saa tallet laegger sig i hjoernet af
   de to bogstaver. */
/* Et menupunkt for noget brugeren ikke maa. Det BLIVER staaende og kan
   trykkes - siden bag det forklarer hvem man skal spoerge - men det maa
   kunne ses paa forhaand at der er en laas. */
/* Support skal kunne findes naar noget ikke virker. Punktet er derfor
   tydeligere end de andre: en tynd streg langs kanten og en farve der
   traekker oejet - uden at raabe som et aktivt punkt goer. */
.side-link.is-accent {
    color: var(--accent-text);
    box-shadow: inset 2px 0 0 var(--accent);
}
.side-link.is-accent .side-link-short { color: var(--accent); }
.side-link.is-accent:hover { color: var(--text); }

/* Et tal der ligger under det det boer. Ikke roedt - der er ikke noget
   i stykker - men gult: noget der skal ses paa. */
.stat-value.is-warn { color: #ffc46b; }

/* Den lille linje under etiketten. Snittet hoerer til tallet, ikke ved
   siden af det. */
.stat-sub {
    display: block; margin-top: 2px;
    font-family: "Outfit", sans-serif;
    font-size: 11px; font-weight: 500;
    letter-spacing: 0; text-transform: none;
    color: var(--text-muted);
}
.stat-sub.is-warn { color: #ffc46b; }

/* Forklaringen paa uploadsiden. Adskilt fra det man arbejder i, men i
   den samme rude - det er noget man laeser EEN gang og saa ved. */
.enc-help {
    margin-top: 22px; padding-top: 18px;
    border-top: 1px solid var(--line);
}
.enc-help-title {
    margin: 0 0 6px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 15px; font-weight: 600; color: var(--label);
}
.enc-help .note { margin: 0 0 8px; max-width: 60rem; }
.enc-help .note:last-child { margin-bottom: 0; }

/* En sag i listen. Hele navnet er et link, men det skal ikke SE ud som
   et link - understreget blaat midt i en tabel traekker oejet vaek fra
   status, som er det man skimmer efter. */
.tk-link {
    display: flex; align-items: center; gap: 11px;
    color: inherit; text-decoration: none; min-width: 0;
}
.tk-link:hover .dir-title { color: var(--accent); }
.tk-row:hover { background: var(--glow-2); }

/* Prikken gentager status som farve. Man loeber ned ad venstre kant og
   ser hvad der er aabent, uden at laese et eneste ord. */
.tk-dot {
    width: 9px; height: 9px; border-radius: 999px;
    flex: 0 0 auto;
}
.tk-dot.is-open    { background: var(--accent); }
.tk-dot.is-waiting { background: #ffc46b; }
.tk-dot.is-closed  { background: var(--text-muted); opacity: 0.5; }

/* Sagsnummeret. Ens bredde paa cifrene, saa numrene staar under
   hinanden i stedet for at danse. */
.tk-nr {
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

/* Tallet oeverst faar samme farve som status. Nul staar daempet - der
   er ingen grund til at et nul raaber lige saa hoejt som et tal. */
.tk-count.is-open    { color: var(--accent); }
.tk-count.is-waiting { color: #ffc46b; }
.tk-count.is-closed  { color: var(--text-muted); }

/* Supportsagens status. Tre tilstande, tre farver - man skal kunne
   skimme en liste og se hvad der venter. */
.tk-status {
    display: inline-block; margin-right: 8px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 12px; font-weight: 700; letter-spacing: 0.04em;
    text-transform: uppercase;
}
.tk-status.is-open    { color: var(--accent); }
.tk-status.is-waiting { color: #ffc46b; }
.tk-status.is-closed  { color: var(--text-muted); }

/* Traaden. Kundens beskeder til venstre, vores til hoejre - saa kan man
   se hvem der sagde hvad uden at laese navnene. */
.tk-thread { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.tk-msg {
    border: 1px solid var(--line); border-radius: 12px;
    padding: 12px 14px; background: var(--surface);
    max-width: 44rem;
}
.tk-msg.is-support {
    margin-left: auto;
    border-color: var(--line-strong); background: var(--ok-bg);
}
.tk-msg-head {
    display: flex; gap: 12px; align-items: baseline;
    margin-bottom: 6px;
}
.tk-msg-who {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-weight: 600; color: var(--label);
}
.tk-msg-when { font-size: 12px; color: var(--text-muted); }
.tk-msg-body { line-height: 1.55; overflow-wrap: anywhere; }

/* Statusknapperne staar for sig under svarfeltet. */
.tk-statusform {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin-top: 14px; padding-top: 14px;
    border-top: 1px solid var(--line);
}
.tk-facts { margin-top: 12px; }

.side-link.is-locked { color: var(--text-muted); opacity: 0.62; }
.side-link.is-locked:hover { opacity: 1; }

/* Samme paa en flise. */
.tile.is-locked { opacity: 0.62; }
.tile.is-locked:hover { opacity: 1; }
.tile.is-locked .tile-note { color: var(--text-muted); }

/* Beskeden paa selve siden. Ikonet og teksten side om side, saa det
   laeses som een ting og ikke som en fejlmeddelelse. */
.locked-note {
    display: flex; align-items: flex-start; gap: 14px;
    padding: 4px 0 8px;
}
.locked-icon {
    width: 26px; height: 26px; flex: 0 0 auto; margin-top: 2px;
    fill: none; stroke: var(--text-muted); stroke-width: 1.7;
    stroke-linecap: round; stroke-linejoin: round;
}

.side-rail .side-badge,
.sidebar.is-narrow .side-badge {
    position: absolute; top: 4px; right: 4px; margin-left: 0;
}

/* =====================================================================
   Se hvad en player spiller
   ===================================================================== */
.pv-pick { max-width: 420px; margin-bottom: 16px; }

.pv-split {
    display: grid; gap: 18px;
    grid-template-columns: minmax(0, 1fr) 300px;
    align-items: start;
}
@media (max-width: 900px) {
    .pv-split { grid-template-columns: minmax(0, 1fr); }
}

/* Fladen er 16:9, som skaermen. Sort bag, saa et billede der ikke
   fylder det hele, ser ud som paa en skaerm og ikke som et hul. */
.pv-stage {
    position: relative; width: 100%; aspect-ratio: 16 / 9;
    border: 1px solid var(--line); border-radius: 12px;
    background: #05070d; overflow: hidden;
}

.pv-slot { position: absolute; inset: 0; }
.pv-slot img,
.pv-slot video { width: 100%; height: 100%; object-fit: contain; display: block; }
.pv-slot iframe { width: 100%; height: 100%; border: 0; display: block; background: #fff; }

/* Det der ikke kan vises tro. Navnet og hvorfor - saa sloejfens rytme
   stadig passer, og man kan se hvad der staar paa skaermen imens. */
.pv-card {
    position: absolute; inset: 0;
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 10px; padding: 30px; text-align: center;
}
.pv-card strong {
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 26px; color: var(--text); overflow-wrap: anywhere;
}
.pv-card span { color: var(--text-muted); font-size: 14px; max-width: 46ch; }
.pv-card a { color: var(--accent); font-size: 14px; }

/* Hvor langt vi er i det nuvaerende indslag. */
.pv-bar {
    position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
    background: rgba(255, 255, 255, 0.14);
}
.pv-bar span { display: block; height: 100%; width: 0; background: var(--accent); }

.pv-controls {
    display: flex; align-items: center; gap: 10px;
    margin-top: 12px; flex-wrap: wrap;
}
.pv-controls .btn-ghost { padding: 0 11px; }
.pv-sound { margin: 0 0 0 6px; }
.pv-total { margin-left: auto; color: var(--text-muted); font-size: 13px; }

/* Listen ved siden af. Den ruller for sig, saa fladen bliver staaende. */
.pv-list {
    list-style: none; margin: 0; padding: 0;
    max-height: 62vh; overflow-y: auto;
}

.pv-item {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 9px 10px; border-radius: 9px;
    cursor: pointer;
    transition: background 140ms ease;
}
.pv-item:hover { background: var(--field-bg); }
.pv-item.is-now { background: var(--ok-bg); box-shadow: inset 2px 0 0 var(--accent); }

.pv-nr {
    flex: 0 0 auto; min-width: 20px;
    color: var(--text-muted); font-size: 12px; padding-top: 2px;
    font-variant-numeric: tabular-nums;
}
.pv-name { min-width: 0; }
.pv-title {
    display: block; color: var(--text); font-size: 13px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pv-sub {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin-top: 3px; color: var(--text-muted); font-size: 11px;
}

/* =====================================================================
   Rundturen

   Fire felter i stedet for eet lag med et hul. Et hul kraever enten en
   maske eller en box-shadow paa tusinder af pixels, og begge dele
   daekker det man skulle kigge paa naar browseren runder af. Fire
   rektangler om maalet er der ikke noget i vejen med.
   ===================================================================== */
.tour { position: fixed; inset: 0; z-index: 90; }
.tour[hidden] { display: none; }

.tour-shade {
    position: fixed;
    background: rgba(3, 8, 16, 0.74);
    animation: fadeIn 180ms ease both;
}

/* Rammen om det fremhaevede. Den lyser svagt, saa oejet finder den
   uden at den staeler billedet. */
.tour-ring {
    position: fixed;
    border: 2px solid var(--accent);
    border-radius: 10px;
    box-shadow: 0 0 0 4px var(--ring-1), 0 0 24px var(--glow-1);
    pointer-events: none;
    transition: left 220ms ease, top 220ms ease,
                width 220ms ease, height 220ms ease;
}

.tour-card {
    position: fixed;
    width: min(340px, calc(100vw - 32px));
    padding: 18px 20px 16px;
    border: 1px solid var(--line-strong); border-radius: 16px;
    background: var(--panel);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    transition: left 220ms ease, top 220ms ease;
}
/* Trin uden et maal - velkomsten og afskeden - staar midt paa. */
.tour-card.is-middle {
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
}

.tour-step {
    font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--text-muted);
}
.tour-card h3 {
    margin: 6px 0 8px;
    font-family: "Rajdhani", "Outfit", sans-serif;
    font-size: 22px; line-height: 1.1;
}
.tour-card p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--text); }

/* Hvor langt er der igen? Uden dem ved man ikke om det er to trin
   eller tolv, og saa springer man over for en sikkerheds skyld. */
.tour-dots { display: flex; gap: 5px; margin: 14px 0 12px; }
.tour-dot {
    width: 6px; height: 6px; border-radius: 999px;
    background: var(--line-strong);
    transition: background 160ms ease, width 160ms ease;
}
.tour-dot.is-done { background: var(--accent-2); }
.tour-dot.is-here { width: 18px; background: var(--accent); }

.tour-actions { display: flex; align-items: center; gap: 8px; }
/* "Spring over" skubbes til venstre og de to andre til hoejre - saa er
   der ikke to naboknapper der goer det modsatte af hinanden. */
.tour-actions .btn-cancel { margin-right: auto; }
.tour-actions [hidden] { display: none; }

/* Spoergsmaalstegnet i toppen. */
.tour-again {
    display: inline-flex; align-items: center; justify-content: center;
    width: var(--control-h); height: var(--control-h);
    padding: 0;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--field-bg); color: var(--text-muted);
    cursor: pointer;
    transition: color 140ms ease, border-color 140ms ease;
}
.tour-again:hover { color: var(--accent); border-color: var(--line-strong); }
.tour-again svg {
    width: 18px; height: 18px;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
}

/* Mens turen koerer, maa siden ikke rulle under den. */
body.tour-open { overflow: hidden; }

/* Paa en telefon er der ikke plads ved siden af - kortet laegger sig
   nederst, hvor tommelfingeren er. */
@media (max-width: 720px) {
    .tour-card {
        left: 16px !important;
        right: 16px;
        top: auto !important;
        bottom: 16px;
        width: auto;
        transform: none;
    }
    .tour-card.is-middle { left: 16px !important; top: auto !important; }
}
