        /* ============================================================
           V21.2: PREMIUM FONT — Inter erstatter Segoe UI/system-fonts.
           Inter er specifikt designet til UI'er og giver Aorta et mere
           "färdig produkt"-look på tværs af platforme. Vi henter kun
           400/500/600 weights for at holde payload'en lille (~50KB).
           ============================================================ */
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');

        /* ============================================================
           V20.2: ANTI-FOUC PRELOAD GUARD
           <body class="preload"> dropper ALLE transitions under app-boot
           så elementer ikke "fader" fra default-state til deres rigtige
           tema-værdier ved første paint. bootApp() fjerner klassen via
           requestAnimationFrame() når DOM er mounted og setTheme er kaldt
           — derefter virker normale transitions igen for runtime-skift.

           !important er nødvendigt fordi mange specifikke selektorer
           længere nede sætter transition-værdier (fx .weather-widget,
           .modal-overlay osv.). Universal selector + !important er den
           kanoniske "no-FOUC"-pattern.
           ============================================================ */
        body.preload * { transition: none !important; }

        /* --- CSS VARIABLER --- */
        :root {
            --bg-color: #121212;
            --card-bg: #1e1e1e;
            --widget-bg: #252525;
            --text-main: #ffffff;
            --text-muted: #a0a0a0;
            --text-blue-accent: #64b5f6;
            --border-color: #333;
            --accent-blue: #2979ff;

            /* --- AORTA EVENT-TYPE FARVEPALETTE (V11) --- */
            /* Hver event_type har sin egen identitet, der bevares uanset
               resolved-status. (Farven ændres IKKE længere ved resolveBday.) */
            --color-birthday:  #ff80ab;   /* Lyserød — Fødselsdag */
            --color-task:      #1de9b6;   /* Turkis — Opgave */
            --color-family:    #29b6f6;   /* Laguneblå — Familie */
            --color-kid:       #ffe082;   /* Påskegul — Børn / Skole */
            --color-private:   #424242;   /* Diamantsort — Privat */
            /* V13: nye kategorier */
            --color-important: #ef5350;   /* Rød — Vigtigt (læge/hospital).
                                             Bruges som basis-farve + minestrimmel. */
            --color-ceremony:  #5c5c8a;   /* Dyb dæmpet indigo — Højtidelighed/Sorg */
            --color-vacation:  #ff9800;   /* Solnedgangs-orange — Ferie */
            /* Bagudkompatibilitet: 'parents' aliaseres til family. */
            --color-parents:  var(--color-family);

            /* Status / system-farver (bibeholdes). */
            --color-warning: #ffab00;
            --color-danger:  #ff5252;
            --color-success: #00e676;
            /* V21.3: Alias for ENSARTEDE '+'-knapper i kalender + indbakke.
               Bevidst lidt grønnere/dybere end --color-success så plus-knapperne
               har en distinkt "tilføj"-tone og ikke ligner success-bekræftelse. */
            --accent-green:  #1abc6e;

            --gradient-briefing: linear-gradient(135deg, #2a2a72 0%, #009ffd 100%);
            --shadow-std: 0 4px 15px rgba(0,0,0,0.5);
            /* Tema-følsomme tokens for elementer der tidligere var hardcoded. */
            --btn-default-bg: #333;
            --btn-default-text: #ffffff;
            --tag-private-bg: #2c2c2c;
            --tag-private-border: #555;
            --schedule-grid-bg: #111;
            --ai-badge-bg: #667eea;
            /* V15: Dæmpet rød til puls-animation på 'AORTA INDBAKKE'-headeren
               når der ligger uløste/pending opgaver. Mørkt tema = let kølig
               rød der står godt mod baggrunden uden at "skrige". */
            --inbox-pulse-color: #d97a7a;

            /* =========================================================
               V16: 16-FARVERS HUSSTANDS-PALETTE (DUAL-COLOR TAGGING)
               Hvert medlem (voksen eller barn) kan vælge én af disse 16
               kontrastfyldte farver. Bruges på højre side af event-kort
               som diskret farve-bar (venstre side bevarer event-typens farve).
               Material Design 400-niveau — vibrant nok til både mørkt
               og lyst tema, uden at "skrige".
            ========================================================= */
            --member-1:  #ef5350;  /* Rød */
            --member-2:  #ec407a;  /* Pink */
            --member-3:  #ab47bc;  /* Magenta */
            --member-4:  #7e57c2;  /* Lilla */
            --member-5:  #5c6bc0;  /* Indigo */
            --member-6:  #29b6f6;  /* Blå */
            --member-7:  #26c6da;  /* Cyan */
            --member-8:  #26a69a;  /* Teal */
            --member-9:  #66bb6a;  /* Grøn */
            --member-10: #9ccc65;  /* Lime */
            --member-11: #ffee58;  /* Gul */
            --member-12: #ffca28;  /* Rav */
            --member-13: #ffa726;  /* Orange */
            --member-14: #ff7043;  /* Dyb-orange */
            --member-15: #8d6e63;  /* Brun */
            --member-16: #78909c;  /* Skifer */

            font-size: 1.5vmin;
        }

        [data-theme="light"] {
            --bg-color: #f0f2f5;
            --card-bg: #ffffff;
            --widget-bg: #f8f9fa;
            --text-main: #1a1a1a;
            --text-muted: #636e72;
            --text-blue-accent: #1976d2;
            --border-color: #dfe6e9;
            --shadow-std: 0 4px 15px rgba(0,0,0,0.1);
            --btn-default-bg: #cfd8dc;
            --btn-default-text: #1a1a1a;
            --tag-private-bg: #424242;
            --tag-private-border: #757575;
            --schedule-grid-bg: #eceff1;
            --ai-badge-bg: #5c6bc0;
            /* V15: Lyst tema — let varmere, mere mættet rød der er synlig
               på den lyse muted-tekst uden at virke larmende. */
            --inbox-pulse-color: #c0392b;
        }

        /* =========================================================
           V21.11: AMBIENT PASTEL TINT-SYSTEM
           ─────────────────────────────────────────────────────────
           data-tint er en SEKUNDÆR akse oven på den eksisterende
           light/dark-tema. Brugeren vælger en pastel-tone (sage/sky/
           sand/rose/yellow), og hver tone har TO udgaver:
             • light: meget bleg pastel-baggrund med lidt mere mættet
               kort-farve (kontrast bevares)
             • dark : dyb stemnings-tone (fx flaskegrøn for sage) med
               let lysere kort så event-cards stadig "popper"
           
           ARKITEKTUR: vi overrider kun --bg-color og --card-bg.
           Tekst-farver, accent-farver osv. arves fra det aktive
           data-theme. Det holder kompleksiteten lav og garanterer
           at ALLE eksisterende komponenter (kalender, indbakke,
           modaler) får den nye tone uden ekstra arbejde.
           
           NEUTRAL = INGEN regel her. Når data-tint="neutral" (default),
           bruges :root- og [data-theme="light"]-defaults uændret.
           Det betyder også at gamle brugere uden tint-præference
           får exakt samme look som V21.10 — tint-systemet er
           bagudkompatibelt by design.
           
           SWATCHES vises desuden visuelt i settings via .tint-swatch
           — sværværdierne dér MATCHER --bg-color her, så den lille
           cirkel i UI'et er en mini-preview af den faktiske vægkant.
           ========================================================= */

        /* === LIGHT TINTS (V21.12 BOLD EDITION) — tydeligt farvet bg, lyse cremede kort
           V21.11's pasteller var (HSL 22%/93% niveau) — så blege at de
           læste som "beskidt hvid". V21.12 pumper saturation til 25-50%
           og sænker bg-lightness til ~80-86%, så hver tone er ÉJEBLIKKELIG
           genkendelig. Card-bg holdes meget lys (95-97% lightness, lavere
           sat) så tekst-kontrasten mod #1a1a1a forbliver perfekt læsbar. */
        [data-theme="light"][data-tint="sage"] {
            --bg-color: #cfe3d0;   /* HSL 122° 27% 85% — klart salviegrøn */
            --card-bg:  #f0f7f1;   /* HSL 130° 27% 96% — bleg cremegrøn */
        }
        [data-theme="light"][data-tint="sky"] {
            --bg-color: #bcd4ea;   /* HSL 211° 53% 83% — klar lyseblå */
            --card-bg:  #ecf4fb;   /* HSL 210° 65% 96% */
        }
        [data-theme="light"][data-tint="sand"] {
            --bg-color: #ead7b8;   /* HSL 36° 51% 82% — varm hvede */
            --card-bg:  #faf3e3;   /* HSL 42° 78% 94% */
        }
        [data-theme="light"][data-tint="rose"] {
            --bg-color: #f0c6d0;   /* HSL 348° 60% 86% — tydelig rosa */
            --card-bg:  #fbe6eb;   /* HSL 348° 70% 94% */
        }
        [data-theme="light"][data-tint="yellow"] {
            --bg-color: #f5e289;   /* HSL 50° 84% 75% — påskegul */
            --card-bg:  #fcf6dc;   /* HSL 52° 86% 93% */
        }

        /* === DARK TINTS (V21.12 BOLD EDITION) — dyb, rig stemnings-tone
           V21.11's mørke værdier var næsten neutral-sorte (kun 1-2 hex-
           punkter farvet). V21.12 hæver saturation til 40-65% og holder
           lightness lav (10-13% bg, 15-19% card) så vi får klar mood-
           dybde mens cards stadig "popper" 5-7 lightness-points op. */
        [data-theme="dark"][data-tint="sage"] {
            --bg-color: #0e2a1a;   /* HSL 142° 50% 11% — dyb skovgrøn */
            --card-bg:  #14361f;   /* HSL 138° 47% 15% */
        }
        [data-theme="dark"][data-tint="sky"] {
            --bg-color: #0b1d36;   /* HSL 217° 67% 13% — dyb midnatsblå */
            --card-bg:  #122a4b;   /* HSL 217° 60% 18% */
        }
        [data-theme="dark"][data-tint="sand"] {
            --bg-color: #322210;   /* HSL 33° 53% 13% — rig jord-brun */
            --card-bg:  #432e15;   /* HSL 32° 53% 17% */
        }
        [data-theme="dark"][data-tint="rose"] {
            --bg-color: #3a0f1c;   /* HSL 348° 59% 14% — rig burgundy */
            --card-bg:  #4d1626;   /* HSL 348° 56% 19% */
        }
        [data-theme="dark"][data-tint="yellow"] {
            --bg-color: #332d12;   /* HSL 50° 47% 13% — dyb oliven */
            --card-bg:  #44391a;   /* HSL 49° 45% 18% */
        }

        /* --- GLOBAL LAYOUT --- */
        body {
            font-family: 'Inter', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            background-color: var(--bg-color);
            color: var(--text-main);
            /* V21.9: EDGE-TO-EDGE — outer body padding reduceret fra 2rem til
               0.5rem så Aorta strækker sig næsten helt ud til skærmkanten.
               Dashboardet er allerede fixed-height (100vh) så reduktionen
               kommer rent som ekstra plads til indhold. */
            margin: 0; padding: 0.5rem;
            height: 100vh; width: 100vw;
            box-sizing: border-box;
            display: flex; overflow: hidden; 
            transition: background 0.5s ease, color 0.5s ease;
            user-select: none;
        }

        /* V21.9: Grid-gap reduceret fra 1.5rem → 0.5rem så de tre paneler
           lægger sig tættere op ad hinanden. Sammen med body's nye 0.5rem
           padding giver det "tabletvenligt" edge-to-edge look. */
        /* V21.31.7: align-items: stretch GJORT EKSPLICIT
           ─────────────────────────────────────────────────────────────
           Grid-default ER stretch, men brugerens flow-test viser at
           højre kolonne (.panel.right-panel) krymper når indbakken
           har <8 kort — så det implicitte stretch holder ikke vand
           her (sandsynligvis pga. .panel's overflow:hidden + indre
           flex-content der ikke claimer height). Vi sætter stretch
           eksplicit som forsikring så alle 3 paneler ALTID har samme
           højde uanset content-volume i højre kolonne. */
        .dashboard-container { flex: 1; display: grid; grid-template-columns: 22rem 1fr 24rem; gap: 0.5rem; min-height: 0; align-items: stretch; }
        
        .panel {
            background-color: var(--card-bg);
            /* V21.9: TYNDE RAMMER — padding reduceret massivt (1.5rem → 0.5rem)
               og border-radius lidt ned (1.5rem → 0.9rem) så panelets "ramme"
               omkring indholdet visuelt forsvinder. Indholdet (vejr, kalender,
               indbakke) får dermed maksimal plads. */
            border-radius: 0.9rem;
            padding: 0.5rem;
            display: flex; flex-direction: column; justify-content: space-between; 
            box-shadow: var(--shadow-std); border: 1px solid var(--border-color);
            overflow: hidden; position: relative;
        }
        /* V21.31.7: HØJRE-PANEL FULD HØJDE-CHAIN
           ─────────────────────────────────────────────────────────────
           Forrige iterationer (V21.31.4-6) prøvede forskellige varianter
           af height:100% / flex:1 på subset af elementerne — ingen virkede
           konsekvent når indbakken havde få kort. Brugeren har nu defineret
           den eksakte spec der ENDELIG løser det:
           
           1. .dashboard-container { align-items: stretch } — explicit grid
              stretch så alle 3 .panel-items garanteret er lige høje.
           2. .panel.right-panel { height: 100%; display: flex; flex-direction: column }
              — eksplicit fuld højde + flex-context til børn (display:flex
              er allerede arvet fra .panel, men eksplicit her redundant for
              robusthed mod fremtidige .panel-refactors).
           3. .right-panel-content { flex: 1; display: flex; flex-direction: column; min-height: 0 }
              — flex:1 så den fylder al panel-højde, min-height:0 så flex-
              children kan shrink under deres intrinsic content-size, og
              flex-column for at orchestrere børn (.inbox-list + .shopping-
              panel).
           4. .inbox-list { flex: 1 1 auto; overflow-y: auto } — shorthand
              betyder grow:1 (fyld al overskydende plads), shrink:1 (kan
              krympe hvis nødvendigt), basis:auto (start fra content-size).
              overflow-y:auto giver scrollbar når indbakken har MERE indhold
              end pladsen tillader.
           5. .shopping-panel { margin-top: auto !important } — fjederen
              der presser shopping-panelet til bunden af .right-panel-content
              når .inbox-list ikke fylder hele plads-kvoten.
           
           justify-content:flex-start overrider .panel's default space-between
           så indholdet starter fra toppen. */
        /* V21.31.8: height:100% FJERNET — lad grid-stretch håndtere højden
           naturligt. Eksplicit height:100% kombineret med grid-row-auto-sizing
           kunne udvide højre kolonne ud over de andre paneler (brugeren ser
           det grå panel-felt fortsætte til viewport-bunden uden afrundede
           hjørner, mens midter- og venstre-panel stopper et par px før).
           Med .dashboard-container { align-items: stretch } er alle 3 grid-
           items garanteret samme højde — vi har ikke brug for explicit
           override på højre panel. */
        .panel.right-panel {
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
        }

        /* --- UI ELEMENTER --- */
        .corner-icon-left { position: absolute; top: 1rem; left: 1rem; font-size: 1.5rem; z-index: 10; filter: grayscale(100%) opacity(0.3); transition: all 0.5s ease; }
        .gps-active { filter: grayscale(0%) opacity(1); text-shadow: 0 0 10px rgba(0, 230, 118, 0.5); }
        
        .top-btn-group { position: absolute; top: 1rem; right: 1rem; display: flex; gap: 0.5rem; z-index: 10; }
        .control-btn { 
            background: transparent; border: 1px solid var(--border-color); 
            color: var(--text-muted); font-size: 1.2rem; 
            width: 2.5rem; height: 2.5rem; border-radius: 50%;
            cursor: pointer; display: flex; align-items: center; justify-content: center;
            transition: transform 0.2s, color 0.2s, border-color 0.2s; 
        }
        .control-btn:hover { transform: scale(1.1); color: var(--text-main); border-color: var(--text-main); }
        
        /* Widgets */
        .clock-widget { text-align: center; margin-bottom: 0.5rem; margin-top: 0.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem; flex-shrink: 0; }
        .time { font-size: 4rem; font-weight: bold; line-height: 1; letter-spacing: -2px; }
        .date { font-size: 1rem; color: var(--text-muted); margin-top: 0.5rem; }

        /* ============================================================
           V21.32 → V21.32.1 → V21.32.2: COMMAND CENTER — DROP-ZONES
           ============================================================
           Per Køreplan §2.3.4–2.3.5: Aorta er et Command Center. ALLE Cells
           kan afsluttes via Grønt Flueben (forbliver i kalenderen, dæmpet
           grøn) eller Kompostbunke (eksisterende soft-delete).
           
           V21.32.2 LAYOUT-revision (per brugeranmodning):
           ─────────────────────────────────────────────────────────────
           V21.32.1 brugte to AFLANGE felter side-om-side (horisontal grid).
           Brugeren ønsker i stedet to STORE LOGOER i RUNDE CIRKLER, stablet
           LODRET (oven på hinanden). Det giver et mere ikonisk look der
           sætter selve symbolerne i centrum frem for tekst-labels — mere
           hands-on og mindre form-agtigt.
           
             • Default state: pointer-events:none + opacity:0
               → zoner er fysisk i DOM men usynlige + klik gennem dem.
             • Aktivt drag: .is-active-klassen sættes via JS på dragstart
               → opacity:1 + pointer-events:auto, store cirkulære targets.
             • dragend (drop ELLER cancel) → klassen fjernes igen.
           
           Layout-mekanik:
             • Wrapper: position:absolute + inset:0, flex column, centreret
               både horisontalt og vertikalt → cirklerne lander præcis
               midt i venstre panel uanset panel-højde.
             • To CIRKULÆRE zoner stablet vertikalt (gap: 1.25rem):
                 [○ Grønt Flueben]     ← top
                 [○ Kompostbunke ]     ← bund
             • Hver cirkel = 11rem diameter (skalerer ned på mobil) med
               border-radius:50% + aspect-ratio:1 så den er PERFEKT rund
               uanset evt. fremtidige content-overflow.
             • STORT ikon (5rem) i centrum — labelen er BLEVET FLYTTET
               UD af cirklen og placeres som lille tekst lige under, så
               cirkel-formen ikke forstyrres af tekstindhold.
             • Subtilt backdrop på wrapper'en (sort 38% + blur 4px) så
               briefing/vejr/smarthome dæmpes en anelse — brugeren ved
               at de er i "command-center mode" uden at konteksten
               forsvinder helt.
             • V21.43 (Køreplan §2.4.8 — REVISION af tidl. §2.3.9):
               Drag-over på en zone aktiverer .is-drag-over → pulserende
               box-shadow-glow + scale 1.04x + lysere dashed border.
               Asymmetrisk farve-strategi:
                 — Fuldført  → grønt glow (matcher base-tonen)
                 — Kompost   → RØDT glow oven på BRUN base (rødt =
                               destruktiv action; brun = kompost-identitet)
               prefers-reduced-motion deaktiverer pulse-animationen men
               beholder en statisk glow-ring så feedback'en bevares.
           ============================================================ */
        .cell-action-zones {
            position: absolute;
            inset: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 1.25rem;
            padding: 1rem;
            z-index: 50;
            pointer-events: none;
            opacity: 0;
            background: rgba(0, 0, 0, 0);
            transition: opacity 0.18s ease, background-color 0.18s ease;
        }
        .cell-action-zones.is-active {
            pointer-events: auto;
            opacity: 1;
            background: rgba(0, 0, 0, 0.38);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
        }
        /* Hver zone er en ÆGTE cirkel — width = height + border-radius:50%.
           aspect-ratio:1 garanterer at hvis vi senere ændrer width via
           media-query, følger height pænt med uden separat height-override. */
        .cell-action-zone {
            width: 11rem;
            height: 11rem;
            aspect-ratio: 1 / 1;
            border-radius: 50%;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 0.5rem;
            text-align: center;
            cursor: copy;
            user-select: none;
            border: 3px dashed var(--border-color);
            background: rgba(20, 20, 20, 0.92);
            backdrop-filter: blur(6px);
            -webkit-backdrop-filter: blur(6px);
            box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
            transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
        }
        .cell-action-zone-icon {
            width: 5rem;
            height: 5rem;
            display: block;
            object-fit: contain;
            pointer-events: none; /* så drag-events rammer parent-div, ikke <img> */
            filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.5));
        }
        .cell-action-zone-label {
            font-size: 0.78rem;
            font-weight: 700;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--text-main);
            line-height: 1;
            pointer-events: none;
            opacity: 0.85;
        }
        /* Per zone-tones — grøn for færdig, jordbrun for kompost. Dashed
           border-color matcher tonens hovedfarve så cirklerne har deres egen
           "identitet" selv ved at glance. Radial-gradient i stedet for
           lineær, så lyset stråler ud fra centrum og forstærker den
           cirkulære form. */
        .cell-action-zone-complete {
            border-color: rgba(0, 230, 118, 0.7);
            background: radial-gradient(
                circle at 50% 40%,
                rgba(0, 230, 118, 0.32) 0%,
                rgba(20, 20, 20, 0.92) 70%
            );
        }
        .cell-action-zone-compost {
            /* Jordbrun-tone for kompost. Vi har ingen --color-compost endnu,
               så vi bruger en hardcoded SaddleBrown-derivative der matcher
               eksisterende Compost logo.svg's palette. */
            border-color: rgba(139, 111, 71, 0.75);
            background: radial-gradient(
                circle at 50% 40%,
                rgba(139, 111, 71, 0.38) 0%,
                rgba(20, 20, 20, 0.92) 70%
            );
        }

        /* ============================================================
           V21.43: DRAG-OVER GLOW-FEEDBACK (Køreplan §2.4.8)
           ------------------------------------------------------------
           To separate keyframes — én pr. farve — så glow-pulsen "stråler"
           ud fra cirklen i den korrekte tone. To-shadow-pattern:
             • Indre lag (0px → 14px) = den "ekspanderende ring" der
               vokser udad og fader bort = hjerte-slag-effekt
             • Ydre lag (28px → 64px) = en stationær soft-halo der altid
               er tændt og skifter intensitet i takt med den indre ring
           Kombineret giver det "varme" pulserende glow uden at hoppe.

           Asymmetri-detalje per spec:
             • Fuldført  → samme grønne tone som base = harmonisk
             • Kompost   → RØD glow (220,38,38) oven på BRUN base = bevidst
                           visuel dissonans der signalerer "destruktiv" mens
                           kompost-identiteten bevares.

           Scale 1.04 + lysere dashed border = taktil "kortet ER nu låst
           ind på denne zone"-følelse. Transition på transform/border gør
           skiftet smooth ind/ud, mens box-shadow-pulsen er ren animation
           (kan ikke transition'es da den er i et keyframe).

           prefers-reduced-motion: animation:none + statisk glow-ring
           bevarer feedback uden vestibular-trigger.
           ============================================================ */
        @keyframes zoneDragOverGlowGreen {
            0%, 100% {
                box-shadow:
                    0 0 0 0 rgba(0, 230, 118, 0.65),
                    0 0 28px 4px rgba(0, 230, 118, 0.45);
            }
            50% {
                box-shadow:
                    0 0 0 14px rgba(0, 230, 118, 0),
                    0 0 64px 10px rgba(0, 230, 118, 0.85);
            }
        }
        @keyframes zoneDragOverGlowRed {
            0%, 100% {
                box-shadow:
                    0 0 0 0 rgba(220, 38, 38, 0.7),
                    0 0 28px 4px rgba(220, 38, 38, 0.45);
            }
            50% {
                box-shadow:
                    0 0 0 14px rgba(220, 38, 38, 0),
                    0 0 64px 10px rgba(220, 38, 38, 0.9);
            }
        }
        .cell-action-zone.is-drag-over {
            transform: scale(1.04);
            cursor: copy;
        }
        .cell-action-zone-complete.is-drag-over {
            border-color: rgba(0, 230, 118, 1);
            background: radial-gradient(
                circle at 50% 40%,
                rgba(0, 230, 118, 0.55) 0%,
                rgba(20, 20, 20, 0.92) 75%
            );
            animation: zoneDragOverGlowGreen 1.1s ease-in-out infinite;
        }
        .cell-action-zone-compost.is-drag-over {
            /* Asymmetrisk: BRUN base bevares (kompost-identitet), men en
               rød ydre dashed border + radial-tint markerer "destruktiv
               action er ved at ske". Border-color skifter fra brun til
               rød så kanten matcher pulsen. */
            border-color: rgba(220, 38, 38, 0.95);
            background: radial-gradient(
                circle at 50% 40%,
                rgba(139, 111, 71, 0.55) 0%,
                rgba(60, 18, 18, 0.92) 75%
            );
            animation: zoneDragOverGlowRed 1.1s ease-in-out infinite;
        }
        @media (prefers-reduced-motion: reduce) {
            .cell-action-zone-complete.is-drag-over {
                animation: none;
                box-shadow:
                    0 0 0 4px rgba(0, 230, 118, 0.85),
                    0 0 32px 6px rgba(0, 230, 118, 0.55);
            }
            .cell-action-zone-compost.is-drag-over {
                animation: none;
                box-shadow:
                    0 0 0 4px rgba(220, 38, 38, 0.85),
                    0 0 32px 6px rgba(220, 38, 38, 0.55);
            }
        }
        /* Mobil: shrink cirkel-størrelsen så de stadig kan stables med
           luft mellem dem på små skærme. Aspect-ratio holder dem runde
           uden at vi skal sætte height eksplicit. */
        @media (max-width: 480px) {
            .cell-action-zones {
                gap: 0.85rem;
                padding: 0.6rem;
            }
            .cell-action-zone {
                width: 8rem;
                height: 8rem;
            }
            .cell-action-zone-icon {
                width: 3.5rem;
                height: 3.5rem;
            }
            .cell-action-zone-label {
                font-size: 0.65rem;
            }
        }

        /* V21.3: Briefing-kortet er nu dynamisk i højden — det vokser nedad
           hvis dagens briefing-tekst bliver længere (fx flere events i dag).
           min-height sikrer at kortet altid har en visuel "tung" tilstedeværelse
           selv på dage med ingen events. cursor:pointer signalerer at kortet
           kan trykkes på for at få oplæst dagens briefing via TTS. */
        .briefing-card {
            background: var(--gradient-briefing); color: white;
            padding: 1.2rem 1.2rem 1rem 1.2rem;
            border-radius: 1rem; margin-bottom: 0.5rem; flex-shrink: 0;
            display: flex; flex-direction: column; justify-content: center;
            height: auto; min-height: 4rem;
            cursor: pointer;
            transition: transform 0.15s ease, box-shadow 0.15s ease;
            /* V21.42 push-to-talk: position:relative for at indeholde
               .briefing-voice-overlay; touch-callout/user-select disabled
               under recording for at undgå at iOS Safari åbner kontekst-
               menuen ved langt tryk på briefing-teksten. */
            position: relative;
            -webkit-touch-callout: none;
        }
        .briefing-card:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(0,0,0,0.35); }
        .briefing-card:active { transform: translateY(0); }

        /* ============================================================
           V21.42: PUSH-TO-TALK FEEDBACK PÅ BRIEFING-KORTET (§2.4.7)
           ------------------------------------------------------------
           Dual-mode interaktion (kort tryk = TTS, lang tryk = optagelse)
           kræver to nye visuelle states ovenpå basis-kortet:

             • .is-pressing  (0-499 ms efter pointerdown):
               Kortet "trykker ned" lidt — scale 0.985 + svag dæmpning.
               Det er en ren mikro-affordance der signalerer at JS HAR
               registreret trykket og at noget sker hvis brugeren bliver
               ved. Bevidst subtil — vi vil ikke chokere brugere der
               bare laver et alm. kort tryk.

             • .is-recording (efter long-press-tærsklen rammer):
               Rød pulserende glow-ramme udenom kortet (samme keyframe-
               familie som .voice-test-btn-recording). Briefing-text +
               briefing-title fades ned så .briefing-voice-overlay tager
               over visuelt. Pointer-events:none på overlay'et betyder
               at klik går GENNEM til kortet selv → så et tryk under
               optagelse trigger det normale tap-toggle-stop-flow.

           prefers-reduced-motion deaktiverer puls-animationen men
           bevarer den røde ring så vestibular-følsomme stadig får
           tydelig "live-mic"-affordance.
           ============================================================ */
        .briefing-card.is-pressing {
            transform: scale(0.985);
            transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
            box-shadow: inset 0 0 0 9999px rgba(0,0,0,0.06);
        }
        .briefing-card.is-recording {
            box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.85),
                        0 6px 20px rgba(220, 38, 38, 0.35);
            animation: aortaVoicePulse 1.4s ease-out infinite;
            cursor: pointer; /* fortsat klikbart — tap stopper recording */
        }
        .briefing-card.is-recording .briefing-title,
        .briefing-card.is-recording .briefing-text {
            opacity: 0.18;
            transition: opacity 0.18s ease;
        }
        .briefing-voice-overlay {
            display: none;
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            align-items: center;
            justify-content: center;
            gap: 0.55rem;
            color: white;
            font-weight: 700;
            font-size: 1.05rem;
            letter-spacing: 0.01em;
            padding: 0 0.8rem;
            text-align: center;
            line-height: 1.2;
            pointer-events: none;
            z-index: 2;
            border-radius: 1rem;
            user-select: none;
        }
        .briefing-card.is-recording .briefing-voice-overlay,
        .briefing-card.is-thinking  .briefing-voice-overlay {
            display: flex;
        }
        .briefing-voice-overlay .briefing-voice-icon {
            font-size: 1.4rem;
            line-height: 1;
            filter: drop-shadow(0 0 6px rgba(255,255,255,0.45));
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.6rem;
            height: 1.6rem;
        }
        /* V21.49.1: Briefing-voice-icon er nu et <img> (Ear/Brain SVG) i
           stedet for emoji. Skal udfylde hele wrapperen og bevare aspect-
           ratio. Drop-shadow på wrapperen ovenfor giver glow-effekten. */
        .briefing-voice-overlay .briefing-voice-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }
        /* Thinking-state (efter recordingen er stoppet, mens vi venter på
           Cloud Run + Gemini): grå/blå overlay i stedet for rød — visuelt
           tydeligt at vi IKKE længere optager, men også ikke idle endnu. */
        .briefing-card.is-thinking {
            box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.65),
                        0 6px 18px rgba(96, 165, 250, 0.25);
        }
        .briefing-card.is-thinking .briefing-title,
        .briefing-card.is-thinking .briefing-text {
            opacity: 0.18;
        }
        @media (prefers-reduced-motion: reduce) {
            .briefing-card.is-recording {
                animation: none;
                box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.85),
                            0 6px 18px rgba(220, 38, 38, 0.25);
            }
            .briefing-card.is-pressing {
                transition: none;
            }
        }
        /* V21.3 → V21.4: Vaske- og opvaskemaskine side om side
           ─────────────────────────────────────────────────────────────
           V21.3 stillede dem op i 2 kolonner men beholdt det horisontale
           layout (knap til venstre + tekst til højre) — det blev for
           trangt på 50% bredde og tekster som "Vaskemaskine" blev
           afkortet med ellipsis. V21.4 stabler indholdet vertikalt:
           ikon-knap øverst, titel + status centreret nedenunder. Hver
           halvdel læses nu som et selvstændigt mini-widget der minder
           om dashboardets statusgrids — pænt og visuelt afbalanceret
           uden at presse teksten. */
        .appliances-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 0.6rem;
        }
        .appliances-row .task-row {
            flex-direction: column;
            align-items: center;
            text-align: center;
            min-width: 0;
            gap: 0.5rem;
            padding: 0.8rem 0.5rem;
        }
        .appliances-row .task-info {
            display: flex;
            flex-direction: column;
            align-items: center;
            min-width: 0;
            width: 100%;
            gap: 0.15rem;
        }
        .appliances-row .task-title {
            font-size: 0.85rem;
            line-height: 1.15;
            white-space: normal;
            overflow: hidden;
            text-overflow: clip;
            color: var(--text-main);
        }
        .appliances-row .task-status {
            font-size: 0.75rem;
            line-height: 1.15;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 100%;
        }
        /* Knappen er nu det visuelle "anker" øverst i kortet. Vi giver
           den lidt ekstra højde + bevarer scale-100-ikonets centrering
           inde i den runde ramme. */
        .appliances-row .task-btn {
            width: 3.6rem;
            height: 3.6rem;
            margin-bottom: 0.1rem;
        }
        .briefing-title { font-size: 0.75rem; font-weight: bold; opacity: 0.8; margin-bottom: 0.5rem; text-transform: uppercase;}
        .briefing-text { font-size: 1rem; line-height: 1.3; }

        .weather-widget { background: var(--widget-bg); padding: 1.2rem; border-radius: 1rem; text-align: center; flex-shrink: 0; border: 1px solid var(--border-color); transition: background 0.5s ease; }
        body[data-theme="dark"] .weather-widget { background: var(--bg-color); }
        .weather-header { font-size: 1rem; color: var(--text-muted); margin-bottom: 0.5rem; }
        .temp-row { display: flex; justify-content: center; align-items: center; gap: 1rem; margin-bottom: 1rem; }
        .temp-val { font-size: 3rem; font-weight: bold; }
        .weather-icon-lg { font-size: 3rem; }
        .clothing-divider { border-top: 1px solid rgba(255,255,255,0.1); margin: 0 1rem 1rem 1rem; }
        [data-theme="light"] .clothing-divider { border-color: rgba(0,0,0,0.1); }
        .clothing-container { display: flex; align-items: center; justify-content: center; gap: 1.5rem; text-align: left; }
        .clothing-icons { display: flex; flex-direction: column; font-size: 1.8rem; gap: 0.2rem; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.3)); }
        .clothing-text-group { display: flex; flex-direction: column; gap: 0.2rem;}
        .clothing-main { font-weight: bold; font-size: 1.1rem; color: var(--text-main); }
        .clothing-sub { font-size: 0.9rem; color: var(--text-blue-accent); } 

        /* V21.5 → V21.6: HUSK MADPAKKE — STATUS-CHIP-BJÆLKE
           ─────────────────────────────────────────────────────────────
           V21.5 brugte en accent-blå venstre-kant + .widget-bg-baggrund.
           UI-feedback viste at den blå kant brød med dashboard-panelets
           rene "mørke status-chip"-look (Elpris, Alarm, Hoveddør, Inde
           bruger alle var(--bg-color) + var(--border-color)). V21.6
           omstiler bjælken til at MATCHE de andre status-felter:
             • Samme baggrund som .status-chip (var(--bg-color))
             • Samme border (1px solid var(--border-color))
             • Samme border-radius (1rem — som status-grid's chips)
             • INGEN accent-farvet venstre-kant
             • Mere padding (0.8rem 1rem) så teksten har "luft"
           Kortet strækker sig stadig over hele bredden (block-level
           via flex på parent). 🥪-emojien sidder ude til venstre,
           teksten flyder venstre-stillet derefter. */
        .lunchbox-widget {
            display: flex;
            align-items: center;
            gap: 0.7rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            color: var(--text-main);
            padding: 0.8rem 1rem;
            margin-bottom: 0.5rem;
            border-radius: 1rem;
            font-size: 0.9rem;
            line-height: 1.25;
            flex-shrink: 0;
        }
        .lunchbox-widget .lunchbox-icon {
            font-size: 1.5rem;
            line-height: 1;
            flex-shrink: 0;
        }
        .lunchbox-widget .lunchbox-text {
            flex: 1 1 auto;
            min-width: 0;
            word-wrap: break-word;
            overflow-wrap: anywhere;
        }
        /* Bold-titlen "Husk madpakke:" matcher nu chip-val'ens look —
           samme color/weight, ingen accent. Det giver et roligere
           "data point"-udseende der harmonerer med status-grid. */
        .lunchbox-widget .lunchbox-text b {
            color: var(--text-main);
            font-weight: 700;
            margin-right: 0.25rem;
        }

        /* Status & Household */
        /* V21.5: 4-KOLONNES STATUS-GRID — alle 4 chips på ÉN række
           ─────────────────────────────────────────────────────────────
           Tidligere blev de 4 chips lagt op som 2×2 grid (2 kolonner ×
           2 rækker). V21.5 placerer dem horisontalt: repeat(4, 1fr) +
           gap reduceret fra 0.8rem → 0.5rem. Hver chip er nu
           kvadrat-lignende (aspect-ratio 1/1) og labels'en er reduceret
           til 0.65rem så de stadig kan rummes uden ellipsis. chip-val
           er bumpet 0.95rem (fra 1rem) for samme grund. Resultat: et
           kompakt status-bånd der efterligner Apple Wallet's quick-
           glance pattern frem for et tungt 2×2-felt. */
        /* ============================================================
           V21.35: VENSTRE-PANEL BOTTOM-GRUPPE
           ============================================================
           Wrapper omkring de 3 nederste sektioner i venstre panel
           (madpakke + 4 status-chips + maskiner). Dens eneste opgave er
           at presse hele bottom-gruppen til BUNDEN af panelet via
           margin-top: auto, så det "spildte" rum i bunden af panelet
           flyttes op MELLEM vejr/tøj og madpakke i stedet — hvilket
           giver Briefing-kortet plads til at vokse dynamisk ned hvis
           dagens event-opsummering fylder mere end 2 linjer.
           
           Vigtigt:
             • flex-shrink: 0 — bottom-gruppen må ALDRIG krympe under
               sit naturlige indhold; det er Briefing der skal absorbere
               variabel højde, ikke chip-rækken eller maskine-knapperne.
             • Indre spacing (gap) sætter afstand mellem madpakke,
               chips og maskiner uden at duplikere de eksisterende
               margin-bottom på .status-grid m.fl. (se note nedenfor).
             • De gamle margin-bottom-værdier på .lunchbox-widget /
               .status-grid bevares for bagudkompatibilitet, men gap
               vinder hvis de stables.
           ============================================================ */
        .left-panel-bottom {
            margin-top: auto;
            display: flex;
            flex-direction: column;
            flex-shrink: 0;
        }

        .status-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; margin-bottom: 0.5rem; flex-shrink: 0; }
        .status-chip {
            background: var(--bg-color);
            padding: 0.5rem 0.3rem;
            border-radius: 0.7rem;
            border: 1px solid var(--border-color);
            text-align: center;
            cursor: pointer;
            aspect-ratio: 1 / 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 0.25rem;
            min-width: 0;
            overflow: hidden;
        }
        .chip-label { font-size: 0.65rem; color: var(--text-muted); display: block; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
        .chip-val { font-size: 0.95rem; font-weight: bold; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
        .val-good { color: var(--color-success); } .val-bad { color: var(--color-danger); }
        .alarm-off { color: var(--text-muted); } .alarm-on { color: var(--color-danger); text-shadow: 0 0 5px rgba(255, 82, 82, 0.4); } .alarm-night { color: var(--accent-blue); }

        .household-section { display: flex; flex-direction: column; gap: 0.8rem; border-top: 1px solid var(--border-color); padding-top: 1rem; flex-shrink: 0; }
        .task-row { display: flex; align-items: center; gap: 1rem; background: var(--bg-color); padding: 0.8rem; border-radius: 1rem; border: 1px solid var(--border-color); }
        .task-btn { background: var(--btn-default-bg); color: var(--btn-default-text); border: none; padding: 0; border-radius: 0.8rem; cursor: pointer; font-size: 1.5rem; width: 3.5rem; height: 3.5rem; display: flex; align-items: center; justify-content: center; transition: background 0.2s, color 0.2s; }
        .task-btn.active { background: var(--color-success); } .task-btn.alert { background: var(--color-warning); animation: pulseBtn 1s infinite; }
        @keyframes pulseBtn { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } }
        .task-info { display: flex; flex-direction: column; width: 100%; }
        .task-title { font-size: 0.9rem; font-weight: bold; }
        .task-status { font-size: 0.8rem; color: var(--text-muted); }

        /* CENTER PANEL
           ────────────────────────────────────────────────────────────────
           V21.17: gap reduceret 1.5rem → 0.6rem. Den ekstra vertikale luft
           gik tidligere mellem .calendar-3day og .calendar-month (eneste
           to børn). Med .month-header-outside som NYT 3. barn (sektions-
           overskrift), ville et 1.5rem-gap mellem hver give 3rem dødt
           hvidrum. 0.6rem holder visuel adskillelse uden at æde plads
           fra dags-cellerne i grid'et. */
        .center-content { display: flex; flex-direction: column; height: 100%; gap: 0.6rem; }
        
        /* V21.19: 3-DAGES STRIBE — UNIFORM KORT-HØJDE PR. KOLONNE.
           ────────────────────────────────────────────────────────────────
           Tre samtidige greb tvinger ALLE event-cards i en .day-column
           til at have NØJAGTIG samme højde, uanset indhold:
             1) .day-column → display:flex; flex-direction:column.
                Kortene bliver dermed flex-children der kan distribueres.
             2) Cards → flex: 1 1 0; height: auto. Hvert kort tager en
                LIGE andel af kolonnens resthøjde (efter day-header).
             3) min-height: 0 på cards så flex-shrink kan virke når der
                er mange kort i kolonnen (uden 0-floor klemmes kortet
                ALDRIG, hvilket bryder distributionen).
           Resultat: 1 kort i kolonnen = fylder hele resthøjden.
                     3 kort i kolonnen = hver tager 1/3 af resthøjden.
           Visuelt scanner brugeren nu en pæn, gridded række på tværs af
           de tre dage med konsistente kort-højder. */
        .calendar-3day { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; flex: 0 0 auto; height: 45%; }
        .day-column {
            background: var(--bg-color);
            border-radius: 1rem;
            padding: 1rem;
            border: 2px dashed transparent;
            transition: background-color 0.2s;
            overflow: hidden;
            position: relative;
            display: flex;
            flex-direction: column;
            gap: 0.5rem;
            min-height: 0;
        }
        .day-column.drag-over { border-color: var(--color-warning); background: rgba(255, 171, 0, 0.1); }
        .day-header { 
            text-align: center; font-weight: bold; border-bottom: 1px solid var(--border-color); 
            margin-bottom: 1rem; padding-bottom:0.5rem; font-size:1.1rem; text-transform: uppercase; 
            position:relative; display:flex; justify-content:center; align-items:center; 
        }

        /* V21.17: 4-UGERS KALENDER — STRETCH-LAYOUT.
           ────────────────────────────────────────────────────────────────
           Tre samtidige greb maksimerer dags-cellernes hit-area:
             1) padding 1rem → 0.4rem (sparer ~10px på hver side = 20px
                horisontalt, 20px vertikalt).
             2) margin: 0 -7px strækker selve kortet UD i .panel's egen
                0.5rem-padding (= 8px). Brutto +14px bredde i alt, hvilket
                fordeles ligeligt mellem de 7 columns + 6 gaps i grid'et.
             3) Når .month-header er moved OUT (V21.17 HTML-flyt) og denne
                container er `flex: 1` i en column, vinder grid'et alle
                de pixels headeren tidligere åd internt.
           Tilsammen vokser hver dags-celle med ~5-7px både horisontalt og
           vertikalt — tap-target går fra "fingertip-præcision" til
           "comfortable thumb". */
        /* V21.18: 4-UGERS KALENDER — 2px SMALLERE PR. SIDE.
           ────────────────────────────────────────────────────────────────
           V21.17 strakte .calendar-month UD med margin: 0 -7px (= +14px
           bredde i alt). Det viste sig at være en anelse for meget — kortet
           "kysser" panel-kanten på små viewports og bryder den visuelle
           ramme. Vi trækker derfor 2px IND igen pr. side: -7px → -5px,
           hvilket giver +10px total ekstra bredde (i stedet for +14px).
           Dags-cellerne taber kun ~0.6px hver (ifht. 7 columns), helt
           usynligt for brugeren, men kortet får sin "ramme-følelse" tilbage. */
        .calendar-month { 
            flex: 1; background: var(--bg-color); border-radius: 1rem; padding: 0.4rem; 
            border: 1px solid var(--border-color); display: flex; flex-direction: column; position:relative;
            overflow: hidden;
            margin-left: -5px;
            margin-right: -5px;
        }
        .month-header { font-size: 0.9rem; font-weight: bold; color: var(--text-muted); margin-bottom: 0.5rem; display: flex; justify-content: space-between; flex-shrink: 0;}
        /* V21.17: SEKTIONS-OVERSKRIFT (out-of-grid).
           ────────────────────────────────────────────────────────────────
           Bruger samme typografi som den gamle .month-header (font-size /
           weight / muted-farve) så identiteten er bevaret — men SIDDER
           NU UDENFOR .calendar-month-kortet, fysisk i .panel's hvide
           sektions-rum. Padding på siderne aligner overskriften med
           kortets indhold trods den negative margin på selve kortet. */
        .month-header-outside {
            margin-bottom: 0;
            padding: 0.1rem 0.5rem 0.2rem 0.5rem;
            align-items: center;
            flex-shrink: 0;
        }
        /* V21.18: TYPOGRAFISK PARITET — hint-teksten ("Træk opgaver herned")
           ────────────────────────────────────────────────────────────────
           skal nu have NØJAGTIG samme font-size og weight som titel-teksten
           ("Planlægning (4 Uger)") for at signalere ligeværd: begge er en
           del af samme sektions-header-rang. Tidligere var hint'en mindre
           (0.85rem) og normal weight, hvilket gjorde den til "fodnote" og
           degraderede pointer-ikonet i øjnene af brugeren.
           Pointer-SVG'en gøres samtidig 50% større (1.2em → 1.8em) så
           ikonet matcher den nye, mere fremtrædende tekstvægt og giver
           tydeligt visuelt cue om "træk hertil". */
        .month-header-outside .month-header-hint {
            font-size: 0.9rem;
            font-weight: bold;
            color: var(--text-muted);
            display: inline-flex;
            align-items: center;
            gap: 0.3rem;
        }
        /* V21.29 (revision): Pointer-ikonet skaleret +50% (1.8em → 2.7em)
           så det matcher den nye visuelle vægt af nav-knapperne på samme
           linje. <img> har som default ingen ramme; vi sætter alligevel
           border:none + background:transparent eksplicit så hverken bruger-
           agent-stilarter eller fremtidige globale img-resets kan komme
           til at give den et utilsigtet "kort"-look. display:block
           eliminerer baseline-spacing under inline-img. */
        .month-header-outside .month-header-hint .aorta-icon {
            width: 2.7em;
            height: 2.7em;
            border: none;
            background: transparent;
            display: block;
        }

        /* =========================================================
           V21.29 (revision): SEKTIONS-HEADER-LINJE — TRE-KOLONNE-LAYOUT
           ─────────────────────────────────────────────────────────
           Strukturen er:
             [header-left-block]  [header-middle-block]  [header-right-block]
                  TITEL              PERIODE-NAV              HINT + IKON
           Hver wrapper får flex: 1 så de tre blokke deler bredden
           ligeligt. Det betyder at den midterste navigations-blok er
           PERFEKT centreret horisontalt i parent'en — uanset om
           titel-teksten er "Planlægning (4 Uger)" (DA, 19 chars) eller
           "Planung (4 Wochen)" (DE, 18) eller en længere fransk variant.
           Ingen wrapper må shrinke ift. de andre, så vi får ægte
           3-spalter-symmetri.

           justify-content på hver wrapper aligner indholdet inden for
           sin egen kolonne: titlen ankrer venstre, navigationen midt,
           hint'en højre. Sammenlignet med den oprindelige
           .month-header's `justify-content: space-between` (som
           forskubbede nav'en mod den længste neighbour) får vi nu
           ægte midter-stabilitet — også når brugeren skifter sprog
           runtime.
           ========================================================= */
        .calendar-header-line {
            display: flex;
            align-items: center;
            gap: 0.6rem;
            /* Fjerner den default margin-bottom fra .month-header (0.5rem)
               for at holde linjen vertikalt stram — ekstra plads frigives
               til selve kalender-griddet. */
            margin-bottom: 0.15rem;
        }
        .calendar-header-line > .header-left-block,
        .calendar-header-line > .header-middle-block,
        .calendar-header-line > .header-right-block {
            flex: 1 1 0;
            display: flex;
            align-items: center;
            min-width: 0;   /* tillader text-truncation hvis labelen vokser */
        }
        .calendar-header-line > .header-left-block   { justify-content: flex-start; }
        .calendar-header-line > .header-middle-block { justify-content: center;     }
        .calendar-header-line > .header-right-block  { justify-content: flex-end;   }

        /* =========================================================
           V21.29 (revision): PERIODE-NAVIGATION (INLINE I HEADER)
           ─────────────────────────────────────────────────────────
           Følger Aortas 'Ambient Pastel' / Premium SaaS UI-DNA:
             • Cirkulære tap-targets med soft shadow (ingen neon).
             • Card-bg som baggrund så knapperne arver alle aktive
               tema-tints (sage/sky/sand/rose/yellow) automatisk —
               ingen hardcodede farver der kunne klashe med tinten.
             • Hover bruger en blød alpha-tone af --accent-blue så
               affordansen er tydelig uden at "skrige".
             • Label har FAST min-bredde så pilene ikke hopper når
               månedsnavnet skifter længde ("Maj 2026" vs "Februar 2026").
             • Knapperne er nu 32×32 (ned fra 40×40 i den standalone
               variant) så header-linjen forbliver vertikalt stram
               — den begrænsende faktor er nu det opskalerede pointer-
               ikon (~2.7em ≈ 38px), ikke nav-knapperne.
           ========================================================= */
        .month-nav-container {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 20px;
            /* Ingen padding her — wrapper-blokken (.header-middle-block)
               styrer den horisontale centering, og den vertikale luft
               styres af .calendar-header-line's align-items. */
            padding: 0;
            flex-shrink: 0;
        }
        .nav-btn {
            width: 32px;
            height: 32px;
            border-radius: 50%;
            background: var(--card-bg);
            color: var(--text-main);
            border: 1px solid var(--border-color);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            padding: 0;
            box-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.06);
            transition: transform 0.15s ease, background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
        }
        .nav-btn:hover {
            background: rgba(41, 121, 255, 0.10);   /* soft alpha af --accent-blue */
            border-color: var(--accent-blue);
            color: var(--accent-blue);
            transform: scale(1.06);
            box-shadow: 0 2px 6px rgba(0,0,0,0.12), 0 1px 3px rgba(0,0,0,0.08);
        }
        .nav-btn:active {
            transform: scale(0.96);
            box-shadow: 0 1px 2px rgba(0,0,0,0.10);
        }
        .nav-btn:focus-visible {
            outline: 2px solid var(--accent-blue);
            outline-offset: 2px;
        }
        .nav-btn svg {
            display: block;
            pointer-events: none;
        }
        .nav-label {
            font-family: 'Inter', system-ui, sans-serif;
            font-weight: 600;
            font-size: 0.95rem;
            color: var(--text-main);
            text-align: center;
            min-width: 7.5em;
            letter-spacing: 0.01em;
            user-select: none;
            /* Enkelt-linje altid — så header-linjen aldrig hopper i
               højde fordi labelen pludselig wrapper. */
            white-space: nowrap;
        }

        .month-grid { 
            display: grid; grid-template-columns: repeat(7, 1fr); 
            grid-template-rows: auto repeat(4, minmax(0, 1fr)); 
            gap: 0.4rem; height: 100%; 
            min-height: 0; overflow: hidden; 
        }
        .month-day-name { text-align: center; font-size: 0.7rem; color: var(--text-muted); padding-bottom: 0.2rem; }
        
        /* V21.17: min-height bumped 0 → 4.2rem så cellerne har en GULV-
           højde selv på små viewports hvor flex-1 ellers ville lade dem
           kollapse til ~2.5rem og gøre tap-target umuligt. På normale
           viewports er det grid-row-fordelingen der bestemmer (cellerne
           bliver gerne 5-6rem høje), men min-height beskytter mod
           "kollaps" ved zoom/portrait/små skærme. */
        .month-cell { 
            background: var(--card-bg); border-radius: 0.4rem; border: 1px solid var(--border-color); 
            display: flex; flex-direction: column; padding: 0.3rem;
            font-size: 0.8rem; cursor: pointer; transition: all 0.2s; position: relative;
            overflow: hidden; min-height: 4.2rem; 
        }
        .month-cell.drag-over { background: rgba(41, 121, 255, 0.2); border-color: var(--accent-blue); }
        .month-cell.today { border: 1px solid var(--accent-blue); color: var(--accent-blue); font-weight: bold; }
        
        /* 4-WEEK HEADER ROW (Dato + Plus) - ALIGN LEFT */
        .month-cell-header {
            display: flex; justify-content: flex-start; align-items: center; gap: 0.3rem;
            width: 100%; margin-bottom: 2px; flex-shrink: 0;
        }
        .month-date-text { font-size: 0.7rem; white-space: nowrap; pointer-events: none;}

        /* V21.3: ENSARTET '+'-KNAP — rund, grøn, hvidt fedt plus
           ----------------------------------------------------------
           Tidligere brugte kalender-cellerne og indbakken hver deres
           egen variant af "+"-tegnet (rgb(255,255,255,0.1) cirkel m. mute
           tekst). Det virkede svagt og fragmenteret. Nu er ALLE add-
           knapper visuelt ens: rund accent-grøn baggrund + hvidt 700-
           weight plus, med et lille hover-bounce + skygge så det føles
           som en "rigtig" knap. Fonten skaleres med selve knappens
           størrelse, så den lille variant i månedsceller stadig har
           samme proportion som den store i indbakken. */
        .add-btn-3day,
        .add-btn-month,
        .add-btn-inline {
            background: var(--accent-green, #00e676);
            color: #ffffff;
            font-weight: 700;
            line-height: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            cursor: pointer;
            z-index: 100;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
            transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.15s ease;
            user-select: none;
        }
        .add-btn-3day:hover,
        .add-btn-month:hover,
        .add-btn-inline:hover {
            transform: scale(1.12);
            box-shadow: 0 3px 8px rgba(0, 0, 0, 0.35);
            background: var(--color-success);
            color: #ffffff;
        }
        .add-btn-3day {
            position: absolute; left: 0; top: -0.2rem;
            width: 1.6rem; height: 1.6rem;
            font-size: 1.1rem;
        }
        .add-btn-month {
            width: 1.1rem; height: 1.1rem;
            font-size: 0.85rem;
        }
        .add-btn-inline {
            display: inline-flex;
            width: 1.7rem; height: 1.7rem;
            font-size: 1.15rem;
            margin-left: 5px;
        }

        /* MEAL ICON */
        .meal-icon {
            position: absolute; top: 0.2rem; right: 0.2rem; font-size: 1rem; cursor: pointer; z-index: 100;
            transition: transform 0.2s; opacity: 0.8;
        }
        .meal-icon:hover { transform: scale(1.2); opacity: 1; }
        .meal-text { font-size: 0.7rem; color: var(--text-blue-accent); font-style: italic; margin-top: auto; padding-left: 2px;}

        /* EVENTS (BARS) */
        .cal-event-bar {
            height: auto;
            min-height: 2.6rem;
            line-height: 1.15;
            font-size: 0.8rem;
            padding: 3px 4px; border-radius: 3px; margin-top: 3px;
            white-space: normal;
            overflow: hidden; text-overflow: ellipsis;
            color: #000; font-weight: bold; cursor: pointer; box-shadow: 0 1px 2px rgba(0,0,0,0.2);
            touch-action: none; display: flex; align-items: center; flex-shrink: 0;
            z-index: 50; position: relative;
            /* V16: Højre side bruges til ejerens farve via ::after-bar (se nedenfor).
               Vi tilføjer lille right-padding for at give plads til den 4px brede
               farve-stribe, så selve teksten ikke flyder ind under den. */
            padding-right: 7px;
        }
        /* V16: Diskret farve-bar på højre side af event-baren = ejerens farve.
           Tegnet via en pseudo-element så vi ikke kollidere med multi-day-radius.
           Inline style på .cal-event-bar sætter --owner-color (CSS custom prop). */
        .cal-event-bar[data-owner-color]::after {
            content: '';
            position: absolute;
            top: 0; bottom: 0; right: 0;
            width: 4px;
            background: var(--owner-color, transparent);
            border-radius: 0 3px 3px 0;
        }
        .cal-event-bar.multi-day::after,
        .cal-event-bar.multi-day-mid::after { display: none; }
        .cal-event-bar.multi-day { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: -5px; }
        .cal-event-bar.multi-day-mid { border-radius: 0; margin-left: -5px; margin-right: -5px; }
        .cal-event-bar.multi-day-end { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: -5px; }

        /* CARDS INBOX */
        /* V21.5: Lidt mere "luft" pr. kort + lysere baggrund ift. dark-mode
           panelets dybeste niveau (--card-bg er panelets farve; vi løfter
           kortene 1 niveau med en let translucent overlay i dark-mode).
           padding bumpet fra 1rem → 1rem 1.2rem så event-titler ikke
           står helt ude ved kanten. */
        .event-card {
            padding: 1rem 1.2rem; border-radius: 0.6rem; background: var(--card-bg); margin-bottom: 0.8rem;
            border-left: 0.4rem solid #555;
            /* V16: Højre side reserveres til ejerens (medlemmets) personlige farve.
               Default = transparent, sættes via inline style fra render-koden hvis
               eventet har en kendt ejer (created_by eller allokeret medlem). */
            border-right: 0.4rem solid transparent;
            font-size: 0.9rem; box-shadow: 0 2px 5px rgba(0,0,0,0.1);
            cursor: pointer; position: relative; touch-action: none; z-index: 50;
            /* V21.4: liste-elementer (ul#inbox-list) skal IKKE have native
               bullet-styling — vi rydder list-style så event-cards renderer
               1:1 som tidligere (de plejede at være <div>'s, nu er de <li>'s
               for semantisk korrekthed inde i en <ul>). */
            list-style: none;
        }
        /* V21.5: Marginalt lysere kort i DARK MODE — hver event-card løftes
           visuelt 1 lag op fra panelets baggrund, så de skiller sig
           tydeligere ud uden at blive aggressivt lyse. I LIGHT MODE bevares
           den eksisterende --card-bg (papir-hvid) — den fungerer godt mod
           panelets hvide baggrund og behøver ikke yderligere kontrast. */
        body[data-theme="dark"] ul#inbox-list .event-card {
            background: rgba(255, 255, 255, 0.08);
        }

        /* V21.4: REFAKTORERET INDRE LAYOUT PR. EVENT-KORT
           ─────────────────────────────────────────────────────────────
           Tidligere var titel/undertekst/dato-hint render'et inline med
           <br>-brudte linjer, hvilket fik underteksten til at smyge sig
           ind under ikonet (vi havde et padding-left:1.7em hack for at
           kompensere). Nu er strukturen rene flex-kolonner:
             .event-card-flex   = flex-row, align-items:flex-start, gap
             .event-card-icon   = kolonne 1, fixed-width container
             .event-card-text   = kolonne 2, flex-col med titel+sub+dato
           align-items:flex-start sikrer at en højde-skaleret SVG (.scale-100)
           ikke "trækker" rækken ned. Fixed-width på ikon-kolonnen
           reserverer plads til den visuelt skalerede SVG (transform:scale
           ændrer kun visuel størrelse, ikke layout-bredde — derfor
           manuel reservation). */
        .event-card .event-card-flex {
            display: flex;
            align-items: flex-start;
            gap: 0.8rem;
            width: 100%;
            min-width: 0;
        }
        .event-card .event-card-icon {
            flex: 0 0 auto;
            width: 2.5em;       /* svarer til scale-100's visuelle bredde (≈2.4em) + airbag */
            min-width: 2.5em;
            display: flex;
            align-items: flex-start;
            justify-content: flex-start;
            padding-top: 0.1em;  /* let optisk justering ift. fed titel-baseline */
        }
        .event-card .event-card-icon .aorta-icon {
            margin-top: 0;
            margin-right: 0;     /* nul'lér scale-100's globale margin-right airbag */
        }
        .event-card .event-card-text {
            flex: 1 1 auto;
            min-width: 0;
            display: flex;
            flex-direction: column;
            gap: 0.25rem;
            overflow: hidden;
        }
        .event-card .event-card-title {
            font-size: 0.95rem;
            line-height: 1.25;
            color: var(--text-main);
            word-wrap: break-word;
            overflow-wrap: anywhere;
        }
        .event-card .event-card-sub {
            font-size: 0.8rem;
            opacity: 0.75;
            line-height: 1.3;
            color: var(--text-main);
            word-wrap: break-word;
            overflow-wrap: anywhere;
        }
        .event-card .event-card-date {
            font-size: 0.75rem;
            opacity: 0.85;
            line-height: 1.2;
            color: var(--text-main);
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            align-self: flex-start;
        }
        .event-card .event-card-date-text {
            min-width: 0;
        }
        /* V21.15: Plain-tekst variant af .event-card-sted (når brugerens
           "Sted" er en beskrivelse som "Hos Laia" — ikke en rigtig adresse).
           Strip link-styling og hover-effekter, men behold padding/spacing
           så layout flugter med den klikbare adresse-version. */
        .event-card .event-card-sted-plain {
            color: var(--text-main);
            opacity: 0.75;
            cursor: default;
            text-decoration: none;
        }
        .event-card .event-card-sted-plain:hover,
        .event-card .event-card-sted-plain:focus-visible {
            background: transparent;
            color: var(--text-main);
            text-decoration: none;
        }
        /* V21.13: STED-link på event-kortet.
           Klikbart geo:0,0?q=<adresse>-link der åbner native maps-app.
           Vises som diskret pill-row med 📍-ikon + adressetekst. Bruger
           --accent-blue som tone så det skiller sig ud fra dato/note og
           kommunikerer "interaktiv". hover/focus får en let baggrund så
           target-arealet føles som en klikbar UI-region — vigtigt på
           tablet hvor fingre er upræcise.

           pointer-events:auto + position:relative + z-index:1 sikrer at
           selve <a>-elementet er taget over event-card's onclick
           (event.stopPropagation i markup'en stopper bobble til parent —
           men disse layout-properties hjælper også Safari med korrekt
           hit-testing inden for et flex-child der er position:static). */
        .event-card .event-card-sted {
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            font-size: 0.78rem;
            line-height: 1.25;
            color: var(--accent-blue);
            text-decoration: none;
            padding: 0.15rem 0.4rem 0.15rem 0.25rem;
            margin-left: -0.25rem;       /* visuel kompensation for ekstra padding så ikon flugter med titlens venstre kant */
            border-radius: 0.45rem;
            align-self: flex-start;
            max-width: 100%;
            position: relative;
            z-index: 1;
            transition: background-color 0.15s ease, color 0.15s ease;
            word-wrap: break-word;
            overflow-wrap: anywhere;
        }
        .event-card .event-card-sted:hover,
        .event-card .event-card-sted:focus-visible {
            background: rgba(41, 121, 255, 0.12);
            color: var(--color-family);
            outline: none;
            text-decoration: underline;
        }
        .event-card .event-card-sted-icon {
            font-size: 0.9rem;
            line-height: 1;
            flex-shrink: 0;
        }
        .event-card .event-card-sted-text {
            min-width: 0;
        }
        /* FIX NOW-knappen er en søsken til .event-card-flex (ligger i
           bunden af kortet). margin-top giver den luft fra teksten,
           uden at den kollapser ind i tekst-kolonnens flex-flow. */
        .event-card > .fix-btn {
            margin-top: 0.6rem;
        }
        /* Event-type tags — venstre-border farvekode pr. type. */
        .tag-birthday { border-left-color: var(--color-birthday); }
        .tag-task     { border-left-color: var(--color-task); }
        .tag-family   { border-left-color: var(--color-family); }
        .tag-kid      { border-left-color: var(--color-kid); }
        .tag-parents  { border-left-color: var(--color-parents); } /* legacy alias */
        .tag-ceremony { border-left-color: var(--color-ceremony); } /* V13: Højtidelighed/Sorg */
        .tag-vacation { border-left-color: var(--color-vacation); } /* V13: Ferie */
        .tag-warning  { border-left-color: var(--color-warning); } /* status-badge — ikke event-type */
        .tag-resolved { border-left-color: var(--color-success); } /* status-badge — ikke event-type */

        /* ============================================================
           V21.33: GRØNT FLUEBEN — .is-completed på event-cards
           ============================================================
           Per Køreplan §2.3.4: Når en Cell er fuldført (drag til Grønt
           Flueben-zonen) forbliver den på sin kalenderplads, men hele
           kortet får en dæmpet grøn farve så bruger ser at opgaven er
           klaret. Tag-farverne (.tag-birthday, .tag-task, ...) bevares
           via venstre-kant-borderen, så kortet stadig har sin originale
           identitet — den grønne tone lægger sig OVENPÅ som status-lag.
           
           Designvalg:
             • LET tone — lavere kontrast end aktive kort, så øjet
               naturligt zoom-ud og ignorerer dem som "afsluttet kontekst".
             • Bevarer venstre-kant-tag-farven — kortet er stadig læseligt
               som en birthday/task/family-Cell, bare i grønt-overlay.
             • Lille checkmark-badge i øverste højre hjørne (Checkmark
               logo.svg) for tydelig "OPGAVE LØST"-signalering uden tekst.
             • opacity 0.85 — ikke helt udvasket, så bruger kan stadig
               læse titel/tid hvis hun blader tilbage. V21.34 vil tilføje
               1-måned fade-til-grå for ÆLDRE completed cells, så vi
               beholder Den Historiske Dagbog uden visuelt rod.
           ============================================================ */
        .event-card.is-completed {
            background:
                linear-gradient(
                    135deg,
                    rgba(0, 230, 118, 0.18) 0%,
                    rgba(0, 230, 118, 0.08) 100%
                ),
                var(--card-bg);
            opacity: 0.88;
            position: relative;
        }
        /* Checkmark-badge top-right. Vi bruger den canoniske Checkmark
           logo.svg — samme asset som drop-zonen — som baggrundsbillede
           på en pseudo-element. Pseudo-element fremfor <img> så vi ikke
           skal røre HTML-strukturen for hvert event-kort i renderInbox/
           renderCardInTop (de byggesvia createElement og indsættes
           dynamisk). */
        .event-card.is-completed::after {
            content: '';
            position: absolute;
            top: 6px;
            right: 6px;
            width: 1.4rem;
            height: 1.4rem;
            background-image: url('assets/icons/Checkmark logo.svg');
            background-size: contain;
            background-repeat: no-repeat;
            background-position: center;
            filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35));
            pointer-events: none;
            z-index: 2;
        }
        /* Multi-line text-elementer i et completed kort skal også fades
           let så hele kortet føles som en samlet "afsluttet"-tone. */
        .event-card.is-completed .event-card-title,
        .event-card.is-completed .event-card-sub,
        .event-card.is-completed .event-card-date,
        .event-card.is-completed .event-card-sted,
        .event-card.is-completed .event-card-phone {
            opacity: 0.92;
        }

        /* 4-week month-view: .cal-event-bar er kun ~16-20px høj og har
           ingen plads til en checkmark-badge. Vi bruger derfor en mere
           subtil approach: dæmp opacity + læg en grøn tint OVER bar'ens
           type-farve via box-shadow inset. Bar'en bevarer sin type-farve
           som baggrund, men ser tydeligt "afsluttet" ud. */
        .cal-event-bar.cal-event-bar-completed {
            opacity: 0.6;
            box-shadow: inset 0 0 0 9999px rgba(0, 230, 118, 0.35);
            text-decoration: line-through;
            text-decoration-thickness: 1px;
            text-decoration-color: rgba(0, 0, 0, 0.45);
        }

        /* ============================================================
           V21.34: 1-MÅNED FADE — completed cells > 30 dage til neutral grå
           ============================================================
           Per Køreplan §2.3.8: Grønne Cells fader til lys grå efter 1
           måned. Det bevarer Den Historiske Dagbog (rader er stadig
           synlige hvis bruger blader tilbage), men det visuelle rod af
           "alt er grønt fordi alt er færdigt"-effekten elimineres.
           
           .is-completed-aged-klassen stables OVENPÅ .is-completed —
           CSS-cascaden vinder pga. specificitet (to klasser > én).
           Vi nulstiller den grønne baggrund + checkmark-tint og lægger
           en grayscale-filter ovenpå hele kortet. Resultat: kortet
           bevarer sin form og sin event-type-tag-farve på venstre kant
           (så bruger STADIG kan parse hvad det VAR), men selve
           "completed"-overlay-effekten er reduceret til neutral.
           ============================================================ */
        .event-card.is-completed.is-completed-aged {
            background: var(--card-bg);
            opacity: 0.55;
            filter: grayscale(0.85);
        }
        .event-card.is-completed.is-completed-aged::after {
            filter: grayscale(0.9) opacity(0.65);
        }
        .event-card.is-completed.is-completed-aged .event-card-title,
        .event-card.is-completed.is-completed-aged .event-card-sub,
        .event-card.is-completed.is-completed-aged .event-card-date,
        .event-card.is-completed.is-completed-aged .event-card-sted,
        .event-card.is-completed.is-completed-aged .event-card-phone {
            opacity: 0.85;
        }
        /* 4-week month-view aged: erstat grøn box-shadow tint med grå.
           Bar'en bevarer sin type-farve som baggrund (ikke fjernet helt)
           men opacity dæmpes yderligere så aged-rader synker visuelt
           tilbage på grid'et. */
        .cal-event-bar.cal-event-bar-completed.cal-event-bar-completed-aged {
            opacity: 0.4;
            box-shadow: inset 0 0 0 9999px rgba(160, 160, 160, 0.5);
            filter: grayscale(0.6);
        }

        /* ============================================================
           V21.34.1: HISTORISK FADE — ikke-completed events > 30 dage
           ============================================================
           Per brugerens design-valg: Vi auto-grønner KUN multi-day
           events (deres natur er at "være færdige" når perioden er
           ovre). Single-day events der ikke blev manuelt afkrydset —
           glemte lægebesøg, oversete tasks osv. — auto-grønnes IKKE,
           fordi det ville lyve om completion: en grøn checkmark
           insinuerer at opgaven blev løst.
           
           Derimod fades de efter 1 måned til neutral grå (samme look
           som .is-completed-aged) men UDEN checkmark-badge. Det
           signalerer "historisk kontekst" uden at antyde completion.
           Bruger kan stadig se kortets type-farve via venstre-kanten
           hvis hun blader tilbage — kun selve "fyld op"-effekten er
           reduceret så Den Historiske Dagbog forbliver visuelt rolig.
           
           Bemærk: ingen ::after-pseudo-element her — pointen er at
           differentiere fra .is-completed-aged ved at IKKE have
           checkmark.
           ============================================================ */
        .event-card.is-historical-aged {
            background: var(--card-bg);
            opacity: 0.55;
            filter: grayscale(0.85);
        }
        .event-card.is-historical-aged .event-card-title,
        .event-card.is-historical-aged .event-card-sub,
        .event-card.is-historical-aged .event-card-date,
        .event-card.is-historical-aged .event-card-sted,
        .event-card.is-historical-aged .event-card-phone {
            opacity: 0.85;
        }
        /* 4-week month-view historical: samme grå-cast som completed-aged
           men uden grøn box-shadow tint (vi kommer fra "ingen grøn" i
           stedet for "fra grøn til grå"). Bar'en bevarer sin type-farve
           som baggrund så bruger stadig kan parse hvad det VAR. */
        .cal-event-bar.cal-event-bar-historical-aged {
            opacity: 0.4;
            box-shadow: inset 0 0 0 9999px rgba(160, 160, 160, 0.5);
            filter: grayscale(0.6);
        }

        /* ============================================================
           V21.34: AORTA TOAST — fortryd-toast bund-højre
           ============================================================
           Per Køreplan §2.3.7: Lille knap i bund-hjørnet, 5 sek vindue,
           Fortryd-knap der reverserer DB-mutationen. Brugt af
           dropOnCompleteZone og dropOnCompostZone.
           
           Designvalg:
             • position: fixed bund-højre (1.5rem margin) — over alt
               andet UI uden at flytte med scroll. z-index 9999 matcher
               vores modaler så toasten ALTID lægger sig øverst.
             • Slide-in fra højre (translateX 120% → 0) over 250ms
               cubic-bezier — føles aforist og "afsluttet" når den
               sidder, ikke flagrende.
             • Mørk baggrund (var(--card-bg) i light, semi-transparent
               i dark) med stærk box-shadow så toasten har vægt.
             • Progress-bar i bunden (height 3px) der animerer fra
               100% → 0% width over duration ms — visuelt countdown
               så bruger ser hvor lang tid der er tilbage.
             • Pointer-events: none når .is-visible mangler, så
               usynlig toast aldrig æder klik på underliggende UI
               (lærdom fra V21.31's context-menu-saga).
           ============================================================ */
        .aorta-toast {
            position: fixed;
            bottom: 1.5rem;
            right: 1.5rem;
            z-index: 9999;
            min-width: 18rem;
            max-width: 24rem;
            background: var(--card-bg);
            color: var(--text-main);
            border: 1px solid var(--border-color);
            border-radius: 0.75rem;
            padding: 0.85rem 1rem;
            display: flex;
            align-items: center;
            gap: 0.85rem;
            box-shadow:
                0 12px 32px rgba(0, 0, 0, 0.45),
                0 4px 8px rgba(0, 0, 0, 0.25);
            transform: translateX(120%);
            opacity: 0;
            pointer-events: none;
            transition:
                transform 0.25s cubic-bezier(0.2, 0.8, 0.3, 1),
                opacity   0.25s ease;
            overflow: hidden;
        }
        .aorta-toast.is-visible {
            transform: translateX(0);
            opacity: 1;
            pointer-events: auto;
        }
        .aorta-toast-message {
            flex: 1;
            font-size: 0.95rem;
            line-height: 1.35;
            color: var(--text-main);
        }
        .aorta-toast-undo {
            flex: 0 0 auto;
            background: var(--accent-blue, #3b82f6);
            color: #ffffff;
            border: none;
            border-radius: 0.5rem;
            padding: 0.5rem 0.95rem;
            font-size: 0.85rem;
            font-weight: 600;
            cursor: pointer;
            transition: filter 0.15s ease, transform 0.1s ease;
        }
        .aorta-toast-undo:hover {
            filter: brightness(1.1);
            transform: translateY(-1px);
        }
        .aorta-toast-undo:active {
            transform: translateY(0);
            filter: brightness(0.95);
        }
        /* Progress-bar — width animation styres af inline transition-duration
           sat fra JS (default 5000ms). Ved spawn tilføjes .is-running og CSS
           transitions kører fra 100% → 0% over duration ms. */
        .aorta-toast-progress {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 3px;
            width: 100%;
            background: linear-gradient(
                90deg,
                var(--color-success, #00e676) 0%,
                var(--accent-blue, #3b82f6) 100%
            );
            transition-property: width;
            transition-timing-function: linear;
        }
        .aorta-toast-progress.is-running {
            width: 0%;
        }
        /* Mobil-tilpasning: trækker toasten ud i bredden så den fylder
           hele skærmens bund (med margin) — så Fortryd-knappen er fed
           hit-target på touch. */
        @media (max-width: 480px) {
            .aorta-toast {
                left: 0.75rem;
                right: 0.75rem;
                bottom: 0.75rem;
                max-width: none;
                min-width: 0;
            }
        }

        /* V21.4 → V21.5: 'PRIVAT'-KORT — GRÅ/GUL ADVARSELSSTRIBE
           ─────────────────────────────────────────────────────────────
           V21.4 brugte en helomkredsende dashed border på alle 4 sider,
           hvilket gjorde at private kort så ud som "låste/draft"-kort
           snarere end ægte event-kort. V21.5 retter linje med Aortas
           "special-kort"-designsprog (jf. .tag-important's minestrimmel-
           pattern på venstre kant) ved at:
             • Returnere kortet til en NORMAL look — samme baggrund og
               border-radius som alle andre event-cards i indbakken
               (var(--card-bg) i light, .event-card-overlay i dark).
             • Erstatte venstre-kanten med en MARKERET advarselsstribe
               (skiftevis grå og gul) der signalerer "privat" på samme
               måde som havne-/byggesperre-stribe i den fysiske verden.
           Stribens implementering bruger .tag-private::before-pseudoen
           (samme tilgang som .tag-important) så event-cards layout
           bevares 1:1 og hjørner forbliver afrundede. opacity-fadingen
           er fjernet — vi vil hellere have et SOLIDT kort med en
           tydelig "privat"-identitet end et halvgennemsigtigt kort. */
        .tag-private {
            border-left-color: transparent;
            opacity: 1;
            background: var(--card-bg);
            color: var(--text-main);
        }
        .tag-private::before {
            content: '';
            position: absolute;
            top: 0;
            bottom: 0;
            left: -0.4rem;
            width: 0.4rem;
            /* Skiftevis grå (--text-muted) og gul (--color-warning) i
               45-graders striber — minder om byggepladstape og
               kommunikerer "obs, ikke for andre øjne". Samme pseudo-
               element-pattern som .tag-important bruger til sin røde
               minestrimmel, så de to "special-kort" er visuelt
               beslægtede. */
            background: repeating-linear-gradient(
                45deg,
                var(--text-muted) 0,
                var(--text-muted) 8px,
                var(--color-warning) 8px,
                var(--color-warning) 16px
            );
            border-radius: 0.6rem 0 0 0.6rem;
            pointer-events: none;
        }

        /* V13: VIGTIGT — minestrimmel-effekt på venstre kant via ::before pseudo.
           Vi sætter selve borderen transparent og lægger en gradient-stribe oven på
           border-området (left: -0.4rem; width: 0.4rem). Dermed bevares kortets
           layout (samme bredde som andre tag-XXX-kort) og de afrundede hjørner. */
        .tag-important { border-left-color: transparent; }
        .tag-important::before {
            content: '';
            position: absolute;
            top: 0;
            bottom: 0;
            left: -0.4rem;
            width: 0.4rem;
            background: repeating-linear-gradient(45deg, #ef5350 0, #ef5350 10px, #ffffff 10px, #ffffff 20px);
            border-radius: 0.6rem 0 0 0.6rem;
            pointer-events: none;
        }

        /* V21.31: PRIVAT-events i kalender-griddet bruger nu samme visuelle
           "minestrimmel"-logik som VIGTIGT — bare i en mørkegrå/gul palet i
           stedet for rød/hvid. Tidligere var .cal-event-bar-private bare en
           solid mørk #424242 med hvid tekst og stiplet ramme; det blandede
           sig dårligt med Ambient Pastel-tints på light theme og gjorde
           svært at læse hvilken type begivenhed der var skjult.

           Diagonal-stripes annoncerer "noget er anderledes her" uden at
           afsløre indhold, hvilket matcher privacy-konceptet pænt:
           "noget privat sker her, klik for detaljer". Selve titlen pakkes
           — ligesom for VIGTIGT — i en .bar-text-pill med solid theme-aware
           baggrund så bogstaverne ikke drukner i striberne.

           #4b5563 (slate-600) + #eab308 (amber-500) er bevidst valgt:
             • Slate-grå er neutral nok til ikke at konkurrere med event-
               type-farverne i samme grid (ingen overlap med family blå,
               kid gul, important rød).
             • Amber er en advarselsfarve uden at være alarmerende rød —
               signalerer "skjult info" perfekt. */
        .cal-event-bar.cal-event-bar-private {
            background: repeating-linear-gradient(45deg, #4b5563 0, #4b5563 10px, #eab308 10px, #eab308 20px) !important;
            color: #1a1a1a !important;
            border: 1px solid var(--tag-private-border);
        }
        /* V13: VIGTIGT i månedskalenderen — samme minestrimmel som inbox-kortet,
           men hele baren udfyldes med gradienten. Tekst forbliver mørk for
           kontrast mod de hvide striber. */
        .cal-event-bar.cal-event-bar-important {
            background: repeating-linear-gradient(45deg, #ef5350 0, #ef5350 10px, #ffffff 10px, #ffffff 20px) !important;
            color: #1a1a1a !important;
        }
        /* V14: Pille-baggrund om teksten i en VIGTIGT-bar. Render-koden pakker
           selve overskriften i en <span class="bar-text-pill">…</span>, som her
           får en solid baggrund (kortets normale baggrund), så bogstaverne ikke
           drukner i de røde/hvide skrå striber. Theme-aware via CSS-vars.

           V21.31: Samme pille-styling genbruges af PRIVAT-bars (selector-listen
           udvidet) så de to "stripe-typer" deler én visuel pille-grammatik.
           Det giver konsistent læselighed og halverer CSS-vedligehold. */
        .cal-event-bar-important .bar-text-pill,
        .cal-event-bar-private   .bar-text-pill {
            background: var(--card-bg);
            color: var(--text-main);
            padding: 1px 6px;
            border-radius: 4px;
            font-weight: 600;
            box-shadow: 0 0 0 1px rgba(0,0,0,0.08);
        }
        /* V13: HØJTIDELIGHED — dyb dæmpet indigo kræver hvid tekst for læsbarhed. */
        .cal-event-bar.cal-event-bar-ceremony { color: #ffffff !important; }

        /* V14: TILBAGEVENDENDE virtuelle forekomster — tegnes med let dotted
           border + reduceret opacity, så det er visuelt tydeligt at de er
           "afledte" af et master-event. Klikbar (åbner master), ikke draggable. */
        .cal-event-bar.cal-event-bar-recurring {
            outline: 1px dotted rgba(0,0,0,0.35);
            outline-offset: -2px;
            opacity: 0.92;
        }
        .event-card.event-card-recurring {
            outline: 1px dotted rgba(0,0,0,0.25);
            outline-offset: -2px;
            opacity: 0.92;
        }
        .ai-badge { position: absolute; top: 0.5rem; right: 0.5rem; background: var(--ai-badge-bg); color: white; font-size: 0.6rem; padding: 2px 6px; border-radius: 10px; pointer-events: none; }
        /* V21.50.0: Variant der kan rumme et inline-SVG-ikon FØR teksten,
           bl.a. for indkøbsliste-anker-badgen ("[Shoplist SVG] Liste").
           flex + gap holder ikon + tekst pænt aligned vertikalt. */
        .ai-badge.ai-badge-with-icon {
            display: inline-flex;
            align-items: center;
            gap: 0.25rem;
        }
        .aorta-icon-inline {
            width: 0.85rem;
            height: 0.85rem;
            object-fit: contain;
            display: inline-block;
            vertical-align: middle;
        }
        .privacy-badge { position: absolute; bottom: 0.5rem; right: 0.5rem; font-size: 0.8rem; color: var(--text-muted); pointer-events: none;}
        .fix-btn { background: var(--color-danger); color: white; border: none; padding: 0.4rem 0.8rem; border-radius: 0.4rem; font-weight: bold; font-size: 0.75rem; cursor: pointer; margin-top: 0.5rem; display: inline-block; position:relative; z-index:60; }

        /* RIGHT PANEL */
        /* V21.31.6: tilbage til height:100% (per brugerens spec)
           ─────────────────────────────────────────────────────────────
           V21.31.5 byttede height:100% ud med flex:1 + min-height:0 fordi
           brugeren rapporterede at shopping-panel ikke kom i bund. Det
           hjalp ikke. V21.31.6 går tilbage til height:100% MEN tilføjer
           samtidig height:100% på .panel.right-panel (se ovenfor) så
           parent-højden er garanteret konkret. Med begge eksplicit
           definerede har %-baserede børn-højder altid en stabil
           reference at resolve mod. */
        /* V21.31.7: REVERT til flex:1 + min-height:0 (per brugerens reviderede spec)
           ─────────────────────────────────────────────────────────────
           V21.31.6 satte height:100% her som forsøg, men det krævede
           at parent's højde var deterministisk i alle scenarier. Med
           V21.31.7's nye eksplicit align-items:stretch på .dashboard-
           container + height:100% på .panel.right-panel, har parent
           NU en garanteret målbar højde — så flex:1 (sammen med min-
           height:0 så vi tillader flex-children at krympe under deres
           intrinsic size) er den korrekte måde at fylde forælderen,
           samtidig med at vi kan flex-orchestrere børnene (.inbox-list
           + .shopping-panel) korrekt indeni. */
        .right-panel-content { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: 1rem; padding-top: 2rem;}

        /* V21.4: INDBAKKE-ARKITEKTUR — header static + scrollbar liste
           ─────────────────────────────────────────────────────────────
           #inboxList = ydre flex-container der fylder højre panels
           lodrette plads. Den indeholder TO børn:
             1) .inbox-header-row (flex-shrink:0, ALTID synlig)
             2) ul#inbox-list      (flex:1, overflow-y:auto)
           Den ydre container er IKKE selv scrollbar — kun listen.
           Tidligere var hele #inboxList scrollbar, så headeren
           "scrollede med", og det betød at topmenuens store ikoner
           kunne skygge for "AORTA INDBAKKE"-teksten ved scroll. */
        .inbox-list {
            /* V21.31.7: `flex-grow: 1` → `flex: 1 1 auto` (per brugerens reviderede spec)
               ─────────────────────────────────────────────────────────
               Eksplicit shorthand: grow=1 (tag al ledig plads), shrink=1
               (tillad krympning hvis nødvendigt), basis=auto (start fra
               intrinsic content-size). Dette er equivalent med flex-grow:1
               på de fleste browsere, men EKSPLICIT shrink=1 garanterer at
               indbakken kan krympe ned under content-size hvis pladsen
               er knap — i stedet for at presse .shopping-panel ud over
               skærmens nederste kant. Sammen med overflow-y:auto er
               resultatet en altid-bottom-anchored shopping-panel og en
               scrollbar indbakke der ALDRIG presser shopping-panelet væk. */
            flex: 1 1 auto;
            display: flex;
            flex-direction: column;
            min-height: 0;
            border: 2px dashed transparent;
            transition: border 0.3s;
            border-radius: 1rem;
            position: relative;
            /* V21.31.4: overflow-y:auto på OUTER .inbox-list garanterer at
               flex faktisk klipper container-højden ned til den ledige plads
               i .right-panel-content (og ikke vokser udover for at fitte indhold).
               Det får .shopping-panel — som har margin-top:auto !important +
               flex-shrink:0 — til at klistre helt i bund af kolonnen permanent,
               uanset hvor få event-kort der er i indbakken. */
            overflow-y: auto;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .inbox-list::-webkit-scrollbar { display: none; }
        .inbox-list.drag-over { border-color: var(--accent-blue); background: rgba(41, 121, 255, 0.05); }

        /* V21.4 → V21.6: Header-rækken på AORTA INDBAKKE — titel + '+'-knap.
           margin-top:2.5rem skubber headeren ned så top-menuens .scale-150
           ikoner ikke skygger for "AORTA INDBAKKE"-teksten. flex-shrink:0
           låser headeren i toppen så den IKKE forsvinder når listen scroller.
           V21.6: margin-bottom reduceret yderligere (0.6rem → 0.2rem) så
           første event-card lægger sig HELT tæt på header-rækken — UI-
           feedback viste at brugeren oplevede et "tomt" felt før det
           første kort. Kombineret med margin-bottom:-3.5rem på top-
           scroll-pilen (se .scroll-arrow-top nedenfor) er der nu intet
           dødt rum mellem header og første kort. */
        .inbox-header-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-top: 2.5rem;
            margin-bottom: 0.2rem;
            padding-right: 0.2rem;
            flex-shrink: 0;
        }
        .inbox-header-row #inbox-title {
            font-weight: bold;
            color: var(--text-muted);
            font-size: 1.1rem;
        }

        /* V21.12 (DEV): Test Vision-knap øverst i Indbakken.
           Bevidst lille og diskret (samme visuelle vægt som .add-btn-inline)
           så den ikke konkurrerer med "AORTA INDBAKKE"-titlen. Bruger
           --accent-blue som tema-farve for at signalere "AI/dev"-handling
           (samme tone som Kompostbunkens åbn-knap). På sigt erstattes denne
           af native share-target og kamera-capture i Capacitor → så CSS'en
           er bevidst standalone og nem at fjerne. */
        .vision-test-btn {
            background: var(--accent-blue);
            color: #ffffff;
            border: none;
            border-radius: 1rem;
            padding: 0.3rem 0.75rem;
            font-size: 0.75rem;
            font-weight: 600;
            line-height: 1;
            cursor: pointer;
            flex-shrink: 0;
            transition: transform 0.15s ease, background-color 0.15s ease, opacity 0.15s ease;
            white-space: nowrap;
        }
        .vision-test-btn:hover:not(:disabled) {
            transform: scale(1.05);
            background: var(--color-family);
        }
        .vision-test-btn:disabled {
            opacity: 0.6;
            cursor: progress;
        }

        /* V21.4: SELVE DEN SCROLLBARE LISTE — ul#inbox-list
           ─────────────────────────────────────────────────────────────
           overflow-y:auto med skjult native scrollbar (samme pattern
           som .settings-pane). max-height giver browseren en eksplicit
           reference så flex:1 + overflow:auto faktisk udløser scroll.
           position:relative er afgørende for at .scroll-arrow's
           position:sticky binder til denne container — uden den
           ville pilene følge nærmeste position'd ancestor istedet. */
        ul#inbox-list.inbox-items {
            list-style: none;
            margin: 0;
            padding: 0 0.2rem;
            flex: 1 1 auto;
            min-height: 0;
            max-height: calc(100vh - 9rem);
            overflow-y: auto;
            overflow-x: hidden;
            position: relative;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        ul#inbox-list.inbox-items::-webkit-scrollbar { display: none; }

        /* V21.5 → V21.6: Første card starter NU 100% tæt på headeren.
           Bemærk at den TIDLIGERE 0.1rem-margin var redundant fordi den
           virkelige spacing-konsumer var top-scroll-pilen (3.5rem flow-
           højde der lagde sig FØR første kort). Vi har neutraliseret
           pilens flow-bidrag via margin-bottom:-3.5rem (se nedenfor),
           og første card kan derfor ligge ved 0. */
        /* V21.7 → V21.8: Header→første-kort afstand bumpet yderligere.
           V21.7 satte margin-top:0.3rem (~5px); UI-feedback efter V21.7 viste
           at kortet stadig sad marginalt for højt oppe. V21.8 lægger
           præcis 5px / 0.3rem oveni — total 0.6rem (~10px) — så kortet får
           sit eget "luft"-rum mod headeren uden at genintroducere V21.5's
           tunge døde-rum-look. */
        ul#inbox-list .event-card:first-of-type { margin-top: 0.6rem; }
        ul#inbox-list .event-card:last-of-type { margin-bottom: 0.8rem; }
        .inbox-list.drag-over { border-color: var(--accent-blue); background: rgba(41, 121, 255, 0.05); }

        /* V12: Boks omkring Gave/Kørsel-checkboxe i 'Opret Aktivitet'.
           Bruger CSS-variabler så boksen følger temaet (mørk/lys) korrekt. */
        .bday-opts-box {
            background: var(--widget-bg);
            border: 1px solid var(--border-color);
            padding: 1rem;
            border-radius: 0.5rem;
            margin-bottom: 1rem;
        }

        /* SHOPPING LIST PANEL (V12 — inline, DB-backet) — V16.1: pænere layout
           V21.9: FASTLÅST I BUNDEN AF HØJRE KOLONNE
           ─────────────────────────────────────────────────────────────
           margin-top:auto er flex-magien der presser shopping-panelet ned
           til bunden af .right-panel-content's flex-column. Indbakken
           (med flex:1) tager den resterende plads ovenfor, og shopping-
           panelet "klistrer" til bunden uanset om indbakken har 0 eller
           50 events.
           V21.10: margin-bottom 0.5rem → 2rem. Brugeren testede V21.9 og
           shopping-panelet sad for tæt på skærmkanten + bunden af det
           omsluttende .panel (overflow:hidden klippede input-fokus-glow).
           2rem giver luft nok til at input-felternes fokus-ring og
           shadow-blur ikke beskæres, og skaber visuel balance med
           top-btn-group's vertikale start-afstand i toppen. */
        .shopping-panel {
            flex-shrink: 0;
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 1rem;
            /* V21.31.6: padding 1rem → 1rem 1rem 20px (top/sides 1rem,
               bottom 20px per brugerens spec). 20px ekstra åndehul
               under input-rækken så feltet ikke ser klemt mod kortets
               nederste kant. */
            padding: 1rem 1rem 20px 1rem;
            display: flex;
            flex-direction: column;
            gap: 0.75rem;
            max-height: 22rem;
            min-width: 0;
            /* V21.31.5: !important per brugerens spec. Sammen med
               .panel.right-panel's eksplicitte height:100% og
               .right-panel-content's height:100% + .inbox-list's
               flex-grow:1+overflow-y:auto er fjederen nu komplet:
               indbakken sluger ledig plads, shopping-panel tvinges
               i bunden uanset hvad. !important blokerer alle theme-
               overrides og gamle cachede regler. */
            margin-top: auto !important;
            /* V21.31.9: margin-bottom 2rem → 0.4rem (KRITISK ALIGNMENT-FIX)
               ─────────────────────────────────────────────────────────
               2rem (32px) var en gammel margin fra V21.5-tiden, der løftede
               shopping-panel ~32px over panel-bunden. Sammen med .panel's
               base padding (0.5rem = 8px) blev shopping-panel-borderens
               bund 40px over panel-outer-bottom — mens kalender-cellernes
               bund i midter-panelet kun er 14px (0.5rem panel-padding +
               0.4rem calendar-month-padding) over deres panel-outer-bottom.
               Forskel: 26px = præcis det "lidt højere" gap brugeren ser.

               0.4rem matcher calendar-month's padding-bottom (0.4rem), så
               shopping-panel-bund = panel-outer-bottom - 0.5rem - 0.4rem
               = panel-outer-bottom - 0.9rem = SAMME som kalender-cellernes
               bund. Pixel-perfekt alignment med både kalender-griddet og
               appliance-kortene i venstre panel (de bruger samme .panel-
               base padding). */
            margin-bottom: 0.4rem;
        }
        .shopping-panel-header {
            display: flex;
            align-items: center;
            gap: 0.75rem;
            min-width: 0;
        }
        /* V16.1: To rækker — fuld-bredde navn ovenpå, mængde + knap nedenunder.
           Det giver placeholder-teksten fuld plads ("Tilføj vare...") og
           sikrer at ingen feltet bliver klippet over uanset panel-bredde.

           V21.31 (round 4): FAST MARGIN → AUTO-MARGIN-FJEDER
           ─────────────────────────────────────────────────────────────
           Round 1-3 brugte fast margin (10px → 14px → 20px → 20px!important).
           Selv 20px!important rakte ikke visuelt fordi kortet kunne være
           højere end input+header+liste tilsammen — der manglede ikke
           BARE en konstant afstand, der manglede en FJEDER der spiser
           al ledig plads.
           
           Round 4 bytter konstant margin ud med margin-top:auto, der
           i et flex-column-parent (.shopping-panel har display:flex;
           flex-direction:column) fungerer som "konsumér resterende
           plads". Resultat: input-rækken klistrer altid i bunden af
           kortet, uanset hvor stor/lille listen ovenover er.
           Klassen .shopping-panel-input-row bruges KUN på dashboardet
           (modalen bruger .shoplist-modal-add-row), så ingen risiko
           for at ramme modalens layout. */
        .shopping-panel-input-row {
            display: grid;
            grid-template-columns: 1fr auto;
            grid-template-rows: auto auto;
            gap: 0.45rem;
            align-items: stretch;
            /* V21.31 (round 4 — FJEDER-PATTERN):
               ─────────────────────────────────────────────────────────
               20px-fixen i round 3 var visuelt ikke nok — brugeren ville
               have input-rækken HELT i bund af kortet, uanset hvor høj
               header+liste er. Det opnår vi via auto-margin-fjeder:
               
               .shopping-panel har display:flex; flex-direction:column;
               (verificeret i CSS linje ~1262). I et flex-column-layout
               fungerer `margin-top: auto` på et child som "spis al
               resterende plads ovenfor" — præcis som `flex: 1` ville
               gøre på en flex-spacer, men UDEN at child'en selv vokser.
               
               Resultat:
                 ┌────────────────────────────┐
                 │  Header                    │
                 │  Liste-items               │
                 │  ......                    │
                 │  (whitespace expander)     │  ← margin-top: auto
                 │  [input-felt + qty + btn]  │  ← presset i bund
                 │                       (5px gap til bunden)
                 └────────────────────────────┘
               
               margin-bottom: 5px giver et lille åndehul mellem input
               og kortets nederste kant så det ikke ser klemt ud.
               
               !important fastholdes for at slå alle theme-overrides og
               cached gamle regler — brugeren har en historik af CSS
               der ikke gik igennem cache. */
            margin-top: auto !important;
            margin-bottom: 5px;
        }
        .shopping-panel-input-row .shop-name-input {
            grid-column: 1 / -1;
            padding: 0.6rem 0.75rem;
            font-size: 0.9rem;
            min-width: 0;
        }
        .shopping-panel-input-row .shop-qty-input {
            grid-column: 1;
            padding: 0.6rem 0.75rem;
            font-size: 0.9rem;
            min-width: 0;
        }
        .shop-add-btn {
            grid-column: 2;
            background: var(--color-task);
            color: #1a1a1a;
            border: none;
            border-radius: 0.5rem;
            font-weight: bold;
            font-size: 1.4rem;
            padding: 0 1.1rem;
            cursor: pointer;
            transition: transform 0.15s;
            min-width: 3rem;
        }
        .shop-add-btn:hover { transform: scale(1.05); }
        .shopping-icon { font-size: 1.6rem; flex-shrink: 0; }
        .shopping-content { flex: 1; min-width: 0; overflow: hidden; }
        .shopping-title { font-weight: bold; font-size: 1rem; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .shopping-sub { font-size: 0.8rem; color: var(--text-muted); }

        /* MODALS (Z-INDEX 4000) */
        .modal-overlay {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%;
            background: rgba(0,0,0,0.85); z-index: 4000;
            display: none; justify-content: center; align-items: flex-start; backdrop-filter: blur(5px);
            /* V21.24: Scroll flyttes fra .modal-content op til selve overlay'et.
               Begrundelse: Når en aorta-select-dropdown åbner og rager ud over
               modalens nedre kant, må modalens indhold IKKE klippes — vi vil
               gerne lade dropdown-menuen "svæve" frit over knapperne og evt.
               videre ned over backdroppen. Det kræver at .modal-content har
               overflow: visible (sat længere nede), hvilket fjerner dens egen
               interne scroll. Til gengæld arver vi her ansvaret for at lange
               modaler stadig kan scrolles på små skærme.
               
               align-items skiftet fra 'center' til 'flex-start' fordi flex-
               centering kombineret med overflow-y: auto har den klassiske
               "tall content gets clipped at top"-bug (flex-centering bruger
               negativ margin-effekt der falder uden for scroll-containerens
               nået-bare-areal). Med flex-start anker vi fra toppen, og
               vertikal centrering når-der-er-plads opnås via auto-margin på
               .modal-content (sat i regelen umiddelbart efter). */
            overflow-x: hidden;
            overflow-y: auto;
            padding: 2rem 1rem;
        }
        /* V21.24: Auto-margin trick — i en flex-container med align-items:
           flex-start absorberer auto-margin på flex-children al ekstra plads
           i ALLE retninger (inkl. vertikalt). Så når modalen er kortere end
           viewporten centrerer den visuelt; når den er højere lægger den
           sig naturligt mod paddingens top og scrolles via overlay'et. */
        .modal-overlay > .modal-content {
            margin: auto;
        }
        .modal-content {
            background: var(--card-bg); padding: 2rem; border-radius: 1.5rem;
            width: 35rem; max-width: 96vw; box-sizing: border-box;
            border: 1px solid var(--border-color); box-shadow: 0 10px 40px rgba(0,0,0,0.6);
            /* V21.24: max-height + overflow-y fjernet (var: 90vh + auto).
               Selve scroll-ansvaret er flyttet op til .modal-overlay så
               aorta-select-dropdowns kan svæve ud over modalens kant uden
               at blive klippet. overflow: visible på begge akser er den
               eneste konfiguration der lader absolut-positionerede børn
               (vores dropdowns) bryde ud — overflow-x: hidden ville per
               CSS-spec tvinge overflow-y til 'auto', og dermed re-introducere
               clipping. Modaler med deres egen layout-arkitektur (Settings,
               Shopping List, Compost, Weekly Meal) overskriver dette i
               deres egne klasser længere nede. */
            max-height: none;
            overflow: visible;
        }
        .modal-header { font-size: 1.2rem; font-weight: bold; margin-bottom: 1.5rem; border-bottom: 1px solid var(--border-color); padding-bottom: 1rem;}
        .modal-row { margin-bottom: 1.5rem; }
        .modal-label { display: block; margin-bottom: 0.5rem; color: var(--text-muted); font-size: 0.9rem; }
        .option-group { display: flex; gap: 0.5rem; flex-wrap: wrap; }
        .option-btn { flex: 1; padding: 0.8rem; background: var(--bg-color); border: 1px solid var(--border-color); color: var(--text-main); border-radius: 0.5rem; cursor: pointer; text-align: center; white-space: nowrap; }
        .option-btn.selected { background: var(--accent-blue); color: white; border-color: var(--accent-blue); }
        /* V21.10: PRIMÆR-KNAP-RADIUS er nu source-of-truth for hele Aorta.
           Alle handling-knapper (Gem, Slet, +Tilføj Barn, Scan Skema,
           Åbn Kompostbunken osv.) bruger .save-btn eller .delete-btn som
           base — så ved at sætte 50px her én gang, arver alle varianter
           automatisk pille-formen.
           V21.9 forsøgte at gøre dette via .btn-premium-override (50px),
           men det skabte to konkurrerende regler. V21.10 rydder op:
             • .save-btn / .delete-btn → 50px (her, grundregel)
             • .btn-premium → INGEN border-radius (arver fra .save-btn)
             • .household-mode-btn → beholder egen 50px (ikke en .save-btn) */
        .save-btn { width: 100%; background: var(--color-success); padding: 1rem; border: none; border-radius: 50px; font-weight: bold; font-size: 1rem; cursor: pointer; color: black; margin-top: 1rem;}
        .delete-btn { width: 100%; background: var(--color-danger); padding: 1rem; border: none; border-radius: 50px; font-weight: bold; font-size: 1rem; cursor: pointer; color: white; margin-top: 1rem;}
        /* ────────────────────────────────────────────────────────────────
           V21.46.7: PERSON MULTI-PICKER (foldet aorta-stil dropdown)
           ────────────────────────────────────────────────────────────────
           Vises lige under .person-chips i opret/rediger-modal'erne. Giver
           et alternativt interaktionsbillede ovenpå samme state — chips
           er stadig synlige ovenfor, multipicker'en er en dropdown med
           ✓-checkmarks ved valgte personer. Begge kontroller manipulerer
           den SAMME chips-container's .selected-klasser via togglePersonChip.

           Designet matcher .aorta-select-trigger / .aorta-select-menu
           visuelt (border, padding, font-size, chevron-rotation) så
           dropdownen føles som en del af det samme designsprog som
           Type-pickeren ovenfor.
           ──────────────────────────────────────────────────────────────── */
        .person-multipicker {
            position: relative;
            margin-top: 0.4rem;
            display: block;
        }

        /* V21.48.3: ALIAS-LÆRING-BANNER i Edit Modal
           ────────────────────────────────────────────────────────────────
           Vises proaktivt når title indeholder et ukendt proper noun
           (fx "Sofie") + præcis 1 person er valgt + navnet ikke er i
           alias-listen. Klik åbner suggestion-modal hvor brugeren kan
           gemme det som permanent alias. Subtle styling (ikke alarm,
           ikke advarsel) — det er en VENLIG forslag-prompt. */
        .alias-learn-banner {
            display: flex;
            align-items: center;
            gap: 0.7rem;
            padding: 0.7rem 1rem;
            background: var(--color-bg-elev-1, rgba(120, 200, 220, 0.08));
            border: 1px solid var(--color-accent, rgba(120, 200, 220, 0.35));
            border-radius: 0.6rem;
            cursor: pointer;
            transition: background 0.15s ease, transform 0.1s ease;
        }
        .alias-learn-banner:hover {
            background: var(--color-bg-elev-2, rgba(120, 200, 220, 0.15));
            transform: translateY(-1px);
        }
        .alias-learn-banner:active {
            transform: translateY(0);
        }
        .alias-learn-banner .aorta-icon {
            width: 1.4rem;
            height: 1.4rem;
            flex: 0 0 auto;
        }
        .alias-learn-banner-text {
            flex: 1 1 auto;
            font-size: 0.85rem;
            line-height: 1.35;
            color: var(--text-primary, inherit);
        }
        .alias-learn-banner-text strong {
            color: var(--color-accent-strong, var(--color-accent, inherit));
            font-weight: 600;
        }
        .alias-learn-banner-cta {
            flex: 0 0 auto;
            font-size: 1.1rem;
            color: var(--color-accent, inherit);
            font-weight: 600;
            opacity: 0.7;
        }
        .alias-learn-banner:hover .alias-learn-banner-cta {
            opacity: 1;
        }
        .person-multipicker-trigger {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            width: 100%;
            padding: 0.45rem 0.7rem;
            background: var(--bg-color);
            color: var(--text-color, var(--text-main));
            border: 1px dashed var(--border-color);
            border-radius: 0.55rem;
            font-size: 0.9rem;
            font-family: inherit;
            text-align: left;
            cursor: pointer;
            transition: border-color 0.12s ease, background 0.12s ease;
        }
        .person-multipicker-trigger:hover,
        .person-multipicker-trigger[aria-expanded="true"] {
            border-color: var(--accent-color, #5b8def);
            border-style: solid;
        }
        .person-multipicker-icon {
            font-size: 1rem;
            opacity: 0.85;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.1rem;
            height: 1.1rem;
        }
        .person-multipicker-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
        }
        .person-multipicker-label {
            flex: 1 1 auto;
            line-height: 1.2;
        }
        .person-multipicker-trigger .aorta-select-trigger-chevron {
            margin-left: auto;
        }
        .person-multipicker-trigger[aria-expanded="true"] .aorta-select-trigger-chevron {
            transform: rotate(180deg);
        }
        .person-multipicker-menu {
            position: absolute;
            top: calc(100% + 0.3rem);
            left: 0;
            right: 0;
            min-width: 100%;
            max-height: 18rem;
            overflow-y: auto;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.55rem;
            padding: 0.3rem;
            box-shadow: 0 8px 24px rgba(0,0,0,0.18);
            z-index: 9999;
            display: flex;
            flex-direction: column;
            gap: 0.15rem;
        }
        .person-multipicker-menu[hidden] { display: none; }
        .person-multipicker-option {
            display: flex;
            align-items: center;
            gap: 0.55rem;
            width: 100%;
            padding: 0.5rem 0.6rem;
            background: transparent;
            color: var(--text-main);
            border: 0;
            border-radius: 0.45rem;
            font-size: 0.95rem;
            font-family: inherit;
            text-align: left;
            cursor: pointer;
            transition: background 0.1s ease;
        }
        .person-multipicker-option:hover {
            background: rgba(91, 141, 239, 0.10);
        }
        .person-multipicker-option.is-selected {
            background: rgba(91, 141, 239, 0.18);
        }
        .person-multipicker-check {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.1rem;
            height: 1.1rem;
            font-size: 0.9rem;
            opacity: 0;
            color: var(--accent-color, #5b8def);
            transition: opacity 0.1s ease;
        }
        .person-multipicker-option.is-selected .person-multipicker-check {
            opacity: 1;
        }
        .person-multipicker-dot {
            width: 0.75rem;
            height: 0.75rem;
            border-radius: 50%;
            background: var(--dot-color, #888);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-size: 0.7rem;
            line-height: 1;
            flex: 0 0 auto;
        }
        .person-multipicker-option-family .person-multipicker-dot {
            background: transparent;
            width: auto;
            height: auto;
            font-size: 1rem;
        }
        .person-multipicker-name {
            flex: 1 1 auto;
            line-height: 1.2;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        /* V21.46.7: Privacy-lock styling — bruges af applyPrivacyLockForType()
           til at signalere at Synlighed-knapperne er låst af type='Privat
           (Skjult)'. Begge .option-btn'er fade'r til 60% opacity, viser
           not-allowed-cursor, og pointer-events:none stopper både klik og
           keyboard-fokus så brugeren ikke kan tab'e ind i en "død" knap.
           Den valgte knap (Privat) bevarer sin .selected-styling så det
           visuelt er tydeligt at "Privat er valgt og låst". */
        .option-group.privacy-locked .option-btn {
            opacity: 0.55;
            cursor: not-allowed;
            pointer-events: none;
        }
        .option-group.privacy-locked .option-btn.selected {
            opacity: 0.85;
        }
        .input-field { width: 100%; padding: 0.8rem; background: var(--bg-color); border: 1px solid var(--border-color); color: var(--text-main); border-radius: 0.5rem; box-sizing: border-box; font-size: 1rem;}
        .input-disabled { opacity: 0.5; cursor: not-allowed; background: var(--btn-default-bg); color: var(--btn-default-text); }
        .select-field { width: 100%; padding: 0.8rem; background: var(--bg-color); border: 1px solid var(--border-color); color: var(--text-main); border-radius: 0.5rem; font-size: 1rem; cursor:pointer;}

        /* ────────────────────────────────────────────────────────────────
           V21.14: KOMPAKT MODAL-LAYOUT (.modal-compact)
           ────────────────────────────────────────────────────────────────
           Ny variant af .modal-content brugt af #addEventModal og #editModal.
           Mål: hele "Opret/Rediger Aktivitet"-formularen skal kunne ses på
           én skærm uden vertikal scroll på en almindelig laptop (≥720px
           viewport-højde). Vi opnår det via tre greb:
             1) Tighter padding (1.25rem ned fra 2rem) + tighter row-gap
                (0.75rem ned fra 1.5rem).
             2) Grid-rækker (.modal-row-grid) der lægger 2-3 felter side om
                side i stedet for hver-på-sin-linje.
             3) Header med mindre bottom-margin og handlings-knapper i en
                .modal-actions-flex-række (Gem + Annuller side om side).
           Bevarer det responsive sikkerhedsnet (overflow-y:auto) i tilfælde
           af meget små skærme — vi tager bare scroll'en VÆK fra den almindelige
           desktop-/tablet-flow. */
        .modal-content.modal-compact {
            padding: 1.25rem 1.4rem 1.4rem;
            /* V21.24: max-height fjernet (var: 92vh). Add Event- og Edit
               Event-modalen er nu fri til at strække sig så aorta-select-
               dropdowns (især "Tilbagevendende" der sidder nederst) kan
               åbne nedad uden at blive klippet af modalens nedre kant.
               Overlay'et tager scroll-ansvar hvis hele modalen + en åben
               dropdown ville være højere end viewporten. */
            max-height: none;
        }
        .modal-content.modal-compact .modal-header {
            font-size: 1.1rem;
            margin-bottom: 0.9rem;
            padding-bottom: 0.6rem;
        }
        .modal-content.modal-compact .modal-row {
            margin-bottom: 0.75rem;
        }
        .modal-content.modal-compact .modal-label {
            margin-bottom: 0.3rem;
            font-size: 0.78rem;
            text-transform: uppercase;
            letter-spacing: 0.03em;
        }
        .modal-content.modal-compact .input-field,
        .modal-content.modal-compact .select-field {
            padding: 0.55rem 0.65rem;
            font-size: 0.95rem;
            border-radius: 0.55rem;
        }
        /* Date/time/number inputs: stop white text på mørk baggrund i Chrome */
        .modal-content.modal-compact input[type="date"]::-webkit-calendar-picker-indicator,
        .modal-content.modal-compact input[type="time"]::-webkit-calendar-picker-indicator {
            filter: invert(0.85);
            cursor: pointer;
        }
        .modal-content.modal-compact .save-btn,
        .modal-content.modal-compact .delete-btn {
            padding: 0.7rem;
            font-size: 0.95rem;
            margin-top: 0;
        }
        .modal-content.modal-compact .modal-hint-line {
            margin: -0.4rem 0 0.6rem 0.1rem;
        }
        /* Birthday-opts pakkes ind i en lille box så den ikke stjæler ekstra
           lodret plads når den er skjult. */
        .modal-content.modal-compact .bday-opts-box {
            margin-bottom: 0.75rem;
            padding: 0.6rem 0.8rem;
            background: var(--bg-color);
            border-radius: 0.6rem;
            border: 1px solid var(--border-color);
        }

        /* GRID UTILITY — placerer felter side om side.
           grid-template-columns sættes pr. variant. gap er tight (0.6rem)
           så modal forbliver kompakt. På meget smalle skærme (≤480px)
           kollapser vi tilbage til 1 kolonne for at undgå crampede inputs. */
        .modal-row-grid {
            display: grid;
            gap: 0.6rem;
            margin-bottom: 0.75rem;
        }
        .modal-row-grid .modal-row { margin-bottom: 0; }
        .modal-row-grid-2 { grid-template-columns: 1fr 1fr; }
        .modal-row-grid-3 { grid-template-columns: 1fr 1fr 1fr; }
        @media (max-width: 480px) {
            .modal-row-grid-2,
            .modal-row-grid-3 { grid-template-columns: 1fr; }
        }

        /* Handlings-knapper i bunden — Gem + Annuller side om side så vi
           sparer en hel række højde. Edit-modalen bruger samme klasse men
           med .modal-actions-edit-modifier for at vise [Gem | 🗑️ Slet]. */
        .modal-actions {
            display: grid;
            grid-template-columns: 2fr 1fr;
            gap: 0.6rem;
            margin-top: 0.75rem;
        }
        .modal-actions-edit { grid-template-columns: 2fr 1fr; }

        /* ────────────────────────────────────────────────────────────────
           V21.14: PERSON-CHIPS (multi-select)
           ────────────────────────────────────────────────────────────────
           Befolket dynamisk af populatePersonChips() i app.js. Hver chip
           viser et farvet dot (medlemmets color_hex) + display_name. Klik
           toggler .selected-tilstand. "Familien"-chip vælger alle på én
           gang (XOR-logik: hvis alle valgt, så afvælg alle).
           CSS holder sig 100% data-drevet — farve læses fra
           --chip-color CSS-variablen som JS sætter inline pr. chip. */
        .person-chips {
            display: flex;
            flex-wrap: wrap;
            gap: 0.3rem;
            min-height: 2.4rem;
            padding: 0.35rem 0.4rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.55rem;
            box-sizing: border-box;
            align-content: flex-start;
        }
        .person-chip {
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            padding: 0.2rem 0.55rem 0.2rem 0.4rem;
            border-radius: 999px;
            background: var(--card-bg);
            border: 1.5px solid var(--border-color);
            color: var(--text-muted);
            font-size: 0.78rem;
            font-weight: 500;
            cursor: pointer;
            user-select: none;
            transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
        }
        .person-chip:hover {
            transform: translateY(-1px);
            color: var(--text-main);
        }
        .person-chip.selected {
            background: color-mix(in srgb, var(--chip-color) 22%, var(--card-bg));
            border-color: var(--chip-color);
            color: var(--text-main);
        }
        .person-chip-dot {
            width: 0.7rem;
            height: 0.7rem;
            border-radius: 50%;
            background: var(--chip-color, var(--text-muted));
            flex-shrink: 0;
            border: 1px solid rgba(255, 255, 255, 0.15);
        }
        /* "Familien"-chip har et ikon i stedet for en farve-dot, men respekterer
           samme valgt-tilstand. */
        .person-chip.person-chip-family .person-chip-dot {
            background: transparent;
            border: none;
            font-size: 0.85rem;
            line-height: 1;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .person-chip.person-chip-family.selected {
            background: color-mix(in srgb, var(--accent-blue) 22%, var(--card-bg));
            border-color: var(--accent-blue);
        }

        /* ────────────────────────────────────────────────────────────────
           V21.14: TELEFON-LINK på event-kortet (tap-to-call)
           ────────────────────────────────────────────────────────────────
           Renderet af renderInbox() når ev.phone er sat. Genbruger samme
           visuelle sprog som .event-card-sted (sted-link). */
        .event-card .event-card-phone {
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            font-size: 0.78rem;
            line-height: 1.25;
            color: var(--accent-blue);
            text-decoration: none;
            padding: 0.15rem 0.4rem 0.15rem 0.25rem;
            margin-left: -0.25rem;
            border-radius: 0.45rem;
            align-self: flex-start;
            max-width: 100%;
            position: relative;
            z-index: 1;
            transition: background-color 0.15s ease, color 0.15s ease;
            word-break: break-all;
        }
        .event-card .event-card-phone:hover,
        .event-card .event-card-phone:focus-visible {
            background: rgba(41, 121, 255, 0.12);
            color: var(--color-family);
            outline: none;
            text-decoration: underline;
        }
        .event-card .event-card-phone-icon {
            font-size: 0.9rem;
            line-height: 1;
            flex-shrink: 0;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.16: VIEW EVENT MODAL — "Locked View"
           ────────────────────────────────────────────────────────────────
           Read-only præsentations-modal der åbnes når brugeren klikker et
           event-kort. Designet som rolig info-display (info-rows i 2-kol
           grid: label til venstre, value til højre) — IKKE en form. Den
           store "Rediger"-knap nederst er den eneste vej til redigering;
           dermed kan brugeren ikke utilsigtet ændre data ved et fejl-tap.
           
           Layout-principper:
             • Header med stor titel + type-ikon
             • Hver info-row: label (bold, muted) + value (større, læselig)
             • Klikbare links (Pin/Phone) bevarer event.stopPropagation
               så de fungerer uden at lukke modalen
             • Footer med "Rediger" (primary, stor) + "Luk" (sekundær) */
        .view-event-modal {
            padding: 1.5rem 1.75rem;
            max-width: 32rem;
            /* V21.17: position:relative giver share-knappen et stabilt
               positioneringsanker så den absolut-positionerede top-right
               placering altid er ift. selve modal-kortet (ikke nærmeste
               flex-parent som ellers ville være .modal-overlay = hele
               viewporten). */
            position: relative;
        }
        .view-event-header {
            display: flex;
            align-items: center;
            gap: 0.75rem;
            margin-bottom: 1.25rem;
            padding-bottom: 1rem;
            /* V21.17/V21.18/V21.19: ekstra padding-right reserverer plads
               så header-titlen ikke kan kollidere med share-knappens
               hit-area. V21.19 bumper SVG'en til 72px og container til
               4.8rem (= ~76.8px), uden cirkel-bg men stadig hit-area.
               Reservation: 4.8rem + 0.85rem right-offset + ~0.4rem buffer. */
            padding-right: 6rem;
            border-bottom: 1px solid var(--border-color);
        }
        /* V21.17: SHAR'ORTA-knap (Aorta Share Protocol).
           ────────────────────────────────────────────────────────────────
           Sidder absolut top-right af modalens kort så den er konsistent
           tilgængelig uanset hvor lang titlen er. Pure SVG-glyph (24px) i
           en let baggrundscirkel der "lifter" på hover så det føles som
           en native dele-handling. cursor:pointer + transition for smooth
           tap-feedback på touch-devices. */
        /* V21.18/V21.19: SHAR'ORTA-knap — RAMME-FRI, FRITSTÅENDE GLYPH.
           ────────────────────────────────────────────────────────────────
           V21.18 puttede ikonet i en mørk cirkel-cap så det fik visuel
           tyngde. Det viste sig at konkurrere med selve Shar'orta-mærkets
           identitet (logoet er DESIGNET til at stå frit). V21.19 stripper
           derfor ALT chrome:
             • background-cirkel    → transparent
             • border               → 0
             • box-shadow           → none
             • hover box-shadow     → erstattet af opacity+scale-feedback
           Selve SVG'en bumpes 48 → 72px (+50%) så den "fylder" pladsen
           hvor cirklen før sad. Hit-area-zonen bevares dog ≥48×48px via
           container-størrelsen så fingeren stadig har et komfortabelt
           target på touch-screens. */
        .view-event-share-btn {
            position: absolute;
            top: 0.85rem;
            right: 0.85rem;
            width: 4.8rem;
            height: 4.8rem;
            padding: 0;
            border: 0;
            background: transparent;
            border-radius: 0;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            box-shadow: none;
            transition: transform 0.12s ease, opacity 0.12s ease;
            z-index: 5;
            opacity: 0.95;
        }
        .view-event-share-btn:hover,
        .view-event-share-btn:focus-visible {
            transform: scale(1.08);
            opacity: 1;
            background: transparent;
            box-shadow: none;
            outline: none;
        }
        .view-event-share-btn:active {
            transform: scale(0.96);
        }
        .view-event-share-btn img {
            width: 72px;
            height: 72px;
            object-fit: contain;
            background: transparent;
            border: 0;
            pointer-events: none;
            user-select: none;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.23: AORTA SELECT — GENERIC CUSTOM DROPDOWN FRAMEWORK
           ────────────────────────────────────────────────────────────────
           Erstatter ALLE native <select>-elementer i appen (Type, Person,
           Recurrence, Sprog, Danger Zone child/adult-pickers) med en
           konsistent custom dropdown der respekterer Aortas designsprog:
           
             • dark-theme palette (var(--card-bg), var(--border-color))
             • SVG-ikoner ved siden af labels (især event-type ikoner)
             • farvede CSS-prikker (.aorta-select-dot) for kategoriske
               valg så brugeren får øjeblikkelig visuel orientering
             • smooth fade-in animation der matcher Shar'orta-menuen
             • fuld keyboard a11y (role=listbox/option, aria-expanded,
               Esc lukker, Tab forlader)
           
           STRUKTUR (genereret af inline HTML eller buildAortaSelect()
           helper i app.js):
           
             <div class="aorta-select-container" data-aorta-select>
               <input type="hidden" name="..." id="..." value="...">
               <button type="button" class="aorta-select-trigger"
                       aria-haspopup="listbox" aria-expanded="false">
                 <span class="aorta-select-trigger-icon">…</span>
                 <span class="aorta-select-trigger-label">…</span>
                 <span class="aorta-select-trigger-chevron">▾</span>
               </button>
               <div class="aorta-select-menu" role="listbox" hidden>
                 <button type="button" class="aorta-select-option"
                         role="option" data-value="…">
                   <span class="aorta-select-dot" style="--dot-color:#…"></span>
                   <span class="aorta-select-option-icon">…</span>
                   <span class="aorta-select-option-label">…</span>
                 </button>
                 …
               </div>
             </div>
           
           DESIGN-NOTER:
             • Container bruger position:relative så menuen kan absolut-
               positioneres lige under triggeren uanset hvor i layoutet
               dropdownen sidder. Det er anderledes end Shar'orta-menuen
               der bruger fast top/right-koordinater (specifikt designet
               til ét sted i view-event-modalen).
             • Triggeren har samme padding/font som .input-field så
               formularen visuelt flyder lige uden at "et felt skiller
               sig ud". Vi læner op ad eksisterende .select-field-styling.
             • Menuen z-indexes 1000 så den lægger sig OVER alt andet i
               modalen — også over save/delete-knapperne i bunden hvis
               brugeren scroller eller dropdownen er bunden af formen.
             • .aorta-select-dot bruger CSS custom property --dot-color
               så vi kan passe farven via inline style="--dot-color:#abc"
               uden at generere unik CSS pr. profil/type. Width/height
               settet på dot'en er rund 0.7rem så den matcher
               person-chip-dot-størrelsen for visuel konsistens.
           ──────────────────────────────────────────────────────────────── */
        .aorta-select-container {
            position: relative;
            display: block;
            width: 100%;
            box-sizing: border-box;
        }
        .aorta-select-trigger {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            width: 100%;
            padding: 0.55rem 0.75rem;
            background: var(--bg-color);
            color: var(--text-color);
            border: 1px solid var(--border-color);
            border-radius: 0.55rem;
            font-size: 0.95rem;
            font-family: inherit;
            text-align: left;
            cursor: pointer;
            box-sizing: border-box;
            transition: border-color 0.12s ease, background 0.12s ease;
        }
        .aorta-select-trigger:hover,
        .aorta-select-trigger:focus-visible {
            border-color: var(--accent-color, #5b8def);
            outline: none;
        }
        .aorta-select-trigger[aria-expanded="true"] {
            border-color: var(--accent-color, #5b8def);
            background: rgba(255, 255, 255, 0.03);
        }
        /* V21.23 [Commit 4]: disabled-state — bruges når dropdownen er
           tom (fx Danger Zone uden børn i husstanden). Cursor not-allowed
           + reduceret opacity + chevron-fade matcher native <select disabled>'s
           visuelle adfærd så brugeren intuitivt forstår at knappen ikke
           kan klikkes. pointer-events: none stopper også keyboard-fokus
           på Tab så vi ikke har "døde" tab-stops. */
        .aorta-select-trigger[disabled],
        .aorta-select-trigger[aria-disabled="true"] {
            opacity: 0.55;
            cursor: not-allowed;
            pointer-events: none;
        }
        .aorta-select-trigger[disabled] .aorta-select-trigger-chevron,
        .aorta-select-trigger[aria-disabled="true"] .aorta-select-trigger-chevron {
            opacity: 0.3;
        }
        .aorta-select-trigger-icon {
            flex: 0 0 auto;
            width: 1.2rem;
            height: 1.2rem;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }
        .aorta-select-trigger-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
            background: transparent;
            border: 0;
            pointer-events: none;
        }
        .aorta-select-trigger-icon:empty {
            display: none;
        }
        .aorta-select-trigger-label {
            flex: 1 1 auto;
            line-height: 1.2;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .aorta-select-trigger-chevron {
            flex: 0 0 auto;
            font-size: 0.9rem;
            opacity: 0.65;
            transition: transform 0.18s ease, opacity 0.12s ease;
        }
        .aorta-select-trigger[aria-expanded="true"] .aorta-select-trigger-chevron {
            transform: rotate(180deg);
            opacity: 1;
        }
        /* Selve menu-popoveren. Placeret lige under triggeren via top:100%.
           min-width 100% sikrer at menuen er mindst lige så bred som
           triggeren — den kan være bredere hvis labels er lange (overflow
           horisontalt absolut, så den vokser højre-ud uden at presse layout). */
        .aorta-select-menu {
            position: absolute;
            top: calc(100% + 0.3rem);
            left: 0;
            right: 0;
            min-width: 100%;
            /* V21.24: Ingen intern scrollbar i dropdown-menuerne. Menuen
               vokser til den højde, dens indhold kræver. Hvis den nederste
               kant af menuen ville rage ud over modalens kant, sørger
               .modal-overlay's overflow-y: auto + .modal-content's
               overflow: visible (begge sat længere oppe) for at hele
               modalen kan scrolle i overlay-laget i stedet — så menuen
               aldrig bliver klippet visuelt.

               z-index: 9999 sikrer at menuen svæver over ALT andet
               (modal-headers, knapper, view-event-modal-share-knappen,
               etc.) selv på tværs af stacking-context-grænser i moderne
               browsere. Tidligere 1000 var nok internt i .modal-content
               men ikke nødvendigvis nok når menuen overlapper med ydre
               UI-elementer der har deres egne højere z-index. */
            max-height: none;
            overflow: visible;
            padding: 0.4rem;
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 0.85rem;
            box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35);
            z-index: 9999;
            animation: aortaSelectMenuIn 120ms ease-out;
            transform-origin: top center;
        }
        .aorta-select-menu[hidden] {
            display: none;
        }
        @keyframes aortaSelectMenuIn {
            from { opacity: 0; transform: translateY(-4px) scale(0.98); }
            to   { opacity: 1; transform: translateY(0) scale(1); }
        }
        .aorta-select-option {
            display: flex;
            align-items: center;
            gap: 0.65rem;
            width: 100%;
            padding: 0.6rem 0.7rem;
            background: transparent;
            border: 0;
            border-radius: 0.55rem;
            color: var(--text-color);
            font-size: 0.95rem;
            font-weight: 500;
            font-family: inherit;
            text-align: left;
            cursor: pointer;
            transition: background 0.1s ease, transform 0.06s ease;
        }
        .aorta-select-option + .aorta-select-option {
            margin-top: 0.1rem;
        }
        .aorta-select-option:hover,
        .aorta-select-option:focus-visible {
            background: rgba(255, 255, 255, 0.06);
            outline: none;
        }
        .aorta-select-option:active {
            transform: scale(0.98);
            background: rgba(255, 255, 255, 0.10);
        }
        .aorta-select-option[aria-selected="true"] {
            background: rgba(91, 141, 239, 0.12);
            font-weight: 600;
        }
        .aorta-select-option[aria-selected="true"]::after {
            content: '✓';
            margin-left: auto;
            color: var(--accent-color, #5b8def);
            font-weight: 700;
            font-size: 0.95rem;
        }
        .aorta-select-option[disabled],
        .aorta-select-option[aria-disabled="true"] {
            opacity: 0.45;
            cursor: not-allowed;
        }
        /* Farvet rund prik — bruges til Type-options (matcher tag-XXX
           farver fra event-cards) og Person-options (matcher member.color_hex).
           --dot-color sættes inline pr. option så vi undgår at generere
           unik CSS pr. profil. */
        .aorta-select-dot {
            flex: 0 0 auto;
            width: 0.75rem;
            height: 0.75rem;
            border-radius: 50%;
            background: var(--dot-color, #888);
            border: 1px solid rgba(255, 255, 255, 0.18);
            box-sizing: border-box;
        }
        /* SVG-ikon i selve option-rækken (bruges hvis option er semantisk
           et "type" med tilhørende ikon — fx Familie / Forældre med
           Family logo.svg). Holdes adskilt fra .aorta-select-dot så en
           option enten har ikon, prik eller begge. */
        .aorta-select-option-icon {
            flex: 0 0 auto;
            width: 1.4rem;
            height: 1.4rem;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }
        .aorta-select-option-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
            background: transparent;
            border: 0;
            pointer-events: none;
        }
        .aorta-select-option-icon:empty {
            display: none;
        }
        .aorta-select-option-label {
            flex: 1 1 auto;
            line-height: 1.2;
        }
        /* Når aorta-select bruges inden for .modal-compact (Add/Edit-modaler)
           skal triggeren matche compact .input-field-størrelsen så formularen
           ser ensartet ud. */
        .modal-content.modal-compact .aorta-select-trigger {
            padding: 0.55rem 0.65rem;
            font-size: 0.95rem;
            border-radius: 0.55rem;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.31: AORTA CONTEXT MENU — generic positioned-at-cursor menu
           ────────────────────────────────────────────────────────────────
           Lille DOM-node der spawnes ved cursor-position når brugeren skal
           træffe et hurtigt valg uden at åbne en hel modal. Første
           anvendelse er smart drop af multi-day events (Ferie):
           "Flyt hele perioden" vs "Juster kun startdato". Designet er
           bevidst lavt-bygget så den kan genbruges af fremtidige right-
           click/long-press-flows uden refactor.

           Designsproget følger .aorta-select-menu (samme card-bg, border,
           shadow, padding, hover-tint) så brugeren intuitivt forstår at
           det ER en menu — bare en der svæver fri af form-feltet.

           Position: fixed (ikke absolute) så cursor-koordinaterne
           direkte mapper til viewport. JS sørger for at clamp'e position
           hvis menuen ville falde uden for skærmens kanter.

           z-index: 99999 ligger over modaler (9999), aorta-select-menu
           (deres egen 9999) og alt andet — context-menuen er ALTID på
           top fordi den er en modal interaktion brugeren startede.
           ──────────────────────────────────────────────────────────── */
        .aorta-context-menu {
            position: fixed;
            min-width: 13rem;
            max-width: 22rem;
            background: var(--card-bg);
            color: var(--text-main);
            border: 1px solid var(--border-color);
            border-radius: 0.7rem;
            box-shadow: 0 12px 32px rgba(0,0,0,0.35), 0 2px 6px rgba(0,0,0,0.18);
            padding: 0.4rem;
            z-index: 99999;
            font-family: 'Inter', system-ui, sans-serif;
            opacity: 0;
            transform: scale(0.96) translateY(-4px);
            transform-origin: top left;
            transition: opacity 120ms ease, transform 120ms ease;
            pointer-events: none;
        }
        .aorta-context-menu.is-visible {
            opacity: 1;
            transform: scale(1) translateY(0);
            pointer-events: auto;
        }
        .aorta-context-menu-header {
            font-size: 0.78rem;
            font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.04em;
            padding: 0.35rem 0.6rem 0.45rem 0.6rem;
            border-bottom: 1px solid var(--border-color);
            margin-bottom: 0.3rem;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .aorta-context-menu-option {
            display: flex;
            align-items: flex-start;
            gap: 0.6rem;
            width: 100%;
            padding: 0.55rem 0.65rem;
            background: transparent;
            color: var(--text-main);
            border: 0;
            border-radius: 0.5rem;
            font: inherit;
            font-size: 0.92rem;
            cursor: pointer;
            text-align: left;
            transition: background 120ms ease;
        }
        .aorta-context-menu-option + .aorta-context-menu-option {
            margin-top: 0.1rem;
        }
        .aorta-context-menu-option:hover,
        .aorta-context-menu-option:focus-visible {
            background: rgba(41, 121, 255, 0.10);
            outline: none;
        }
        .aorta-context-menu-option-icon {
            flex: 0 0 auto;
            font-size: 1.1rem;
            line-height: 1.2;
            width: 1.2rem;
            text-align: center;
            color: var(--accent-blue);
        }
        .aorta-context-menu-option-text {
            flex: 1 1 auto;
            display: flex;
            flex-direction: column;
            gap: 0.15rem;
            min-width: 0;
        }
        .aorta-context-menu-option-label {
            font-weight: 600;
            line-height: 1.2;
        }
        .aorta-context-menu-option-sub {
            font-size: 0.78rem;
            color: var(--text-muted);
            line-height: 1.25;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.25: AORTA SEGMENT — chip-segment-control (radio-style)
           ────────────────────────────────────────────────────────────────
           Visuel selector hvor alle muligheder vises som tappable chips i
           stedet for at gemmes bag en dropdown. Bruges først af
           "Tilbagevendende"-feltet i Add/Edit Event-modalen, hvor den 7-
           options-lange dropdown førhen flød ud over bunden af viewporten.

           Designet matcher .aorta-select-trigger så formular-elementer i
           samme modal har konsistent visuelt sprog: transparent baggrund,
           subtil border, samme border-radius og dark-theme-farver. Den
           valgte chip får accent-farvet border + svag accent-baggrund, og
           ikke-valgte chips bevarer den neutrale border-color.

           Layout: flex-wrap så chips automatisk bryder ned på smalle
           skærme. Med 7 chips ender vi typisk på 4+3 eller 3+4 på mobile
           viewport (≤ 480px) og på én enkelt række på desktop (≥ 600px
           modal-bredde). flex: 1 1 auto sikrer at chips fylder rækken
           jævnt — så vi ikke ender med en sidste chip der hænger
           ubalanceret af sig selv.

           Touch-target: min-height 2.6rem (~42px) ligger over Apple/Google
           HIG-anbefalingen på 44pt på touch-enheder, og chips har
           tilstrækkelig padding til at fingerspidser ikke kommer mellem
           to chips. */
        .aorta-segment {
            display: flex;
            flex-wrap: wrap;
            gap: 0.4rem;
            width: 100%;
            box-sizing: border-box;
        }
        /* V21.30 — KONTRAST-FIX
           ─────────────────────────────────────────────────────────────
           Tidligere brugte chippen ikke-eksisterende CSS-variabler
           (`--text-color`, `--accent-color`) som faldt tilbage til
           hardcodede fallback-farver (#e0e0e0 lysegrå tekst,
           #29b6f6 lyseblå accent). På dark theme var det ok, men på
           light theme blev den lysegrå tekst nærmest usynlig på den
           hvide/cremede kort-baggrund — og den hvide tekst på den
           lyse accent-tonede selected-baggrund var lige så svær at
           læse.
           
           Fixet bytter alle fallback-farver ud med ÆGTE tema-tokens
           der findes i :root og [data-theme="light"]:
             • `--text-main`   — automatisk hvid på dark, sort på light
             • `--accent-blue` — codebase-defineret accent (#2979ff)
                                som matcher .option-btn.selected,
                                FAB'erne og det øvrige interaktive
                                visuelle sprog i appen.
           
           Resultat: chippen har stærk kontrast på BEGGE temaer og på
           tværs af alle Ambient Pastel-tints (sage/sky/sand/rose/
           yellow). Tap-affordansen er nu professionel og indbydende
           uden at "skrige" — premium SaaS UI-DNA bevaret. */
        .aorta-segment-chip {
            flex: 1 1 auto;
            min-width: 4.5rem;
            min-height: 2.6rem;
            padding: 0.45rem 0.7rem;
            background: transparent;
            /* V21.30: --text-main giver ægte tema-adaptiv kontrast
               (hvid på dark, sort på light) — samme tekstfarve som
               .option-btn og .input-field bruger andre steder, så
               chips læses som ægte interaktive form-controls (ikke
               passive labels). */
            color: var(--text-main);
            border: 1px solid var(--border-color);
            border-radius: 0.55rem;
            font-size: 0.92rem;
            font-weight: 500;
            font-family: inherit;
            line-height: 1.15;
            cursor: pointer;
            text-align: center;
            box-sizing: border-box;
            transition: border-color 120ms ease, background-color 120ms ease, color 120ms ease;
            -webkit-tap-highlight-color: transparent;
        }
        .aorta-segment-chip:hover {
            /* V21.30: --accent-blue (#2979ff) er den kanoniske accent
               i codebasen. Hover-tinten bruger samme RGB med 10% alpha
               så hover-feedback er synlig uden at konkurrere med den
               fully-saturated selected-state. */
            border-color: var(--accent-blue);
            background: rgba(41, 121, 255, 0.10);
            color: var(--text-main);
        }
        .aorta-segment-chip:focus-visible {
            outline: 2px solid var(--accent-blue);
            outline-offset: 1px;
        }
        /* Selected state: accent-farvet border + medium accent-tinted baggrund.
           Vi bruger BÅDE .is-selected og [aria-checked="true"] som selectors
           så styling forbliver synkroniseret med a11y-state — ingen risiko
           for visuel desync.

           V21.30: Tekst skiftet fra #ffffff til var(--text-main). På dark
           theme er det stadig hvid tekst på lyseblå tint (samme look som
           før). På light theme bliver det sort tekst på lyseblå tint —
           HØJ kontrast hvor det før var næsten ulæselig hvid-på-lys.
           Background-tinten bumpet 0.18 → 0.22 og bordens accent skiftet
           fra det non-eksisterende --accent-color (faldback #29b6f6) til
           --accent-blue (#2979ff) så selected-state står klart frem og
           matcher resten af appens accent-system. */
        .aorta-segment-chip.is-selected,
        .aorta-segment-chip[aria-checked="true"] {
            border-color: var(--accent-blue);
            background: rgba(41, 121, 255, 0.22);
            color: var(--text-main);
            font-weight: 600;
            box-shadow: 0 0 0 1px var(--accent-blue) inset;
        }
        .aorta-segment-chip.is-selected:hover,
        .aorta-segment-chip[aria-checked="true"]:hover {
            /* Hover oven på selected = en anelse stærkere fyld så det
               stadig føles "live" når musen er over den valgte chip. */
            background: rgba(41, 121, 255, 0.28);
        }
        .aorta-segment-chip[disabled],
        .aorta-segment-chip[aria-disabled="true"] {
            opacity: 0.5;
            cursor: not-allowed;
            pointer-events: none;
        }
        /* Inden for .modal-compact: lidt strammere padding så chip-rækken
           harmonerer visuelt med de øvrige felter (date/time/duration osv.)
           der allerede er compact-stylet. */
        .modal-content.modal-compact .aorta-segment {
            gap: 0.35rem;
        }
        .modal-content.modal-compact .aorta-segment-chip {
            padding: 0.4rem 0.55rem;
            font-size: 0.88rem;
            min-height: 2.4rem;
            border-radius: 0.5rem;
        }
        /* Mobile: 7 chips kan ikke pænt bo på én række på smalle skærme
           — sørg for at chip-bredde tilpasses så vi får 3-4 pr. række
           uden voldsomme tekstombrydninger. */
        @media (max-width: 480px) {
            .aorta-segment-chip {
                flex: 1 1 calc(33.333% - 0.4rem);
                min-width: 0;
                font-size: 0.85rem;
                padding: 0.45rem 0.4rem;
            }
            .modal-content.modal-compact .aorta-segment-chip {
                font-size: 0.82rem;
                padding: 0.4rem 0.35rem;
            }
        }

        /* ────────────────────────────────────────────────────────────────
           V21.22: SHAR'ORTA DROPDOWN MENU (#sharortaDropdown)
           ────────────────────────────────────────────────────────────────
           Custom dropdown der åbner under Shar'orta-knappen i view-event-
           modalens header. Vi bygger det HELT manuelt (i stedet for at
           bruge native <select> eller <dialog>) fordi:
             • Ingen browser leverer en native dropdown der visuelt matcher
               Aortas dark-theme uden ekstrem CSS-hacking
             • Vi har brug for egen tap-feedback på touch (scale + bg-flash)
             • Item-row layoutet kombinerer ikon + label på en måde
               native UI-controls ikke understøtter
           
           DESIGN-DECISIONS:
             • position: absolute relativt til .view-event-modal (parent
               har position:relative). Top/right matcher botten af share-
               knappen (top: ~6.5rem) så dropdown'en "hænger" lige under.
             • Skjult som default via display:none — vi toggler en
               .is-open-modifier-klasse fra JS i stedet for at sætte
               style.display direkte (mere CSS-idiomatisk og åbner for
               fremtidige animationer via @keyframes).
             • z-index over modal-content (z=10) men under modal-overlay-
               click-catcher (overlay sidder bag content) så outside-click
               stadig kan ramme overlay'en.
             • min-width 16rem giver konsistent visuel vægt uanset
               item-tekst-længde (i18n: dansk vs. engelsk vs. tysk har
               vidt forskellig label-bredde).
             • Subtil border + shadow så menuen "lifter" over modal-
               kortet uden at konkurrere med selve modalens box-shadow.
           ──────────────────────────────────────────────────────────────── */
        .dropdown-content {
            display: none;
        }
        .dropdown-content.is-open {
            display: block;
        }
        .sharorta-dropdown {
            position: absolute;
            /* Share-knappen sidder top:0.85rem, height:4.8rem → bunden er
               ~5.65rem. Vi giver ekstra 0.4rem luft så menuen ikke klistrer
               til knappen. Right-koordinaten matches så menuens højre kant
               flugter med knappens højre kant (visuelt anker). */
            top: 6.05rem;
            right: 0.85rem;
            min-width: 16rem;
            max-width: calc(100vw - 4rem);
            padding: 0.4rem;
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 0.85rem;
            box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35);
            z-index: 10;
            /* Kort fade-in når .is-open tilføjes — føles som en native menu. */
            animation: sharortaDropdownIn 120ms ease-out;
            transform-origin: top right;
        }
        @keyframes sharortaDropdownIn {
            from { opacity: 0; transform: translateY(-4px) scale(0.98); }
            to   { opacity: 1; transform: translateY(0) scale(1); }
        }
        .sharorta-dropdown-item {
            display: flex;
            align-items: center;
            gap: 0.65rem;
            width: 100%;
            padding: 0.65rem 0.75rem;
            background: transparent;
            border: 0;
            border-radius: 0.55rem;
            color: var(--text-color);
            font-size: 0.95rem;
            font-weight: 500;
            text-align: left;
            cursor: pointer;
            transition: background 0.12s ease, transform 0.06s ease;
        }
        .sharorta-dropdown-item + .sharorta-dropdown-item {
            margin-top: 0.15rem;
        }
        .sharorta-dropdown-item:hover,
        .sharorta-dropdown-item:focus-visible {
            background: rgba(255, 255, 255, 0.06);
            outline: none;
        }
        .sharorta-dropdown-item:active {
            transform: scale(0.98);
            background: rgba(255, 255, 255, 0.10);
        }
        .sharorta-dropdown-item-icon {
            flex: 0 0 auto;
            width: 1.6rem;
            height: 1.6rem;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }
        .sharorta-dropdown-item-icon img {
            width: 100%;
            height: 100%;
            object-fit: contain;
            display: block;
            background: transparent;
            border: 0;
            pointer-events: none;
        }
        .sharorta-dropdown-item-label {
            flex: 1 1 auto;
            line-height: 1.2;
        }
        @media (max-width: 480px) {
            .sharorta-dropdown {
                /* På mobile: brug fuld bredde med små marginer så menuen
                   ikke "stikker ud" af modalen ved smal viewport. */
                top: 5.4rem;
                right: 0.6rem;
                min-width: 12rem;
            }
            .sharorta-dropdown-item {
                padding: 0.7rem 0.7rem;
                font-size: 1rem;
            }
        }

        /* ────────────────────────────────────────────────────────────────
           V21.18: SHAR'ORTA FALLBACK SHARE MENU (#shareFallbackModal)
           ────────────────────────────────────────────────────────────────
           Vist når navigator.share() ikke er tilgængelig (= ikke-mobile
           browsere typisk). Tre store, klart adskilte action-buttons så
           brugeren kan vælge sin foretrukne dele-kanal uden cognitiv
           overhead. Hver knap har TITLE + SUB-tekst så den kommunikerer
           både handling og forventet resultat.
           Layout-pattern: identisk modal-overlay + modal-content som de
           øvrige modaler i appen, så ingen overraskelser i interaktions-
           mønsteret (click-outside lukker, Esc lukker, etc). */
        .share-fallback-modal {
            max-width: 28rem;
            padding: 1.5rem 1.5rem 1.25rem;
        }
        .share-fallback-sub {
            margin: 0 0 1rem;
            color: var(--text-muted);
            font-size: 0.9rem;
            font-style: italic;
            text-align: center;
        }
        .share-fallback-options {
            display: flex;
            flex-direction: column;
            gap: 0.6rem;
            margin-bottom: 1rem;
        }
        .share-fallback-btn {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: 0.2rem;
            padding: 0.85rem 1rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            cursor: pointer;
            text-align: left;
            color: var(--text-main);
            transition: background-color 0.12s ease, border-color 0.12s ease,
                        transform 0.06s ease;
            font-family: inherit;
        }
        .share-fallback-btn:hover,
        .share-fallback-btn:focus-visible {
            background: var(--card-bg);
            border-color: var(--accent-blue);
            outline: none;
        }
        .share-fallback-btn:active {
            transform: scale(0.98);
        }
        /* Primær-action (Aorta Smart Link) får accent-blå venstre-bar
           så den signaleres som anbefalet/standard valg uden at de øvrige
           options gemmes væk. */
        .share-fallback-btn-primary {
            border-left: 4px solid var(--accent-blue);
        }
        .share-fallback-btn-title {
            font-weight: 600;
            font-size: 1rem;
        }
        .share-fallback-btn-sub {
            font-size: 0.8rem;
            color: var(--text-muted);
            line-height: 1.3;
        }

        .view-event-title-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 2.5rem;
            height: 2.5rem;
            border-radius: 0.6rem;
            background: var(--bg-color);
            flex-shrink: 0;
        }
        .view-event-title-icon img {
            width: 1.6rem;
            height: 1.6rem;
            object-fit: contain;
        }
        .view-event-title {
            margin: 0;
            font-size: 1.35rem;
            font-weight: 700;
            color: var(--text-main);
            line-height: 1.25;
            word-break: break-word;
        }
        .view-event-row {
            display: grid;
            grid-template-columns: 7.5rem 1fr;
            gap: 0.75rem;
            padding: 0.6rem 0;
            border-bottom: 1px solid color-mix(in srgb, var(--border-color) 50%, transparent);
            align-items: start;
        }
        .view-event-row:last-of-type {
            border-bottom: none;
        }
        .view-event-row-label {
            font-size: 0.78rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            color: var(--text-muted);
            padding-top: 0.15rem;
        }
        .view-event-row-value {
            font-size: 0.95rem;
            color: var(--text-main);
            line-height: 1.4;
            word-break: break-word;
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 0.4rem;
        }
        .view-event-row-value.view-event-note {
            display: block;
            white-space: pre-wrap;
        }
        /* Klikbare links inden i modalen — Pin (sted) + Phone (telefon).
           Genbruger samme blå accent som event-card-sted/-phone så det
           visuelle sprog er konsistent på tværs af inbox-kort og denne modal. */
        .view-event-row-value a {
            color: var(--accent-blue);
            text-decoration: none;
            display: inline-flex;
            align-items: center;
            gap: 0.4rem;
            padding: 0.2rem 0.5rem;
            border-radius: 0.45rem;
            transition: background-color 0.15s ease, color 0.15s ease;
        }
        .view-event-row-value a:hover,
        .view-event-row-value a:focus-visible {
            background: rgba(41, 121, 255, 0.12);
            color: var(--color-family);
            text-decoration: underline;
            outline: none;
        }
        /* Person-chips i view modal — small color-dot + navn (ikke klikbar). */
        .view-event-persons {
            gap: 0.5rem;
        }
        .view-event-person-chip {
            display: inline-flex;
            align-items: center;
            gap: 0.4rem;
            padding: 0.25rem 0.6rem;
            border-radius: 1rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            font-size: 0.85rem;
            color: var(--text-main);
        }
        .view-event-person-chip-dot {
            width: 0.6rem;
            height: 0.6rem;
            border-radius: 50%;
            background: var(--chip-color, #888);
            box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
            flex-shrink: 0;
        }
        /* Status-badges (Gave/Kørsel) — grøn=afklaret, rød=mangler. */
        .view-event-tasks {
            gap: 0.5rem;
            flex-wrap: wrap;
        }
        .view-event-task-badge {
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            padding: 0.25rem 0.6rem;
            border-radius: 0.5rem;
            font-size: 0.8rem;
            font-weight: 600;
        }
        .view-event-task-badge.task-open {
            background: rgba(229, 57, 53, 0.15);
            color: #c62828;
            border: 1px solid rgba(229, 57, 53, 0.3);
        }
        .view-event-task-badge.task-resolved {
            background: rgba(67, 160, 71, 0.15);
            color: #2e7d32;
            border: 1px solid rgba(67, 160, 71, 0.3);
        }
        .view-event-actions {
            margin-top: 1.5rem;
            padding-top: 1rem;
            border-top: 1px solid var(--border-color);
        }
        /* Stor primær Rediger-knap — visuelt fremhævet for at gøre det
           tydeligt at det er den eneste vej til redigering fra denne
           read-only præsentation. */
        .view-event-edit-btn {
            font-size: 1rem;
            padding: 0.85rem 1rem;
            font-weight: 700;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.16: MONTH VIEW DOT-INDIKATORER på cal-event-bar
           ────────────────────────────────────────────────────────────────
           4-ugers månedsvisningen er meget kompakt — der er ikke plads til
           SVG-ikoner i selve event-baren uden at trykke titel-teksten ud.
           I stedet viser vi små farve-prikker i barens højre kant:
             • rød  = Sted findes
             • grøn = Telefonnummer findes
           Brugeren ser straks at der er ekstra info uden at zooming. Klik
           på baren åbner viewEventModal hvor de fulde data fremgår med
           klikbare links. */
        .cal-event-bar {
            position: relative;
        }
        .cal-event-bar .cal-bar-dots {
            position: absolute;
            top: 50%;
            right: 0.25rem;
            transform: translateY(-50%);
            display: inline-flex;
            gap: 0.15rem;
            pointer-events: none;
        }
        .cal-event-bar .cal-bar-dots .dot {
            width: 0.4rem;
            height: 0.4rem;
            border-radius: 50%;
            display: inline-block;
            box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
        }
        .cal-event-bar .cal-bar-dots .dot-red   { background: #e53935; }
        .cal-event-bar .cal-bar-dots .dot-green { background: #43a047; }

        /* ────────────────────────────────────────────────────────────────
           V21.16: 3-DAGES STRIP TOP-CARDS — SVG-ikoner (Pin + Phone)
           ────────────────────────────────────────────────────────────────
           Top-kortene i 3-dages striben er større end month-bars og har
           plads til klikbare SVG-links. Vi viser:
             • Pin-rød   hvis Sted er en ægte adresse (geo:-link)
             • Phone-grøn hvis Telefon findes (tel:-link)
           Layout: lille footer-row UNDER titlen så ikoner ikke krasher
           med dots-positioning eller titel-tekst. */
        /* V21.19: TOP-CARD ACTIONS — ABSOLUT TOP-RIGHT.
           ────────────────────────────────────────────────────────────────
           V21.18 placerede actions som en footer-row UNDER titlen i kortets
           normal-flow. Det stjal vertikal plads og fik kortets layout til
           at vippe alt efter om der var actions eller ej. V21.19 flytter
           dem til top-right hjørnet med absolute-positioning så:
             • Titlen får ALTID hele kortets bredde til disposition
             • Ikon-rækken bliver konsistent placeret på tværs af alle kort
             • Den nye flex:1 1 0-kort-distribution (jf. V21.19 ovenfor)
               påvirkes ikke af variabel content-højde
           gap: 0.4rem mellem pin og phone bevarer side-om-side layoutet
           som tidligere. flex-wrap forhindret bevidst — vi vil hellere
           lade ikonerne overflowe end at lade dem stable lodret. */
        .top-card-actions {
            position: absolute;
            top: 0.5rem;
            right: 0.5rem;
            display: inline-flex;
            gap: 0.4rem;
            align-items: center;
            z-index: 3;
            flex-wrap: nowrap;
        }
        /* V21.18/V21.19: PIN/PHONE-LINKS — RAMME-FRI, TRANSPARENT.
           ────────────────────────────────────────────────────────────────
           Ingen baggrund, ingen border, ingen box-shadow — ikonerne står
           HELT FRIT på kort-baggrunden. Hover-feedback er en lille scale
           + opacity-bump (ingen visuel ramme genindføres).
           Padding er reduceret (V21.18 0.15rem 0.25rem → V21.19 0.1rem)
           for at undgå at ikonerne dækker over titlen i top-right-hjørnet. */
        .top-card-action-link {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: auto;
            height: auto;
            padding: 0.1rem;
            background: transparent;
            border: 0;
            box-shadow: none;
            border-radius: 0;
            text-decoration: none;
            position: relative;
            z-index: 2;
            opacity: 0.95;
            transition: transform 0.1s ease, opacity 0.1s ease;
            vertical-align: middle;
        }
        .top-card-action-link:hover,
        .top-card-action-link:focus-visible {
            transform: scale(1.08);
            opacity: 1;
            outline: none;
            background: transparent;
            box-shadow: none;
        }
        .top-card-action-link img {
            /* V21.18: 12px → 18px (+50%). Phone-default = 18px.
               V21.19: Pin-specifik override længere nede gør pin'en
               yderligere 50% større (= 27px) så den dominerer som
               primær lokation-cue. */
            width: 18px;
            height: 18px;
            display: block;
            background: transparent;
            border: 0;
            pointer-events: none;
            vertical-align: middle;
        }
        /* V21.19/V21.21: PIN-SPECIFIK STYLING.
           ────────────────────────────────────────────────────────────────
           Pin'en på 3-dages-kortene er:
             • IKKE klikbar (rendret som <span>, ikke <a>) — passer til
               brugerens flow hvor de tap'er kortet for at åbne Locked View
               og DER kan vælge at åbne maps. Forhindrer fejl-tap når
               fingeren er på vej mod kort-baggrunden men rammer pin-ikonet.
             • V21.21: yderligere 50% større (27 → 40px) så den klart
               dominerer som "kortet har en lokation"-cue selv på små
               viewports/iPad-portrait. Dropper også til 18px på
               max-width: 480px så pin'en ikke æder mere end ~25%
               af kortets bredde på mobile screens.
             • Helt transparent baggrund + ingen border (eksplicit reset
               så browser-defaults eller arvede regler aldrig kan smitte
               igennem til selve SVG-billedet). */
        .top-card-action-pin {
            cursor: default;
            pointer-events: none;
            background: transparent;
            border: 0;
            box-shadow: none;
            padding: 0;
        }
        .top-card-action-pin img {
            width: 40px;
            height: 40px;
            background: transparent;
            border: 0;
            box-shadow: none;
        }
        @media (max-width: 480px) {
            .top-card-action-pin img {
                width: 28px;
                height: 28px;
            }
        }

        /* ────────────────────────────────────────────────────────────────
           V21.15: CUSTOM INLINE-IKONER (Pin, Phone, Calendar)
           ────────────────────────────────────────────────────────────────
           Erstatter Unicode-emoji 📍📞📅 med Aortas dedikerede SVG-aktiver
           (assets/icons/Pin-red, Phone green, Calendar). Vi bruger lille
           inline-størrelse (16px, vertical-align: middle) så de flugter
           med tekst-line-height inde i .event-card-sted/.event-card-phone/
           .event-card-date-pillerne. SVG-fil-pathene er case-sensitive
           på Linux (Cloud Run/static hosting), så vi bevarer den eksakte
           "Pin-red logo.svg"-skrivemåde gennem hele kodebasen.
           pointer-events:none sikrer at ikonet aldrig kaper klikket fra
           dets parent-link/-card (kritisk for at click-routing forbliver
           upåvirket af at vi indsætter ikonerne i innerHTML-strenge). */
        /* V21.18: PIN/PHONE/CALENDAR INLINE-IKONER — STØRRE & RAMME-FRI.
           ────────────────────────────────────────────────────────────────
           16px → 18px på base-størrelsen for bedre læselighed på tablets
           og bedre proportional vægt vs. den omkringliggende tekst. Vi
           tilføjer EKSPLICIT background:transparent + border:0 så
           parent-styling (eksempelvis hvis ikonet sidder i en pille med
           baggrund) ALDRIG kan smitte gennem til selve SVG-billedet.
           vertical-align:middle + display:inline-block + line-height:1
           sikrer at SVG'en sidder midt på text-baseline UDEN at øge
           container'ens line-height, så kortets totalhøjde ikke vokser. */
        .aorta-icon-inline {
            width: 18px;
            height: 18px;
            vertical-align: middle;
            display: inline-block;
            line-height: 1;
            flex-shrink: 0;
            object-fit: contain;
            background: transparent;
            border: 0;
            box-shadow: none;
            pointer-events: none;
            user-select: none;
        }
        .aorta-icon-inline.aorta-icon-sm { width: 16px; height: 16px; }
        .aorta-icon-inline.aorta-icon-lg { width: 22px; height: 22px; }
        /* V21.19: Pin-SVG i Locked View's "Sted"-række er BEVIDST 50%
           større end den generiske inline-størrelse (18px → 27px) for
           at give adresse-rækken en visuel "kort-anker"-vægt der matcher
           den større Shar'orta-knap i samme modal-header. Den større pin
           hjælper også brugeren med at scanne efter "kan jeg klikke for
           rute?" i et øjeblik. transparent-baggrund og ingen border
           arves fra .aorta-icon-inline (eksplicit reset der). */
        .aorta-icon-inline.view-event-sted-pin {
            width: 27px;
            height: 27px;
            margin-right: 0.25rem;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.15: SMÅ INDIKATOR-PRIKKER (.event-card-dots / .dot-red / .dot-green)
           ────────────────────────────────────────────────────────────────
           Visuel "cue" på de SMÅ kort i 3-dages strip + month view, hvor
           der ikke er plads til hverken ikoner eller tekst. Hver prik
           signalerer at eventet HAR data i et bestemt felt:
             • .dot-red   → ev.sted findes (lokation registreret)
             • .dot-green → ev.phone findes (telefonnummer registreret)
           Brugeren kan klikke kortet for at se detaljerne i den store
           visning. Dots har pointer-events:none så de ikke stjæler klik
           fra kortets onclick-handler — hele kortet skal forblive klikbart. */
        .event-card-dots {
            position: absolute;
            top: 0.35rem;
            right: 0.5rem;
            display: inline-flex;
            gap: 0.2rem;
            z-index: 2;
            pointer-events: none;
        }
        .event-card-dots .dot {
            width: 0.45rem;
            height: 0.45rem;
            border-radius: 50%;
            display: inline-block;
            box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
        }
        .event-card-dots .dot-red   { background: #e53935; }
        .event-card-dots .dot-green { background: #43a047; }
        /* V21.20/V21.21: 3-DAGES STRIP CARDS — UNIFORM HØJDE + FULD BREDDE.
           ────────────────────────────────────────────────────────────────
           KRITISK BUGFIX-HISTORIE:
             V21.19 → flex: 1 1 0 stretchede kortene VERTIKALT så ét kort
                      fyldte hele kolonnen (gigantiske tomme kasser).
             V21.20 → fjernede vertikal stretch via flex: 0 0 auto +
                      align-self: flex-start. Højden virkede igen, MEN
                      align-self: flex-start tvang også HORISONTAL
                      "intrinsic størrelse" på cross-axis (= cardene
                      skrumpede sammen om teksten i stedet for at fylde
                      kolonnens bredde).
             V21.21 → fix: bevar flex: 0 0 auto for højden (= ingen
                      vertikal stretch), MEN tving align-self: stretch
                      + width: 100% så kortene fylder hele kolonnens
                      bredde igen. Det er den korrekte adskillelse:
                        • main-axis (column = vertikal): ingen stretch
                        • cross-axis (= horisontal): fuld stretch
                      
           HUSKEREGEL: I et flex-container med flex-direction: column er
           cross-axis horisontalt; default align-items er stretch. V21.20
           overred det med align-self: flex-start. V21.21 retter overrid'en
           uden at miste højde-fix'et.
           
           position: relative bevares så .top-card-actions (Pin/Phone
           SVG'er fra V21.19) kan absolut-positioneres top-right INDE i
           kortet uden at hoppe ud i parent-koordinatsystemet. */
        #day-today .event-card,
        #day-tmrw  .event-card,
        #day-plus2 .event-card {
            position: relative;
            display: flex;
            flex-direction: column;
            justify-content: flex-start;
            box-sizing: border-box;
            flex: 0 0 auto;        /* V21.20: ALDRIG strækkende vertikalt — defense in depth */
            align-self: stretch;   /* V21.21: TVING horisontal stretch (cross-axis) */
            width: 100%;           /* V21.21: belt-and-braces — fyld altid kolonnens bredde */
            min-height: 4rem;
            height: auto;
        }
        /* Day-header må IKKE stretche — den er en label oven på listen
           af kort. flex: 0 0 auto låser den til intrinsic højde uanset
           hvor mange kort der ligger nedenunder. */
        .day-column > .day-header {
            flex: 0 0 auto;
        }
        /* V21.19: TOP-CARD TITEL — reserver plads til absolut-positionerede
           actions i top-right. Pin (27px) + phone (18px) + 0.4rem gap +
           0.5rem right-offset = ~3.5rem. Vi giver lidt buffer for at
           ikoner aldrig kolliderer med titel-tekst på lange titler. */
        #day-today .top-card-title,
        #day-tmrw  .top-card-title,
        #day-plus2 .top-card-title {
            display: inline-block;
            padding-right: 3.6rem;
            line-height: 1.3;
        }
        /* Større dots på dayview-kort så de ses tydeligt i den brede liste. */
        .dayview-event-card .event-card-dots .dot {
            width: 0.55rem;
            height: 0.55rem;
        }

        /* ────────────────────────────────────────────────────────────────
           V21.15: CLICK-SAFETY for event-cards
           ────────────────────────────────────────────────────────────────
           Når kortets indhold rebuildes via innerHTML (badge + ikon + tekst),
           er der risiko for at child-elementer som <img>, <b>, <span> tager
           "ownership" af et klik via deres egen layout. Vi forsikrer at:
             1) Hele .event-card er klikbart (cursor:pointer + pointer-events:auto).
             2) Ikoner og tekst-spans inde i kortet IKKE har pointer-events:none
                (de skal også passere klik op til parent — men ikke kaper det).
             3) Den eneste explicit pointer-events:none er på .aorta-icon-inline
                ovenfor, som bevidst skal være "transparent" for klik. */
        .event-card,
        .dayview-event-card {
            cursor: pointer;
            pointer-events: auto;
        }
        .event-card .event-card-text,
        .event-card .event-card-icon,
        .event-card .event-card-flex,
        .event-card .event-card-title,
        .event-card .event-card-date,
        .event-card .event-card-sub {
            pointer-events: auto;
        }

        /* TABS */
        .tabs { display: flex; border-bottom: 1px solid var(--border-color); margin-bottom: 1.5rem; }
        .tab { flex: 1; padding: 1rem; text-align: center; cursor: pointer; border-bottom: 2px solid transparent; color: var(--text-muted); }
        .tab.active { border-bottom-color: var(--accent-blue); color: var(--text-main); font-weight: bold; }
        .tab-content { display: none; }
        .tab-content.active { display: block; }

        /* CHILD ITEM */
        .child-item { background: var(--bg-color); border: 1px solid var(--border-color); padding: 1rem; border-radius: 0.8rem; margin-bottom: 1rem; }

        /* V21.4 → V21.6: BØRNEPROFIL-ACTION-KNAPPER (Scan/Gem/Slet barn)
           ─────────────────────────────────────────────────────────────────
           De tre store knapper i bunden af hver børneprofil. UI-feedback
           viste at ikonerne INDENI knapperne stadig var for små selv med
           V21.4's .scale-100-wrapper — kameraet/disketten/skraldespanden
           kunne knapt aflæses. V21.6 dropper transform:scale-tilgangen
           helt og skalerer ikonet RENT via direkte width/height (1.8em)
           på selve <img>-tagget. Det giver:
             • Ægte layout-bredde (= visuel bredde) — ingen "spøgelses-
               plads"-problemer som scale-transform har.
             • Ingen interaktion med transform-origin — ikonet sidder
               præcis hvor flex-layout'et placerer det.
             • Direkte kontrollerbar via almindelige em-værdier. */
        /* V21.7: Reducer vertikal padding markant — selve bjælken bliver
           slankere mens .child-action-icon's 3em-ikon må gerne "bryde" knappens
           indre linjer let og fylde hele knap-højden vertikalt. Den horisontale
           padding (1rem) bevares så teksten holder god afstand til knap-rammen. */
        .child-action-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 1.2rem;
            text-align: center;
            font-weight: 600;
            padding: 0.4rem 1rem;
            line-height: 1.2;
            overflow: visible;
        }
        .child-action-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
            transform: none !important;   /* override eventuel arvet .scale-X */
            min-width: 3em;
            height: 3em;
        }
        /* DRASTISK BUMP: 3em direkte width/height på selve <img>
           (≈45px ved 0.95rem button-font, hvor V21.4's transform-baserede
           .scale-100 nåede maksimalt ~36px). 3em matcher .scale-150's
           visuelle størrelse uden at lide under transform-stakkens
           layout-mismatch (V21.4-knappen havde visuelt 36px-ikon men
           layout-bredden var kun 18px → ikonet "smyge sig" ind i label-
           teksten i flex-rækken). V21.6 sizer img'et direkte så layout
           = visuel = 3em. Kameraet (Scan Skema), disketten (Gem barn)
           og skraldespanden (Slet barn) er nu klart aflæselige i normal
           læseafstand. */
        .child-action-icon .aorta-icon {
            width: 3em;
            height: 3em;
            margin-top: 0;
            margin-right: 0;
            transform: none !important;
        }
        /* Behold klasse-aliasserne .scale-100/150 — eksisterende HTML
           (V21.4-templaten) bruger dem allerede som dock-points, men i
           V21.6 leverer de IKKE selv skaleringen. Den faste 2em-størrelse
           ovenfor er det nye standard-look. */
        .child-action-icon.scale-100,
        .child-action-icon.scale-150 {
            transform: none !important;
            margin-right: 0;
        }

        .checkbox-group { display: flex; gap: 1rem; margin-top: 0.5rem; }
        .checkbox-label { display: flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; cursor: pointer;}
        
        /* SCHEDULE CHECKBOXES */
        .schedule-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.5rem; margin-top: 1rem; background: var(--schedule-grid-bg); padding: 0.5rem; border-radius: 0.5rem;}
        .schedule-day { font-size: 0.7rem; text-align: center; color: var(--text-muted); }
        .schedule-check { text-align: center; }

        /* WORK HOURS LIST */
        .work-hour-row {
            display: flex; justify-content: space-between; align-items: center;
            margin-bottom: 0.5rem; font-size: 0.9rem; gap: 0.6rem;
            flex-wrap: wrap;
        }
        .work-day-label { width: 3rem; color: var(--text-muted); flex-shrink: 0; }
        .time-inputs {
            display: flex; gap: 0.4rem; align-items: center;
            flex: 1; min-width: 0;
        }
        .time-inputs input {
            width: auto; flex: 1; min-width: 0; max-width: 8rem;
            padding: 0.4rem 0.5rem;
        }

        /* SHOPPING LIST ITEMS (inline panel) */
        .shop-list-ul {
            list-style: none; padding: 0; margin: 0;
            max-height: 14rem; overflow-y: auto;
            background: var(--bg-color);
            border-radius: 0.5rem;
        }
        .shop-list-li {
            padding: 0.55rem 0.75rem;
            border-bottom: 1px solid var(--border-color);
            display: flex; justify-content: space-between; align-items: center;
            color: var(--text-main); font-size: 0.9rem;
        }
        .shop-list-li:last-child { border-bottom: none; }
        .shop-item-text { flex: 1; }
        .shop-item-qty { color: var(--text-muted); font-size: 0.8rem; margin-left: 0.5rem; }
        .shop-item-remove {
            background: var(--color-success); color: #1a1a1a; border: none;
            width: 24px; height: 24px; border-radius: 50%;
            cursor: pointer; font-weight: bold; font-size: 0.9rem; line-height: 1;
            display: flex; align-items: center; justify-content: center;
        }
        .shop-item-remove:hover { transform: scale(1.1); }
        .shop-list-empty {
            padding: 1rem; text-align: center;
            color: var(--text-muted); font-size: 0.85rem; font-style: italic;
        }

        /* =========================================================
           V15: DAY VIEW (overlay-modal til "klik på dato")
           Vises når man klikker på dato-cellen i månedsvisningen
           eller dato-headeren i 3-dages visningen. Lister samtlige
           events for den dag i et stort, læsbart format. Erstatter
           den ældre, fragile zoomDay-logik der klonede DOM-bars.
        ========================================================= */
        #dayViewBackdrop {
            position: fixed; top:0; left:0; width:100%; height:100%;
            background: rgba(0,0,0,0.55); backdrop-filter: blur(3px);
            z-index: 3500; display: none;
        }
        #dayViewModal {
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
            width: min(560px, 92vw); max-height: 82vh;
            background: var(--card-bg); border: 2px solid var(--accent-blue);
            border-radius: 1rem; z-index: 3600; display: none;
            box-shadow: 0 30px 80px rgba(0,0,0,0.85);
            flex-direction: column; overflow: hidden;
        }
        .dayview-header {
            background: var(--bg-color); padding: 1rem 1.25rem;
            border-bottom: 1px solid var(--border-color);
            display: flex; justify-content: space-between; align-items: center;
            font-size: 1.4rem; font-weight: bold; color: var(--text-main);
        }
        .dayview-close {
            cursor: pointer; font-size: 1.6rem; color: var(--text-muted);
            padding: 0 0.4rem; border-radius: 0.4rem;
        }
        .dayview-close:hover { color: var(--text-main); background: var(--btn-default-bg); }
        .dayview-body {
            padding: 1.25rem; overflow-y: auto; flex: 1;
            display: flex; flex-direction: column; gap: 0.75rem;
        }
        .dayview-empty {
            color: var(--text-muted); font-style: italic; text-align: center;
            padding: 2rem 1rem;
        }
        .dayview-event-card {
            position: relative;
            padding: 0.85rem 1rem;
            border-radius: 0.7rem;
            background: var(--card-bg);
            border-left: 0.4rem solid #555;
            box-shadow: 0 1px 3px rgba(0,0,0,0.15);
            cursor: pointer;
            transition: transform 0.12s ease;
        }
        .dayview-event-card:hover { transform: translateX(2px); }
        .dayview-event-time {
            font-size: 0.85rem; color: var(--text-muted); font-weight: 600;
            display: block; margin-bottom: 0.2rem;
        }
        .dayview-event-title {
            font-size: 1.05rem; font-weight: bold; color: var(--text-main);
            display: block;
        }
        .dayview-event-loc {
            font-size: 0.8rem; color: var(--accent-blue);
            display: inline-flex; align-items: center; gap: 0.3rem;
            margin-top: 0.25rem;
            padding: 0.1rem 0.35rem;
            border-radius: 0.4rem;
            text-decoration: none;
            transition: background-color 0.15s ease, color 0.15s ease;
            position: relative; z-index: 1;
        }
        .dayview-event-loc:hover,
        .dayview-event-loc:focus-visible {
            background: rgba(41, 121, 255, 0.12);
            color: var(--color-family);
            outline: none;
            text-decoration: underline;
        }
        /* V21.15: Plain-tekst variant — Sted er en beskrivelse ("Hos Laia"),
           ikke en rigtig adresse. Strip link-styling så det ikke ser klikbart
           ud (vi rendrer det som <span>, ikke <a>, men styling matchede før). */
        .dayview-event-loc-plain {
            color: var(--text-muted);
            cursor: default;
        }
        .dayview-event-loc-plain:hover,
        .dayview-event-loc-plain:focus-visible {
            background: transparent;
            color: var(--text-muted);
            text-decoration: none;
        }
        /* V21.15: TELEFON-link på dayview-kort. Samme visuelle vægt som
           sted-linket; den grønne SVG-glyph signalerer "ring nu". */
        .dayview-event-phone {
            font-size: 0.8rem; color: var(--accent-blue);
            display: inline-flex; align-items: center; gap: 0.3rem;
            margin-top: 0.25rem; margin-left: 0.5rem;
            padding: 0.1rem 0.35rem;
            border-radius: 0.4rem;
            text-decoration: none;
            transition: background-color 0.15s ease, color 0.15s ease;
            position: relative; z-index: 1;
            word-break: break-all;
        }
        .dayview-event-phone:hover,
        .dayview-event-phone:focus-visible {
            background: rgba(67, 160, 71, 0.15);
            color: var(--color-family);
            outline: none;
            text-decoration: underline;
        }
        .dayview-event-card.event-card-recurring {
            outline: 1px dotted rgba(0,0,0,0.25);
            outline-offset: -2px;
            opacity: 0.92;
        }
        /* Klik-affordance på dato-tekst i månedsceller og 3-dages-headers. */
        .month-date-text { cursor: pointer; }
        .month-date-text:hover { text-decoration: underline; }
        .day-header-clickable { cursor: pointer; }
        .day-header-clickable:hover { color: var(--accent-blue); }

        /* =========================================================
           V15: PULSERENDE 'AORTA INDBAKKE' header når der ligger
           uløste/pending opgaver. Blød animation mellem mutet
           tekst og en dæmpet rød — INGEN separate prikker/badges.
        ========================================================= */
        @keyframes inbox-soft-pulse {
            0%, 100% { color: var(--text-muted); }
            50%      { color: var(--inbox-pulse-color, #d97a7a); }
        }
        .inbox-title.pulsing {
            animation: inbox-soft-pulse 2.6s ease-in-out infinite;
        }

        /* ZOOM CARD (POP OUT - Z:3000) */
        #zoom-card {
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
            width: 45vw; height: 40vh; 
            background: var(--card-bg); border: 2px solid var(--accent-blue);
            border-radius: 1rem; z-index: 3000; display: none;
            padding: 0; 
            box-shadow: 0 30px 80px rgba(0,0,0,0.95);
            flex-direction: column; overflow: hidden; 
        }
        #zoom-backdrop { position: fixed; top:0; left:0; width:100%; height:100%; background: transparent; z-index: 2500; display: none; }
        
        .zoom-header { 
            background: var(--bg-color); padding: 1rem; border-bottom: 1px solid var(--border-color);
            display: flex; justify-content: space-between; align-items: center; font-size: 1.5rem; font-weight: bold;
        }
        .zoom-meal-icon { font-size: 2rem; cursor: pointer; }
        .zoom-body { padding: 1.5rem; overflow-y: auto; flex: 1; }

        /* Larger Text in Zoom Body */
        .zoom-body .cal-event-bar { font-size: 1.2rem; min-height: 3rem; margin-bottom: 8px; }

        /* --- VISIBILITY HELPERS --- */
        .hidden { display: none !important; }
        #app-root { display: contents; }

        /* --- AUTH SCREEN --- */
        #auth-screen {
            position: fixed; inset: 0; z-index: 5000;
            display: flex; align-items: center; justify-content: center;
            background: var(--bg-color);
            padding: 1rem; box-sizing: border-box;
            overflow-y: auto;
        }

        .auth-card {
            width: 100%; max-width: 26rem;
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 1.25rem;
            padding: 1.5rem;
            box-shadow: var(--shadow-std);
            box-sizing: border-box;
        }

        .auth-brand {
            background: var(--gradient-briefing);
            border-radius: 0.85rem;
            padding: 1.5rem 1rem;
            text-align: center;
            color: #ffffff;
            margin-bottom: 1.5rem;
        }
        .auth-logo { font-size: 2.5rem; line-height: 1; }
        .auth-title {
            font-size: 1.8rem; font-weight: 800; letter-spacing: 0.4rem;
            margin-top: 0.4rem;
        }
        .auth-tagline {
            font-size: 0.85rem; opacity: 0.9; margin-top: 0.2rem;
            font-weight: 300; letter-spacing: 0.05rem;
        }

        .auth-row { margin-bottom: 0.9rem; }
        .auth-row label {
            display: block;
            font-size: 0.75rem; font-weight: 600;
            color: var(--text-muted);
            text-transform: uppercase; letter-spacing: 0.05rem;
            margin-bottom: 0.3rem;
        }
        .auth-hint {
            display: block;
            font-size: 0.7rem; color: var(--text-muted);
            margin-top: 0.25rem;
        }

        .auth-btn {
            width: 100%; margin-top: 0.5rem;
            font-size: 1rem; font-weight: 700;
            letter-spacing: 0.05rem;
        }
        .auth-btn:disabled { opacity: 0.5; cursor: not-allowed; }

        .auth-toggle {
            display: block; width: 100%;
            background: none; border: none;
            color: var(--text-blue-accent);
            font-size: 0.85rem; cursor: pointer;
            margin-top: 1rem; padding: 0.4rem;
            text-align: center;
        }
        .auth-toggle:hover { text-decoration: underline; }

        .auth-message {
            display: none;
            padding: 0.7rem 0.9rem;
            border-radius: 0.5rem;
            margin-bottom: 1rem;
            font-size: 0.85rem; line-height: 1.4;
        }
        .auth-message.visible { display: block; }
        .auth-error {
            background: rgba(255, 82, 82, 0.12);
            color: var(--color-danger);
            border-left: 3px solid var(--color-danger);
        }
        .auth-info {
            background: rgba(0, 229, 255, 0.10);
            color: var(--color-parents);
            border-left: 3px solid var(--color-parents);
        }

        /* =========================================================
           V16: 16-FARVERS PALETTE-PICKER
           Bruges af profile-color (voksne) og child-color (børn).
           Render-koden i app.js fylder denne container med 16
           swatch-knapper. Hver knap er et farvet kvadrat med rund
           hover/active-effekt.
        ========================================================= */
        .color-palette {
            display: grid;
            grid-template-columns: repeat(8, minmax(0, 1fr));  /* minmax(0,1fr) = må krympe under content-bredde */
            gap: 0.45rem;
            margin-top: 0.5rem;
            padding: 0.6rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            box-sizing: border-box;
            width: 100%;
            max-width: 100%;
            overflow: hidden;
        }
        .color-swatch {
            aspect-ratio: 1 / 1;
            min-width: 0;
            border-radius: 0.4rem;
            border: 2px solid transparent;
            cursor: pointer;
            position: relative;
            transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
            box-shadow: 0 1px 2px rgba(0,0,0,0.2);
        }
        .color-swatch:hover {
            transform: scale(1.08);
            border-color: var(--text-main);
        }
        .color-swatch.selected {
            border-color: var(--text-main);
            box-shadow: 0 0 0 2px var(--accent-blue), 0 2px 6px rgba(0,0,0,0.4);
        }
        .color-swatch.selected::after {
            content: '✓';
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            color: rgba(0,0,0,0.85);
            font-weight: 900;
            font-size: 1.1rem;
            text-shadow: 0 1px 2px rgba(255,255,255,0.6);
        }

        /* =========================================================
           V21.11: TINT-PALETTE (Mit Farvetema)
           ─────────────────────────────────────────────────────────
           Adskilt fra .color-palette fordi:
             • 7 cirkulære swatches (1 neutral + 6 pasteller) — ikke
               16 firkanter som member-paletten
             • større per-swatch (3rem cirkel) — det er en ambient-
               tone, ikke en member-tag, og brugeren vælger sjældent
               (= bør være glæde-fyldt at klikke på)
             • visuel "delt" preview: venstre halvdel = light bg,
               højre halvdel = dark bg, så man ser begge dimensioner
               af tonen før valg (krævet i user-spec: "begge tints
               skal være forståelige før klik")
             • neutral-swatchen får en diagonal grå/sort split som
               visuelt "no tint" indikator — adskiller den fra et
               tomt felt
           Selected state: tyk accent-blue ring + checkmark (samme
           designsprog som .color-swatch.selected for konsistens). */
        .tint-palette {
            display: flex;
            flex-wrap: wrap;
            gap: 0.9rem;
            margin-top: 0.6rem;
            padding: 0.7rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            justify-content: flex-start;
            align-items: center;
        }
        .tint-swatch {
            width: 3rem;
            height: 3rem;
            border-radius: 50%;
            cursor: pointer;
            border: 2px solid var(--border-color);
            position: relative;
            transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
            box-shadow: 0 1px 3px rgba(0,0,0,0.25);
            /* Den rene baggrundsfarve (light-variant) sættes inline via JS,
               men halvdelen er overskrevet af ::after med dark-varianten
               så swatchen viser BEGGE tilstande på én gang. */
            overflow: hidden;
        }
        .tint-swatch::after {
            /* Højre halvdel = dark bg-farve. Sættes via inline CSS-variabel
               --tint-dark på selve swatchen — så vi kan have én CSS-regel
               og 7 forskellige farver. */
            content: '';
            position: absolute;
            top: 0;
            right: 0;
            width: 50%;
            height: 100%;
            background: var(--tint-dark, transparent);
            border-left: 1px solid rgba(255,255,255,0.15);
        }
        .tint-swatch:hover {
            transform: scale(1.08);
            border-color: var(--text-main);
        }
        .tint-swatch.selected {
            border-color: var(--accent-blue);
            box-shadow: 0 0 0 3px var(--accent-blue), 0 2px 6px rgba(0,0,0,0.4);
        }
        .tint-swatch.selected::before {
            content: '✓';
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--accent-blue);
            font-weight: 900;
            font-size: 1.4rem;
            text-shadow: 0 1px 3px rgba(255,255,255,0.85);
            z-index: 2;
        }
        /* Neutral-swatchen er et særligt tilfælde: den repræsenterer
           "ingen tone". Vi viser den som diagonal split mellem default
           lys og default mørk baggrund — så selv neutral-valget får
           et visuelt udsagn om at "begge defaults bevares". */
        .tint-swatch.tint-neutral {
            background: linear-gradient(135deg, #f0f2f5 0%, #f0f2f5 49%, #1e1e1e 51%, #1e1e1e 100%);
        }
        .tint-swatch.tint-neutral::after {
            display: none; /* split sker via gradient ovenfor */
        }

        /* =========================================================
           V16: NY INDSTILLINGSMENU — SIDEBAR LAYOUT
           Stor modal med vertikal nav til venstre + indhold til højre.
           V16.1: Strikt fast størrelse, ingen horisontal scroll, kun
           højre pane må scrolle lodret. Sidebar og ramme står fast.
        ========================================================= */
        .modal-content.settings-modal-large {
            width: min(900px, 96vw);
            max-width: 900px;
            height: 85vh;
            max-height: 85vh;
            padding: 0;
            display: flex;
            flex-direction: column;
            overflow: hidden;          /* aldrig horisontal scroll på modalen */
        }
        .settings-modal-large .modal-header {
            padding: 1.2rem 1.5rem;
            margin: 0;
            border-bottom: 1px solid var(--border-color);
            flex-shrink: 0;
            overflow: hidden;
        }
        .settings-grid {
            display: grid;
            grid-template-columns: 13rem minmax(0, 1fr);  /* minmax(0,1fr) = grid-child må krympe */
            min-height: 0;
            flex: 1;
            overflow: hidden;
        }
        .settings-nav {
            background: var(--bg-color);
            border-right: 1px solid var(--border-color);
            padding: 1rem 0.5rem;
            overflow-y: auto;
            overflow-x: hidden;
            display: flex;
            flex-direction: column;
            gap: 0.2rem;
            min-width: 0;
        }
        .settings-nav-item {
            padding: 0.7rem 0.9rem;
            border-radius: 0.5rem;
            color: var(--text-muted);
            cursor: pointer;
            font-size: 0.9rem;
            display: flex;
            align-items: center;
            gap: 0.55rem;
            transition: background 0.15s, color 0.15s;
            user-select: none;
            /* V21.46.5: tillad to-linjers wrap for lange titler (fx
               "Husstand & Familie", "Vask & Opvask") så vi
               undgår "Husstand & Fa..."-trunkering. Line-height holder
               rækkerne tætte så den visuelle hop er minimal. */
            white-space: normal;
            line-height: 1.2;
            min-width: 0;
        }
        .settings-nav-item:hover {
            background: var(--card-bg);
            color: var(--text-main);
        }
        .settings-nav-item.active {
            background: var(--accent-blue);
            color: #fff;
            font-weight: 600;
        }
        .settings-nav-icon { font-size: 1.05rem; flex-shrink: 0; }
        .settings-pane {
            padding: 1.4rem 1.6rem;
            overflow-y: auto;
            overflow-x: hidden;          /* aldrig horisontal scroll inde i panen */
            min-height: 0;
            min-width: 0;                /* tillader at panen krymper i grid */
        }
        .settings-pane h3 {
            margin: 0 0 1rem 0;
            font-size: 1.1rem;
            color: var(--text-main);
            border-bottom: 1px solid var(--border-color);
            padding-bottom: 0.5rem;
            word-wrap: break-word;
        }
        .settings-pane .modal-row { margin-bottom: 1.2rem; }

        /* V17: Underpunkter inde i en settings-section (fx Fødselsdag/Arbejdstider
           som lever inden i Min Profil). Diskret separator, ingen badges, holder
           sig 1:1 i look-and-feel med top-niveau-sektioner. */
        .settings-subsection {
            margin-top: 1.4rem;
            padding-top: 1rem;
            border-top: 1px solid var(--border-color);
            min-width: 0;
        }
        .settings-subsection h4 {
            margin: 0 0 0.8rem 0;
            font-size: 0.98rem;
            font-weight: 600;
            color: var(--text-main);
            display: flex;
            align-items: center;
            gap: 0.45rem;
            word-wrap: break-word;
        }
        .settings-section { display: none; min-width: 0; }
        .settings-section.active { display: block; }

        /* V17/V18: DANGER ZONE — visuelt isoleret med rød accent-stribe i toppen
           så den klart adskiller sig fra harmless settings-subsections. Ingen
           tung baggrund (vi vil ikke skrige); kun en klar visuel grænse. */
        .settings-subsection.settings-danger-zone {
            margin-top: 1.6rem;
            padding-top: 1.2rem;
            border-top: 2px solid var(--color-danger);
        }

        /* V18: DANGER ZONE MODAL — bredere modal-content end default for at give
           plads til 3 destruktive sektioner uden trængsel.
           V21.7: .modal-content giver allerede max-height:90vh + overflow-y:auto,
           men browserens native scrollbar var synlig. Vi skjuler den her — appens
           dynamiske scroll-pile (initScrollIndicators) tilkobles i
           openDangerZoneModal() og overtager den visuelle scroll-feedback.
           position:relative er allerede sat på base .modal-overlay/.modal-content
           og er ikke nødvendigt at gentage. */
        .modal-content.danger-zone-modal {
            width: min(560px, 96vw);
            max-width: 560px;
            position: relative;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .modal-content.danger-zone-modal::-webkit-scrollbar { display: none; }
        /* Hver sektion (Slet barn / Slet voksen / Slet husstand) er sin egen
           visuelt afgrænsede boks. Ikke skrigende rød — kun dæmpet rød border
           der signalerer "destruktiv handling herinde". */
        .dz-section {
            border: 1px solid var(--color-danger);
            border-radius: 0.6rem;
            padding: 1rem;
            margin-bottom: 1rem;
            background: rgba(255, 82, 82, 0.04);   /* meget dæmpet rød tone */
        }
        .dz-section h4 {
            margin: 0 0 0.6rem 0;
            font-size: 1rem;
            font-weight: 700;
            color: var(--color-danger);
            display: flex;
            align-items: center;
            gap: 0.45rem;
        }
        .dz-section .modal-row { margin-bottom: 0.8rem; }
        /* "Kritisk" sektion (slet hele husstanden) får en endnu kraftigere
           accent — repeating-stripe baggrund i meget lav opacitet for at
           understrege at det er "the big one". */
        .dz-section.dz-section-critical {
            background:
                repeating-linear-gradient(
                    -45deg,
                    rgba(255, 82, 82, 0.08) 0,
                    rgba(255, 82, 82, 0.08) 10px,
                    transparent 10px,
                    transparent 20px
                );
        }
        .dz-delete-btn {
            background: var(--color-danger) !important;
            color: #fff !important;
            font-weight: 700;
        }
        .dz-delete-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }
        /* Lukke-X i dangerZoneModal headeren — let dæmpet for ikke at stjæle
           opmærksomhed fra de røde knapper. */
        .dz-close:hover { opacity: 1 !important; }

        /* V19: KOMPOSTBUNKEN — restorativ pendant til Danger Zone.
           Bevidst BLÅ accent (ikke rød eller grøn) — vi vil ikke hverken
           skræmme eller fejre; vi vil bare dokumentere "her ligger ting der
           kan komme tilbage". Grøn ville skjule alvoren ved sletning, rød
           ville signalere fare. Blå = neutral oplysning. */
        .settings-subsection.settings-compost-zone {
            margin-top: 1.4rem;
            padding-top: 1rem;
            border-top: 2px solid var(--accent-blue);
        }

        .modal-content.compost-modal {
            width: min(560px, 96vw);
            max-width: 560px;
            display: flex;
            flex-direction: column;
            max-height: 88vh;
            overflow: hidden;
        }
        /* V21.7: Skjul den native scrollbar — appens egne dynamiske scroll-pile
           (initScrollIndicators) tager over. position:relative er nødvendig så
           .scroll-arrow-top / .scroll-arrow-bottom kan ankre sig til containeren. */
        .compost-list {
            list-style: none;
            margin: 0.8rem 0 0 0;
            padding: 0;
            overflow-y: auto;
            min-height: 4rem;
            max-height: 60vh;
            display: flex;
            flex-direction: column;
            gap: 0.5rem;
            position: relative;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .compost-list::-webkit-scrollbar { display: none; }
        .compost-list:empty::after {
            /* Fallback hvis JS ikke har kaldt renderCompostList — viser tomt
               state direkte. Selve "Kompostbunken er tom"-teksten injiceres af
               renderCompostList() som <li class="compost-empty"> så vi kan
               oversætte den. Denne ::after er "no-JS"-fallback. */
            content: '—';
            display: block;
            text-align: center;
            color: var(--text-muted);
            padding: 1rem;
            font-style: italic;
        }
        .compost-item {
            display: flex;
            align-items: center;
            gap: 0.8rem;
            padding: 0.8rem 1rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            min-width: 0;
        }
        .compost-item-main {
            flex: 1 1 auto;
            min-width: 0;     /* tillader text-overflow at virke */
        }
        .compost-item-title {
            font-weight: 600;
            color: var(--text-main);
            font-size: 0.95rem;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .compost-item-meta {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            margin-top: 0.25rem;
            font-size: 0.75rem;
            color: var(--text-muted);
        }
        .compost-item-type-badge {
            display: inline-block;
            padding: 0.1rem 0.45rem;
            border-radius: 0.3rem;
            background: rgba(33, 150, 243, 0.15);
            color: var(--accent-blue);
            font-weight: 600;
            font-size: 0.7rem;
            text-transform: uppercase;
            letter-spacing: 0.03em;
        }
        .compost-item-type-badge.type-inbox {
            background: rgba(255, 171, 0, 0.15);
            color: var(--color-warning);
        }
        .compost-restore-btn {
            background: var(--accent-blue);
            color: #fff;
            border: none;
            padding: 0.5rem 0.9rem;
            border-radius: 0.5rem;
            font-weight: 600;
            font-size: 0.8rem;
            cursor: pointer;
            white-space: nowrap;
            flex-shrink: 0;
            transition: background 120ms ease, transform 120ms ease;
        }
        .compost-restore-btn:hover { transform: translateY(-1px); }
        .compost-restore-btn.restored {
            background: var(--color-success);
            color: #1a1a1a;
            cursor: default;
        }
        .compost-empty {
            list-style: none;
            text-align: center;
            color: var(--text-muted);
            font-style: italic;
            padding: 1.2rem;
        }
        .compost-close:hover { opacity: 1 !important; }

        /* V20: Diskret soft-delete knap til editModal/fixModal.
           Bevidst LAV visuel vægt — sletning er ikke længere "farlig"
           fordi V19's Kompostbunken giver brugeren 7 dage til at
           gendanne. Vi adskiller derfor visuelt fra:
             • .save-btn (grøn, primær handling)
             • .dz-delete-btn (fuldrød, irreversibel handling)
           Resultat: transparent baggrund + rød tekst + dæmpet border.
           Ved hover bliver baggrunden svagt rød så brugeren ser
           feedback uden at den dominerer modal-flowet. */
        .soft-delete-btn {
            background: transparent !important;
            color: var(--color-danger) !important;
            border: 1px solid var(--color-danger) !important;
            margin-top: 0.5rem !important;
            opacity: 0.85;
            transition: opacity 120ms ease, background 120ms ease;
        }
        .soft-delete-btn:hover {
            opacity: 1;
            background: rgba(244, 67, 54, 0.08) !important;
        }

        /* Sikring: ingen direkte child af settings-pane må forårsage horisontal scroll. */
        .settings-pane > section,
        .settings-pane > section > * {
            max-width: 100%;
            box-sizing: border-box;
        }
        .settings-pane .input-field,
        .settings-pane .select-field {
            max-width: 100%;
            box-sizing: border-box;
        }
        .settings-footer {
            border-top: 1px solid var(--border-color);
            padding: 0.8rem 1.5rem;
            background: var(--bg-color);
            display: flex;
            justify-content: flex-end;
            gap: 0.6rem;
            flex-shrink: 0;
        }
        .settings-footer .save-btn { width: auto; min-width: 9rem; margin-top: 0; }

        /* Ansvarsfraskrivelse-paragraf for sektioner */
        .settings-help {
            font-size: 0.78rem;
            color: var(--text-muted);
            line-height: 1.45;
            margin-top: 0.4rem;
            padding: 0.6rem 0.8rem;
            background: var(--bg-color);
            border-left: 3px solid var(--accent-blue);
            border-radius: 0 0.4rem 0.4rem 0;
        }

        /* Integrationer placeholder-kort */
        .integration-card {
            display: flex; align-items: center; gap: 0.9rem;
            padding: 0.9rem 1rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            margin-bottom: 0.6rem;
        }
        .integration-icon { font-size: 1.6rem; }
        .integration-info { flex: 1; }
        .integration-info .int-title { font-weight: bold; font-size: 0.95rem; }
        .integration-info .int-sub { font-size: 0.78rem; color: var(--text-muted); }
        .integration-status {
            font-size: 0.72rem; padding: 0.2rem 0.6rem; border-radius: 1rem;
            background: var(--btn-default-bg); color: var(--btn-default-text);
        }

        /* ============================================================
           V21.52.0 (Sprint E): GOOGLE CALENDAR INTEGRATION + ICAL FEED
           ============================================================
           Active states for .integration-card når en provider er klar
           til at forbindes (vis "Forbind"-knap) eller allerede forbundet
           (vis status-tekst + Disconnect-knap). Layoutet matcher den
           eksisterende inerte stil ('Kommer snart'-badge) så ingen
           visuel "spring" ved tilstandsskift.
           ============================================================ */
        .integration-action {
            display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
            justify-content: flex-end;
        }
        .integration-action .save-btn {
            font-size: 0.78rem; padding: 0.35rem 0.75rem; border-radius: 0.5rem;
            white-space: nowrap;
        }
        .integration-connected-state {
            display: flex; flex-direction: column; align-items: flex-end; gap: 0.3rem;
        }
        .integration-status-text {
            font-size: 0.75rem; color: var(--color-success);
            text-align: right; line-height: 1.3;
        }
        .disconnect-btn {
            background: transparent; border: 1px solid var(--color-danger);
            color: var(--color-danger);
            padding: 0.3rem 0.7rem; border-radius: 0.5rem;
            cursor: pointer; transition: all 0.15s ease;
            font-weight: 600; font-size: 0.75rem;
        }
        .disconnect-btn:hover {
            background: var(--color-danger); color: #fff;
        }

        /* iCal-feed-sektion — input-felt med to knapper i samme række.
           Wraps på smalle skærme så Kopiér/Forny ikke tvinger horizontal scroll. */
        .ical-container {
            display: flex; align-items: stretch; gap: 0.4rem; flex-wrap: wrap;
            margin-top: 0.5rem;
        }
        .ical-container .input-field {
            flex: 1; min-width: 200px;
            font-family: 'SF Mono', Menlo, Consolas, monospace;
            font-size: 0.75rem; color: var(--text-muted);
        }
        .ical-container .save-btn {
            white-space: nowrap; font-size: 0.85rem;
        }

        /* Kilde-badge på inbox-items der kommer fra ekstern provider.
           Lille ikon i øverste højre hjørne af inbox-kortet — så brugeren
           kan se "ahh, det her kom fra Google" uden at skulle læse meta-
           feltet. Position absolute kræver at parent (.inbox-card) har
           position relative, hvilket den allerede har. */
        .source-badge {
            position: absolute; top: 4px; right: 4px;
            width: 1.3rem; height: 1.3rem;
            background: var(--bg-color);
            border-radius: 50%; padding: 2px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
            border: 1px solid var(--border-color);
            display: flex; align-items: center; justify-content: center;
            z-index: 5;
            pointer-events: none;
        }
        .source-badge img {
            width: 100%; height: 100%; object-fit: contain;
        }

        /* ============================================================
           V21.36 / V21.51.1: MASKINE-INDSTILLINGER — Vask & Opvask-sektion
           ============================================================
           .machine-card wrapper en hvidevare-blok (Vaskemaskine eller
           Opvaskemaskine) i Indstillinger-modalen. Genbrugt visuel
           sprog fra .integration-card (samme bg-color, border, border-
           radius) men højere padding fordi indholdet er flere modal-
           rows i stedet for én flex-række.

           Layout:
             • .machine-card-title — h4 med ikon til venstre + tekst.
               Uses display:flex så ikonet aligner pænt med teksten.
             • .modal-row inden i kortet — eksisterende patternen
               for label + input-felt, ingen overrides nødvendige.
             • .machine-test-hint — lille subtle paragraph der gør
               det tydeligt at testere kan bruge meget små værdier
               (fx 0.001 t ≈ 3.6 sek) uden at brugeren skal grave
               i README'en eller spørge AI.
           ============================================================ */
        .machine-card,
        .device-card {                             /* V21.43.5: device-card genbruger machine-card-look */
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            padding: 1rem 1.1rem;
            margin-bottom: 1rem;
        }
        .machine-card-title,
        .device-card-title {                       /* V21.43.5: samme h4-look */
            margin: 0 0 0.9rem 0;
            display: flex;
            align-items: center;
            gap: 0.5rem;
            font-size: 1rem;
            font-weight: 600;
            color: var(--text-color);
        }
        .machine-card-title .aorta-icon,
        .device-card-title .aorta-icon {
            width: 1.4em;
            height: 1.4em;
        }
        /* Sidste .modal-row inden i et .machine-card skal IKKE have
           ekstra margin-bottom — den er allerede dækket af kortets
           egen padding-bottom. */
        .machine-card .modal-row:last-child {
            margin-bottom: 0;
        }
        /* ────────────────────────────────────────────────────────────
           V21.46.2: Memory editor (Smart Context Memory)
           ──────────────────────────────────────────────────────────── */
        .memory-list {
            display: flex;
            flex-direction: column;
            gap: 0.4rem;
        }
        .memory-empty {
            font-size: 0.85rem;
            color: var(--text-muted);
            font-style: italic;
            padding: 0.5rem 0;
        }
        .memory-row {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 0.6rem;
            padding: 0.55rem 0.75rem;
            background: var(--surface-color, var(--bg-color));
            border: 1px solid var(--border-color);
            border-radius: 0.5rem;
            font-size: 0.9rem;
        }
        .memory-row.is-weak {
            opacity: 0.65;
            border-style: dashed;
        }
        .memory-row-text {
            flex: 1;
            min-width: 0;
            display: flex;
            flex-direction: column;
            gap: 0.15rem;
        }
        .memory-row-alias {
            font-weight: 600;
            color: var(--text-color);
            display: flex;
            align-items: center;
            gap: 0.4rem;
            flex-wrap: wrap;
        }
        .memory-row-alias .arrow {
            color: var(--text-muted);
            font-weight: 400;
        }
        .memory-row-target {
            color: var(--text-muted);
        }
        /* V21.49.0 (2.5.3.13): relation_label vises som lille tag inline efter
           target ("Sofie → Victoria · klassekammerat") og context_hint som
           subtil 2. linje ("fra 3.A klassen"). Begge er lette sub-strings der
           ikke konkurrerer med selve alias→target-rowen. */
        .memory-row-relation {
            font-weight: 400;
            font-size: 0.78rem;
            color: var(--text-muted);
            font-style: italic;
        }
        .memory-row-context {
            font-size: 0.72rem;
            color: var(--text-muted);
            opacity: 0.85;
            margin-top: 0.1rem;
        }
        .memory-row-meta {
            font-size: 0.72rem;
            color: var(--text-muted);
            display: flex;
            gap: 0.5rem;
            flex-wrap: wrap;
        }
        .memory-badge-weak {
            font-size: 0.65rem;
            padding: 0.1rem 0.4rem;
            background: var(--text-muted);
            color: var(--bg-color);
            border-radius: 0.4rem;
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .memory-row-actions {
            display: flex;
            gap: 0.3rem;
            flex-shrink: 0;
        }
        .memory-row-actions button {
            border: none;
            background: transparent;
            color: var(--text-muted);
            font-size: 0.85rem;
            cursor: pointer;
            padding: 0.3rem 0.5rem;
            border-radius: 0.3rem;
            transition: background 0.15s, color 0.15s;
        }
        .memory-row-actions button:hover {
            background: var(--bg-color);
            color: var(--text-color);
        }
        .memory-row-actions .btn-delete:hover {
            color: #ef5350;
        }

        /* ────────────────────────────────────────────────────────────
           V21.51.0 (Sprint D): AI-FORBRUG progress-bars
           ────────────────────────────────────────────────────────────
           Tre premium-SaaS-look progress-bars i Indstillinger > AI-forbrug.
           Fyldningsfarven graduerer fra accent-blå (lavt forbrug) over
           orange (75%+) til rød (100%). Smooth width-transition gør
           re-render efter hver AI-aktion lille men synlig.
        */
        .ai-usage-card {
            display: flex;
            flex-direction: column;
            gap: 1.4rem;
            background: var(--surface-color, var(--bg-color));
            border: 1px solid var(--border-color);
            border-radius: 0.7rem;
            padding: 1.1rem 1.2rem;
            margin-top: 0.6rem;
        }
        .ai-usage-row {
            display: flex;
            flex-direction: column;
            gap: 0.35rem;
        }
        .ai-usage-label {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            gap: 0.8rem;
            flex-wrap: wrap;
        }
        .ai-usage-title {
            font-weight: 600;
            color: var(--text-color);
            font-size: 0.95rem;
            letter-spacing: 0.005em;
        }
        .ai-usage-count {
            font-variant-numeric: tabular-nums;
            font-size: 0.85rem;
            color: var(--text-muted);
            font-weight: 500;
        }
        .ai-usage-sub {
            font-size: 0.78rem;
            color: var(--text-muted);
            line-height: 1.4;
            margin: 0;
            opacity: 0.92;
        }
        .ai-usage-bar {
            width: 100%;
            height: 0.6rem;
            background: rgba(0, 0, 0, 0.08);
            border-radius: 999px;
            overflow: hidden;
            margin-top: 0.2rem;
        }
        body.dark .ai-usage-bar {
            background: rgba(255, 255, 255, 0.08);
        }
        .ai-usage-bar-fill {
            height: 100%;
            width: 0;
            background: linear-gradient(90deg, #29b6f6 0%, #26c6da 100%);
            border-radius: 999px;
            transition: width 0.45s ease-out, background 0.3s ease;
        }
        .ai-usage-bar-fill.warn {
            background: linear-gradient(90deg, #ffa726 0%, #ff7043 100%);
        }
        .ai-usage-bar-fill.danger {
            background: linear-gradient(90deg, #ef5350 0%, #c62828 100%);
        }
        .ai-usage-footer {
            font-size: 0.72rem;
            color: var(--text-muted);
            opacity: 0.8;
            margin: 0.4rem 0 0;
            text-align: right;
        }

        .machine-test-hint {
            font-size: 0.78rem;
            color: var(--text-muted);
            line-height: 1.45;
            margin-top: 0.4rem;
            padding: 0.5rem 0.8rem;
            background: var(--bg-color);
            border-left: 3px solid var(--color-warning);
            border-radius: 0 0.4rem 0.4rem 0;
        }
        .machine-test-hint b {
            color: var(--text-color);
            font-family: monospace;
            background: var(--card-bg);
            padding: 0.05rem 0.35rem;
            border-radius: 0.25rem;
        }

        /* =========================================================
           V16: BØRNEPROFILER — DYNAMISKE FRITIDSAKTIVITETER
           Erstatter de hardcodede idræt/svømning-rækker. Hver aktivitet
           er en række med navn + ugedage (M-S) + slet-knap. + Tilføj
           opretter en ny tom række. Skoleskema håndteres senere af AI.
        ========================================================= */
        .activities-block {
            margin-top: 1rem;
            border-top: 1px solid var(--border-color);
            padding-top: 0.75rem;
        }
        /* V21.6: "Fritidsaktiviteter"-headeren har nu en MARKANT større
           SVG til venstre for teksten — UI-feedback viste at det gamle
           1.2em-ikon næsten forsvandt mod overskriften. Vi bumper
           selve <img>-tagget direkte (i stedet for at bruge .scale-X
           på samme element, som ville rode med transform-origin og
           mismatchet flow-bredde). flex-layout sikrer at ikonet og
           teksten står lodret centreret, så det ikke "hopper" over
           teksten ved højere font-size. */
        .activities-block h4 {
            display: flex;
            align-items: center;
            gap: 0.6rem;
            margin: 0 0 0.7rem 0;
            font-size: 0.95rem;
            color: var(--text-muted);
            font-weight: 600;
        }
        .activities-block h4 .aorta-icon {
            width: 1.8em;
            height: 1.8em;
            margin-top: 0;
            margin-right: 0;
            flex-shrink: 0;
        }
        .activities-list {
            display: flex; flex-direction: column; gap: 0.5rem;
        }
        .activity-row {
            background: var(--card-bg);
            border: 1px solid var(--border-color);
            border-radius: 0.6rem;
            padding: 0.6rem 0.7rem;
            display: flex; flex-direction: column; gap: 0.5rem;
            min-width: 0;
            box-sizing: border-box;
        }
        .activity-row-top {
            display: flex; gap: 0.4rem; align-items: center;
            flex-wrap: wrap;
            min-width: 0;
        }
        .activity-emoji {
            width: 2.4rem; flex-shrink: 0;
            text-align: center;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.4rem;
            padding: 0.4rem 0;
            font-size: 1.1rem;
            box-sizing: border-box;
        }
        /* V21.3 → V21.6: Aktivitets-rækkens SVG-ikon (Activity logo2.svg)
           i venstre side. Container-størrelsen bumpet (2.4rem → 3.2rem)
           og ikonet selv (1.8em → 2.6em) så hver aktivitets-række har
           et tydeligt visuelt anker til venstre — UI-feedback viste at
           det forrige ikon var for diskret og ikke kommunikerede
           "fritidsaktivitet". transform: none nul'lér eventuel
           .scale-50-arvet skalering så ikonet vokser RENT via
           width/height (bedre layout-flow end transform). */
        .activity-emoji-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 3.2rem;
            height: 3.2rem;
            flex-shrink: 0;
        }
        .activity-emoji-icon .aorta-icon {
            width: 2.6em;
            height: 2.6em;
            margin-top: 0;
            margin-right: 0;
            transform: none;
        }
        .activity-name {
            flex: 1 1 8rem;
            min-width: 0;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.4rem;
            padding: 0.4rem 0.6rem;
            color: var(--text-main);
            font-size: 0.9rem;
            box-sizing: border-box;
        }
        /* V21.3: Tids-feltet er bredere (min-width:5rem + width:auto) så
           hele klokkeslættet "17:30" ALTID er synligt — ikke klippet
           til "17:" på smalle viewports. */
        .activity-time {
            min-width: 5rem;
            width: auto;
            flex-shrink: 0;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.4rem;
            padding: 0.4rem 0.5rem;
            color: var(--text-main);
            font-size: 0.85rem;
            box-sizing: border-box;
        }
        .activity-delete {
            background: var(--color-danger);
            color: #fff;
            border: none;
            border-radius: 0.4rem;
            width: 2rem; height: 2rem;
            cursor: pointer;
            font-weight: bold;
        }
        .activity-days {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 0.3rem;
        }
        .activity-day-toggle {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            padding: 0.35rem 0;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.4rem;
            color: var(--text-muted);
            cursor: pointer;
            user-select: none;
        }
        .activity-day-toggle.selected {
            background: var(--accent-blue);
            color: #fff;
            border-color: var(--accent-blue);
        }
        /* V21.3: '+ Tilføj aktivitet'-knap omdesignet — den stiplede
           tomme boks er erstattet med en visuelt rigere kombo:
             [rund grøn '+' cirkel]   Tilføj aktivitet
           Den runde cirkel matcher de øvrige '+'-knapper i kalenderen
           og indbakken (samme --accent-green tone), så hele appens
           "tilføj"-sprog er ensartet. Selve knappen er stadig en
           bred flexbox-knap så den giver et tydeligt klik-mål.
           Vi bruger ::before til at injicere cirklen + tegnet, så
           de eksisterende data-i18n-attributter på knappen IKKE
           rammes (de overskriver stadig text-content med den
           oversatte label "Tilføj aktivitet"). */
        .activity-add-btn {
            background: transparent;
            border: none;
            color: var(--text-main);
            padding: 0.6rem 0.4rem;
            border-radius: 0.5rem;
            cursor: pointer;
            font-size: 0.9rem;
            font-weight: 600;
            text-align: left;
            display: inline-flex;
            align-items: center;
            gap: 0.7rem;
            transition: color 0.12s ease, transform 0.12s ease;
        }
        .activity-add-btn::before {
            content: '+';
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.7rem;
            height: 1.7rem;
            border-radius: 50%;
            background: var(--accent-green);
            color: #ffffff;
            font-weight: 700;
            font-size: 1.15rem;
            line-height: 1;
            flex-shrink: 0;
            box-shadow: 0 2px 4px rgba(0,0,0,0.25);
            transition: transform 0.12s ease, box-shadow 0.12s ease;
        }
        .activity-add-btn:hover {
            color: var(--text-main);
        }
        .activity-add-btn:hover::before {
            transform: scale(1.1);
            box-shadow: 0 3px 8px rgba(0,0,0,0.35);
        }

        /* =========================================================
           V16: SHOPPING LIST MODAL — dedikeret simpel visning
           Åbnes når man klikker på indkøbsliste-ankeret i indbakken eller
           på "🛒 Indkøbstur"-eventet i kalenderen. Erstatter Edit Modal
           for shopping-anchors. Viser KUN listen + tilføj-række + køb-handling.
        ========================================================= */
        /* V21.31 (polish): overflow: hidden klipper indholdet til
           border-radius på .modal-content. Tidligere kunne den nederste
           input-række + grønne knap (med deres egen baggrund) "stikke
           ud" forbi modalens afrundede hjørner — det fik footer'en til
           at se firkantet ud i bunden mens toppen var blød. SCOPED til
           #shoppingListModal så vi ikke utilsigtet brækker den globale
           .modal-content-regel der bevidst bruger overflow: visible
           (V21.24) for at lade aorta-select-dropdowns svæve fri af
           modal-kanten i Add/Edit Event-modalen. position: relative
           er en defensiv tilføjelse så scroll-pile (sticky) inden i
           .shoplist-modal-body har en well-defined scroll-container. */
        #shoppingListModal .modal-content {
            width: min(520px, 94vw);
            max-width: 520px;
            display: flex;
            flex-direction: column;
            padding: 0;
            max-height: 88vh;
            overflow: hidden;
            position: relative;
        }
        .shoplist-modal-header {
            padding: 1.1rem 1.4rem;
            border-bottom: 1px solid var(--border-color);
            display: flex; justify-content: space-between; align-items: center;
            font-size: 1.1rem; font-weight: bold;
        }
        .shoplist-modal-header .shoplist-close {
            cursor: pointer; font-size: 1.4rem; color: var(--text-muted);
            padding: 0 0.4rem; border-radius: 0.4rem;
        }
        .shoplist-modal-header .shoplist-close:hover { color: var(--text-main); background: var(--btn-default-bg); }
        /* V21.31 (polish): Skjul native scrollbar (Chrome/Safari +
           Firefox + IE/Edge legacy) så .scroll-arrow-pilene fra
           initScrollIndicators bliver det eneste scroll-affordance.
           position: relative er nødvendig for at .scroll-arrow's
           position: sticky binder korrekt til denne container.

           V21.31 (round 2): max-height: 50vh tvinger listen til at
           scrolle tidligt i stedet for at lade modalen vokse til 88vh
           (max-height på .modal-content) ved mange varer. Resultatet:
           modalen forbliver kompakt og elegant — typisk 6-8 varer
           synlige, resten via scroll-pilene. flex: 1 er beholdt så
           body STADIG fylder al tilgængelig plads OP TIL 50vh, hvilket
           giver en stabil header → body → footer-rytme uanset om
           listen er kort eller lang. */
        .shoplist-modal-body {
            padding: 1rem 1.4rem;
            overflow-y: auto;
            flex: 1;
            min-height: 0;
            max-height: 50vh;
            position: relative;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .shoplist-modal-body::-webkit-scrollbar { display: none; }
        .shoplist-modal-add-row {
            display: grid;
            grid-template-columns: 1fr auto;
            grid-template-rows: auto auto;
            gap: 0.5rem;
            padding: 1rem 1.4rem;
            border-top: 1px solid var(--border-color);
            background: var(--bg-color);
            flex-shrink: 0;
        }
        .shoplist-modal-add-row .input-field {
            padding: 0.65rem 0.8rem;
            font-size: 0.95rem;
            min-width: 0;
            box-sizing: border-box;
        }
        .shoplist-modal-add-row .shop-name-input { grid-column: 1 / -1; }
        .shoplist-modal-add-row .shop-qty-input  { grid-column: 1; }
        .shoplist-modal-add-row .shop-add-btn {
            grid-column: 2;
            min-width: 3rem;
            font-size: 1.4rem;
            padding: 0 1rem;
        }
        .shoplist-modal-list {
            list-style: none; padding: 0; margin: 0;
            display: flex; flex-direction: column; gap: 0.4rem;
        }
        .shoplist-modal-li {
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.5rem;
            padding: 0.7rem 0.85rem;
            display: flex;
            align-items: center;
            gap: 0.7rem;
        }
        .shoplist-modal-li .shop-item-text {
            flex: 1;
            color: var(--text-main);
            font-size: 0.95rem;
        }
        .shoplist-modal-li .shop-item-qty {
            color: var(--text-muted);
            font-size: 0.78rem;
            margin-left: 0.4rem;
        }
        .shoplist-modal-li .shop-item-remove {
            background: var(--color-success); color: #1a1a1a; border: none;
            width: 28px; height: 28px; border-radius: 50%;
            cursor: pointer; font-weight: bold; font-size: 0.95rem; line-height: 1;
            display: flex; align-items: center; justify-content: center;
        }
        .shoplist-modal-empty {
            padding: 2rem 1rem;
            text-align: center;
            color: var(--text-muted);
            font-style: italic;
        }
        /* Skjul den gamle inline-liste i højre panel — vi beholder kun input-rækken.
           shop-list-ul behøves stadig som DOM-knude (eksisterende kode tegner i den),
           men den gøres helt usynlig og max-height 0 så layoutet ikke tager plads. */
        .shopping-panel .shop-list-ul {
            display: none !important;
        }

        /* =========================================================
           V21.41.2: SHOPPING AGGREGATION MODAL (#shoppingAggregationModal)
           ---------------------------------------------------------
           Vises ved word-boundary substring-tvivl mellem en ny vare
           og en eksisterende ("mælk" vs "økologisk mælk", "ost" vs
           "feta ost" osv.). Tre handlings-knapper i lodret stak,
           sammenligning af eksisterende vs ny i et 2-rækkers grid.
           Bruger eksisterende .modal-overlay + .modal-content.modal-compact
           som ramme — vi tilføjer kun de specifikke .sam-* klasser.
        ========================================================= */
        .sam-lead {
            margin: 0.25rem 0 1.1rem;
            line-height: 1.4;
            color: var(--text-muted);
        }
        .sam-comparison {
            display: flex;
            flex-direction: column;
            gap: 0.6rem;
            margin-bottom: 1.4rem;
            padding: 0.85rem 1rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.7rem;
        }
        .sam-row {
            display: grid;
            grid-template-columns: 7rem 1fr;
            gap: 0.6rem;
            align-items: baseline;
        }
        .sam-row .sam-label {
            color: var(--text-muted);
            font-size: 0.82rem;
            font-weight: 600;
        }
        .sam-row .sam-value {
            color: var(--text-main);
            font-size: 0.98rem;
            line-height: 1.3;
            word-break: break-word;
        }
        .sam-row .sam-name {
            font-weight: 600;
        }
        .sam-row .sam-qty {
            color: var(--text-muted);
            font-size: 0.85rem;
            margin-left: 0.35rem;
        }
        .sam-row-existing .sam-name {
            color: var(--accent-blue);
        }
        .sam-row-incoming .sam-name {
            color: var(--text-main);
        }
        .sam-actions {
            display: flex;
            flex-direction: column;
            gap: 0.55rem;
            margin-top: 0.25rem;
        }
        /* "Opdater eksisterende" — visuelt afdæmpet ift. primær "Tilføj som ny",
           bevidst ikke samme grønne success-farve (det skal IKKE ligne den
           primære default-handling). Gul/orange = "OBS, du flytter mængde
           ind på en eksisterende vare". */
        .sam-actions .save-btn { margin-top: 0; }
        .sam-actions .sam-btn-merge {
            background: var(--color-warning, #f0a040);
            color: #1a1a1a;
        }
        .sam-actions .sam-btn-cancel {
            background: var(--btn-default-bg, #2a2a2a);
            color: var(--text-muted);
            margin-top: 0;
        }

        /* =========================================================
           V21.43.5: ME-IDENTIFICATION PICKER MODAL ("Hvem er 'mig'?")
           ---------------------------------------------------------
           Vises på delte enheder (køkken-tablet) når voice/SMS
           indeholder "mig"/"jeg". Chip-grid med voksne + børn,
           hver med en farve-prik så brugeren genkender sin egen
           palette-farve, plus "Familie"- og "Annullér"-knapper i
           bunden. Genbruger .modal-overlay + .modal-content.modal-compact
           som ramme — kun .mim-* klasser tilføjes.
        ========================================================= */
        .mim-lead {
            margin: 0.25rem 0 1.1rem;
            line-height: 1.4;
            color: var(--text-muted);
        }
        .mim-chip-list {
            display: flex;
            flex-wrap: wrap;
            gap: 0.55rem;
            justify-content: center;
            padding: 0.85rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.7rem;
            margin-bottom: 1.2rem;
            min-height: 3rem;
        }
        .mim-chip {
            display: inline-flex;
            align-items: center;
            gap: 0.5rem;
            padding: 0.55rem 0.95rem;
            background: var(--card-bg, var(--bg-elevated, #2a2a2a));
            border: 1px solid var(--border-color);
            border-radius: 1.4rem;
            color: var(--text-main);
            font-size: 0.95rem;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.12s ease, background 0.15s ease, border-color 0.15s ease;
            -webkit-tap-highlight-color: transparent;
        }
        .mim-chip:hover {
            background: var(--accent-blue);
            color: #fff;
            border-color: var(--accent-blue);
        }
        .mim-chip:active {
            transform: scale(0.96);
        }
        .mim-chip-dot {
            display: inline-block;
            width: 0.85rem;
            height: 0.85rem;
            border-radius: 50%;
            border: 2px solid rgba(255,255,255,0.85);
            box-shadow: 0 0 0 1px rgba(0,0,0,0.25);
            flex-shrink: 0;
        }
        .mim-chip-name {
            line-height: 1;
        }
        .mim-actions {
            display: flex;
            flex-direction: column;
            gap: 0.55rem;
            margin-top: 0.25rem;
        }
        .mim-actions .save-btn { margin-top: 0; }
        .mim-actions #mim-btn-cancel {
            background: var(--btn-default-bg, #2a2a2a);
            color: var(--text-muted);
            margin-top: 0;
        }
        @media (prefers-reduced-motion: reduce) {
            .mim-chip { transition: none; }
            .mim-chip:active { transform: none; }
        }

        /* =========================================================
           V21.44: HUSSTANDSKONTO ONBOARDING-WIZARD
           ─────────────────────────────────────────────────────────
           V21.45.2: Det permanente .ha-banner blev FJERNET fordi det
           tog en hel kolonne i layoutet og forstyrrede UI. I stedet
           er onboarding-wizarden den eneste bruger-kommunikation om
           privacy-modellen — vises ÉN gang per (auth-bruger × enhed)
           ved første login som husstandskonto, kvitteres med en knap.
           Hvis du vil genintroducere et permanent visuelt mærke, brug
           en lille badge i header eller status-stribe i stedet for
           en fuld-kolonne disclaimer.

           Wizard-modal'en (ha-wizard) er en standard modal-overlay
           med UDVIDET indhold (lead + 3 punkter + tip).
           ========================================================= */

        /* Wizard-modal indre styling — mere "fortæl"-orienteret end et
           almindeligt action-modal. Liste-punkter får et lille gult
           bullet-mærke matching tidligere banner-tone. */
        .ha-wizard {
            max-width: 560px;
        }
        .ha-wizard-lead {
            font-size: 0.95rem;
            line-height: 1.45;
        }
        .ha-wizard-list {
            list-style: none;
            padding: 0;
            margin: 1rem 0 0.5rem 0;
            display: flex;
            flex-direction: column;
            gap: 0.7rem;
        }
        .ha-wizard-list li {
            position: relative;
            padding: 0.6rem 0.75rem 0.6rem 2.2rem;
            background: rgba(255,255,255,0.03);
            border: 1px solid rgba(255,255,255,0.08);
            border-radius: 0.5rem;
            font-size: 0.88rem;
            line-height: 1.4;
        }
        .ha-wizard-list li::before {
            content: "";
            position: absolute;
            left: 0.85rem;
            top: 1rem;
            width: 0.55rem;
            height: 0.55rem;
            border-radius: 50%;
            background: rgba(255,193,7,0.85);
            box-shadow: 0 0 6px rgba(255,193,7,0.45);
        }
        .ha-wizard-list li b { color: var(--text-primary, #fff); }
        .ha-wizard-tip {
            margin-top: 0.85rem;
            font-style: italic;
            opacity: 0.85;
        }

        /* =========================================================
           V21.0: NATIVE SVG-IKONSÆT — globale skalerings-klasser
           ---------------------------------------------------------
           Aorta er gået fra midlertidige Unicode-emojis (der varierer
           voldsomt i størrelse, baseline og farve på tværs af OS/font)
           til et skræddersyet SVG-bibliotek i assets/icons/.

           To klasser dækker 99% af brugen:
             • .aorta-icon     = inline med tekst (badges, knapper,
                                 event-kort, headers — 1.2em så de
                                 vokser proportionalt med font-size).
             • .aorta-icon-lg  = store ikoner (logo, dashboard-widgets,
                                 integrations-cards — 2em).

           vertical-align:middle + margin-top:-0.2em sikrer optisk
           centrering med tekst-baseline; uden marginen "hænger" SVG'en
           lidt for lavt ift. tekstens cap-height. object-fit:contain
           bevarer aspect-ratio uanset SVG'ens viewBox.
        ========================================================= */
        .aorta-icon {
            width: 1.2em;
            height: 1.2em;
            vertical-align: middle;
            display: inline-block;
            object-fit: contain;
            margin-top: -0.2em;
        }
        .aorta-icon-lg {
            width: 2em;
            height: 2em;
            vertical-align: middle;
            display: inline-block;
            object-fit: contain;
        }

        /* =========================================================
           V21.2: GLOBALE SKALERINGS-KLASSER
           ---------------------------------------------------------
           Bruges til at "boome" SVG'er i specifikke UI-flader
           (topmenu, dashboard-knapper, settings nav-bar) uden at
           ændre på fonten/teksten omkring. transform-origin sættes
           bevidst til "left center" så ikonet ikke "hopper" til
           højre når det vokser inde i en flexbox-knap.
           .icon-center bruges når et ikon skal vokse OMKRING sit
           eget center (fx i modal-headers hvor det er det eneste
           grafiske element).
        ========================================================= */
        .scale-50  { transform: scale(1.5); transform-origin: left center; }
        .scale-100 { transform: scale(2.0); transform-origin: left center; }
        .scale-150 { transform: scale(2.5); transform-origin: left center; }
        .icon-center { transform-origin: center center; }

        /* =========================================================
           V21.2: PREMIUM INPUTS & SELECTS
           ---------------------------------------------------------
           Subtile borders, blødere radius og en accent-blue glow ved
           focus. Vi targeter native inputs + select bredt; men holder
           specificiteten lav så .input-field/.select-field-overrides
           længere nede stadig vinder hvor de eksplicit sætter
           padding/farver.
        ========================================================= */
        input[type="text"],
        input[type="number"],
        input[type="date"],
        input[type="time"],
        input[type="email"],
        input[type="password"],
        input[type="search"],
        select {
            border-radius: 8px;
            border: 1px solid rgba(255,255,255,0.2);
            padding: 0.6rem;
            background: var(--bg-color);
            color: var(--text-main);
            box-sizing: border-box;
            outline: none;
            transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
        }
        [data-theme="light"] input[type="text"],
        [data-theme="light"] input[type="number"],
        [data-theme="light"] input[type="date"],
        [data-theme="light"] input[type="time"],
        [data-theme="light"] input[type="email"],
        [data-theme="light"] input[type="password"],
        [data-theme="light"] input[type="search"],
        [data-theme="light"] select {
            border-color: rgba(0,0,0,0.15);
        }
        input[type="text"]:focus,
        input[type="number"]:focus,
        input[type="date"]:focus,
        input[type="time"]:focus,
        input[type="email"]:focus,
        input[type="password"]:focus,
        input[type="search"]:focus,
        select:focus {
            border-color: var(--accent-blue);
            box-shadow: 0 0 0 2px var(--accent-blue);
        }

        /* =========================================================
           V21.2: PREMIUM 'DOT' CHECKBOXES (iOS-style cirkulære)
           ---------------------------------------------------------
           Browser-default checkbox/radio er platform-divergent og
           passer dårligt til Aorta's øvrige look. Vi nulstiller med
           appearance:none og bygger en cirkel (border-radius:50%)
           der ved :checked får en indre prik via box-shadow inset.
           Inset i bg-color giver en "donut-effekt" hvor selve
           ringen bliver accent-blå og prikken matcher kortets bg.
        ========================================================= */
        input[type="checkbox"],
        input[type="radio"] {
            appearance: none;
            -webkit-appearance: none;
            width: 1.2rem;
            height: 1.2rem;
            border-radius: 50%;
            border: 2px solid var(--text-muted);
            cursor: pointer;
            transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
            vertical-align: middle;
            margin-right: 0.5rem;
            flex-shrink: 0;
            background: transparent;
            padding: 0;
        }
        input[type="checkbox"]:checked,
        input[type="radio"]:checked {
            background-color: var(--accent-blue);
            border-color: var(--accent-blue);
            box-shadow: inset 0 0 0 3px var(--bg-color);
        }
        input[type="checkbox"]:focus-visible,
        input[type="radio"]:focus-visible {
            box-shadow: inset 0 0 0 3px var(--bg-color), 0 0 0 2px var(--accent-blue);
        }

        /* =========================================================
           V21.2: SKJULTE SCROLLBARS + DYNAMISKE PILE-INDIKATORER
           ---------------------------------------------------------
           Settings-pane og modal-body skjuler native scrollbar
           (Firefox: scrollbar-width:none, IE: -ms-overflow-style,
           WebKit: ::-webkit-scrollbar) for et renere look. I stedet
           injicerer JS to .scroll-arrow-divs (top/bottom) der fader
           ind/ud baseret på faktisk scroll-position. position:sticky
           er valgt over fixed/absolute så pilene følger med viewport
           inde i selve den scrollende container — uafhængigt af
           hvor stor containeren er.
        ========================================================= */
        .settings-pane,
        .modal-body {
            -ms-overflow-style: none;
            scrollbar-width: none;
            position: relative;
        }
        .settings-pane::-webkit-scrollbar,
        .modal-body::-webkit-scrollbar { display: none; }

        /* V21.4 → V21.5: Større scroll-pile (3.5rem) + højere z-index så
           de altid svæver OVER event-kortene (ellers blev de skjult bag
           kortenes z-index:50). z-index:200 ligger over kortene men
           under modal-overlays (z-index:1000+). */
        .scroll-arrow {
            position: sticky;
            left: 50%;
            transform: translateX(-50%);
            width: 3.5rem;
            height: 3.5rem;
            z-index: 200;
            opacity: 0;
            transition: opacity 0.2s ease;
            pointer-events: none;
            background: radial-gradient(circle, var(--bg-color) 45%, transparent 80%);
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .scroll-arrow img {
            width: 2.4em;
            height: 2.4em;
            margin-top: 0;
        }
        .scroll-arrow.visible { opacity: 0.6; }
        /* V21.6: Scroll-pile er position:sticky og lægger sig som
           DOM-børn i scroll-containeren. Sticky elementer optager
           NORMALT deres egen højde i flow'et (3.5rem) ved deres
           naturlige position — for top-pilen betyder det 3.5rem
           tomt rum FØR det første event-kort, hvilket UI-feedback
           specifikt klagede over (".. ligger ikke tæt nok på
           AORTA INDBAKKE-headeren ..").
           Løsningen er negative margin der "absorberer" pilens
           flow-bidrag uden at ødelægge sticky-positioneringen:
             • Top-pil:    margin-bottom: -3.5rem  → første card
                            kan ligge ved offset 0.
             • Bund-pil:   margin-top:    -3.5rem  → sidste card
                            ligger op ad container-bunden.
           Resultat: pilene svæver fortsat OVER kortene ved scroll
           (z-index:200, opacity:0.6), men optager ZERO flow-plads
           ved scrollTop=0 / scrollEnd. Brugeren ser nu intet "dødt"
           rum i toppen af scroll-området. */
        .scroll-arrow-top    { top: 0;    margin-bottom: -3.5rem; }
        .scroll-arrow-top img { transform: rotate(180deg); }
        .scroll-arrow-bottom { bottom: 0; margin-top: -3.5rem; }

        /* =========================================================
           V21.2 → V21.4: PRIVAT-BOKS LÆSBARHED I LIGHT MODE — RETIRET
           ---------------------------------------------------------
           Tidligere overskrev vi .tag-private's tekstfarve til hvid
           i light mode for at kompensere for den hardcodede mørke
           baggrund. V21.4 fjerner den hardcoded baggrund helt
           (kortet bruger nu var(--card-bg) som alle andre kort) +
           dashed-ramme som identitetsmarkør, så override'en er
           ikke længere nødvendig. Tom blok bevaret som breadcrumb.
        ========================================================= */

        /* =========================================================
           V21.2: VEJR-WIDGET — VIND-ROW & TØJIKON-LAYOUT
           ---------------------------------------------------------
           .wind-row vises lige under temperatur-rækken og indeholder
           pil + m/s-tekst. Tøj-ikon-spans pakkes nu så flere ikoner
           kan stå side om side (idræt + svømning + tøj på samme
           dag) i stedet for at klippes til kun én emoji som før.
        ========================================================= */
        /* V21.3 → V21.5: Vejr-stats-grid — vind + UV side om side
           ─────────────────────────────────────────────────────────────
           V21.3 introducerede en single-column wind-row under temperatur-
           rækken. V21.5 splitter rækken i to celler 50/50:
             • Venstre  = vindpil + hastighed (.wind-row)
             • Højre    = UV-index + Solcreme-advarsel (.uv-row)
           Begge er visuelle "stats-tiles" der deler styles via
           .weather-stat-basisklassen — så fontstørrelse, farve og
           padding er ensartet. Solcreme-advarslen lyser op i en
           markant accent-farve (color-warning) når UV ≥ 3 og er
           skjult ellers. */
        .weather-stats-row {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 0.6rem;
            margin-top: 0.4rem;
            margin-bottom: 0.2rem;
            align-items: stretch;
        }
        .weather-stat {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            gap: 0.2rem;
            font-size: 0.85rem;
            color: var(--text-muted);
            min-width: 0;
            padding: 0.2rem 0.3rem;
        }
        /* Bevar V21.3's pil+hastighed-row som inline flex (horisontalt
           layout) inde i den nye 2-kolonne struktur. */
        .wind-row {
            flex-direction: row;
            gap: 0.7rem;
        }
        .wind-row .wind-speed-val {
            font-size: 1.2rem;
            font-weight: 600;
            color: var(--text-main);
            letter-spacing: -0.02em;
        }
        .uv-row {
            flex-direction: column;
            gap: 0.15rem;
            text-align: center;
        }
        .uv-row .uv-val {
            font-size: 1.2rem;
            font-weight: 600;
            color: var(--text-main);
            letter-spacing: -0.02em;
        }
        /* Solcreme-advarsel: bold, accent-orange, opfanger øjet uden
           at skrige. Vi bruger color-warning (Aorta's standard for
           "vær opmærksom") så den glider visuelt sammen med resten
           af appens advarselssprog (alarm-on, FIX NU, status_hang_up
           bruger samme tone-of-voice). */
        .uv-row .uv-warning {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--color-warning);
            text-transform: uppercase;
            letter-spacing: 0.04em;
            line-height: 1.1;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
        }
        /* V21.3: Vindpilen får sit eget størrelses-ikon i stedet for
           .scale-100 fordi JS bruger inline transform:rotate(...) til at
           dreje den efter vindretning. .scale-100 ville sætte
           transform:scale(2.0) som inline-rotation derefter overskriver
           — så vi får ingen visuel skalering. Ved at bruge eksplicit
           width/height i CSS bliver ikonet større UDEN at gå gennem
           transform-stakken. */
        .wind-arrow-lg {
            width: 2em !important;
            height: 2em !important;
            margin-top: 0 !important;
            transform-origin: center center !important;
        }
        .clothing-icons {
            display: flex;
            flex-direction: column;
            gap: 0.3rem;
        }
        .clothing-icons span {
            display: flex;
            flex-wrap: wrap;
            gap: 0.2rem;
            justify-content: center;
            align-items: center;
        }

        /* V21.3: BØRNE-DYNAMISK TØJVISNING (2 SPALTER)
           ----------------------------------------------------
           Aktiveres af updateWeatherUI() når husstanden har børn i
           BEGGE kategorier (flyverdragt + vinterjakke) og temperaturen
           kræver overtøj (t < 10°C). Hver spalte får sin egen header
           (barnets navn hvis 1+1 børn, ellers kategori-label) og sit
           eget mini-grid af tøj-ikoner. Den almindelige "Mildt / En
           trøje er nok"-tekst skjules samtidig (display:none sættes
           inline fra JS), fordi den taler om HELE familien — og det
           gør splittelsen netop mod-til. */
        .clothes-two-cols {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 0.8rem;
            width: 100%;
            text-align: center;
        }
        .clothes-col {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 0.3rem;
            min-width: 0;
        }
        .clothes-col-header {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--text-blue-accent);
            text-transform: uppercase;
            letter-spacing: 0.04em;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 100%;
        }
        .clothes-col-icons {
            display: flex;
            flex-wrap: wrap;
            gap: 0.25rem;
            justify-content: center;
            align-items: center;
        }
        /* Når 2-spalte-visning er aktiv, skal #clothesIconBot fylde HELE
           bunden af weather-widget'en — derfor neutraliserer vi den
           normale .clothing-container flexbox så span'en spreder sig. */
        .weather-widget.clothes-twocol-active .clothing-container {
            display: block;
        }
        .weather-widget.clothes-twocol-active #clothesIconBot {
            display: block;
            width: 100%;
        }
        .weather-widget.clothes-twocol-active #clothesIconTop {
            display: none;
        }

        /* =========================================================
           V21.2.1: SKALERINGS-LAYOUT-FIX
           ---------------------------------------------------------
           transform: scale() ændrer kun den VISUELLE størrelse —
           layout-flowet ser stadig ikonet i sin oprindelige
           1.2em-bredde. Det betyder at tekst og naboelementer
           lægger sig oven på det skalerede ikon.

           Fix-strategien er to-delt:
             (a) Inline-kontekster (badge + tekst, briefing-title,
                 settings-nav osv.): tilføj `margin-right` på selve
                 .scale-N-klassen, der svarer til den ekstra visuelle
                 bredde ikonet optager. Beregning:
                   Ekstra bredde = (scale - 1) * 1.2em
                   • .scale-50  →  0.5 * 1.2 = 0.6em → 0.7em (airbag)
                   • .scale-100 →  1.0 * 1.2 = 1.2em → 1.4em (airbag)
                   • .scale-150 →  1.5 * 1.2 = 1.8em → 2.0em (airbag)
             (b) Standalone-knap-kontekster (.control-btn, .task-btn,
                 .corner-icon-left, .meal-icon m.fl.): ikonet er
                 alene i sin parent og skal IKKE have ekstra højre-
                 margin (det ville kun forskyde det fra centeret).
                 Vi nulstiller margin-right OG skifter transform-
                 origin til center-center så ikonet vokser symmetrisk
                 omkring knappens midte.
        ========================================================= */

        /* (a) Universel højremargin der reserverer plads til tekst-følgere. */
        .scale-50  { margin-right: 0.7em; }
        .scale-100 { margin-right: 1.4em; }
        .scale-150 { margin-right: 2.0em; }

        /* (b) Standalone-cases — ikon alene i sin parent → ingen margin
           OG center-skalering så ikonet vokser symmetrisk i knappen. */
        .icon-center,
        .control-btn .aorta-icon,
        .task-btn   .aorta-icon,
        .corner-icon-left .aorta-icon,
        .meal-icon  .aorta-icon,
        .zoom-meal-icon .aorta-icon {
            margin-right: 0;
        }
        .control-btn .aorta-icon,
        .task-btn   .aorta-icon,
        .corner-icon-left .aorta-icon,
        .meal-icon  .aorta-icon,
        .zoom-meal-icon .aorta-icon,
        .icon-center {
            transform-origin: center center;
        }

        /* TOP-MENU — bredere knapper + lidt mere mellemrum så .scale-150
           ikoner ikke stikker ud over kanten eller rammer naboknappen.
           V21.3: Knapperne i topmenuen er nu "frameless" — ingen baggrund,
           ingen border, ingen shadow. Selve SVG-ikonet svæver frit og er
           skaleret op via .scale-150 for at fungere som primær genvej. */
        .top-btn-group { gap: 1.2rem; }
        .control-btn {
            width: 3.4rem;
            height: 3.4rem;
        }
        .control-btn-frameless {
            background: transparent !important;
            border: none !important;
            box-shadow: none !important;
            padding: 0;
            color: var(--text-main);
        }
        .control-btn-frameless:hover {
            transform: scale(1.08);
            border: none !important;
            background: transparent !important;
        }

        /* TASK-BTN (vask/opvask) — udvid så .scale-100 ikonet (≈2.88rem
           ved knappens 1.5rem font-size) sidder pænt inde i den runde
           ramme uden at blive klippet af border-radius. */
        .task-btn {
            width: 4.4rem;
            height: 4.4rem;
        }

        /* SETTINGS-NAV — pr. brugerens spec: bump gap markant så de
           store .scale-150 ikoner får luft til labels (Husstanden,
           Børneprofiler osv.). Vi nulstiller .scale-150's margin-right
           her så gap'en alene styrer afstanden — ellers ville de to
           regler stable plads ovenpå hinanden og ende med >3rem mellem
           ikon og tekst.
           V21.3: Ikon-span'en er nu rykket ud til venstre kant
           (margin-left:0) og selve labels skubbes til højre via en stor
           padding-left på span'en, så teksten KLART går fri af det
           opskalerede grafik-element — uanset .scale-150's transform-
           origin. */
        .settings-nav-item {
            gap: 0;
            padding: 0.85rem 0.6rem 0.85rem 0.4rem;
        }
        .settings-nav-item .scale-150 {
            margin-right: 0;
        }
        .settings-nav-item > span:not(.settings-nav-icon) {
            padding-left: 2.6rem;
            display: inline-block;
            min-width: 0;
            /* V21.46.5: matcher den nye wrap-strategi i base-styles —
               vi vil hellere have to linjer end "Husstand & Fa..." */
            white-space: normal;
            line-height: 1.2;
        }
        .settings-nav-icon {
            margin-left: 0;
            flex-shrink: 0;
        }

        /* V21.3: Sub-ikoner inde i indstillings-panelerne (h3, h4, og
           label-spans foran fx 'Min Farve', 'Mit sprog', 'Tema',
           'Fødselsdag', 'Arbejdstider' osv.). De stod alt for små i
           forhold til labels'ne — vi opskalerer dem til 1.5em + en
           lille højre-margin så de virker som "rigtige" sektion-ikoner
           uden at gå over i det jumbo-format som .scale-150 giver
           sidebaren. */
        /* V21.7: Global opskalering af alle menu-/sektion-ikoner. 1.8em = 150% af
           .aorta-icon's 1.2em basis, så sektion-headers ('Min Profil', 'Min farve',
           'Tema', 'Fødselsdag', 'Arbejdstider', 'Hjemmets navn', 'Adresse(r)',
           'Husstandstype', 'Enheds-logins', 'Kompostbunken', 'Farezone',
           'Integrationer'), modal-headers (Kompostbunken/Farezone-modaler) og
           dz-section h4'er (Slet Børneprofil/Voksen/Husstand) alle får samme
           tydelige, indbydende ikon-størrelse. */
        .settings-pane h3 .aorta-icon,
        .settings-pane h4 .aorta-icon,
        .settings-subsection h4 .aorta-icon,
        .modal-row .modal-label .aorta-icon,
        .modal-header > .aorta-icon,
        .dz-section h4 .aorta-icon,
        .compost-modal .modal-header .aorta-icon,
        .danger-zone-modal .modal-header .aorta-icon {
            width: 1.8em;
            height: 1.8em;
            margin-right: 0.55rem;
            margin-top: -0.25em;
            vertical-align: middle;
        }
        /* Specifikt for de små farvepalette/tema-ikoner i venstre kolonne
           af option-btn'erne — bevar deres normalstørrelse, ellers
           bryder de option-knapperne. */
        .option-btn .aorta-icon {
            width: 1.2em;
            height: 1.2em;
            margin-right: 0.3rem;
        }

        /* DASHBOARD WIDGETS — eksplicit padding-airbag på titler hvor
           der står et stort ikon foran. .scale-100's universelle
           margin-right håndterer det meste, men disse to titler
           er korte og fed-tryk så vi giver dem en ekstra mikro-
           padding-left for at få teksten KLART fri af ikonet selv
           på tablet-skærme hvor base-fonten er presset. (Vi
           BEHOLDER inline-flowet — display:flex på briefing-title
           ville bryde data-i18n-applikationen der sætter inner-
           HTML'en som tekst-streng.) */
        .briefing-title { padding-left: 0.2rem; }
        .briefing-text  { padding-left: 0.2rem; }

        /* TASK-ROW (vask/opvask) — selve tekst-blokken (.task-info)
           ligger som flex-sibling efter .task-btn, så den får luft
           via row'ens gap. Men vi bumper gap'en lidt så den udvidede
           4.4rem knap stadig efterlader pænt mellemrum til titlen. */
        .task-row { gap: 1.2rem; }

        /* =========================================================
           V21.8: THE GREAT ICON REFACTOR — EM-BASEREDE STØRRELSER
           ---------------------------------------------------------
           Baggrund: V21.0–V21.7 brugte transform:scale på .scale-50/
           .scale-100/.scale-150 til at "boome" SVG-ikonerne i topmenu,
           dashboard, settings-nav osv. Det virker visuelt MEN bryder
           DOM-flow: et transform:scaled element optager IKKE sin
           visuelle størrelse i layout — det får sin originale 1.2em
           bounding-box. Vi har derfor måttet kompensere med margin-
           right airbags (.scale-50 → 0.7em, .scale-100 → 1.4em, osv.)
           og diverse "flex-row gap"-justeringer. Det giver
           uforudsigelig adfærd når layoutet skifter (mobil/tablet/
           splittede paneler).
           V21.8 indfører eksplicit width/height i em på de specifikke
           elementer brugeren har bedt om — først som målrettede
           selectors (på <img>'erne der allerede er klassificeret
           via parent), så ikon-DOM-størrelsen MATCHER den visuelle
           størrelse. Resultat: ingen "spøgelses-bredde", flexbox-
           gaps virker forventeligt, og Aorta's UI proportioner er
           forudsigelige på alle skærmstørrelser.
           Eksisterende .scale-X klasser bevares som backwards-
           compat dock-points — de leverer transform:scale OG margin-
           airbag som før, men de OVERSKRIVES af V21.8-reglerne herunder
           i de specifikke kontekster. Andre kontekster (top-menu,
           settings-nav-item) er bevidst urørte da de allerede ser
           korrekte ud med transform-tilgangen + de eksplicitte
           margin/gap-overrides der er målrettet dem. */

        /* OPGAVE 1.1: Madpakke-ikon — 1.5em med Foodpack-SVG.
           Tidligere var det en 🥪-emoji (font-size:1.5rem). V21.8
           skifter til Foodpack logo.svg som matcher resten af
           ikon-systemet (theme-aware, vector, skarpt på alle skærme). */
        .lunchbox-widget .lunchbox-icon img.aorta-icon {
            width: 1.5em;
            height: 1.5em;
            transform: none;
            margin-top: 0;
            margin-right: 0;
        }

        /* OPGAVE 1.2: H4-headers + tema-knapper + modal-headers + ikoner
           inde i sletning/gendan-knapper. Alle på 1.8em (= 150% af
           1.2em-base). V21.7-reglen ovenfor leverer allerede 1.8em på
           settings h3/h4 + modal-headers — vi udvider blot scoped'et
           til at omfatte tema-option-knapperne og knap-ikonerne i
           Kompostbunken/Farezonen.
           Vi nul'lér også .option-btn .aorta-icon's globale 1.2em-cap
           specifikt for tema-knapperne, så ikonet kan vokse ift. den
           generelle option-btn-regel (1.2em). */
        .option-group .option-btn img.aorta-icon[src*="Auto Theme"],
        .option-group .option-btn img.aorta-icon[src*="Sun"],
        .option-group .option-btn img.aorta-icon[src*="Moon"] {
            width: 1.8em !important;
            height: 1.8em !important;
            margin-right: 0.4rem;
            vertical-align: middle;
        }
        /* Knapper inde i Kompost-modalen (Gendan) + Farezone-modalen
           (Slet barn / Slet voksen / Slet husstand). Disse er alle
           .save-btn-varianter (.compost-restore-btn, .dz-delete-btn)
           og deres ikoner skal stå tydeligt i 1.8em så brugeren visuelt
           kan aflæse handlingen FØR de læser teksten. */
        .compost-restore-btn img.aorta-icon,
        .dz-delete-btn img.aorta-icon {
            width: 1.8em;
            height: 1.8em;
            transform: none;
            margin-right: 0.5rem;
            vertical-align: middle;
        }

        /* OPGAVE 1.3: H3-hovedoverskrifter (Min Profil, Husstanden,
           Børneprofiler, Integrationer) — bumpes fra V21.7's 1.8em
           op til 2.0em så de visuelt skiller sig ud fra h4 sub-
           headers. Dette er en specifik override af V21.7-reglen
           ovenfor (samme selector-stak men senere i CSS-filen vinder). */
        .settings-pane h3 .aorta-icon {
            width: 2em;
            height: 2em;
            margin-right: 0.6rem;
        }

        /* OPGAVE 2: DE 7 PREMIUM-KNAPPER — 2.4em ikoner + lækkert design
           ─────────────────────────────────────────────────────────────
           Premium-knapper er de "store handlings-knapper" der lever i
           Børneprofil-formularen og i de to administrative modaler
           (Kompost + Farezone). De har alle:
             • 2.4em ikon (sat eksplicit på <img>'et indeni)
             • Pæn padding (0.55rem 1.2rem — slank men luftig)
             • 0.9rem border-radius (premium, ikke "appy")
             • Hover-effekt (translateY-1px + udvidet shadow)
             • flex-layout med gap der respekterer ikon-bredden
           V21.7's .child-action-btn-padding (0.4rem 1rem) bevares
           ved at .btn-premium IKKE overskriver vertikal padding når
           den anvendes på child-action-btn (specifik selector vinder).
           Selve farveskemaet (success-grøn for "Gem", danger-rød for
           "Slet" osv.) sættes inline i HTML'et — det respekteres da
           vi ikke definerer background/color her. */
        .btn-premium {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 0.7rem;
            padding: 0.55rem 1.2rem;
            /* V21.10: border-radius FJERNET. .btn-premium anvendes altid
               sammen med .save-btn (Compost, Danger, Scan Skema, Gem barn,
               Slet barn — alle har class="save-btn btn-premium"), så den
               arver nu rent 50px fra .save-btn's grundregel. Mindre dublering,
               én sand kilde. */
            font-weight: 600;
            line-height: 1.2;
            cursor: pointer;
            transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
            box-shadow: 0 2px 6px rgba(0,0,0,0.18);
            border: none;
            text-align: center;
        }
        .btn-premium:hover {
            transform: translateY(-1px);
            box-shadow: 0 6px 14px rgba(0,0,0,0.28);
            filter: brightness(1.05);
        }
        .btn-premium:active {
            transform: translateY(0);
            box-shadow: 0 2px 6px rgba(0,0,0,0.18);
        }
        .btn-premium img.aorta-icon,
        .btn-premium .child-action-icon img.aorta-icon {
            width: 2.4em !important;
            height: 2.4em !important;
            transform: none !important;
            margin: 0 !important;
            flex-shrink: 0;
            vertical-align: middle;
        }
        /* For .btn-premium der OGSÅ er .child-action-btn (Scan Skema /
           Gem barn / Slet barn): genbrug V21.7's slanke vertikale
           padding (0.4rem) for at bevare den slanke pille-form, men
           giv lidt mere horisontal padding så 2.4em-ikonet får luft. */
        .child-action-btn.btn-premium {
            padding: 0.4rem 1.2rem;
        }
        /* .child-action-icon-wrapperen (V21.4-arv) skal IKKE selv have
           .scale-100's transform (det skubber ikonet visuelt videre
           hvis CSS-cascaden alligevel rammer det). Vi forcer transform-
           reset og lader inner-img'ets 2.4em være den eneste sizing. */
        .btn-premium .child-action-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            transform: none !important;
            margin: 0 !important;
            min-width: 2.4em;
            height: 2.4em;
            flex-shrink: 0;
        }

        /* OPGAVE 2.3: HUSSTANDSTYPE — RENE IKON-KNAPPER (1 hus / 2 huse)
           ─────────────────────────────────────────────────────────────
           Tidligere var "1 Husstand" / "2 Husstande" tekst-baserede
           option-btn'er. V21.8 erstatter teksten med rene house-ikoner:
             • #btn-mode-1: ÉT 2.4em House-SVG centreret
             • #btn-mode-2: TO 2.4em House-SVG'er ved siden af hinanden
           Det giver en glance-able visuel forskel uden behov for at
           læse teksten — perfekt til familie-tablet på køleskabet. */
        .household-mode-group {
            display: flex;
            gap: 0.6rem;
            justify-content: center;
            align-items: stretch;
        }
        .household-mode-btn {
            flex: 1;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 0.4rem;
            padding: 0.7rem 0.8rem;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            /* V21.9: 50px = fuldt pille-formet (matcher .btn-premium pattern).
               Tidligere 0.8rem var let-afrundet rektangel — nu helt rund
               som en iOS-segmented-control. */
            border-radius: 50px;
            cursor: pointer;
            min-height: 3.4em;
            transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
        }
        .household-mode-btn:hover {
            transform: translateY(-1px);
            border-color: var(--accent-blue);
        }
        .household-mode-btn.selected {
            background: var(--accent-blue);
            border-color: var(--accent-blue);
        }
        .household-mode-btn img.aorta-icon {
            width: 2.4em !important;
            height: 2.4em !important;
            transform: none !important;
            margin: 0 !important;
            vertical-align: middle;
        }
        /* V21.10: filter-egenskaben er HELT FJERNET. V21.8/V21.9 kæmpede
           med at få ikonet til at "skille sig ud" mod accent-blå selected-
           baggrund via brightness(0)-filter (sort ikon) eller invert(1)
           (hvidt ikon). Brugeren ønsker nu det native, farvede SVG-ikon
           uændret oven på selected-baggrunden — designet ser pænere ud
           med ikonets oprindelige tone-på-tone end med tvunget farveskift.
           Vi bevarer .selected-reglen tom som en eksplicit dokumentations-
           anker, så fremtidige iterationer ved at vi BEVIDST IKKE
           filtrerer ikonet ved selected state. */
        .household-mode-btn.selected img.aorta-icon {
            /* (intet filter — native SVG-farver bevares) */
        }

        /* V21.9: V21.8's nth-child(1)/(2) padding-override (1rem på venstre+
           center) er FJERNET — alle tre paneler har nu samme tynde 0.5rem
           padding (sat globalt på .panel ovenfor). Edge-to-edge-flowet er
           ensartet på tværs af kolonnerne, hvilket giver et roligere look
           uden vilkårligt forskellige rammetykkelser. */

        /* OPGAVE 6 (V21.9): SHOPPING-PANELET FASTLÅST I BUND
           ─────────────────────────────────────────────────────────────
           .right-panel-content er en flex-column med height:100% — som
           sammen med margin-top:auto på .shopping-panel skubber shopping-
           panelet til BUNDEN af den højre panel-kasse, uafhængigt af hvor
           få elementer indbakke-listen indeholder. Sammen med margin-bottom:
           0.5rem (matcher den nye panel-padding/grænse-tykkelse) får vi en
           perfekt "klisterbund"-effekt, hvor input-felterne aldrig falder
           ud over den ydre panel-bund.
           padding-top blev reduceret yderligere (1.5rem → 1rem) så
           top-btn-group's ikoner stadig har plads, men selve scrollbare
           indhold kan strække sig næsten lige op til top-baseline. */
        .right-panel-content {
            display: flex;
            flex-direction: column;
            /* V21.31.7: REVERT til flex:1 + min-height:0 (per brugerens reviderede spec).
               Se forklaring ved den første definition (linje ~1167). Når
               .dashboard-container har eksplicit align-items:stretch og
               .panel.right-panel har eksplicit height:100%, er parent
               .panel's højde deterministisk — flex:1 er da det korrekte
               valg fordi det både fylder parent OG opretholder flex-
               formatting context for børn (.inbox-list flex:1 1 auto +
               .shopping-panel margin-top:auto). min-height:0 låser op
               for flex-shrinking under intrinsic content-size. */
            flex: 1;
            min-height: 0;
            padding-top: 1rem;
            padding-bottom: 0;
            gap: 0.6rem;
        }

        /* =========================================================
           V21.8: WEEKLY MEAL MODAL — 7 DAGES MADPLAN
           ---------------------------------------------------------
           7 rækker (Mandag–Søndag) med ret-input + AI-opskrift-knap.
           Når brugeren trykker "Søg opskrift", folder en ingrediens-
           container ud INDE i samme modal med checkbokse til hvert
           foreslået ingrediens + en "Tilføj valgte til indkøbslisten"-
           knap. Mockup-data i V21.8 — Fase 2 hooker AI'en på.
        ========================================================= */
        .modal-content.weekly-meal-modal {
            width: min(640px, 96vw);
            max-width: 640px;
            position: relative;
            -ms-overflow-style: none;
            scrollbar-width: none;
        }
        .modal-content.weekly-meal-modal::-webkit-scrollbar { display: none; }
        .weekly-meal-list {
            display: flex;
            flex-direction: column;
            gap: 0.5rem;
            margin-top: 0.6rem;
        }
        .weekly-meal-row {
            display: grid;
            grid-template-columns: 5.5rem 1fr auto;
            gap: 0.6rem;
            align-items: center;
            background: var(--bg-color);
            border: 1px solid var(--border-color);
            border-radius: 0.7rem;
            padding: 0.55rem 0.7rem;
        }
        .weekly-meal-day {
            font-weight: 700;
            color: var(--text-main);
            font-size: 0.95rem;
            white-space: nowrap;
        }
        .weekly-meal-row .weekly-meal-input {
            width: 100%;
            min-width: 0;
            padding: 0.5rem 0.65rem;
            font-size: 0.9rem;
        }
        .weekly-meal-ai-btn {
            background: var(--accent-blue);
            color: #fff;
            border: none;
            border-radius: 0.6rem;
            padding: 0.45rem 0.7rem;
            font-size: 0.8rem;
            font-weight: 600;
            cursor: pointer;
            white-space: nowrap;
            display: inline-flex;
            align-items: center;
            gap: 0.35rem;
            transition: filter 0.15s ease, transform 0.15s ease;
        }
        .weekly-meal-ai-btn:hover { filter: brightness(1.1); transform: translateY(-1px); }
        .weekly-meal-ai-btn img.aorta-icon { width: 1.2em; height: 1.2em; transform: none; margin: 0; }

        /* AI INGREDIENS-FORSLAG CONTAINER (skjult som default) */
        .ai-ingredients-panel {
            margin-top: 1rem;
            padding: 0.9rem 1rem;
            border-radius: 0.9rem;
            background: var(--card-bg);
            border: 1px solid var(--accent-blue);
            box-shadow: 0 4px 14px rgba(41, 121, 255, 0.18);
        }
        .ai-ingredients-panel[hidden] { display: none; }
        .ai-ingredients-header {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            font-weight: 700;
            color: var(--accent-blue);
            margin-bottom: 0.5rem;
            font-size: 1rem;
        }
        .ai-ingredients-header img.aorta-icon { width: 1.4em; height: 1.4em; transform: none; margin: 0; }
        .ai-ingredients-subtitle {
            font-size: 0.8rem;
            color: var(--text-muted);
            margin-bottom: 0.7rem;
        }
        .ai-ingredients-list {
            display: flex;
            flex-direction: column;
            gap: 0.35rem;
            margin-bottom: 0.9rem;
        }
        .ai-ingredient-item {
            display: flex;
            align-items: center;
            gap: 0.55rem;
            padding: 0.4rem 0.55rem;
            background: var(--bg-color);
            border-radius: 0.5rem;
            border: 1px solid var(--border-color);
            font-size: 0.9rem;
            cursor: pointer;
        }
        .ai-ingredient-item input[type="checkbox"] {
            margin-right: 0; /* nul'lér default 0.5rem så vores gap styrer afstanden */
        }
        .ai-ingredient-name { flex: 1; }
        .ai-ingredient-qty { font-size: 0.8rem; color: var(--text-muted); }
        .ai-ingredients-actions {
            display: flex;
            gap: 0.5rem;
            flex-wrap: wrap;
        }
        .ai-ingredients-actions .save-btn {
            margin-top: 0;
            flex: 1 1 auto;
        }

        /* OPGAVE 3.1: MADPLAN-IKON I SHOPPING-PANEL HEADER
           Nyt ikon-knap i højre side af shopping-panel-header der åbner
           weeklyMealModal. Samme størrelse som indkøbs-ikonet (.aorta-
           icon-lg = 2em). Klik propagerer ikke til parent-headeren
           (vi stopper events i JS). */
        .shopping-panel-header {
            position: relative;
        }
        .shopping-mealplan-btn {
            margin-left: auto;
            background: transparent;
            border: none;
            cursor: pointer;
            padding: 0.3rem;
            border-radius: 0.5rem;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
            transition: background 0.15s ease, transform 0.15s ease;
        }
        .shopping-mealplan-btn:hover {
            background: rgba(255,255,255,0.06);
            transform: scale(1.08);
        }
        .shopping-mealplan-btn img.aorta-icon-lg {
            width: 2em;
            height: 2em;
            transform: none;
            margin: 0;
        }

        /* ============================================================
           V21.37: VOICE / STT — recording-state visual feedback
           (Step 4 §2.4.1)
           ============================================================
           Knappen #voiceTestBtn lever i Indstillinger → Integrationer
           som en almindelig dev-knap (graa baggrund, save-btn-styling).
           Mens MediaRecorder kører, tilføjer recordVoiceCommand()
           klassen .voice-test-btn-recording → vi pulserer en rød
           border + skifter baggrund til mørk-rød så brugeren tydeligt
           kan se at mikrofonen er live. CSS-only animation; ingen JS-
           ticking nødvendig udover knap-tekstens elapsed-counter.

           Vi STYLE'er IKKE selve knapteksten her — den styres af JS
           (ikon + label + counter bygges i recordVoiceCommand). CSS
           sørger kun for den visuelle "live-mic"-affordance. Når
           recorder.stop() kaldes fjerner JS klassen igen og knappen
           går tilbage til neutral grå.
           ============================================================ */
        @keyframes aortaVoicePulse {
            0%   { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.55); }
            70%  { box-shadow: 0 0 0 10px rgba(220, 38, 38, 0); }
            100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0); }
        }
        .voice-test-btn-recording {
            background: #7f1d1d !important;  /* dyb rød — overskriver inline #555 */
            color: #fef2f2 !important;
            animation: aortaVoicePulse 1.4s ease-out infinite;
        }
        /* Respect reduced-motion: brugere med 'prefers-reduced-motion'
           skal stadig kunne se RØDT (statisk shadow) men uden den
           blinkende puls — undgår triggers for vestibular-følsomhed. */
        @media (prefers-reduced-motion: reduce) {
            .voice-test-btn-recording {
                animation: none;
                box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.55);
            }
        }
