/* bevaegelse.css — ÉT fælles bevægelses-lag for hele hovedappen (Fase 8, 29. sep 2026 — JARVIS-STIL §4).
   Indlæses SIDST på alle sider. Bruger kun --bev-*-tokens fra tokens.css; sidernes egne stilark bruger de samme
   tokens og keyframes herfra (ingen per-side variationer):

     sideskift   200 ms fade + 4 px glid (View Transitions hvor browseren kan, ellers fade-in ved load)
     klik        scale(.98) 80 ms + tilbage — styres af src/bevaegelse.js (Web Animations, ét sted), + vibrate(8) på touch
     kort ind    fade + 6 px glid, stagger 30 ms
     toasts      ÉN komponent: glider ned fra toppen, forsvinder efter 4 s (src/bevaegelse.js: toast())
     modaler     fade + scale fra .98 (250 ms)
     sheets      glid op med fjeder (320 ms)
     menuer      kaskade 20 ms pr. punkt (src/bevaegelse.js: kaskade())
     skeletons   én lys flade der "ånder" — aldrig spinnere
   prefers-reduced-motion: alt ovenstående er slået fra (tokens = 0 + animation: none) — kun farveskift. */

/* =========================================================
   KEYFRAMES (de eneste ind-animationer i appen)
   Individuelle egenskaber (translate/scale) i stedet for transform, så de aldrig kolliderer med elementers
   egen placering (fx translateX(-50%) eller universkortets noder). Slutværdien for translate/scale er altid `none`
   (ikke 0 0) — ellers bliver et element med fill-mode "both" en containing block for position:fixed-børn (fx
   boble-arket). Opaciteten slutter implicit i elementets egen værdi (fx de hvilende noder på universkortet: .3).
   ========================================================= */
@keyframes bev-side-ind  { from { opacity: 0; translate: 0 var(--bev-glid-side); } to { translate: none; } }
@keyframes bev-kort-ind  { from { opacity: 0; translate: 0 var(--bev-glid-kort); } to { translate: none; } }
@keyframes bev-modal-ind { from { opacity: 0; scale: .98; } to { scale: none; } }
@keyframes bev-ark-op    { from { opacity: 0; translate: 0 32px; } to { translate: none; } }
@keyframes bev-fade-ind  { from { opacity: 0; } }
@keyframes bev-toast-ind { from { opacity: 0; translate: 0 -12px; } to { translate: none; } }
@keyframes bev-kaskade   { from { opacity: 0; translate: 0 4px; } to { translate: none; } }
@keyframes skelet-aande  { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* =========================================================
   SIDESKIFT — cross-document View Transitions (Chrome 126+, Safari 18.2+): den gamle side fader ud og den nye
   glider 4 px op på 200 ms. Browsere uden: .side/hovedcontaineren fader ind ved load (bev-side-ind), så der
   aldrig er et hårdt blink. Header/sidebar fastholdes som egne lag, så kun indholdet skifter.
   ========================================================= */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: var(--bev-side) var(--bev-ud) both bev-side-ud; }
::view-transition-new(root) { animation: var(--bev-side) var(--bev-kurve) both bev-side-ind; }
@keyframes bev-side-ud { to { opacity: 0; } }

/* Alle JS-byggede sider får samme fade-in ved load som .side (ingen afvigende side-animationer) */
.app--skal .akt-side, .app--skal .log-side, .app--skal .uk-side, .app--skal .kc-side, .app--skal .dashboard,
.app--skal .rg-side {
    animation: bev-side-ind var(--bev-side) var(--bev-kurve);   /* uden fill: containeren må ikke fange fixed-børn */
}
/* Indlæsnings-skelettet (før profilen er hentet) vises først efter 250 ms — hurtige sideskift blinker ikke */
.app .laster { animation: bev-fade-ind var(--bev-standard) var(--bev-ud) 250ms both; }

/* =========================================================
   INGEN LAYOUT-HOP: scrollbaren reserverer altid sin plads (indholdet hopper ikke når en lang liste loader),
   tal står fast (tabular-nums), og billeder uden mål får et fast forhold.
   ========================================================= */
.app > main { scrollbar-gutter: stable; }
.kpi__vaerdi, .taeller, .pille__antal, .notif__antal { font-variant-numeric: tabular-nums; }

/* =========================================================
   MENUER — kaskade: punkterne kommer 20 ms efter hinanden (src/bevaegelse.js sætter --i og .kaskade-punkt)
   ========================================================= */
.kaskade-punkt {
    animation: bev-kaskade var(--bev-standard) var(--bev-kurve) both;
    animation-delay: calc(var(--i, 0) * var(--bev-kaskade));
}

/* =========================================================
   TOASTS — ÉN fælles komponent (src/bevaegelse.js: toast(); notifikationer.js bruger den samme)
   Øverst, centreret under headeren (og under iPhone-notch/Dynamic Island via safe-area).
   ========================================================= */
.toasts {
    position: fixed;
    top: calc(var(--header-hoejde) + var(--trin-2) + env(safe-area-inset-top));
    left: 50%;
    translate: -50% 0;
    z-index: 100;
    display: flex;
    flex-direction: column;
    gap: var(--trin-2);
    width: min(440px, calc(100vw - 2 * var(--trin-4)));
    pointer-events: none;
}
body:not(.app--skal) .toasts { top: calc(var(--trin-4) + env(safe-area-inset-top)); }
.toast {
    display: flex;
    align-items: stretch;
    background: var(--farve-hvid);
    border-radius: var(--radius-kort);
    box-shadow: var(--skygge-staerk);
    border: 1px solid rgba(14, 58, 93, .08);
    border-left: 4px solid var(--farve-blaa);
    overflow: hidden;
    pointer-events: auto;
    animation: bev-toast-ind var(--bev-standard) var(--bev-kurve);
}
.toast--succes  { border-left-color: var(--farve-groen); }
.toast--warning { border-left-color: var(--farve-gul); }
.toast--error   { border-left-color: var(--farve-roed); }
.toast--vedvarende { border-color: rgba(194, 59, 59, .3); }
.toast--vedvarende .toast__kind { color: var(--farve-roed); }
.toast--ud { pointer-events: none; }   /* udgangen animeres af src/bevaegelse.js */
.toast--stille { animation: none; }
.toast__krop {
    flex: 1;
    display: flex;
    gap: var(--trin-3);
    align-items: flex-start;
    min-height: 48px;
    padding: var(--trin-3) var(--trin-4);
    text-align: left;
    background: transparent;
    color: inherit;
    font: inherit;
    border: 0;
}
button.toast__krop { cursor: pointer; transition: background-color var(--bev-hover) var(--bev-ud); }
button.toast__krop:hover { background: var(--farve-baggrund-lys); }
.toast__krop:focus-visible { outline: none; box-shadow: inset var(--fokus-ring); }
.toast__ikon { flex: none; color: var(--farve-blaa); margin-top: 1px; display: inline-flex; }
.toast--succes  .toast__ikon { color: var(--farve-groen); }
.toast--warning .toast__ikon { color: var(--farve-gul); }
.toast--error   .toast__ikon { color: var(--farve-roed); }
.toast__tekst { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: var(--tekst-sm); }
.toast__kind { font-size: var(--tekst-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--farve-tekst-daempet); }
.toast__kind:empty { display: none; }
.toast__titel { font-weight: 600; color: var(--farve-tekst); overflow-wrap: anywhere; }
.toast__body { color: var(--farve-tekst-daempet); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.toast__body:empty { display: none; }
.toast__luk {
    flex: none;
    width: 48px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--farve-tekst-svag);
    background: transparent;
    border: 0;
    border-left: 1px solid var(--farve-kant);
    cursor: pointer;
    transition: color var(--bev-hover) var(--bev-ud), background-color var(--bev-hover) var(--bev-ud);
}
.toast__luk:hover { color: var(--farve-navy); background: var(--farve-blaa-svag); }
.toast__luk:focus-visible { outline: none; box-shadow: inset var(--fokus-ring); }

/* =========================================================
   MODALER og BOTTOM SHEETS — fælles for alle <dialog>er der ikke har deres egen klasse-regel
   (de navngivne dialoger i components/filer/universkort/… bruger de samme keyframes herover)
   ========================================================= */
dialog[open]:not(.kc-skuffe):not(.palet):not(.log-panel):not(.fil-panel):not(.uk-panel):not(.uk-modal):not(.pv-panel):not(.styring-dialog) {
    animation: bev-modal-ind var(--bev-standard) var(--bev-kurve);
}
dialog::backdrop { animation: bev-fade-ind var(--bev-standard) var(--bev-ud); }
@media (max-width: 639.98px) {
    dialog[open]:not(.kc-skuffe):not(.palet):not(.log-panel):not(.fil-panel):not(.uk-panel):not(.uk-modal):not(.pv-panel):not(.styring-dialog) {
        animation: bev-ark-op var(--bev-ark) var(--bev-fjeder);
    }
}

/* =========================================================
   prefers-reduced-motion: ALT ovenstående slås fra — kun farveskift (JARVIS §4)
   (tokens er allerede 0 ms; her dræbes også uendelige animationer og view transitions)
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }
    ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
    .kaskade-punkt, .toast, dialog[open], dialog::backdrop, .app .laster, .side,
    .app--skal .akt-side, .app--skal .log-side, .app--skal .uk-side, .app--skal .kc-side, .app--skal .dashboard, .app--skal .rg-side {
        animation: none !important;
    }
    .app .laster::before, .skelet__blok, .spinner { animation: none !important; }
}
