/* ============ Login ============ */
.login-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-alt);
    padding: 24px;
}
.login-card {
    background: #fff;
    border: 1px solid var(--line);
    padding: 44px 40px;
    width: 100%;
    max-width: 400px;
    box-shadow: 0 20px 50px rgba(0, 0, 0, .06);
}
.login-logo { height: 42px; width: auto; margin-bottom: 26px; }
.login-card h1 { font-size: 22px; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 24px; }
.checkbox-row { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted); margin-bottom: 20px; }
.checkbox-row input { width: auto; }
.btn-block { width: 100%; text-align: center; }
.login-back { display: inline-block; margin-top: 22px; font-size: 14px; color: var(--muted); text-decoration: none; }
.login-back:hover { color: var(--black); }

/* ============ Admin shell ============ */
.admin {
    display: grid;
    grid-template-columns: 250px 1fr;
    /* Fixed row = viewport height (minmax(0,…) stops the row growing to content) so each column
       is exactly 100dvh tall and scrolls its own overflow — sidebar nav vs. main content. */
    grid-template-rows: minmax(0, 100dvh);
    height: 100dvh;
    overflow: hidden;
    background: var(--bg-alt);
}

.admin-sidebar {
    background: #edeff2;
    color: #3a3a3a;
    border-right: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    padding: 14px 14px;
    height: 100%;
    min-height: 0;
}
.admin-brand { padding: 2px 6px 10px; border-bottom: 1px solid #dfe1e6; margin-bottom: 8px; }
.admin-brand-link { display: flex; flex-direction: column; gap: 8px; text-decoration: none; }
.admin-logo { max-height: 40px; max-width: 100%; width: auto; object-fit: contain; align-self: flex-start; }

/* Nav scrolls on its own so brand + footer stay pinned and the grey fills the full height even
   on short screens (flex child needs min-height:0 to be allowed to shrink and scroll). */
.admin-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; min-height: 0; margin: 0 -6px; padding: 0 6px; }
.admin-nav a {
    text-decoration: none;
    color: #3a3d42;
    padding: 7px 11px;
    border-radius: 7px;
    font-size: 13.5px;
    font-weight: 500;
    transition: background .15s ease, color .15s ease;
}
.admin-nav a:hover { background: #e2e5ea; color: var(--black); }
.admin-nav a.active { background: var(--accent); color: #fff; }
/* Thin divider between logical nav groups (Inhalt / Konfiguration / Verwaltung). */
.admin-nav-sep { height: 1px; background: #dfe1e6; margin: 5px 6px; flex-shrink: 0; }

.admin-nav-foot { border-top: 1px solid #dfe1e6; margin-top: 8px; padding-top: 8px; display: flex; flex-direction: column; gap: 1px; }
.admin-nav-foot a, .admin-nav-foot .linklike {
    text-decoration: none; color: #6b7078; font-size: 13px; padding: 5px 11px;
    background: none; border: none; text-align: left; cursor: pointer; font-family: inherit;
}
.admin-nav-foot a:hover, .admin-nav-foot .linklike:hover { color: var(--black); }
/* "Website" + "Ausloggen" as two equal buttons side by side. */
.admin-foot-actions { display: flex; gap: 6px; margin-bottom: 4px; align-items: stretch; }
/* Website (icon) 25% · language (code) 25% · logout 50% */
.admin-foot-actions > .admin-foot-icon { flex: 1; }
.admin-foot-actions > .admin-foot-lang { flex: 1; position: relative; display: flex; }
.admin-foot-actions > .admin-foot-logout { flex: 2; margin: 0; display: flex; }
.admin-foot-lang .admin-foot-btn, .admin-foot-logout .admin-foot-btn { width: 100%; }
.admin-foot-actions .admin-foot-btn {
    width: 100%; display: flex; align-items: center; justify-content: center; gap: 6px;
    white-space: nowrap; line-height: 1.2;
    text-decoration: none; color: #4a4f57; font-size: 13px; font-family: inherit;
    background: #f3f4f6; border: 1px solid #e2e4e8; border-radius: 8px; padding: 8px 8px; cursor: pointer;
}
.admin-foot-actions .admin-foot-btn:hover { color: var(--black); background: #e9ebef; border-color: #d3d6db; }
.admin-foot-icon { font-size: 15px; }
/* Language dropdown (opens upward, above the button) */
.admin-foot-lang-menu {
    position: absolute; bottom: calc(100% + 6px); left: 0; min-width: 168px; z-index: 60;
    background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 6px;
    box-shadow: 0 12px 30px rgba(0,0,0,.16); display: flex; flex-direction: column; gap: 2px;
}
.admin-foot-lang-menu form { flex: none; margin: 0; display: block; }
.admin-lang-opt {
    width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
    padding: 8px 10px; border-radius: 7px; font: inherit; color: var(--black);
    display: flex; justify-content: space-between; gap: 10px; align-items: center;
}
.admin-lang-opt:hover { background: #eef1f6; }
.admin-lang-opt.is-current { color: var(--accent); font-weight: 600; }
/* Engine name + running version, pinned at the very bottom under the logout button. */
.admin-cms-foot { display: flex; align-items: baseline; gap: 8px; margin-top: 2px; padding-top: 8px; border-top: 1px solid #e6e8ec; }
.admin-cms-foot .cms { font-family: var(--font-head); font-weight: 600; letter-spacing: .22em; font-size: 11px; color: #8a8f98; text-transform: uppercase; }
.admin-cms-foot .admin-version { font-family: var(--font-head); font-size: 11px; color: #a8adb4; letter-spacing: .02em; }
.admin-cms-foot:hover .cms, .admin-cms-foot:hover .admin-version { color: var(--accent); }

.admin-main { display: flex; flex-direction: column; min-width: 0; height: 100%; min-height: 0; overflow-y: auto; }
.admin-topbar {
    display: flex; align-items: center; justify-content: space-between;
    background: #fff; border-bottom: 1px solid var(--line);
    padding: 18px 32px; position: sticky; top: 0; z-index: 10;
}
.admin-topbar-title { font-family: var(--font-head); font-weight: 600; font-size: 20px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-user { font-size: 14px; color: var(--muted); }

/* Mobile menu button (hamburger) — hidden on desktop, shown in the drawer breakpoint. */
.admin-menu-toggle { display: none; }
.admin-menu-toggle span {
    display: block; width: 20px; height: 2px; background: var(--black); border-radius: 2px;
    transition: transform .2s ease, opacity .2s ease;
}
.admin-menu-toggle span + span { margin-top: 4px; }
body.nav-open .admin-menu-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
body.nav-open .admin-menu-toggle span:nth-child(2) { opacity: 0; }
body.nav-open .admin-menu-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.admin-backdrop { display: none; }

.admin-content { padding: 32px; max-width: 1500px; width: 100%; }
/* Keep single text inputs readable on wide screens (lists/tables still use full width). */
.card .form-field > input:not([type=color]),
.card .form-field > .color-field,
.card .form-field > .optcolor,
.card .form-field > select { max-width: 760px; }

/* ============ Cards / tables / buttons ============ */
.card { background: #fff; border: 1px solid var(--line); padding: 24px; margin-bottom: 24px; }
.card h2 { font-size: 18px; text-transform: none; margin-bottom: 16px; }

.page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; gap: 16px; flex-wrap: wrap; }
.page-head h1 { font-size: 26px; margin: 0; }

/* The page title already appears in the top bar, so the per-page <h1> is redundant: hide it (keeping
   any action buttons in the header row), and collapse the whole row when the title was its only child. */
.admin-content .page-head > h1 { display: none; }
.admin-content .page-head:not(:has(> :not(h1))) { display: none; margin: 0; }

/* Same for the <h2> above a list: the tab or the page title already names it, so repeating it right
   in front of the toolbar says nothing. Scoped to [data-list] so section headings elsewhere stay. */
.admin-content [data-list] > .page-head > h2 { display: none; }

/* Clickable list rows (menu list) */
.block-item-link { text-decoration: none; color: inherit; cursor: pointer; }
.block-item-link:hover { border-color: var(--accent); }

/* Menu management + template menu mapping */
.menu-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.menu-card-head h2 { margin: 0 0 2px; }
.menu-map { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.menu-map-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.menu-map-row code { background: #f1f1f1; padding: 4px 8px; border-radius: 5px; }
.menu-map-row .menu-map-arrow { color: var(--muted); }
.menu-map-row select { min-width: 220px; }
.menu-ref { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.menu-ref li { display: flex; align-items: center; gap: 12px; }
.menu-ref li code { background: #f1f1f1; padding: 3px 9px; border-radius: 5px; min-width: 84px; }
.menu-ref li span { color: var(--muted); font-size: 13.5px; }

/* Custom-layout: label + starter button row, live slot detection */
.label-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.slot-detect { margin-top: 8px; font-size: 13px; }
.slot-detect.muted { color: var(--muted); }
.slot-detect.has-slots { color: #2b6a2b; }
.slot-detect code { background: #eef4ee; padding: 2px 7px; border-radius: 5px; margin-right: 4px; }

/* Component field rows */
#field-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.field-row { display: flex; gap: 10px; align-items: center; margin: 0; padding: 8px 10px; background: #f7f8fa; border: 1px solid var(--line); border-radius: 8px; }
.field-row .fr-label { flex: 1 1 auto; min-width: 0; }
.field-row .fr-type { flex: 0 0 170px; width: 170px; }
.field-row .fr-label, .field-row .fr-type { height: 34px; }

/* Component designer: live preview + debug */
.component-preview .cp-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 6px; }
.component-preview .cp-head h2 { margin: 0; }
.cp-sample { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px 16px; margin: 10px 0 16px; }
.cp-sample-row { display: flex; flex-direction: column; gap: 4px; }
.cp-sample-lab { font-size: 12.5px; color: var(--muted); }
.cp-sample-lab { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; }
.cp-sample-inp { font-size: 13.5px; padding: 7px 9px; border: 1px solid var(--line); border-radius: 6px; font-family: inherit; }
textarea.cp-sample-inp { resize: vertical; min-height: 0; }
.cp-frame-wrap { border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: #fff; }
.cp-frame { width: 100%; height: 300px; border: 0; display: block; background: #fff; }

/* Die Vorschau steht im ZWEISPALTER des Plugin-Editors (.pf-tree > .pf-side/.pf-list + .pf-main):
   links die Felder, die man ausfüllt, rechts das, was dabei herauskommt. Kein zweites
   Spaltenraster daneben — dieses hier kann den Umbruch auf schmale Fenster schon, und der andere
   Zweispalter des Admin (.live-editor) ist eine ganze SEITE (100vh, .admin-content ohne Rand) und
   passt nicht in einen Reiter in einer Karte in einem Formular.
   Breiter als der Dateibaum, weil links Eingabefelder stehen und keine Dateinamen: in 230 Pixeln
   ist ein Textfeld nicht mehr zu lesen. */
.cp-tree.pf-tree { --pf-side-width: 330px; }
.cp-tree .pf-list { padding: 12px; gap: 12px; }
/* Eine Spalte statt der selbsttätigen Kachelung: die Felder stehen jetzt in der schmalen Spalte
   untereinander und nicht mehr über die volle Breite verteilt. */
.cp-tree .cp-sample { grid-template-columns: 1fr; margin: 0; }
/* Der Rahmen füllt die rechte Spalte, statt auf seinen 300 festen Pixeln zu beharren — sonst
   klaffte unter ihm eine leere Fläche, sobald die Feldliste links länger wird. */
.cp-tree .cp-frame { flex: 1 1 auto; height: auto; min-height: 320px; }
.cp-debug { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 14px; font-size: 13px; }
.cp-dbg-row { display: flex; gap: 12px; align-items: baseline; padding: 4px 0; flex-wrap: wrap; }
.cp-dbg-row > span { color: var(--muted); min-width: 210px; }
.cp-dbg-row .cp-warn { color: #b3261e; }
.cp-debug code { background: #eef0f3; padding: 2px 8px; border-radius: 5px; font-size: 12.5px; margin: 0 2px 2px 0; display: inline-block; }
.cp-debug code.cp-bad { background: #fbeaea; color: #b3261e; }
.cp-dbg-ok { color: #2b6a2b; padding: 6px 0; }
.cp-dbg-out { margin-top: 10px; }
.cp-dbg-out-label { color: var(--muted); margin-bottom: 5px; }
.cp-dbg-out pre { background: #0f1115; color: #d6d6d6; border-radius: 8px; padding: 12px 14px; overflow-x: auto; max-height: 220px; font-family: ui-monospace, monospace; font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; margin: 0; }
#placeholder-hint { color: var(--accent); }

/* Tag filter chips (media library) */
.tag-filter { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }
.tag-chip { text-decoration: none; font-size: 13px; padding: 5px 12px; border: 1px solid var(--line); border-radius: 999px; color: var(--ink); background: #fff; }
.tag-chip:hover { border-color: var(--accent); }
.tag-chip.active { background: var(--accent); color: #fff; border-color: var(--accent); }
/* Media library grid */
.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; }
.media-card {
    display: flex; flex-direction: column; text-align: left; padding: 0;
    border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #fff;
    cursor: pointer; font: inherit; color: inherit; transition: border-color .12s, box-shadow .12s, transform .12s;
}
.media-card:hover { border-color: var(--accent); box-shadow: 0 6px 18px rgba(0, 0, 0, .08); transform: translateY(-2px); }
.media-card { position: relative; }
.media-card.dragging { opacity: .45; }
.media-drag { position: absolute; top: 6px; left: 6px; z-index: 2; background: rgba(15,15,16,.6); color: #fff; border-radius: 6px; padding: 1px 6px; font-size: 13px; line-height: 1.3; cursor: grab; opacity: 0; transition: opacity .12s ease; }
.media-grid--sortable .media-card:hover .media-drag { opacity: 1; }
.media-drag:active { cursor: grabbing; }
.media-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.media-thumb { aspect-ratio: 4 / 3; background-size: cover; background-position: center; background-color: #f1f1f1; }
.media-meta { padding: 10px 12px; }
.media-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.media-card-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }

/* Mini tag chips (read-only preview + add-suggestions) */
.mini-chip { display: inline-block; font-size: 11px; line-height: 1.5; padding: 1px 8px; border-radius: 999px; background: #eef0f3; color: #555; border: 1px solid transparent; }
.mini-chip-add { cursor: pointer; background: #fff; border-color: var(--line); color: var(--accent); font: inherit; font-size: 11px; }
.mini-chip-add:hover { border-color: var(--accent); background: var(--accent); color: #fff; }

/* Media detail dialog */
.modal-media { max-width: 860px; }
.media-modal-body { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 24px; }
.media-modal-body > .action-bar { grid-column: 1 / -1; margin-top: 4px; }
.media-preview { display: flex; align-items: flex-start; justify-content: center; background: #f4f5f7; border: 1px solid var(--line); border-radius: 10px; padding: 12px; }
.media-preview img { max-width: 100%; max-height: 420px; border-radius: 6px; }
.media-detail { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.media-detail-name { font-weight: 600; font-size: 14px; word-break: break-word; }
.media-detail-form { display: flex; flex-direction: column; gap: 14px; margin: 0; }
.media-detail-info { font-size: 12px; color: var(--muted); }
.copy-row { display: flex; gap: 8px; }
.copy-row input { flex: 1; min-width: 0; }
.tag-suggest { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.modal-foot { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 4px; align-items: center; }

/* Tag chip picker (type + Enter, no manual commas). Chips and the input are both pill-shaped;
   the input is an outlined pill (no ×) that turns into a filled chip on Enter. */
.tag-input { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; cursor: text; }
.tag-chip-item { display: inline-flex; align-items: center; gap: 4px; background: var(--accent); color: #fff; border-radius: 999px; padding: 4px 8px 4px 12px; font-size: 12.5px; line-height: 1.5; }
.tag-x { background: none; border: none; color: #fff; cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; opacity: .8; }
.tag-x:hover { opacity: 1; }
.tag-entry { flex: 0 1 auto; min-width: 140px; border: 1px solid var(--line); border-radius: 999px; outline: none; padding: 4px 14px; margin: 0; font: inherit; font-size: 12.5px; background: #fff; color: var(--black); }
.tag-entry::placeholder { color: var(--muted); }
.tag-entry:focus { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent); }
/* Collapsed "+" chip that expands into the tag input on click. */
.tag-add-chip { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 1px dashed var(--muted); border-radius: 999px; background: #fff; color: var(--muted); font-size: 17px; line-height: 1; cursor: pointer; transition: border-color .15s ease, color .15s ease; }
.tag-add-chip:hover { border-color: var(--accent); color: var(--accent); border-style: solid; }

/* Action bar: positive → negative order; the destructive action sits apart on the right */
.action-bar { border-top: 1px solid var(--line); margin-top: 16px; padding-top: 16px; }
.action-bar .act-danger { margin: 0; margin-left: auto; }

/* Media picker modal (image fields) */
.media-picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; max-height: 60vh; overflow-y: auto; }
.media-pick { position: relative; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; cursor: pointer; background: #fff; padding: 0; aspect-ratio: 1 / 1; }
.media-pick img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-pick:hover { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.media-pick.selected { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--accent); }
.media-pick.selected::after { content: "✓"; position: absolute; top: 4px; right: 5px; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--accent); color: #fff; font-size: 13px; font-weight: 700; }
.media-picker-foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; padding: 12px 16px; border-top: 1px solid var(--line); }
.media-picker-foot .mp-count { margin-right: auto; }
.mp-head-actions { display: flex; align-items: center; gap: 10px; }
/* URL text field with the "pick page" button integrated INTO the field (right edge). */
.link-field { position: relative; display: block; }
.link-field > input { width: 100%; padding-right: 40px; box-sizing: border-box; }
.link-field .link-field-btn {
    position: absolute; top: 50%; right: 4px; transform: translateY(-50%);
    width: 30px; height: 30px; padding: 0; margin: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; background: transparent; color: var(--muted, #6b7280);
    border-radius: 6px; cursor: pointer; font-size: 18px; line-height: 1;
}
.link-field .link-field-btn:hover { background: var(--accent, #de7e11); color: #fff; }
.link-field .link-field-btn .ti { font-size: 18px; }

/* Optional color widget: swatch + hex text (may be empty) + clear button. */
/* Same box as .color-field, plus a clear button — an optional colour may be empty ("inherit"), */
/* which a colour input cannot express on its own. */
.optcolor {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 14px 16px;
    border: 1px solid #cfcfcf;
    background: #fff;
    transition: border-color .18s ease;
}
.optcolor:focus-within { border-color: var(--black, #111); }
.optcolor .optcolor-pick {
    flex: 0 0 auto;
    width: 22px !important;
    height: 22px !important;
    min-width: 22px !important;
    padding: 0 !important;
    border: 1px solid rgba(0, 0, 0, .18) !important;
    border-radius: 3px;
    background: none !important;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}
.optcolor .optcolor-pick::-webkit-color-swatch-wrapper { padding: 0; }
.optcolor .optcolor-pick::-webkit-color-swatch { border: 0; border-radius: 2px; }
.optcolor .optcolor-pick::-moz-color-swatch { border: 0; border-radius: 2px; }
.optcolor .optcolor-hex {
    flex: 1 1 auto;
    min-width: 0;
    width: auto !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    font-size: 16px;
    font-family: var(--font-mono, ui-monospace, monospace);
}
.optcolor .optcolor-hex:focus { outline: none; border: 0; }
.optcolor .optcolor-clear {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    border: 0;
    background: none;
    cursor: pointer;
    color: #9aa0a6;
    font-size: 18px;
    line-height: 1;
    padding: 0;
}
.optcolor .optcolor-clear:hover { color: #111; }
/* Dimmed swatch = no value set, so the colour shown is only the fallback. */
.optcolor.is-empty .optcolor-pick { opacity: .35; }

/* Plugin asset (library) file manager. */
.asset-upload { display: flex; gap: 8px; align-items: center; margin: 10px 0 14px; flex-wrap: wrap; }
.asset-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.asset-table th, .asset-table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line, #eceef1); vertical-align: middle; }
.asset-table th { font-weight: 600; color: #6b7280; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; }
.asset-table .a-name { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.asset-table .a-url { width: 100%; min-width: 160px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 4px 6px; }
textarea.code-area { width: 100%; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; line-height: 1.5; }
.link-picker-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; }
.link-pick { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; text-align: left; padding: 10px 14px; border: 1px solid var(--line); border-radius: 8px; background: #fff; cursor: pointer; }
.link-pick:hover { border-color: var(--accent); background: #f7f8fa; }
.link-pick .lp-title { font-weight: 600; }
.link-pick .lp-url { font-size: 12.5px; color: var(--muted); }

/* Icon picker — the current icon as a button, the grid in a dialog.
   Die Klassen sind dieselben wie vorher, als das Raster noch dauerhaft im Formular stand: das
   Raster (.icon-grid/.icon-tile/.icon-more) und die Zeile mit dem aktuellen Symbol
   (.icon-current*) sind unverändert, nur umgezogen. Neu ist allein, was der Dialog braucht. */
.icon-picker .icon-current { display: flex; align-items: center; gap: 12px; margin: 4px 0 10px; }
.icon-current-preview { width: 40px; height: 40px; border: 1px solid var(--line); border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; color: var(--accent); }
.icon-current-preview .ti { font-size: 22px; }
.icon-current-name { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 13px; color: var(--muted); flex: 1; min-width: 0; }
.icon-picker .icon-search { max-width: 620px; }
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 8px; max-width: 620px; margin-top: 8px; max-height: 264px; overflow-y: auto; padding: 2px; }
.icon-tile { display: inline-flex; align-items: center; justify-content: center; height: 46px; border: 1px solid var(--line); border-radius: 8px; background: #fff; cursor: pointer; color: var(--ink); }
.icon-tile .ti { font-size: 22px; }
.icon-tile:hover { border-color: var(--accent); }
.icon-tile.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, #fff); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Die erste Kachel: „kein Symbol“. Gleiche Größe, gleiche Stelle, gleiches Verhalten wie jede
   andere — unterschieden allein durch die gedämpfte Fläche (--bg-alt, die es im Admin schon gibt)
   und das X. Die Auswahlmarkierung .icon-tile.sel wiegt schwerer (zwei Klassen gegen eine) und
   gewinnt deshalb, damit auch DIESE Kachel sichtbar gewählt ist, wenn kein Symbol gesetzt ist. */
.icon-tile-none { background: var(--bg-alt); color: var(--muted); }
.icon-tile-none:hover { border-color: var(--accent); }
.icon-more { grid-column: 1 / -1; color: var(--muted); font-size: 13px; padding: 6px 2px; }

/* Das Kästchen mit dem aktuellen Symbol IST jetzt der Knopf, der den Dialog öffnet — deshalb
   Zeigefinger und ein Rand, der auf Berührung reagiert. Es bleibt dasselbe Kästchen wie zuvor,
   damit die Menüpunkte nicht plötzlich anders aussehen als die Komponenten. */
button.icon-current-preview { background: #fff; cursor: pointer; padding: 0; }
button.icon-current-preview:hover { border-color: var(--accent); }
button.icon-current-preview:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Kein Symbol gesetzt: dieselbe abweichende Fläche und dasselbe X wie die erste Kachel im Dialog —
   der Knopf zeigt also genau die Kachel, die dort gewählt ist. Ein leeres Kästchen sähe dagegen aus
   wie ein Symbol, das nicht laden wollte. Die Farben sind die vorhandenen Größen des Admin
   (--bg-alt für die gedämpfte Fläche, --muted für das Zeichen), kein neuer Farbwert. */
button.icon-current-preview.is-empty { background: var(--bg-alt); color: var(--muted); }
/* Ein gespeicherter Name, den die Schrift nicht kennt. Er BLEIBT stehen — die Farbe sagt nur, dass
   er nichts zeichnen wird. */
.icon-current-name.is-unknown { color: #b45309; }
/* Das Rohfeld: sichtbar, solange kein Skript läuft. Danach setzt das Skript [hidden]. */
.icon-picker .icon-raw { max-width: 320px; }

.icon-dialog { width: min(700px, 94vw); padding: 18px 20px; }
.icon-dialog-head { margin: 0 0 12px; }
.icon-dialog .icon-search { max-width: none; width: 100%; }
.icon-dialog .icon-grid { max-width: none; max-height: min(46vh, 380px); }
.icon-dialog-foot { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
/* Die Zählung steht links und schiebt die Knöpfe nach rechts — sie ist Auskunft, keine Aktion. */
.icon-dialog-count { flex: 1 1 auto; color: var(--muted); font-size: 12.5px; }

/* Color picker fields (template editor): visible swatch + editable hex */
.color-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
/* The colour widget IS an input box: same border, padding and height as every other field, with a
   small swatch sitting INSIDE it at the front and the hex code next to it. Two separate controls
   side by side never lined up with the rest of a form — different heights, two borders, its own
   width. Here the box is the only thing with a border; the two inputs inside are stripped bare. */
.color-field {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 14px 16px;
    border: 1px solid #cfcfcf;
    background: #fff;
    transition: border-color .18s ease;
}
/* Focus lives on the box, so clicking into the hex field highlights the whole control. */
.color-field:focus-within { border-color: var(--black, #111); }

/* The swatch: a plain square, no chrome of its own. Clicking it opens the native picker. */
/* !important because site.css styles fields with .form-field input:not(…):not(…):not(…), which is
   more specific than anything writable here without contortions. Only the two inputs INSIDE the box
   need it; the box itself does not. */
.color-field input[type=color] {
    flex: 0 0 auto;
    width: 22px !important;
    height: 22px !important;
    min-width: 22px !important;
    padding: 0 !important;
    border: 1px solid rgba(0, 0, 0, .18) !important;
    border-radius: 3px;
    background: none !important;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
}
.color-field input[type=color]::-webkit-color-swatch-wrapper { padding: 0; }
.color-field input[type=color]::-webkit-color-swatch { border: 0; border-radius: 2px; }
.color-field input[type=color]::-moz-color-swatch { border: 0; border-radius: 2px; }

/* The hex field fills the rest and carries no border of its own — the box already has one. */
.color-field .hex {
    flex: 1 1 auto;
    min-width: 0;
    width: auto !important;
    padding: 0 !important;
    border: 0 !important;
    background: none !important;
    font-size: 16px;
    text-transform: uppercase;
    font-family: var(--font-mono, ui-monospace, monospace);
}
.color-field .hex:focus { outline: none; border: 0; }

/* Form section sub-heading + code textareas (template editor) */
.form-section { margin: 22px 0 6px; font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); border-bottom: 1px solid var(--line); padding-bottom: 6px; }
.form-section:first-of-type { margin-top: 4px; }
textarea.code { font-family: var(--font-mono, ui-monospace, monospace); font-size: 13px; line-height: 1.5; white-space: pre; overflow-wrap: normal; }

/* About / system page */
.kv { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.kv:last-of-type { border-bottom: none; }
/* Fixed basis, not min-width: with a minimum a longer label pushes only ITS row, and the values
   end up at a different place in every block. */
.kv-label { flex: 0 0 200px; color: var(--muted); }
@media (max-width: 620px) { .kv { flex-direction: column; gap: 2px; } .kv-label { flex: none; } }
.kv-value { font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
.code-block { background: #0f1115; color: #e6e6e6; border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 8px 0 0; }
.code-block code { font-family: var(--font-mono, ui-monospace, monospace); font-size: 13px; }
.update-result { margin-left: 12px; font-weight: 600; }
.update-result.ok { color: #16a34a; }
.update-result.update { color: var(--accent); }
.update-result.warn { color: #b45309; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 8px; }
.stat { background: #fff; border: 1px solid var(--line); padding: 22px; }
.stat .n { font-family: var(--font-head); font-size: 34px; font-weight: 700; color: var(--black); }
.stat .l { color: var(--muted); font-size: 14px; text-transform: uppercase; letter-spacing: .06em; }
.stat a { text-decoration: none; }

table.data { width: 100%; border-collapse: collapse; background: #fff; }
table.data th, table.data td { text-align: left; padding: 13px 16px; border-bottom: 1px solid var(--line); font-size: 14.5px; vertical-align: middle; }
table.data th { background: #fafafa; text-transform: uppercase; letter-spacing: .05em; font-size: 12px; color: var(--muted); }
table.data tr:last-child td { border-bottom: none; }
table.data .row-unread td { font-weight: 600; }

.badge { display: inline-block; font-size: 11.5px; padding: 3px 9px; border-radius: 999px; letter-spacing: .04em; }
.badge-on { background: #e6f4ea; color: #1e7a34; }
.badge-off { background: #f0f0f0; color: #888; }
.badge-new { background: #0f0f10; color: #fff; }
.badge-err { background: #fde8e8; color: #b42318; }
.admin-nav-plugins { margin-top: 6px; padding-top: 8px; border-top: 1px dashed #dfe1e6; display: flex; flex-direction: column; gap: 4px; }

/* Checkbox lists (e.g. form-notification recipients). */
.check { display: flex; align-items: center; gap: 8px; font-weight: 400; cursor: pointer; }
.check input { flex: 0 0 auto; }
.check-list { display: flex; flex-direction: column; gap: 6px; }
.check-list .check .muted { margin-left: auto; font-size: 12.5px; }
.check.is-muted { opacity: .6; }

/* Read-only "Systemkomponenten" reference list (Components tab). */
.components-system .sys-desc { color: var(--muted); font-size: 13.5px; margin-top: 2px; }
.components-system .sys-meta { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.components-system .sys-meta .mono { color: var(--muted); background: #f4f5f7; padding: 2px 7px; border-radius: 5px; }
.plugin-log { background: #0f1115; color: #d6d6d6; border-radius: 8px; padding: 14px 16px; overflow-x: auto; max-height: 320px; font-family: var(--font-mono, ui-monospace, monospace); font-size: 12.5px; line-height: 1.6; white-space: pre-wrap; margin: 0; }

.btn-sm { padding: 8px 16px; font-size: 12.5px; }
/* Unified, slim admin buttons — one consistent size across the admin (reference: the list
   "Bearbeiten" button). The public site keeps its larger .btn from site.css. */
.admin .btn { padding: 6px 16px; font-size: 12.5px; letter-spacing: .05em; border-width: 1px; min-height: 34px; display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; line-height: 1.15; }
.admin .btn-icon { width: 34px; height: 34px; min-height: 34px; padding: 0; }
.btn-ghost { background: #fff; color: var(--black); border: 1px solid #cfcfcf; }
.btn-ghost:hover { background: var(--black); color: #fff; border-color: var(--black); }
.btn-danger { background: #b3261e; border-color: #b3261e; color: #fff; }
.btn-danger:hover { background: #fff; color: #b3261e; }
/* Icon-only button (e.g. delete): square, matches .btn-sm height, never wraps. Combine with
   .btn .btn-sm .btn-danger / .btn-ghost. Give it a title/aria-label for accessibility. */
.btn-icon { padding: 0; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.btn-icon svg { width: 16px; height: 16px; display: block; }
.btn-icon .ti { font-size: 17px; line-height: 1; }

.actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.inline-form { display: inline; }

/* Keep row action buttons on a single line (last column shrinks to fit) */
table.data th:last-child, table.data td:last-child { width: 1%; white-space: nowrap; }
table.data .actions { flex-wrap: nowrap; justify-content: flex-end; }
table.data .btn { white-space: nowrap; }

/* A wide data table scrolls inside THIS box instead of pushing the whole page — and with it the
   sticky top bar — past the viewport's right edge (which left the header short of full width).
   admin-list.js drops every [data-list-table] into a .table-scroll on load; the table keeps
   width:100% and still stretches when it fits, so only a genuinely too-wide table scrolls here.
   The ≤860 rule further down still covers plain (non-list) tables on small screens. */
.table-scroll { overflow-x: auto; overscroll-behavior-x: contain; }

.muted { color: var(--muted); }
.mono { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 13px; }

.form-grid { display: grid; gap: 18px; }
.form-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.check { display: flex; align-items: center; gap: 8px; }

/* Template gallery: each card shows a small live-styled preview instead of raw columns */
.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, 256px); gap: 20px; }
.tpl-card { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: #fff; display: flex; flex-direction: column; width: 256px; }
.tpl-card.is-active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
/* Live preview: the real public page rendered with this template, scaled down to a thumbnail. */
.tpl-preview { display: block; height: 180px; overflow: hidden; border-bottom: 1px solid var(--line); position: relative; background: #fff; }
.tpl-iframe { position: absolute; top: 0; left: 0; width: 1280px; height: 960px; border: 0; transform: scale(0.2); transform-origin: top left; pointer-events: none; background: #fff; }
.tpl-card-foot { padding: 12px 14px; display: flex; flex-direction: column; gap: 10px; }
.tpl-name { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.tpl-name .muted-font { color: var(--muted); font-weight: 400; font-size: 12px; }
.tpl-card-foot .actions { display: flex; flex-wrap: wrap; gap: 6px; }

/* Tabs (Backup / Restore / Schedule) */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 22px; }
.tab { appearance: none; background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; padding: 10px 16px; font: inherit; font-size: 14.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
.tab:hover { color: var(--black); }
.tab.active { color: var(--black); border-bottom-color: var(--accent); }
/* A hidden tab panel must stay hidden even when it also carries a display-setting class
   (e.g. the template editor's .tab-panel.form-grid, whose display:grid would otherwise win over [hidden]). */
.tab-panel[hidden] { display: none !important; }

/* Backup: collapsible per-item groups, action rows, inspection, schedule status */
/* The page's actions, on one line, positive before negative. A delete is its own <form> and cannot
   nest in the editor form, so it sits here as a flex item next to a save button that reaches its
   form by the form= attribute. */
.form-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
.form-actions .inline-form { display: block; margin: 0; }
.backup-group { border: 1px solid var(--line); border-radius: 8px; padding: 4px 12px; }
.backup-group > summary { display: flex; align-items: center; gap: 10px; list-style: none; cursor: pointer; padding: 8px 4px; }
.backup-group > summary::-webkit-details-marker { display: none; }
.backup-group > summary::before { content: "▸"; color: var(--muted); font-size: 12px; transition: transform .15s; }
.backup-group[open] > summary::before { transform: rotate(90deg); }
.backup-group .backup-count { margin-left: auto; font-size: 12px; color: var(--muted); background: #eef0f3; border-radius: 999px; padding: 1px 9px; }
.backup-items { display: flex; flex-direction: column; gap: 7px; padding: 4px 4px 12px 24px; }
/* Flat sections (no children) — same box, no arrow, aligned checkbox */
.backup-flat .backup-head { display: flex; align-items: center; gap: 10px; padding: 8px 4px; }
.backup-flat .backup-head::before { content: "▸"; visibility: hidden; font-size: 12px; }
.check-sm { font-size: 13.5px; gap: 7px; }
.inspect-result { margin: 4px 0 16px; padding: 14px 16px; border-radius: 8px; font-size: 14px; }
.inspect-result.ok { background: #f2f7f2; border: 1px solid #cfe3cf; }
.inspect-result.err { background: #fbeaea; border: 1px solid #e6bcbc; color: #922; }
.inspect-title { font-weight: 600; margin-bottom: 8px; }
.inspect-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 4px 24px; }
.inspect-list li { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px dotted var(--line); padding: 3px 0; }
.inspect-list span { color: var(--muted); }
.sched-status { display: flex; gap: 28px; flex-wrap: wrap; margin-top: 14px; font-size: 14px; color: var(--muted); }
.sched-status strong { color: var(--black); }
.check input { width: auto; }
.help { font-size: 13px; color: var(--muted); margin-top: 5px; }

/* ============ Block editor ============ */
.block-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
/* "Insert between blocks" hover zones: a faint line appears while hovering the list; the hovered
   zone shows a thick accent line + "add" pill and opens the picker at that position. */
.block-insert { display: flex; align-items: center; justify-content: center; width: 100%; height: 14px; margin: -9px 0; padding: 0; border: none; background: none; cursor: pointer; position: relative; opacity: 0; transition: opacity .12s ease; }
.block-insert::before { content: ""; position: absolute; left: 6px; right: 6px; top: 50%; height: 3px; background: var(--accent); border-radius: 3px; transform: translateY(-50%); }
.block-insert span { position: relative; z-index: 1; font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .02em; background: var(--accent); color: #fff; padding: 2px 10px; border-radius: 999px; white-space: nowrap; }
.block-list:hover .block-insert { opacity: .22; }
.block-insert:hover { opacity: 1; }
.block-item { background: #fff; border: 1px solid var(--line); padding: 16px 18px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.block-item .b-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 9px;
    background: #fbeede; color: var(--accent);
    flex-shrink: 0;
}
.block-item .b-icon svg { width: 22px; height: 22px; }
.block-item .b-icon .ti { font-size: 22px; }
.block-item .b-info { flex: 1; min-width: 0; }
.block-item .b-type { font-weight: 600; }
.block-item .b-sum { color: var(--muted); font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.block-item .b-order { display: flex; flex-direction: column; }

/* Block-type picker tiles (used inside the add-block modal) */
.picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; }
.picker form { margin: 0; }
.picker .tile {
    width: 100%;
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    background: #fff; border: 1px solid var(--line); border-radius: 10px;
    padding: 16px; cursor: pointer; text-align: left; font-family: inherit;
    transition: border-color .15s ease, box-shadow .15s ease, transform .1s ease;
}
.picker .tile:hover { border-color: var(--accent); box-shadow: 0 8px 20px rgba(0, 0, 0, .08); transform: translateY(-1px); }
.picker .tile .t-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 9px;
    background: #fbeede; color: var(--accent);
    margin-bottom: 10px;
}
.picker .tile .t-icon svg { width: 22px; height: 22px; }
.picker .tile .t-name { font-weight: 700; font-size: 15px; color: var(--black); }
.picker .tile .t-desc { color: var(--muted); font-size: 12.5px; line-height: 1.45; margin-top: 3px; }

/* Icon chip in the block-editor page header */
.page-head h1.with-icon { display: inline-flex; align-items: center; gap: 12px; }
.head-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; border-radius: 9px;
    background: #fbeede; color: var(--accent);
}
.head-icon svg { width: 22px; height: 22px; }

/* List action button (always at the end of a list) */
.list-actions { margin-top: 22px; display: flex; gap: 12px; }

/* Drag & drop */
.block-item .drag-handle {
    cursor: grab;
    color: #b7b7b7;
    font-size: 18px;
    line-height: 1;
    padding: 0 6px 0 2px;
    user-select: none;
}
.block-item .drag-handle:active { cursor: grabbing; }
.block-item.dragging { opacity: .55; box-shadow: 0 10px 26px rgba(0, 0, 0, .14); }

/* Modal */
.modal-overlay {
    display: none;
    position: fixed; inset: 0;
    background: rgba(15, 15, 16, .55);
    z-index: 100;
    align-items: flex-start;
    justify-content: center;
    padding: 60px 20px;
    overflow-y: auto;
}
.modal-overlay.open { display: flex; }
.modal {
    background: #fff;
    width: 100%; max-width: 720px;
    border-radius: 10px;
    box-shadow: 0 30px 70px rgba(0, 0, 0, .35);
    overflow: hidden;
}
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; border-bottom: 1px solid var(--line); }
.modal-head h2 { margin: 0; font-size: 18px; }
.modal-close { background: none; border: none; font-size: 18px; cursor: pointer; color: var(--muted); line-height: 1; }
.modal-close:hover { color: var(--black); }
.modal-body { padding: 22px 24px; }

.setup-banner { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.setup-banner .btn { flex: 0 0 auto; }

/* Setup wizard */
.wiz-steps { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; padding: 0; margin: 0 0 22px; }
.wiz-steps li { flex: 1 1 auto; text-align: center; font-size: 12.5px; font-weight: 600; color: var(--muted); padding: 8px 6px; border-bottom: 3px solid var(--line); }
.wiz-steps li.active { color: var(--accent); border-bottom-color: var(--accent); }
.wiz-panel h2 { margin-top: 0; }
.wiz-actions { display: flex; gap: 10px; margin-top: 20px; }
.wiz-actions #wiz-next, .wiz-actions #wiz-finish { margin-left: auto; }
.wiz-themes { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.wiz-theme input { position: absolute; opacity: 0; }
.wiz-theme-card { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border: 2px solid var(--line); border-radius: 10px; cursor: pointer; }
.wiz-theme input:checked + .wiz-theme-card { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
.wiz-theme-card strong { margin-left: 2px; font-size: 13.5px; }
.wiz-swatch { width: 18px; height: 18px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }

/* On phones, dialogs go full-screen so pickers/forms have room and feel native. */
@media (max-width: 640px) {
    .modal-overlay.open { padding: 0; align-items: stretch; }
    .modal { max-width: none; width: 100%; height: 100dvh; border-radius: 0; display: flex; flex-direction: column; }
    .modal-media { max-width: none; }
    .modal-body { flex: 1 1 auto; overflow-y: auto; }
    .modal-head { position: sticky; top: 0; background: #fff; z-index: 1; }
}

/* ============ Live editor (two-pane: block list/settings + preview) ============ */
.admin-content:has(.live-editor) { padding: 0; max-width: none; }

.live-editor {
    display: grid;
    grid-template-columns: 380px 1fr;
    height: calc(100vh - 66px);
    background: #fff;
}
.le-sidebar { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); background: #fff; }
.le-head { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.le-back { text-decoration: none; color: var(--muted); font-size: 13px; white-space: nowrap; }
.le-back:hover { color: var(--black); }
.le-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.le-scroll { flex: 1; overflow-y: auto; padding: 14px; }
.le-section-label { font-size: 12px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin: 2px 2px 10px; }

.le-sidebar .block-list { display: flex; flex-direction: column; gap: 8px; }
.le-sidebar .block-item { display: flex; align-items: center; gap: 6px; padding: 8px; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
.le-sidebar .block-item:hover { border-color: var(--accent); }
.le-sidebar .drag-handle { padding: 0 2px; }
.b-open { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; text-decoration: none; color: inherit; }
.le-sidebar .b-icon { width: 34px; height: 34px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; background: #eaf0fe; color: var(--accent); flex-shrink: 0; }
.le-sidebar .b-icon svg { width: 18px; height: 18px; }
.b-info { display: flex; flex-direction: column; min-width: 0; }
.b-type { font-weight: 600; font-size: 14px; }
.b-sum { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.le-sidebar .block-children { margin: 8px 0 4px 16px; padding-left: 12px; border-left: 2px solid var(--line); display: flex; flex-direction: column; gap: 6px; }
.le-sidebar .block-child { background: #fafafa; }
.le-sidebar .add-child { align-self: flex-start; }

.le-add { margin-top: 12px; }
.le-settings { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px; }
.le-settings summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.le-settings form { margin-top: 12px; }

.le-panel { flex: 1; overflow-y: auto; padding: 14px 16px; }
.le-panel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
.le-panel-title { font-weight: 700; font-size: 16px; }
.le-panel-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.le-delete { margin: 0; }
.le-panel-actions .le-save { margin-left: auto; }

/* Block family navigation in the edit panel — same look as the main block list, current highlighted. */
.le-family { margin-bottom: 16px; }
.le-family .block-list { margin-bottom: 0; }
.block-item.active { outline: 2px solid var(--accent); outline-offset: -2px; }
.block-item.active .b-type { color: var(--accent); }
.le-sidebar .btn { white-space: nowrap; }

.le-preview { display: flex; flex-direction: column; min-width: 0; background: #eceef1; }
.le-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; border-bottom: 1px solid var(--line); background: #fff; }
.le-url { color: var(--muted); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Page switcher in the toolbar -------------------------------------------------------------
   The dropdown itself is the form field "richselect" (.mat-rs*, mat-richselect.css) — everything
   here only places it and adapts the entries to a LIST OF LINKS instead of a value picker. */

/* The bar used to hold the path on the left as the switcher's counterweight. With the path INSIDE the
   switcher there is nothing left of it, so an empty flexible cell takes its place: it is the same
   width as the action group on the right, which is what keeps the switcher in the actual middle
   instead of "centred in whatever is left over". :has() so the FORM editor's toolbar, which shares
   .le-toolbar and has no switcher, keeps its own two-item layout. */
.le-toolbar:has(.le-pagepick)::before { content: ""; flex: 1 1 0; min-width: 0; }
.le-toolbar .le-url { flex: 1 1 0; min-width: 0; }
.le-toolbar-actions { flex: 1 1 0; justify-content: flex-end; flex-wrap: nowrap; }
/* A FIXED basis, not a width that follows the title: at "Start" the trigger shrank to a stub and a
   long title made the whole bar jump on every switch. It is the resting element in the middle now —
   same size on every page — and only gives way when the bar itself gets narrower. */
.le-pagepick { flex: 0 1 440px; min-width: 280px; display: flex; }
.le-pagepick .mat-rs-trigger { width: 100%; min-width: 0; padding: 6px 12px; text-align: left; }
.le-pagepick .mat-rs-current { gap: 9px; flex: 1 1 auto; }
/* The badge is pushed to the right edge of the trigger, in the same column the entries put theirs in,
   so it no longer slides left and right with the length of the title. */
.le-pagepick .mat-rs-trigger .badge { margin-left: auto; flex: 0 0 auto; }
/* .btn shouts in capitals and spaces its letters out — a page title and a path must not. On this site
   the Croatian titles ARE capitals ("APARTMAN 1"), so an uppercasing trigger would hide the one
   difference the operator is looking for, and an uppercased path is unreadable. */
.le-pagepick .mat-rs-trigger { text-transform: none; letter-spacing: normal; }
/* Title over path, both clipped rather than wrapped — the trigger must not change height. */
.le-pagepick .mat-rs-trigger .mat-rs-opt-title,
.le-pagepick .mat-rs-trigger .mat-rs-opt-desc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.le-pagepick .mat-rs-trigger .mat-rs-opt-title { font-size: 14px; }
.le-pagepick .mat-rs-trigger .mat-rs-opt-desc { font-size: 12px; }
/* Trigger is a .btn-ghost, which inverts on hover — badge and path have to come along or they
   disappear into the black. */
.le-pagepick .mat-rs-trigger:hover .badge { background: rgba(255, 255, 255, .18); color: #fff; }
.le-pagepick .mat-rs-trigger:hover .mat-rs-opt-desc { color: rgba(255, 255, 255, .75); }
.le-pagepick .mat-rs-menu { min-width: 340px; }
.le-pagepick .ps-search { padding: 10px 10px 4px; }
.le-pagepick .mat-rs-scroll { max-height: min(60vh, 460px); }
/* Entries are links, not buttons: they need the button's reset back. */
.le-pagepick .mat-rs-opt { text-decoration: none; color: inherit; align-items: flex-start; }
/* The search hides entries with [hidden]. That attribute is a UA rule and loses against the
   class-level "display: flex" of .mat-rs-opt — without this the filter would leave every entry on
   screen. Cost us the whole search once. */
.le-pagepick .mat-rs-opt[hidden] { display: none; }
.le-pagepick .mat-rs-opt-body { flex: 1 1 auto; min-width: 0; }
.le-pagepick .mat-rs-opt-desc { display: block; }
.le-pagepick .mat-rs-opt-tags { flex: 0 0 auto; margin-top: 0; align-self: center; justify-content: flex-end; }
/* The keyboard cursor. Separate from [aria-selected], which marks the page you are ON — the two are
   different things and are on screen at the same time. */
.le-pagepick .mat-rs-opt.is-active { background: rgba(128, 128, 128, .16); box-shadow: inset 0 0 0 2px var(--accent); }
.le-pagepick .bpick-grouphead { padding: 4px 10px 0; margin-bottom: 4px; }
.le-pagepick .ps-section + .ps-section { margin-top: 16px; }
.le-pagepick .bpick-empty { padding: 26px 0; }

/* Phone: the bar stacks and the switcher goes FULL WIDTH on its own line. Squeezing three items
   into 390px left the switcher a stump nobody can read a page title in. */
@media (max-width: 700px) {
    .le-toolbar { flex-wrap: wrap; }
    /* Full width beats any minimum here, and the centring spacer has nothing left to balance once
       the switcher owns its own row — it would only push the button in from the edge. */
    .le-toolbar:has(.le-pagepick)::before { display: none; }
    .le-pagepick { order: -1; flex: 1 1 100%; min-width: 0; }
    .le-pagepick .mat-rs-trigger { width: 100%; justify-content: space-between; }
}
@media (max-width: 600px) {
    /* Full-screen sheet (mat-richselect.css): search bar fixed under the header, list scrolls under
       it — with the on-screen keyboard up, a search box that scrolls away is a search box you
       cannot see what you typed into. Finger-sized rows, no hover-only affordances. */
    .le-pagepick.mat-rs-modal .ps-search { flex: 0 0 auto; padding: 10px 12px; }
    .le-pagepick.mat-rs-modal .mat-rs-opt { padding: 14px 12px; min-height: 56px; }
    .le-pagepick.mat-rs-modal .mat-rs-menu { min-width: 0; }
}
.le-frame-wrap { flex: 1; min-height: 0; padding: 16px; }
.le-preview iframe { width: 100%; height: 100%; border: 1px solid var(--line); border-radius: 8px; background: #fff; box-shadow: 0 8px 30px rgba(0, 0, 0, .07); }

/* Form builder edits an element in the left sidebar with the live preview on the right —
   identical to the block editor (no full-width centered takeover). */

@media (max-width: 900px) {
    .live-editor { grid-template-columns: 1fr; height: auto; }
    .le-preview { height: 72vh; }
    .le-sidebar { border-right: none; border-bottom: 1px solid var(--line); }
}

/* Field editor (admin-blocks.js) */
.field { margin-bottom: 20px; }
.field > label { display: block; font-weight: 600; font-size: 13.5px; margin-bottom: 7px; }
.field input[type=text], .field input[type=url], .field textarea, .field select {
    width: 100%; padding: 11px 13px; border: 1px solid #cfcfcf; font-family: inherit; font-size: 15px; background: #fff;
}
.field textarea { min-height: 90px; resize: vertical; }
.field .field-help { font-size: 12.5px; color: var(--muted); margin-top: 5px; }

.rt-toolbar { display: flex; gap: 4px; flex-wrap: wrap; border: 1px solid #cfcfcf; border-bottom: none; padding: 6px; background: #fafafa; }
.rt-toolbar button { border: 1px solid transparent; background: #fff; cursor: pointer; padding: 5px 10px; font-size: 13px; font-family: inherit; border-radius: 4px; }
.rt-toolbar button:hover { border-color: #cfcfcf; }
.rt-editor { min-height: 140px; border: 1px solid #cfcfcf; padding: 12px 14px; background: #fff; outline: none; font-size: 15px; line-height: 1.6; }
.rt-editor:focus { border-color: var(--black); }
.rt-editor p { margin: 0 0 .7em; }

.list-items { display: flex; flex-direction: column; gap: 12px; }
.list-item { border: 1px solid var(--line); padding: 14px; background: #fbfbfb; }
.list-item-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.list-item-head .li-title { font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.list-item-head .li-actions { display: flex; gap: 6px; }
.icon-btn { border: 1px solid #cfcfcf; background: #fff; cursor: pointer; width: 30px; height: 30px; border-radius: 6px; font-size: 14px; line-height: 1; }
.icon-btn:hover { border-color: var(--black); }

.image-field { display: flex; gap: 12px; align-items: flex-start; }
.image-field .preview { width: 84px; height: 84px; border: 1px solid var(--line); background: #f5f5f4 center/cover no-repeat; flex-shrink: 0; }
.image-field .image-controls { flex: 1; }

.editor-actions { display: flex; gap: 12px; margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--line); }

/* ---- Form builder ---- */
.opt-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; align-items: center; }
/* Rich-select options editor (title/key row + optional image/description/tags for "Auswahl mit Bild") */
.opt-row2 { border: 1px solid var(--line); border-radius: 8px; padding: 8px; }
.opt-top { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; align-items: center; }
.opt-rich { display: none; margin-top: 8px; gap: 6px; }
.opts-rich .opt-rich { display: grid; }
.opt-img-row { display: flex; gap: 8px; align-items: center; }
.opt-img-row input { flex: 1; }
.opt-img-prev { width: 40px; height: 40px; border-radius: 6px; border: 1px solid var(--line); background: #f0f0f0 center/cover no-repeat; flex: none; }
/* Tag chips in the rich-select options editor */
.opt-tags { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; border: 1px solid var(--line); border-radius: 8px; padding: 6px; }
.tag-chip { display: inline-flex; align-items: center; gap: 4px; background: rgba(43,108,255,.1); color: var(--accent, #2b6cff); border-radius: 999px; padding: 3px 4px 3px 10px; font-size: 13px; }
.tag-chip-x { border: none; background: none; cursor: pointer; color: inherit; font-size: 11px; line-height: 1; padding: 2px 4px; border-radius: 50%; }
.tag-chip-x:hover { background: rgba(0,0,0,.12); }
.tag-chip-input { border: none; outline: none; flex: 1; min-width: 90px; background: none; font: inherit; padding: 4px; }

/* ---- Categorised picker (shared by the page block editor AND the form element editor) ---- */
#add-block-modal .modal, #add-element-modal .modal { width: min(1040px, 94vw); max-width: 94vw; }
.bpick { display: flex; flex-direction: column; gap: 14px; }
.bpick-search { position: relative; }
.bpick-search input { width: 100%; padding: 11px 14px 11px 40px; border-radius: 10px;
    border: 1px solid rgba(128,128,128,.28); background: rgba(128,128,128,.08); color: inherit; font-size: 14px; }
.bpick-search input:focus { outline: none; border-color: var(--accent, #2b6cff); }
.bpick-sico { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; opacity: .5; }
.bpick-layout { display: grid; grid-template-columns: 190px 1fr; gap: 16px; align-items: start; }
@media (max-width: 680px) { .bpick-layout { grid-template-columns: 1fr; } .bpick-cats { flex-direction: row; overflow-x: auto; border-right: none; } }
.bpick-cats { display: flex; flex-direction: column; gap: 2px; border-right: 1px solid rgba(128,128,128,.2); padding-right: 8px; }
.bpick-cat { display: flex; align-items: center; justify-content: space-between; gap: 8px; white-space: nowrap;
    text-align: left; padding: 9px 12px; border-radius: 8px; border: none; background: none; color: inherit; cursor: pointer; font-size: 13.5px; }
.bpick-cat:hover { background: rgba(128,128,128,.14); }
.bpick-cat.is-active { background: var(--accent, #2b6cff); color: #fff; }
.bpick-clabel { display: inline-flex; align-items: center; gap: 7px; }
.bpick-cico { font-size: 13px; line-height: 1; }
.bpick-cat-fav .bpick-cico { color: #e6a700; }
.bpick-cat.is-active .bpick-cico { color: #fff; }
.bpick-sep { height: 1px; background: rgba(128,128,128,.22); margin: 8px 6px; }
.bpick-n { font-size: 11.5px; opacity: .75; background: rgba(128,128,128,.22); padding: 1px 8px; border-radius: 999px; }
.bpick-cat.is-active .bpick-n { background: rgba(255,255,255,.25); opacity: 1; color: #fff; }
@media (max-width: 680px) { .bpick-sep { width: 1px; height: auto; margin: 4px 6px; } }
.bpick-main { max-height: 60vh; overflow-y: auto; padding: 3px 4px 4px 3px; }
.bpick-grouphead { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; opacity: .55; margin: 0 0 10px; }
.bpick-group + .bpick-group { margin-top: 14px; }
.bpick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 10px; grid-auto-rows: 1fr; }
.bpick-grid form { margin: 0; height: 100%; position: relative; }
.tile-fav { position: absolute; top: 6px; right: 6px; z-index: 2; width: 22px; height: 22px; padding: 0;
    border: none; background: none; cursor: pointer; border-radius: 6px; font-size: 14px; line-height: 1;
    color: rgba(128,128,128,.5); opacity: 0; transition: opacity .12s ease, color .12s ease; }
.bpick-grid form:hover .tile-fav { opacity: 1; }
.tile-fav:hover { color: #e6a700; background: rgba(128,128,128,.16); }
.tile-fav.on { opacity: 1; color: #e6a700; }
.bpick-flat .bpick-grouphead { display: none; }
.bpick-flat .bpick-group { margin-top: 0 !important; }
.bpick .tile { width: 100%; height: 116px; box-sizing: border-box;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 9px;
    text-align: center; font-family: inherit; color: inherit; cursor: pointer;
    padding: 14px 8px; border-radius: 10px;
    background: rgba(128,128,128,.05); border: 1px solid rgba(128,128,128,.2);
    transition: border-color .15s ease, background .15s ease, transform .1s ease; }
.bpick .tile:hover { border-color: var(--accent, #2b6cff); background: rgba(128,128,128,.1); transform: translateY(-1px); }
.bpick .tile .t-icon { display: inline-flex; align-items: center; justify-content: center;
    width: 42px; height: 42px; border-radius: 10px; flex: none;
    background: rgba(128,128,128,.12); color: var(--accent, #2b6cff); margin: 0; }
.bpick .tile .t-icon svg { width: 22px; height: 22px; }
.bpick .tile .t-name { font-weight: 600; font-size: 12.5px; line-height: 1.25; color: inherit;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bpick .tile .t-desc { display: none; }
.bpick-empty { text-align: center; opacity: .6; padding: 34px 0; }
.bpick-foot { font-size: 12.5px; opacity: .6; border-top: 1px solid rgba(128,128,128,.2); padding-top: 10px; }
.cond-field .cond-box { display: grid; grid-template-columns: 1fr; gap: 8px; }
.cond-field .cond-box select, .cond-field .cond-box input { width: 100%; }
.field.cond-field { border-top: 1px dashed var(--line); padding-top: 14px; }

/* Datepicker per-field button-text overrides */
.dp-texts { border-top: 1px dashed var(--line); padding-top: 12px; }
.dp-texts .dp-text-row { display: grid; grid-template-columns: 1fr 1.3fr; align-items: center;
    gap: 10px; margin-top: 8px; }
.dp-texts .dp-text-cap { font-size: 12.5px; color: var(--muted); }
.dp-texts .dp-text-row input { width: 100%; }

/* per-form submissions: dynamic field list */
.sub-fields { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 2px 14px; max-width: 520px; }
.sub-fields dt { font-weight: 600; color: var(--muted); font-size: 13px; }
.sub-fields dd { margin: 0; white-space: pre-wrap; }

/* ============ Responsive ============ */
@media (max-width: 980px) {
    .admin-content { padding: 24px; }
    .admin-topbar { padding: 16px 24px; }
}

/* Off-canvas drawer for the admin menu */
@media (max-width: 860px) {
    .admin { grid-template-columns: 1fr; }
    .admin-sidebar {
        position: fixed; top: 0; left: 0; bottom: 0; height: 100dvh; width: 264px; max-width: 82vw;
        z-index: 60; overflow-y: auto; transform: translateX(-100%);
        transition: transform .25s ease;
    }
    body.nav-open .admin-sidebar { transform: translateX(0); box-shadow: 0 0 50px rgba(0, 0, 0, .5); }
    .admin-backdrop {
        display: block; position: fixed; inset: 0; z-index: 55; background: rgba(0, 0, 0, .45);
        opacity: 0; visibility: hidden; transition: opacity .25s ease;
    }
    body.nav-open .admin-backdrop { opacity: 1; visibility: visible; }
    body.nav-open { overflow: hidden; }

    .admin-menu-toggle {
        display: inline-flex; flex-direction: column; justify-content: center; align-items: center;
        width: 42px; height: 42px; flex-shrink: 0; padding: 0;
        border: 1px solid var(--line); background: #fff; border-radius: 8px; cursor: pointer;
    }
    .admin-topbar { padding: 12px 16px; gap: 12px; }
    .admin-topbar-title { font-size: 17px; }
    .admin-content { padding: 20px 16px; }
    .admin-user { display: none; }

    .page-head { gap: 12px; margin-bottom: 20px; }
    .page-head h1 { font-size: 22px; }
    .form-row { grid-template-columns: 1fr; }

    /* Wide tables scroll horizontally instead of squishing */
    table.data { display: block; overflow-x: auto; white-space: nowrap; }

    /* Live editor stacks; give the panel the full width */
    .live-editor { grid-template-columns: 1fr; height: auto; }
    .le-preview { height: 70vh; }
    .form-builder.editing .le-panel { max-width: none; }
}

@media (max-width: 560px) {
    .admin-content { padding: 16px 12px; }
    .card { padding: 18px 16px; }
    .media-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 12px; }
    .media-modal-body { grid-template-columns: 1fr; gap: 16px; }
    .media-preview img { max-height: 240px; }
    .stat-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
    .opt-row { grid-template-columns: 1fr; }
    .color-grid { grid-template-columns: 1fr 1fr; }
    .block-item { flex-wrap: wrap; }
    .block-item .actions { width: 100%; justify-content: flex-start; }
    .page-head .btn { flex: 1 1 auto; text-align: center; }
}

/* ===== List toolbar + client-side search / paging / view-toggle (admin index pages) ===== */
.list-toolbar { flex: 1 1 auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.list-toolbar .list-search { margin-right: auto; }   /* pushes toggle + primary button to the right */

/* The toolbar of a LIST is a framed bar: search, filter and the view toggle always live together in
   it, so it reads as one control surface above the records rather than three loose widgets. Scoped
   to [data-list] on purpose — the same class carries the plain back/action buttons in the page head
   of a detail or create page, and those must not end up in a box. */
[data-list] .page-head .list-toolbar {
    border: 1px solid var(--line);
    background: #fff;
    padding: 10px 12px;
}
[data-list] .page-head .list-toolbar .list-search { min-width: 200px; }
/* The bar already frames them, so the controls inside drop their own heavy border. */
[data-list] .page-head .list-toolbar .list-search,
[data-list] .page-head .list-toolbar select.list-search { border-color: var(--line); }
.list-search { height: 34px; min-width: 200px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 8px; font: inherit; font-size: 13.5px; background: #fff; }
.list-search:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent); }
.list-empty { color: var(--muted, #6b7078); padding: 16px 2px; }
/* Same message, but as a row inside the table so the header stays visible. Italic marks it as
   a state rather than data. */
.list-empty-row td { color: var(--muted, #6b7078); font-style: italic; padding: 18px 12px; text-align: center; }
.list-pager { display: flex; gap: 6px; margin-top: 16px; flex-wrap: wrap; }
.pager-btn { min-width: 34px; height: 34px; padding: 0 10px; border: 1px solid var(--line); background: #fff; border-radius: 8px; cursor: pointer; font: inherit; font-size: 13px; color: var(--ink); }
.pager-btn:hover { border-color: var(--accent); }
.pager-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.view-toggle { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.vt-btn { width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; border: 0; background: #fff; color: var(--muted, #6b7078); cursor: pointer; }
.vt-btn + .vt-btn { border-left: 1px solid var(--line); }
.vt-btn.active { background: var(--accent); color: #fff; }
[data-list].list-view-table [data-list-tiles] { display: none; }
[data-list].list-view-tiles [data-list-table] { display: none; }
@media (max-width: 640px) { .list-search { min-width: 0; flex: 1 1 auto; } }

/* ===== Page version switcher (language versions) — dropdown in the block editor header ===== */
.le-versions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; margin-bottom: 14px; }
.le-ver-lbl { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted, #6b7078); }
.le-verselect {
    flex: 1 1 100%; width: 100%; padding: 6px 10px; border-radius: 8px; font-size: 13px;
    border: 1px solid var(--line, #e2e4e8); background: #fff; color: var(--ink, #1a1a1a); cursor: pointer;
}
.le-verselect:hover, .le-verselect:focus { border-color: var(--accent, #2563eb); outline: none; }
.le-ver-addform { display: inline; margin: 0; padding: 0; }
.le-ver-add {
    display: inline-block; padding: 4px 10px; border-radius: 8px; font-size: 12px; font-weight: 600;
    border: 1px dashed var(--line, #cdd2da); background: transparent; color: var(--muted, #6b7078); cursor: pointer;
}
.le-ver-add:hover { border-color: var(--accent, #2563eb); color: var(--accent, #2563eb); }

/* ===== Simple modal dialog (e.g. add-language on the Languages settings tab) ===== */
.mat-dialog {
    border: 0; border-radius: 14px; padding: 22px 24px; min-width: 320px; max-width: 92vw;
    box-shadow: 0 24px 60px rgba(0,0,0,.28); color: var(--ink, #1a1a1a); background: #fff;
}
.mat-dialog::backdrop { background: rgba(15,18,24,.45); }

.admin-foot-lang-menu[hidden]{display:none!important}
.pg-versions[hidden]{display:none!important}

/* ============ Cloud store dialog ============ */
/* Browsing what you could install is a different activity from managing what you already have, so
   the catalogue opens as a dialog instead of hanging under the list. Lives in the shared admin sheet
   because it is admin chrome — the cloud's own store browsing gets the same look for free. */
.modal-store { max-width: 900px; width: 100%; }
.modal-store .modal-body { max-height: 70vh; overflow-y: auto; }
.store-search { margin: 4px 0 14px; }
.store-search .list-search { width: 100%; }
.store-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.store-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid var(--line, #d9dce1);
    border-radius: 10px;
    padding: 14px 16px;
    background: #fff;
    transition: border-color .12s, box-shadow .12s;
}
.store-card:hover { border-color: var(--accent); box-shadow: 0 4px 18px rgba(0, 0, 0, .07); }
/* display:flex on the class beats the browser default for [hidden], so the dialog search could
   not hide anything without this. Same trap the tab panels and modals already guard against. */
.store-card[hidden] { display: none !important; }
/* Accent strip: for a template the colour is what you recognise it by before reading the name. */
.store-card-strip { display: block; height: 6px; border-radius: 3px; margin-bottom: 8px; }
.store-card-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.store-card-sub { font-size: 12px; color: var(--muted, #6b7078); overflow-wrap: anywhere; }
.store-card-text { font-size: 13px; color: var(--muted, #6b7078); }
.store-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 10px; }


/* ============ Template file editor ============ */
/* The pseudo-file list and its CodeMirror modal. Shared because the CMS and the cloud offer the
   same editor (see _TemplateFiles.cshtml); it used to sit inline in the CMS template page. */
.tpl-files { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.tpl-file { display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
    background: #fff; border: 1px solid var(--line, #e2e4e8); border-radius: 10px; padding: 12px 14px; cursor: pointer; font: inherit; }
.tpl-file:hover { border-color: var(--accent); box-shadow: 0 2px 10px rgba(0,0,0,.05); }
.tpl-file-ext { flex: none; width: 46px; height: 46px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-head, sans-serif); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: #fff; }
.ext-html { background: #e44d26; } .ext-css { background: #2965f1; } .ext-js { background: #b8a316; }
.tpl-file-main { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.tpl-file-name { font-size: 15px; display: flex; align-items: center; gap: 8px; }
.tpl-file-name code { font-size: 14px; }
.tpl-file-badge { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: #8a8f98; background: #f1f2f4; border-radius: 999px; padding: 2px 9px; }
.tpl-file-badge.on { color: #fff; background: var(--accent); }
.tpl-file-desc { font-size: 12.5px; color: #6b7078; }
.tpl-file-open { flex: none; color: var(--accent); font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; gap: 5px; }

/* Modal */
.cm-modal { position: fixed; inset: 0; z-index: 3000; background: rgba(17,19,24,.55); display: flex; align-items: stretch; justify-content: center; padding: 3vh 2vw; }
.cm-modal[hidden] { display: none; }
.cm-modal-dialog { background: #fff; border-radius: 12px; width: min(1100px, 100%); display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 70px rgba(0,0,0,.4); }
.cm-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--line, #e2e4e8); }
.cm-modal-file { font-size: 15px; display: inline-flex; align-items: center; gap: 8px; }
.cm-modal-file code { font-size: 14px; }
.cm-modal-close { border: 0; background: none; font-size: 20px; line-height: 1; cursor: pointer; color: #6b7078; padding: 4px 8px; border-radius: 6px; }
.cm-modal-close:hover { background: #f1f2f4; color: #111; }
.cm-modal-editor { flex: 1; min-height: 0; overflow: hidden; }
.cm-modal-editor .CodeMirror { height: 100%; font-size: 13.5px; line-height: 1.5; }
.cm-modal-tokens { padding: 8px 14px; border-top: 1px solid var(--line, #eee); display: flex; flex-wrap: wrap; align-items: center; gap: 6px; max-height: 92px; overflow-y: auto; }
.cm-tokens-label { font-size: 12px; color: #6b7078; margin-right: 4px; }
.cm-token { font-family: var(--mono, monospace); font-size: 12px; background: #f1f2f4; border: 1px solid #e2e4e8; border-radius: 6px; padding: 2px 7px; cursor: pointer; }
.cm-token:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.cm-modal-foot { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--line, #e2e4e8); background: #fafbfc; }

/* Der Editor im Dateibaum eines Templates (.pf-tree > .pf-main, siehe _TemplateFiles.cshtml).
   CodeMirror hat keine eigene Höhe: als Flex-Kind ohne Höhenvorgabe misst es sich auf EINE Zeile,
   und die Fläche stand als 28 Pixel hoher Streifen neben dem Baum. Die Höhe hier statt am Element
   im Markup, weil sie zum Kasten gehört und nicht zum einzelnen Vorkommen. */
.pf-editor .cm-modal-editor { flex: 1 1 auto; height: 320px; }
/* Der Baum der Templates trägt an jeder Zeile ein Abzeichen (angepasst / leer) — die Auskunft, die
   ihn erst nützlich macht. In den 230 Pixeln des Plugin-Baums lag es über dem Dateinamen, deshalb
   hier eine breitere linke Spalte; der Plugin-Baum bleibt, wie er ist.
   Verstellt wird nur noch die STELLSCHRAUBE --pf-side-width und nicht mehr das ganze Raster: wer das
   Raster überschrieb, musste den Umbruch für schmale Fenster gleich mit überschreiben — genau dafür
   stand hier eine zweite @media-Zeile, und die dritte Abweichung hätte sie wieder vergessen. */
.tpl-tree.pf-tree { --pf-side-width: 300px; }
.tpl-tree .pf-file-name { min-width: 0; overflow: hidden; }
.tpl-tree .tpl-file-badge { flex: 0 0 auto; }

/* ---- Hinzufügen dialog -------------------------------------------------------------------------
   The three ways to add something, as equally-weighted choices. Deliberately not a <select> or a row
   of small buttons: each one leads somewhere different (a picker, a page, a form), and the operator
   picks by reading what happens, not by recognising a verb. */
.add-options { display: flex; flex-direction: column; gap: 10px; }

.add-option {
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: 100%;
    text-align: left;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 14px 16px;
    text-decoration: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    transition: border-color .12s, box-shadow .12s;
}
.add-option:hover { border-color: var(--accent); box-shadow: 0 4px 18px rgba(0, 0, 0, .07); }
.add-option-title { font-weight: 600; }
.add-option-sub { font-size: 13px; color: var(--muted); }

/* Mail preview: the finished message, rendered by the server. */
.mail-preview { width: 100%; height: 420px; border: 1px solid var(--line); border-radius: 8px; background: #fff; }

/* The ＋ buttons under the block tree in the settings panel. Wrapping, because a container can
   allow several child types and the sidebar is narrow. */
.le-add-child { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.le-add-child .add-child { align-self: auto; }

/* Multi-select as tick-able chips. A native <select multiple> needs ctrl-click to add a second
   entry and drops the rest without a word if you forget — the exact mistake this field prevents. */
.ms-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.ms-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 10px; border: 1px solid var(--border, #e5e7eb); border-radius: 999px;
    font-size: 13px; cursor: pointer; user-select: none; background: var(--card, #fff);
}
.ms-chip:hover { border-color: var(--accent, #2563eb); }
.ms-chip.on { border-color: var(--accent, #2563eb); background: color-mix(in srgb, var(--accent, #2563eb) 10%, transparent); }
.ms-chip input { margin: 0; }

/* The multi-select dropdown inside the block editor. Its own stylesheet (mat-richselect.css) dresses
   it for the PUBLIC site, where fields are rounded and 16px — next to the admin's square 1px fields
   it read as a foreign control. These few lines pull the trigger back in line with .field above; the
   menu itself keeps the shared styling, because a dropdown panel looks the same in both places. */
.field .mat-rs { position: relative; }
.field .mat-rs-trigger {
    width: 100%; padding: 11px 13px; border: 1px solid #cfcfcf; border-radius: 0;
    font-family: inherit; font-size: 15px; background: #fff; color: inherit;
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    text-align: left; cursor: pointer; box-sizing: border-box; min-height: 0;
}
.field .mat-rs-trigger:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: -2px; }
.field .mat-rs-current { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.field .mat-rs-placeholder { color: var(--muted, #6b7280); }
.field .mat-rs-chev { flex: 0 0 auto; color: var(--muted, #6b7280); font-size: 12px; }

/* Auswahl mit Symbol: die Antwort ist auf einen Blick zu erkennen, bevor man den Text liest. Nur
   wirksam, wo eine Option ein Icon mitbringt — ohne bleibt die Darstellung, wie sie war. */
.add-option:has(.add-option-icon) { display: grid; grid-template-columns: 46px 1fr; align-items: center; column-gap: 14px; }
.add-option-icon { grid-row: 1 / span 2; display: flex; align-items: center; justify-content: center;
    width: 46px; height: 46px; border-radius: 12px; background: #f0f2f5; font-size: 24px; color: var(--accent, #2563eb); }
.add-option:hover .add-option-icon { background: color-mix(in srgb, var(--accent, #2563eb) 12%, transparent); }

/* Sichtbar, aber nicht angepriesen: die Möglichkeit gibt es, sie ist nur nicht freigeschaltet. Der
   Klick führt dorthin, wo man das ändert — deshalb kein pointer-events: none. */
.add-option.is-muted { opacity: .55; }
.add-option.is-muted:hover { opacity: 1; }

/* Plugin-Dateien: links was es gibt, rechts woran man arbeitet — die Anordnung, die jeder aus einem
   Code-Editor kennt. Die Wurzel ist das Plugin, weil die Dateien ihm gehören und sonst nirgendwohin
   reichen. */
/* Die BREITE der linken Spalte ist das einzige, was sich von Fall zu Fall unterscheidet — deshalb
   steht sie als Stellschraube hier und wird von den Abweichungen (.tpl-tree, .cp-tree) nur noch
   umgesetzt. Das Raster selbst und der Umbruch für schmale Fenster stehen dadurch an EINER Stelle:
   wer beides überschreiben musste, hat beim zweiten Mal das eine vergessen. */
.pf-tree { --pf-side-width: 230px; display: grid; grid-template-columns: var(--pf-side-width) 1fr; border: 1px solid #cfcfcf; background: #fff; min-height: 340px; }
.pf-side { border-right: 1px solid #cfcfcf; background: #fafbfc; display: flex; flex-direction: column; min-width: 0; }
.pf-list { padding: 6px; display: flex; flex-direction: column; gap: 1px; flex: 1 1 auto; overflow-y: auto; min-height: 0; }
/* Eine Zeile des Baums: Klapper, Symbol und Name, rechts das, was man mit ihr tun kann. Die
   EINRÜCKUNG setzt das Skript je Ebene am Element selbst — sie sagt, wo ein Knoten hängt, und ist
   damit Inhalt und nicht Aussehen; als Klasse je Tiefe wäre sie bei der vierten Ebene zu Ende. */
.pf-file { display: flex; align-items: center; }
.pf-twist { flex: 0 0 16px; width: 16px; height: 22px; padding: 0; border: 0; background: none;
    display: flex; align-items: center; justify-content: center; cursor: pointer;
    color: var(--muted, #6b7280); font-size: 13px; }
/* Ein Blatt hat nichts aufzuklappen — der Platz bleibt trotzdem stehen, sonst stünden Dateien und
   Ordner derselben Ebene um 16px versetzt. */
.pf-twist:empty { cursor: default; }
.pf-file-name { flex: 1 1 auto; display: flex; align-items: center; gap: 6px; text-align: left;
    padding: 5px 6px; border: 0; background: none;
    cursor: pointer; font-family: var(--font-mono, ui-monospace, monospace); font-size: 12.5px; border-radius: 5px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pf-file-name i { flex: 0 0 auto; color: var(--muted, #6b7280); font-size: 14px; }
.pf-file-name:hover { background: #eef0f4; }
.pf-file.is-open .pf-file-name { background: color-mix(in srgb, var(--accent, #2563eb) 14%, transparent); font-weight: 600; }
/* Derselbe Inhalt wie der Rechtsklick, nur sichtbar: ohne ihn wäre der Baum auf einem Gerät ohne
   rechte Maustaste nicht zu bedienen. Beim Tastaturfokus deshalb auch ohne Mauszeiger da. */
.pf-more { flex: 0 0 auto; border: 0; background: none; cursor: pointer; color: var(--muted, #6b7280);
    padding: 3px 6px; border-radius: 5px; opacity: 0; }
.pf-file:hover .pf-more, .pf-file.is-open .pf-more, .pf-more:focus-visible { opacity: 1; }
.pf-more:hover { background: #eef0f4; }
/* Das Zahnrad an der Wurzel benutzt den Knopf der Menüleiste — derselbe flache Knopf im selben
   Baum. */
.pf-file .pf-menu-item { flex: 0 0 auto; padding: 3px 6px; line-height: 1; }
/* Ziehen im Baum: dieselbe Sprache wie beim Verschieben von Blöcken (.block-item.dragging) — die
   Fracht wird blass, das Ziel hebt sich hervor. Das Hervorheben liegt am Namen und nicht an der
   ganzen Zeile, damit es genauso aussieht wie die offene Datei und nicht wie ein zweiter Zustand. */
.pf-file.dragging { opacity: .55; }
.pf-file.is-drop .pf-file-name { background: color-mix(in srgb, var(--accent, #2563eb) 22%, transparent); }
/* Das Kontextmenü des Baums ist gebaut wie das Sprachmenü in der Fußleiste
   (.admin-foot-lang-menu/.admin-lang-opt) — nur steht es am Zeiger statt an einem Knopf. Deshalb
   position: fixed am body: in der scrollenden Liste wäre es abgeschnitten, sobald es länger ist
   als der Rest des Kastens. */
.pf-ctx { position: fixed; z-index: 80; min-width: 176px; background: #fff; border: 1px solid var(--line, #eceef1);
    border-radius: 10px; padding: 6px; box-shadow: 0 12px 30px rgba(0,0,0,.16);
    display: flex; flex-direction: column; gap: 2px; }
.pf-ctx-item { width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
    padding: 8px 10px; border-radius: 7px; font: inherit; font-size: 13px; color: var(--black, #111); }
.pf-ctx-item:hover, .pf-ctx-item:focus-visible { background: #eef1f6; }
.pf-ctx-item.is-danger { color: #dc2626; }
.pf-ctx-item.is-danger:hover, .pf-ctx-item.is-danger:focus-visible { background: #fee2e2; }

.pf-main { display: flex; flex-direction: column; min-width: 0; }
.pf-editor { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.pf-editor-head { display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 8px 12px; background: #fafafa; border-bottom: 1px solid #e6e8ec; font-size: 12.5px; }
.pf-editor textarea { flex: 1 1 auto; width: 100%; border: 0; border-radius: 0; min-height: 280px; resize: vertical; }
.pf-empty { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; padding: 24px;
    color: var(--muted, #6b7280); font-size: 13.5px; text-align: center; }
/* display:flex aus einer Klasse schlägt das display:none, das der Browser [hidden] mitgibt — ohne
   diese Zeile stehen Editor UND Leerzustand gleichzeitig da, obwohl das Skript einen von beiden
   ausblendet. */
/* Und dieselbe Falle noch einmal, bei der Beschriftung: sie trug hidden, stand aber trotzdem da —
   fünf Dateinamen untereinander unter dem Editor, wie eine zweite, tote Dateileiste neben dem
   Baum. Am laufenden System gefunden, nicht beim Lesen. */
.pf-editor[hidden], .pf-empty[hidden], .pf-editor-head[hidden] { display: none; }

@media (max-width: 800px) { .pf-tree { grid-template-columns: 1fr; } .pf-side { border-right: 0; border-bottom: 1px solid #cfcfcf; } }

/* Menüleiste über dem Editor: Reiter und Aktionen links, die offene Datei daneben. */
.pf-menu { display: flex; align-items: center; gap: 12px; padding: 6px 10px; background: #fafafa;
    border-bottom: 1px solid #e6e8ec; font-size: 12.5px; }
.pf-menu-item { border: 0; background: none; cursor: pointer; padding: 5px 9px; border-radius: 6px;
    font-family: inherit; font-size: 12.5px; white-space: nowrap; }
.pf-menu-item:hover { background: #eef0f4; }
.pf-menu-file { font-weight: 600; }
/* Die beiden Flächen im Editor (Skriptdatei / hochgeladene Datei) erben die Höhe des Bereichs,
   sonst fiele der Kasten bei der kürzeren in sich zusammen. Das display:flex hier ist genau der
   Fall, den .tab-panel[hidden] mit !important abfängt — ohne das stünden beide gleichzeitig da. */
.pf-main > .tab-panel { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
