.cards-section {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    grid-auto-rows: 152px;
    gap: 0.75rem;
    width: 100%;
    padding-bottom: 1rem;
}

/* Section labels (Data / Switches / ...) - small muted, like the mockup's "Mérőszámok". */
.section-title,
.switch-section__header h3 {
    font-size: 13px;
    font-weight: 600;
    color: var(--muted-clr);
    margin: 0 0 0.5rem;
    letter-spacing: 0.2px;
}

/* Sub-group titles (a device name, a settings sub-section) - slightly more prominent. */
.subsection-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-clr);
    margin: 0 0 0.4rem;
}

.card {
    background-color: var(--list-bg);
    border: var(--border-thin);
    border-radius: var(--list-border-radius);
    box-shadow: var(--elev-rest);
    text-align: center;
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

    /* Color modification for special usecases like placeholders. */
    .card.gray {
        background-color: var(--extra-muted-clr);
        cursor: not-allowed;
    }

    /* N3 — elavult (nincs friss adat / offline) kártya: halványítva + deszaturálva jelezzük, hogy a
       mutatott érték NEM friss (az utolsó mért adat a saját dátumával látszik). Az alarm-színű (red/yellow)
       kártyák NEM kapnak Stale-t (lásd DisplaySection), így azok színe megmarad.
       FONTOS: a halványítás/deszaturálás csak a .card-content-re (tartalom) vonatkozik, NEM az egész
       kártyára — így a history (navigációs) ikon a szürke kártyákon is megőrzi a primary színét.
       (A szülőre tett opacity/filter a gyerek ikont is szürkítené, azt a gyerek nem tudja visszacsinálni.)
       A .card-body nevet szándékosan KERÜLJÜK: az a Bootstrap saját osztálya (1rem padding-et adna). */
    .card.stale-card .card-content,
    .card.nodata-card .card-content {
        opacity: 0.5;
        filter: grayscale(0.7);
    }

    .card.ghost {
        display: grid;
        place-content: center;
        height: 100%;
        border: 2px dashed var(--extra-muted-clr);
        background-color: color-mix(in srgb, var(--extra-muted-clr) 12%, transparent);
        cursor: pointer;
    }

        .card.ghost .source-name {
            display: none;
        }

        /* A tartalom (ikon + felirat) MEGBÍZHATÓ középre igazítása — a .card-content (grid) place-content:center.
           (Enélkül magasabb cellában a bal felső sarokba csúszna.) */
        .card.ghost .card-content {
            place-content: center;
        }

        /* Slim add-csempe: Add-ikon + "Kártya hozzáadása" felirat egymás alatt, középen — a régi 52pt "+"
           helyett barátságosabb, és a szerkesztő-sáv "Kártya hozzáadása" gombjával egyértelmű a jelentése. */
        .card.ghost .ghost-add {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 0.5rem;
            padding: 0.5rem;
        }

        .card.ghost .ghost-add__label {
            color: var(--muted-clr);
            font-weight: 600;
            font-size: 0.9rem;
            text-align: center;
        }

    .card.pickableCard {
        cursor: pointer;
    }

        .card.pickableCard:hover {
            background-color: color-mix(in srgb, var(--primary-clr) 8%, var(--list-bg));
            box-shadow: var(--elev-hover);
            transform: translateY(-2px);
        }

        .card.pickableCard:focus-visible {
            outline: 2px solid var(--primary-clr);
            outline-offset: 2px;
            border-radius: inherit;
        }

    .card.non-pickable {
        opacity: 0.7;
        cursor: auto !important;
    }

        .card.non-pickable:hover {
            background-color: var(--extra-muted-clr);
        }

    /* Szerkesztő módban a kártyák húzhatók (Sortable.js) — a grab-kurzor felfedezhetővé teszi az
       átrendezést. A slim add-csempe (.ghost) NEM húzható (Sortable filter: '.card.ghost'), az marad pointer. */
    .cards-section.editing .card:not(.ghost) {
        cursor: grab;
    }

        .cards-section.editing .card:not(.ghost):active {
            cursor: grabbing;
        }

    /* ── Alarm-színű kártyák (piros = Error, sárga = Warning) ──
       A kártya a SZEMANTIKUS notif-háttérrel telik meg (--critical-clr / --warning-clr, azaz --c-notif-*),
       a rajta lévő MINDEN szöveg pedig a hozzá tartozó ON-színt (--c-on-notif) viseli — EXPLICIT módon
       minden leszármazotton. Enélkül a globális `h1..h6,p,span,div { color: text-clr }` (app.css) a
       gyerekeket KÖZVETLENÜL a téma szövegszínére festené (dark témában világosra → olvashatatlan a
       kitöltésen); a .card-re tett szín csak öröklődne, amit a közvetlen elem-szabály felülír. Az on-szín
       témánként helyes (light/dark: fehér, night: szürkés-pirosas), ezért NINCS külön téma-override. */
    .card.red {
        background-color: var(--critical-clr);
    }

    .card.yellow {
        background-color: var(--warning-clr);
    }

    /* A mini-viz (SVG fill/stroke) ÉS a history-gomb ikonja is --primary-clr-t (foreground) és
       --extra-muted-clr-t (track) használ — alarm-háttéren a primary csúnya / nem látszik. A két tokent a
       kártya SCOPE-jában felüldefiniáljuk: a foreground a szöveg on-színe lesz, a track annak halvány
       (második, megengedett) változata. A custom property öröklődik → hat az SVG presentation-attribútumokra
       ÉS a history-ikon inline Color="var(--primary-clr)" értékére is, külön szabály nélkül. */
    .card.red,
    .card.yellow {
        --primary-clr: var(--c-on-notif);
        --extra-muted-clr: color-mix(in srgb, var(--c-on-notif) 30%, transparent);
    }

    .card.red,
    .card.red h1, .card.red h2, .card.red h3, .card.red p, .card.red div,
    .card.red span, .card.red span.timestamp,
    .card.yellow,
    .card.yellow h1, .card.yellow h2, .card.yellow h3, .card.yellow p, .card.yellow div,
    .card.yellow span, .card.yellow span.timestamp {
        color: var(--c-on-notif);
    }

    /* A szürke (placeholder / nem-pickelhető) kártya világos hátterén marad a sötét időbélyeg. */
    .card.gray span.timestamp {
        color: black;
    }

    .card h2 {
        font-size: 28px;
        font-weight: 600;
        margin: 0;
    }

    /* Többsoros érték (pozíció kártya: lat + lon) — kisebb betűvel, hogy a két sor
       összmagassága az egysoros 24px-es h2-ével egyezzen, különben a
       grid-auto-rows: 1fr miatt a sor összes kártyája megnyúlna. */
    .card h2.multiline {
        font-size: 16px;
        line-height: 1.2;
        margin: 5px 0;
    }

    /* Mockup-style value typography: big number + small muted unit. A kis egységet a nagy értékkel
       FÜGGŐLEGESEN KÖZÉPRE igazítjuk (mint a panel-cellák) — enélkül a baseline-igazítás a magas glifeket
       (pl. a "°" fok-jel) középre/lejjebb csúsztatta a nagy szám mellett. Mindkét spanre vertical-align:middle:
       a középpontjaik egy vonalra esnek → egymáshoz képest középre igazítva. */
    .card h2 .metric-value,
    .card h2 .metric-unit {
        vertical-align: middle;
    }

    .card h2 .metric-unit {
        font-size: 13px;
        font-weight: 400;
        color: var(--muted-clr);
        margin-left: 4px;
    }

    /* Alarm-kártyán az érték az on-színt viseli; az egység is azt örökölje (a globális muted helyett),
       csak kicsit halványabban. */
    .card.red h2 .metric-unit,
    .card.yellow h2 .metric-unit {
        color: inherit;
        opacity: 0.85;
    }

    /* No-data placeholder ("Nincs adat") — a "--" helyett olvashatóbb, halvány címke.
       Kisebb és normál súlyú, hogy ne mérőszámnak (nagy számnak) látsszon. */
    .card h2 .metric-nodata {
        font-size: 15px;
        font-weight: 500;
        color: var(--muted-clr);
    }

    .card p {
        font-size: 1rem;
        margin: 0;
    }

        .card span.timestamp {
            font-size: 11px;
            color: var(--muted-clr);
            line-height: 1.25;
        }

        /* Mockup-style freshness indicator before the timestamp. */
        .card .card-status-line {
            display: inline-flex;
            align-items: center;
            gap: 5px;
        }

.card .status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex: none;
    background: var(--c-success);
}

            .card .status-dot.stale {
                background: var(--stale-clr);
            }

.card-nav-btn {
    position: absolute;
    right: 0;
    bottom: 0;
    background: transparent;
    border: none;
    border-radius: var(--list-border-radius);
    transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}

    .card-nav-btn:focus-visible {
        outline: 2px solid var(--primary-clr);
        outline-offset: 2px;
        border-radius: inherit;
    }

/* The NoData status message and the loading ring animation is showcased on FluentUI.Overlay */
.fluent-overlay {
    border-radius: var(--list-border-radius);
    z-index: 0 !important;
}

/* Ghost element while dragging */
.sortable-ghost {
    opacity: 0.4;
    background-color: color-mix(in srgb, var(--extra-muted-clr) 30%, var(--list-bg));
}

.cards-section .card {
    padding: 11px 12px;
    text-align: left;
    /* A törlés-gomb (szerkesztő mód) abszolút pozícionálásához + a history-gomb (card-nav-btn) horgonyához. */
    position: relative;
}

/* Szerkesztő módban a törlés-gomb a kártya jobb felső sarkába LEBEG (nem foglal flow-magasságot), így a
   kártyák NEM lesznek magasabbak edit módban. Korábban a sima kártyák gombja in-flow volt → megnyúltak, és
   a grid-auto-rows:1fr miatt a paneleket is felnyújtotta. A speciális kártyák (switches/preset/panelek) már
   így csinálták; ez a szabály az ÖSSZES kártyára kiterjeszti. */
.cards-section .card > fluent-button {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
}

.card > div {
    height: 100%;
    display: grid;
}

/* min-width: 0 — grid-itemek alapból nem mehetnek a tartalmuk min-mérete alá
   (min-width: auto). A chart canvas inline pixel-szélességet kap a Chart.js-től,
   ami ablak-szűkítéskor nyitva tartaná ezt a láncot: a kártya összemegy, de a
   belső gridek a régi canvas-szélességen ragadnak és túllógnak → a Chart.js
   resize-mérése is a felfújt wrappert látja, így sosem zsugorít. */
.card > div > div {
    display: grid;
    align-items: end;
    min-width: 0;
}

.chart-content {
    min-width: 0;
    /* A "nincs adat" / betöltés FluentOverlay horgonya: az overlay-t a .chart-content-be
       tettük (ChartCard.razor), így az CSAK a chart-régiót fedi, nem az egész kártyát —
       a kártya címe (forrásnév) látható marad, hogy lássék, MELYIK jelnek hiányzik az adata. */
    position: relative;
}

/* A chart-régió overlay-ének teteje a kártya KÖZEPÉN van (a fejléc alatt), nem a kártya felső
   élén — ezért ott ne legyen lekerekítés (különben a szürke lap teteje "úszó" pirulának néz ki).
   Csak az alsó sarkok maradnak lekerekítve, a kártya alsó éléhez igazodva. */
.chart-content .fluent-overlay {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

p.source-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.4;
    font-size: 12px;
    color: var(--muted-clr);
}

.chartbuttons {
    float: right;
    top: 4px;
    right: 4px;
    position: absolute;
    display: block;
}

.marked-for-deletion {
    opacity: 0.3;
    pointer-events: none;
}

/* Chart card */
.value-card {
    display: flex;
    justify-content: space-around;
    gap: 1rem;
    padding: 0.5rem;
    margin-top: 0.5rem;
    border-bottom-left-radius: var(--list-border-radius);
    border-bottom-right-radius: var(--list-border-radius);
    background: var(--background-clr);
}

:root[data-theme="dark"] .value-container label {
    color: var(--muted-clr);
}

:root[data-theme="dark"] .value-container .value {
    color: var(--text-clr);
}

.value-card .value-container {
    display: grid;
    gap: 0.25rem;
}

.value-container label {
    font-weight: 500;
}

.value-container .value {
    font-size: 1.125rem;
}

@media (max-width: 900px) {
    .value-card {
        gap: 0.25rem;
        padding: 0.25rem 0.5rem;
        margin-top: 0.25rem;
    }

    .value-container label {
        font-size: 0.7rem;
    }

    .value-container .value {
        font-size: 0.875rem;
    }
}

@media (max-width: 900px) {
    .chart-content.chart-no-data {
        display: none;
    }
}

/* A kamera-kártyák ugyanazzal a track-mérettel folynak mint a metrika-kártya-rács
   (.cards-section), és egyenként 2 oszlopot fognak át — így pontosan 2 sima kártya szélesek,
   nem nyúlnak teljes szélességűre. */
.cameras-wrapper {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    column-gap: 0.75rem;
    row-gap: 0.75rem;
    align-items: start;
    margin-top: 20px;
}

    .cameras-wrapper > * {
        grid-column: span 2;
    }

/* ── Kamera a metrika-rácson belül ──
   A kamera-kártya a többi kártyával EGY rácsban (.cards-section) él, ugyanazzal a SortableJS
   listával húzható/rendezhető, de 2×2 cellát fog át (= "4 kártyányi" hely), így nem nyúlik teljes
   szélességűre. Megjelenítéskor élő videó, szerkesztés módban placeholder áll a helyén. */
.cards-section .card.camera-card {
    grid-column: span 2;
    grid-row: span 2;
}

/* A videó/placeholder a fejléc (forrásnév + kamera neve) alatt, a kártya teljes szélességében. */
.cards-section .card.camera-card .video-wrapper,
.cards-section .card.camera-card .camera-card__placeholder {
    margin-top: 6px;
    width: 100%;
}

/* A belső grid alapból a value-t a kártya aljára igazítja (align-items:end) — a kamera törzse
   inkább a fejléc alól, fentről induljon. */
.cards-section .card.camera-card > div > div {
    align-items: stretch;
    align-content: start;
}

/* Szerkesztés módú placeholder: a 2×2-es helyfoglalást mutatja élő HLS lejátszó nélkül. */
.camera-card__placeholder {
    display: grid;
    place-items: center;
    align-content: center;
    gap: 6px;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    background: var(--background-clr);
    color: var(--muted-clr);
    font-size: 13px;
    text-align: center;
}

/* Mobil/keskeny nézetben (a dashboard ekkor egyoszlopos, de a kártya-rácsban még elfér 2-3 db
   200px-es oszlop) a kamera-kártya TELJES szélességű legyen — a fél/kétharmad széles tile-on a kis
   videó csúnyán hatott. A "1 / -1" az egész sort átfogja, az aktuális oszlopszámtól függetlenül;
   grid-row:auto, hogy teljes szélességnél ne foglaljon feleslegesen 2 sort.

   FONTOS: a teljes szélességű kamera egyetlen magas sort képez, a rács globális grid-auto-rows:1fr
   pedig fix konténer-magasság híján MINDEN sort a legmagasabbhoz (a kameráéhoz) igazítana → a sima
   kártyák is megnyúlnának. Ezért itt a sorok a saját tartalmukhoz méreteződnek (auto): csak a kamera
   lesz magas, a telemetria-kártyák tömörek maradnak. (Desktopon marad az 1fr az egységes magassághoz.) */
@media (max-width: 768px) {
    .cards-section {
        grid-auto-rows: auto;
    }

    .cards-section .card.camera-card {
        grid-column: 1 / -1;
        grid-row: auto;
    }
}

/* ── Kedvenc kapcsolók a metrika-rácson belül ──
   A FavSwitchesComponent (korábban a dashboard jobb felső fix dobozában) most a kamerával AZONOS módon
   egy opcionális, húzható/rendezhető 2×2 kártya a metrika-rácson belül. A megjelenést a komponens SAJÁT
   kártya-kerete (.fav-switches-card) adja, ezért a külső .card keretét/hátterét/paddingjét semlegesítjük
   (nincs dupla keret) — így a kapcsoló-kártya kinézete változatlan marad. */
.cards-section .card.switches-card {
    grid-column: span 2;
    grid-row: span 2;
    position: relative;
    background: transparent;
    border: none;
    box-shadow: none;
    padding: 0;
    overflow: visible;
    /* Floor, hogy szomszéd-kártyák híján (pl. külön sorba kerülve) se essen össze a belső, abszolút
       pozícionált tartalom (lásd lent). Felfelé NEM nő a tartalomtól — a magasságot a 2×2 cella adja. */
    min-height: 160px;
}

/* A belső tartalom-wrapper a 2×2 cellát ABSZOLÚT pozícióval tölti ki. Ez a kulcs ahhoz, hogy a sok
   kapcsolóból álló hosszú lista NE nyújtsa meg a kártyát: in-flow tartalomként a grid-item a lista
   min-content magasságára nőne (a height:100% + min-height:0 + overflow:hidden ezt NEM akadályozza
   meg — mérésekkel igazolva). Abszolút pozícióval a wrapper nem járul hozzá a kártya intrinsic
   magasságához → a kártyát a 2×2 cella (szomszéd adat-kártyák) mérete adja, a .fav-switches-scroll
   pedig görget, ha a kapcsolók nem férnek ki. (A kamera-kártyánál ez nem kell.) */
.cards-section .card.switches-card > div {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
}

/* A belső magasság-láncot FLEX-szel kötjük be (NEM height:100% százalékkal): a #switch-section
   container-type:inline-size-a (a .name cqw-alapú betűméretéhez kell) megakadályozza, hogy a
   height:100% feloldódjon → a lista a tartalom-magasságra nőtt és túllógott a 2×2 cellán. A flex
   (flex:1 + min-height:0) ezt megkerüli: minden szint a szülő definit magasságára feszül, így a
   .fav-switches-scroll helyesen görget. */
.cards-section .card.switches-card > div > div {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* align-items:stretch KÖTELEZŐ: a globális kártya-szabály a belső grid-re align-items:end-et tesz
       (a metrika-értéket a kártya aljára igazítja). Flex-column-ban az "end" VÍZSZINTESEN zsugorítja a
       gyerekeket a tartalom-szélességre → keskeny viewporton a kapcsoló-doboz és az edit-placeholder
       0/55px-re esett össze ("a switches kártya eltűnt"). A stretch teljes szélességre feszíti őket. */
    align-items: stretch;
}

.cards-section .card.switches-card #switch-section {
    flex: 1 1 auto;
    min-height: 0;
    /* A #switch-section container-type:inline-size-a (a .name cqw betűméretéhez) megtöri a flex
       cross-tengelyű (vízszintes) align-items:stretch-et → keskeny viewporton 0 szélességre esett
       össze a kapcsoló-doboz ("eltűnt"). Explicit width:100% kikényszeríti a teljes szélességet. */
    width: 100%;
}

/* Szerkesztés módban a törlés-gomb a kártya jobb felső sarkába lebeg (a belső tartalom fölé),
   mivel a külső .card paddingja itt 0. */
.cards-section .card.switches-card > fluent-button {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
}

/* Szerkesztés módú placeholder: a 2×2-es helyfoglalást mutatja az élő (interaktív) kapcsoló-kártya
   nélkül, hogy a húzás gördülékeny legyen és reorder közben ne lehessen véletlenül kapcsolni. */
.switches-card__placeholder {
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
    min-height: 160px;
    padding: 8px 10px;
    border-radius: var(--list-border-radius);
    border: var(--border-thin);
    background: var(--list-bg);
    color: var(--muted-clr);
    font-size: 13px;
    text-align: center;
}

/* A placeholder-ikon a fejléc alatti maradék helyet tölti, középre igazítva (a footage-panel mintája). */
.switches-card__placeholder-body {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Mobil/keskeny nézet: a kamera mintájára teljes szélességű, hogy a kapcsolók kényelmesen elférjenek. */
@media (max-width: 768px) {
    .cards-section .card.switches-card {
        grid-column: 1 / -1;
        grid-row: auto;
    }
}

/* ── Preset-kártya a metrika-rácson belül ──
   A térkép fölötti lebegő preset-pilleket leváltó, kihelyezhető kártya: a kamerával/kapcsolókkal AZONOS
   módon él a rácsban (egy SortableJS lista), 2×2 cellát fog át. A külső .card keretét MEGTARTJUK (a régi
   pilleknek nem volt saját kerete) — a "Presets" fejléc a kártya SourceName-je, a tartalom (gombrács +
   lapozó) a PresetCardComponent. */
.cards-section .card.preset-card {
    grid-column: span 2;
    grid-row: span 2;
    position: relative;
}

/* Szerkesztés módban a törlés-gomb a kártya jobb felső sarkába lebeg (a tartalom fölé), hogy ne foglaljon
   sort a magasság-rácsban (különben letolná a fejlécet/gombrácsot). A kapcsoló-kártyával egyezően. */
.cards-section .card.preset-card > fluent-button {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
}

/* Magasság-lánc: a fejléc (auto sor) alatt a tartalom (PresetCardComponent) kitölti a 2×2 cellát. */
.cards-section .card.preset-card > div {
    grid-template-rows: auto 1fr;
}

.cards-section .card.preset-card > div > div {
    align-items: stretch;
    align-content: stretch;
    height: 100%;
    min-height: 0;
}

/* Szerkesztés módú placeholder: a 2×2-es helyfoglalást mutatja az élő (interaktív) preset-kártya nélkül,
   hogy a húzás gördülékeny legyen és reorder közben ne lehessen véletlenül presetet aktiválni. */
.preset-card__placeholder {
    display: grid;
    place-items: center;
    align-content: center;
    height: 100%;
    min-height: 120px;
    color: var(--muted-clr);
}

/* Mobil/keskeny nézet: a kamera/kapcsolók mintájára teljes szélességű. */
@media (max-width: 768px) {
    .cards-section .card.preset-card {
        grid-column: 1 / -1;
        grid-row: auto;
    }
}


/* Percentage fill bar (tank level, fuel, humidity, battery SoC ...) — mockup metric "csík". */
.card .card-bar {
    width: 100%;
    height: 4px;
    margin: 5px 0 2px;
    border-radius: 3px;
    background: var(--extra-muted-clr);
    overflow: hidden;
}

.card .card-bar__fill {
    height: 100%;
    border-radius: 3px;
    background: var(--primary-clr);
    transition: width .3s ease;
}

/* N1 — per-típus mini-vizualizáció (szélirány-nyíl, hőmérő). A value MELLÉ kerül (metric-row),
   NEM alá → a kártya NEM nő magasabbra; a jobb oldali üres helyet használja. Token-színek (mind a 3 témán jó). */
.card .metric-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

/* A dashboard telemetria-kártyáin (.cards-section) a value BALRA, a mini-viz a JOBB oldali üres
   helyre kerül (N1). Máshol (chart-kártyák a .wireframe-ben, kamera stb.) nincs viz, ott a value
   maradjon KÖZÉPEN — különben a space-between az egyetlen value-t balra húzná. */
.cards-section .card .metric-row {
    justify-content: space-between;
}

.card .card-viz {
    display: inline-flex;
    align-items: center;
    flex: none;
}

    .card .card-viz__dir {
        width: 24px;
        height: 24px;
        transition: transform .3s ease;
    }

    .card .card-viz__compass {
        width: 24px;
        height: 24px;
    }

        .card .card-viz__compass g {
            transition: transform .3s ease;
        }

    .card .card-viz__thermo {
        width: 13px;
        height: 26px;
    }

    /* Mélység hullám-vonalak — a dir/compass mintájára négyzetes. */
    .card .card-viz__depth {
        width: 22px;
        height: 22px;
    }

    .card .card-viz__rudder,
    .card .card-viz__gauge {
        width: 30px;
        height: 19px;
    }

    /* Áram-irány nyíl (töltés/merítés) — a dir/compass mintájára. */
    .card .card-viz__arrow {
        width: 20px;
        height: 20px;
    }

        .card .card-viz__rudder g,
        .card .card-viz__gauge g {
            transition: transform .3s ease;
        }

    /* SoC kitöltött gyűrű (a .card-bar % körkörös változata): a primary ív hossza a stroke-dashoffset-tel
       animálódik, így a töltöttség változása gördülékeny — a compass/dir mintájára 24×24. */
    .card .card-viz__ring {
        width: 24px;
        height: 24px;
    }

        .card .card-viz__ring circle {
            transition: stroke-dashoffset .3s ease;
        }

/* === Kártya függőleges ritmusa (név ↔ secondline + levegő a metrika-sor körül) ========================
   A .card-content rács KÉT `auto` sorból áll (NÉV + törzs), és az `align-content: stretch` (a normal
   alapérték) a maradék helyet EGYENLŐEN szórja szét a két sorra: ~8px a névsor ALÁ (holt hely, nem
   margó — a névsor nyúlik meg, a szöveg a tetején marad), a másik ~8px a törzsé. A törzsön belül
   ugyanez ismétlődik (lásd a következő blokkot), így a forrásnév és a secondline közé összesen ~11px
   holt hely került.
   Explicit `auto 1fr`: a névsor pontosan a szövege, MINDEN maradék a törzsé — a név és a secondline
   összezár.
   A :has() FONTOS: a CardComponent üres SourceName esetén ki sem rendeli a .source-name-et (add-csempe,
   kapcsoló-kártya), ott a törzs az EGYETLEN rácselem — fix `auto 1fr` mellett az `auto` sorba esne és
   a tartalmához zsugorodna (az add-csempe középre igazítása és a kapcsoló-kártya teljes magassága
   elveszne). Névsor nélkül tehát marad az egy-soros stretch. */
.cards-section .card > .card-content:has(> .source-name) {
    grid-template-rows: auto 1fr;
}

/* A törzs (secondline + metrika-sor + [%-csík] + dátum) alapból RÁCS `align-items: end`-del (lásd a
   `.card > div > div` szabályt fent): minden elem a saját — egyenlően felnyújtott — sorának az ALJÁN ül,
   ezért a hézag mindig az elem FÖLÉ kerül, a metrika-sor alá pedig SEMMI nem jut → a gauge-mód 56px-es
   vize gyakorlatilag nekifekszik a dátumsornak.
   Flex-oszlopban ez irányítható: a maradék helyet KÉT auto-margó osztja el egyenlően — a metrika-sor
   fölé és a dátum fölé. Következmény: a dátum marad a kártya alján (ott is volt, az `end` miatt), a
   metrika-sor ALÁ viszont ~8px levegő kerül (2.8px helyett), a sor pedig ennyivel feljebb csúszik, így
   a nagy viz nem ér hozzá a dátumhoz.
   Miért auto-margó és nem fix padding: ha a secondline két sorba törik, az auto-margók maguktól 0-ra
   fogynak → a tartalom nem csordul ki a 152px-es cellából.
   Az `align-items: stretch` KÖTELEZŐ: a fenti globális szabály `end`-je flex-oszlopban már a KERESZT-
   (vízszintes) tengelyre szólna, azaz jobbra zsugorítaná a sorokat (ugyanez a csapda a switches-card
   szabálynál is dokumentálva van).
   A :has() kizárja a panel / kamera / kapcsoló-kártyákat: azoknál HideLast → nincs .metric-row, a
   törzsük elrendezése (és a panels.css abszolút-pozíciós felülírása) érintetlen marad. */
.cards-section .card > .card-content > div:has(> .metric-row) {
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

    .cards-section .card > .card-content > div > .metric-row,
    .cards-section .card > .card-content > div > p:last-child {
        margin-top: auto;
    }

/* === Metrika-sor FIX magasság + gauge mód (WS_CardGaugeModes) ========================================
   FIX SOR-MAGASSÁG: a metric-row MINDEN telemetria-kártyán fix 56px (nem csak a gauge-képeseken) →
   a card-content grid nem osztja szét eltérően a maradék helyet, így a forrásnév / secondline / dátum
   kártyáról kártyára AZONOS magasságban van, és a gauge be/ki váltás sem mozdítja őket ("keret").
   56px a legmagasabb, ami a legszűkebb kártyán (source-name + secondline + sor + zónás timestamp) is
   elfér a 152px cellában. A %-csíkos kártyák (--withbar) sora rövidebb (45px), mert alatta ott a 11px
   csík: a sor + csík együtt ≈ 56px, így a dátumsor ott is egy vonalban marad a többivel.
   (A dátum függőleges helyét MOST már a fenti "függőleges ritmus" blokk auto-margója horgonyozza a
   kártya aljára; ez a fix sor-magasság így az ÉRTÉK-blokk egységes helyét/magasságát tartja.) */
.cards-section .card .metric-row {
    height: 56px;
}

    .cards-section .card .metric-row--withbar {
        height: 45px;
    }

/* Gauge mód: UGYANAZ a markup (h2 + .card-viz), csak ez a módosító kerül a sorra; a viz (56px) pont
   kitölti a fix sort. A MŰSZER áll pontosan a sor közepén, a kis érték MELLETTE (jobbra) — ezért 3
   oszlopos rács a korábbi row-reverse flex helyett: ott a viz + érték EGYÜTT került középre, így a
   műszer kártyánként máshová esett (az érték szélességétől függően), és a rács se volt egy vonalban.
   A két szélső 1fr sáv definíció szerint egyforma → a középső (auto) viz-oszlop a sor közepére esik.
   Szándékosan `1fr` és NEM `minmax(0, 1fr)`: ha az érték szélesebb a fél maradéknál, a jobb oldali
   sáv a tartalmáig nő (a bal rovására) és a műszer arrébb csúszik — vagyis a szöveg sosem vágódik le,
   csak a tökéletes középre-igazítás enged (a mai viselkedés). */
.cards-section .card .metric-row--gauge {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 2px;
}

    /* MINDKETTŐN KELL a `grid-row: 1`! A DOM-ban a h2 (3. oszlop) áll elöl, a viz (2. oszlop) mögötte:
       ha csak az oszlopukat kötjük meg, az auto-elhelyezés "sparse" szabálya a visszafelé lépő elemet
       ÚJ SORBA teszi (a kurzor már a 3. oszlop után jár) → a viz a 2. sorba esik, az érték fölé, a sor
       tartalma 56px helyett ~73px lesz és alul belelóg a dátumba. Explicit sorral egyetlen sor marad. */
    .cards-section .card .metric-row--gauge .card-viz {
        grid-column: 2;
        grid-row: 1;
    }

    /* A justify-self:start teszi közvetlenül a műszer mellé (a sávján belül balra zárva), nem a jobb
       sáv közepére. */
    .cards-section .card .metric-row--gauge h2 {
        grid-column: 3;
        grid-row: 1;
        justify-self: start;
        font-size: 1rem;
        line-height: 1;
        margin: 0;
    }

    .cards-section .card .metric-row--gauge .metric-unit {
        font-size: 12px;
    }

    /* Négyzetes viewBox-ú vizek (irány/iránytű/SoC-gyűrű/áram-nyíl/mélység-hullám) egységes 56×56. */
    .cards-section .card .metric-row--gauge .card-viz__dir,
    .cards-section .card .metric-row--gauge .card-viz__compass,
    .cards-section .card .metric-row--gauge .card-viz__ring,
    .cards-section .card .metric-row--gauge .card-viz__arrow,
    .cards-section .card .metric-row--gauge .card-viz__depth {
        width: 56px;
        height: 56px;
    }

    .cards-section .card .metric-row--gauge .card-viz__thermo {
        width: 36px;
        height: 56px;
    }

    .cards-section .card .metric-row--gauge .card-viz__rudder,
    .cards-section .card .metric-row--gauge .card-viz__gauge {
        width: 84px;
        height: 56px;
    }

    /* Optikai igazítás — a félkör-mérő és a hőmérő RAJZA nem tölti ki függőlegesen a viewBox-át (a mérő
       rajza y=3..17.8 a 0..19-ből, a hőmérőé y=3..27 a 0..28-ból), ezért a rajz közepe a doboz közepe
       ALATT van (mérő: +2.5px, hőmérő: +2px a nagyított méreteken). A doboz közepére igazított érték
       emiatt látszik magasabbnak a műszernél — ennyivel feljebb toljuk a rajzot, így a műszer közepe és
       az érték egy vonalba kerül. A transform NEM befolyásolja a layoutot (a sor 56px marad), és ezeknek
       az SVG-knek nincs elem-szintű transformjuk: a mutató forgatása a belső <g>-n ül. (A rudder/nyíl/
       iránytű/gyűrű/hullám rajza már eleve középen van, azokat nem kell tolni.) */
    .cards-section .card .metric-row--gauge .card-viz__gauge {
        transform: translateY(-2.5px);
    }

    .cards-section .card .metric-row--gauge .card-viz__thermo {
        transform: translateY(-2px);
    }

/* No-data card: the freshness dot must NOT read as "fresh" (green) when there is no value.
   A muted grey dot keeps the row aligned without falsely signalling live data. */
.card .status-dot.nodata {
    background: var(--extra-muted-clr);
}

/* === Panel-előnézet (kártya-választó ÉS dashboard szerkesztő mód) =====================================
   A panelek élő komponensként jelennek meg. display:contents → a burkoló nem hoz létre boxot, így a
   panels.css elrendezése (a ChildContent-burkoló > .panel viszony) változatlanul érvényes; a panel az
   előnézetben is helyesen tölti a kártyát. A --static módosító letiltja a panelen belüli pointer-eventeket
   (kártya-választóban MINDIG, a dashboard szerkesztő módjában is) — így a panelen belüli gombok (pl.
   presets-mini) nem sülnek el, a húzás gördülékeny, és a kattintás a kártyára (hozzáadás) jut. */
.panel-preview {
    display: contents;
}

.panel-preview--static * {
    pointer-events: none;
}

/* === Kártya-választó (CardPickerDialog) ===============================================================
   Domain-választó gombsor: egyszerre EGY domaint látunk (a cím-fejlécek helyett kattintható "tab"-ok). */
/* A body felső paddingja (user-kérés: 20px). A dialógus MINDIG "nagyban" nyíljon (mintha görgetni lehetne),
   de a KÁRTYÁK mérete maradjon szokásos: a min-magasság a BODY-n van (NEM a rácson) → a rács a tartalmához
   méreteződik (felül marad), a maradék hely üres; sok kártyánál a body túlnő és a dialógus görget. Korábban a
   rácson volt a min-height → a grid-auto-rows:1fr felnyújtotta az egyetlen sornyi 1×1 kártyát. */
.picker-body {
    padding-top: 20px;
    /* A dialógus fix 90dvh (GhostCard DialogParameters.Height) → a body kitölti a rendelkezésre álló magasságot;
       a rács felül marad (kártyák normál méret), a maradék üres / a body görget sok kártyánál. A flex:1 + a
       min-height:100% együtt kitölti a body-t akár flex-, akár definit-magasságú a FluentDialogBody. */
    flex: 1 1 auto;
    min-height: 100%;
    display: flex;
    flex-direction: column;
}

/* Kereső: ikon + input egy pill-sorban, a tabok/rács fölött. */
.picker-search {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    padding: 0.4rem 0.85rem;
    border: var(--border-thin);
    border-radius: 999px;
    background: var(--list-bg);
}

.picker-search:focus-within {
    border-color: var(--primary-clr);
}

.picker-search__input {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    background: none;
    outline: none;
    color: var(--text-clr);
    font-size: 0.9rem;
}

.picker-search__input::placeholder {
    color: var(--muted-clr);
}

/* Kereső törlése (X) a sáv végén — csak nem üres keresőnél jelenik meg. */
.picker-search__clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    padding: 2px;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--muted-clr);
    cursor: pointer;
}

.picker-search__clear:hover {
    color: var(--text-clr);
}

.picker-search__clear:focus-visible {
    outline: 2px solid var(--primary-clr);
    outline-offset: 1px;
}

/* Üres domain-csoport: középre igazított üzenet, ami kitölti a body maradék (üres) magasságát. A pickerben
   NEM dőlt (user-kérés). A szöveg-spanre EXPLICIT muted (a globális `span{color:text-clr}` felülírná). */
.picker-empty-group {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    color: var(--muted-clr);
    font-size: 14px;
    text-align: center;
}

.picker-empty-group span {
    color: var(--muted-clr);
}

.picker-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 1rem;
}

.picker-tab {
    padding: 0.35rem 0.8rem;
    border: var(--border-thin);
    border-radius: 999px;
    background: var(--list-bg);
    color: var(--text-clr);
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.picker-tab:hover {
    border-color: var(--primary-clr);
}

.picker-tab--active {
    background: var(--primary-clr);
    border-color: var(--primary-clr);
    color: var(--c-on-primary, #fff);
}

/* Már kihelyezett kártya jelzése a pickerben: HANGSÚLYOS brand-keret — primary border + 2px primary gyűrű
   (box-shadow, nincs layout-eltolás). A régi zöld pipa-badge helyett (user-kérés: legyen erősebb a keret). */
.picker-grid .card.picker-onboard {
    border-color: var(--primary-clr);
    box-shadow: 0 0 0 2px var(--primary-clr);
}

/* Törlés-gomb (CardComponent Closeable) — UGYANAZ a kör-alakú gomb a dashboard szerkesztő módjában ÉS a
   kártya-választóban. Magas z-index + saját pointer-events → az élő panel-tartalom fölött is megbízhatóan
   kattintható. A .card már position:relative (lásd .cards-section .card / panel-keretek), így a jobb felső
   sarokhoz horgonyzódik, és NEM ad flow-magasságot (a kártyák edit módban sem lesznek magasabbak). */
.cards-section .card > .card-remove {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: 50%;
    border: var(--border-thin);
    background: var(--list-bg);
    box-shadow: 0 1px 3px var(--c-shadow-sm);
    cursor: pointer;
    pointer-events: auto;
}

.cards-section .card > .card-remove:hover {
    border-color: var(--delete-clr);
}

/* Gauge-mód kapcsoló (CardComponent ShowGaugeToggle) — a törlés-gomb tükörképe a BAL felső sarokban;
   csak szerkesztő módban, gauge-képes kártyán renderelődik. Bekapcsolt állapotban (.on) primary keret +
   halvány primary töltés jelzi, hogy a kártya műszer-nézetben áll. */
.cards-section .card > .card-gauge-toggle {
    position: absolute;
    bottom: 6px;
    right: 6px;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border-radius: 50%;
    border: var(--border-thin);
    background: var(--list-bg);
    box-shadow: 0 1px 3px var(--c-shadow-sm);
    cursor: pointer;
    pointer-events: auto;
}

.cards-section .card > .card-gauge-toggle:hover {
    border-color: var(--primary-clr);
}

.cards-section .card > .card-gauge-toggle.on {
    border-color: var(--primary-clr);
    background: color-mix(in srgb, var(--primary-clr) 12%, var(--list-bg));
}
