:root {
    --scripleaf-green: #177147;
    --scripleaf-green-dark: #0f5535;
    --scripleaf-navy: #0f3947;
    --scripleaf-white: #ffffff;
}

h1:focus {
    outline: none;
}

/* The reconnection/unhandled-exception banner (MainLayout.razor, AdminLayout.razor's static
   #blazor-error-ui markup) is hidden by default in every Blazor project template - only Blazor's own
   JS sets display back to block when a real error/disconnect happens. This rule went missing when
   app.css was rewritten for the redesign below, leaving the banner's placeholder text ("Ein
   unerwarteter Fehler ist aufgetreten...") permanently visible at the end of every page's content. */
#blazor-error-ui {
    position: fixed;
    bottom: 0;
    left: 0;
    z-index: 1000;
    display: none;
    box-sizing: border-box;
    width: 100%;
    padding: 0.75rem 3rem 0.75rem 1.25rem;
    background: #fdf3e3;
    color: #a15c00;
    box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.2);
}

#blazor-error-ui .dismiss {
    position: absolute;
    top: 0.5rem;
    right: 0.75rem;
    cursor: pointer;
}

.scripleaf-hero {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 2rem;
    color: var(--scripleaf-navy);
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* Auth (MainLayout's topbar, LoginDisplay, Pages/Login.razor - Konzept Abschnitt 10.1) */

.scripleaf-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1.5rem;
    border-bottom: 1px solid #e5e5e5;
}

.scripleaf-topbar-brand {
    color: var(--scripleaf-navy);
    font-weight: 700;
    text-decoration: none;
}

.scripleaf-auth-status {
    color: #555;
    font-size: 0.9em;
    margin: 0;
}

.scripleaf-link-button {
    background: none;
    border: none;
    padding: 0;
    color: var(--scripleaf-green-dark);
    text-decoration: underline;
    cursor: pointer;
    font: inherit;
}

.scripleaf-auth {
    max-width: 24rem;
    margin: 3rem auto;
    padding: 1.5rem;
    color: var(--scripleaf-navy);
}

.scripleaf-auth-error {
    color: #b3261e;
    background: #fbeceb;
    border-radius: 4px;
    padding: 0.5rem 0.75rem;
}

.scripleaf-field {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-bottom: 1rem;
}

.scripleaf-field label {
    font-weight: 500;
}

.scripleaf-field input {
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 0.5rem;
}

.scripleaf-auth button[type="submit"] {
    background: var(--accent);
    color: white;
    border: none;
    border-radius: 4px;
    padding: 0.5rem 1.2rem;
    cursor: pointer;
}
.scripleaf-auth button[type="submit"]:hover {
    background: var(--accent-dark);
}

/* Public navigation (books/chapters/pages projection - Home.razor, DocPage.razor) */

.scripleaf-books {
    padding: 0 2rem;
}

.scripleaf-doc {
    max-width: 56rem;
    margin: 0 auto;
    padding: 1.5rem;
    color: var(--scripleaf-navy);
}

.scripleaf-doc img,
.scripleaf-editor img {
    max-width: 100%;
    height: auto;
}

/* Click-to-enlarge (wwwroot/lightbox.js) - only published-content images are clickable, not the
   editor's own (that would fight with placing the cursor/selecting the image node there). */
.scripleaf-doc img {
    cursor: zoom-in;
}

.scripleaf-lightbox {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 5vh 5vw;
    background: rgba(0, 0, 0, .82);
    cursor: zoom-out;
}

.scripleaf-lightbox.open {
    display: flex;
}

.scripleaf-lightbox img {
    max-width: 100%;
    max-height: 100%;
    border-radius: 6px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
    cursor: default;
}

.scripleaf-lightbox-close {
    position: absolute;
    top: 18px;
    right: 24px;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    color: white;
    background: rgba(255, 255, 255, .12);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
}

.scripleaf-lightbox-close:hover {
    background: rgba(255, 255, 255, .22);
}

.scripleaf-breadcrumb {
    padding: 1.5rem 1.5rem 0;
    max-width: 56rem;
    margin: 0 auto;
}

.scripleaf-breadcrumb a {
    color: var(--scripleaf-green-dark);
    text-decoration: none;
}

.scripleaf-breadcrumb a:hover {
    text-decoration: underline;
}

.scripleaf-node-list ul,
ul.scripleaf-node-list {
    list-style: none;
    padding: 0;
    margin: 1rem 0;
}

.scripleaf-node-list li {
    padding: 0.4rem 0;
    border-bottom: 1px solid #e5e5e5;
}

.scripleaf-node-list a {
    color: var(--scripleaf-green-dark);
    text-decoration: none;
    font-weight: 500;
}

.scripleaf-node-list a:hover {
    text-decoration: underline;
}

/* WYSIWYG editor spike (ADR 0007) */

.scripleaf-edit-page {
    max-width: 56rem;
    margin: 0 auto;
    padding: 1.5rem;
    color: var(--scripleaf-navy);
}

.edit-hint {
    color: #555;
    font-size: 0.9em;
}

.editor-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.5rem;
}

.editor-toolbar button {
    border: 1px solid #ccc;
    background: #fff;
    border-radius: 4px;
    padding: 0.3rem 0.6rem;
    cursor: pointer;
}

.editor-toolbar button:hover {
    background: #f0f5f2;
    border-color: var(--scripleaf-green);
}

.scripleaf-editor {
    border: 1px solid #ccc;
    border-radius: 4px;
    min-height: 16rem;
    padding: 1rem;
}

.scripleaf-editor .ProseMirror {
    outline: none;
    min-height: 14rem;
}

.scripleaf-editor ul[data-type="taskList"] {
    list-style: none;
    padding-left: 0.25rem;
}

.scripleaf-editor ul[data-type="taskList"] li {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
}

.scripleaf-editor ul[data-type="taskList"] li > label {
    margin-top: 0.2rem;
}

/* Tables - shared between the editor and the public rendering (Markdig's UseAdvancedExtensions pipe
   tables produce the exact same plain <table>/<tr>/<th>/<td> structure TipTap's table extensions do) */

.scripleaf-doc table,
.scripleaf-editor table {
    border-collapse: collapse;
    width: 100%;
    margin: 1rem 0;
}

.scripleaf-doc th,
.scripleaf-doc td,
.scripleaf-editor th,
.scripleaf-editor td {
    border: 1px solid #ccc;
    padding: 0.4rem 0.6rem;
    text-align: left;
}

.scripleaf-doc th,
.scripleaf-editor th {
    background: #f0f5f2;
    font-weight: 600;
}

/* Internal-link picker (editor.js's openLinkPicker) - a small floating panel, not a full modal */

/* Theme tokens throughout, matching .scripleaf-image-picker below (this used to be the odd one out -
   hardcoded light-mode-only colors, including a submit button that ignored the admin-configurable
   accent color entirely - see SiteBrandingCss.ForAccentColor). */
.scripleaf-link-picker {
    position: fixed;
    top: 4.5rem;
    left: 50%;
    transform: translateX(-50%);
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: var(--shadow);
    padding: 1rem;
    z-index: 1000;
    width: min(24rem, 90vw);
}

.scripleaf-link-picker label {
    display: block;
    font-weight: 500;
    margin-bottom: 0.75rem;
}

.scripleaf-link-picker select,
.scripleaf-link-picker input {
    display: block;
    width: 100%;
    margin-top: 0.25rem;
    padding: 0.4rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--text);
    box-sizing: border-box;
}

.scripleaf-link-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
}

/* "Als Button anzeigen" checkbox - overrides the block/full-width input styling above, which is meant
   for the select/url/text fields, not a checkbox sitting inline with its own label text. */
.scripleaf-link-as-button {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}
.scripleaf-link-as-button input {
    display: inline-block;
    width: auto;
    margin-top: 0;
}

.scripleaf-link-actions button[type="submit"] {
    background: var(--accent);
    color: white;
    border: none;
    border-radius: 4px;
    padding: 0.4rem 1rem;
    cursor: pointer;
}
.scripleaf-link-actions button[type="submit"]:hover {
    background: var(--accent-dark);
}

.scripleaf-link-actions button[data-cancel] {
    background: none;
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.4rem 1rem;
    cursor: pointer;
}

/* Media library image picker (editor.js's openImagePicker) - same floating-panel idea as the link
   picker above, but built with app.css's theme tokens (unlike the link picker's hardcoded light
   colors) so it also works in dark mode. */
.scripleaf-image-picker {
    position: fixed;
    top: 4.5rem;
    left: 50%;
    transform: translateX(-50%);
    width: min(30rem, 92vw);
    max-height: 75vh;
    overflow-y: auto;
    padding: 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow);
    z-index: 1000;
}
.scripleaf-image-picker-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.scripleaf-image-picker-header button { padding: 2px 6px; border: 0; border-radius: 6px; background: none; color: var(--text-soft); font-size: 1rem; cursor: pointer; }
.scripleaf-image-picker-header button:hover { background: var(--surface-soft); color: var(--text); }
.scripleaf-image-picker-breadcrumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; color: var(--text-soft); font-size: .78rem; }
.scripleaf-image-picker-breadcrumbs a { color: var(--text-soft); text-decoration: none; }
.scripleaf-image-picker-breadcrumbs a:hover { color: var(--accent); }
.scripleaf-image-picker-folder-icon { font-size: 1.6rem; }
.scripleaf-image-picker-upload { margin-bottom: 14px; }
.scripleaf-image-picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; }
.scripleaf-image-picker-item { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 6px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-soft); cursor: pointer; overflow: hidden; }
.scripleaf-image-picker-item:hover { border-color: var(--accent); }
.scripleaf-image-picker-item img { width: 100%; height: 64px; object-fit: cover; border-radius: 4px; }
.scripleaf-image-picker-item span { width: 100%; overflow: hidden; color: var(--text-soft); font-size: .68rem; text-overflow: ellipsis; white-space: nowrap; }
.scripleaf-image-picker-empty { grid-column: 1 / -1; margin: 0; padding: 12px 0; color: var(--text-soft); font-size: .82rem; }

.editor-actions {
    margin-top: 0.75rem;
    display: flex;
    align-items: center;
    gap: 1rem;
}

.editor-actions button {
    background: var(--accent);
    color: white;
    border: none;
    border-radius: 4px;
    padding: 0.5rem 1.2rem;
    cursor: pointer;
}
.editor-actions button:hover:not(:disabled) {
    background: var(--accent-dark);
}

.editor-actions button:disabled {
    background: #999;
    cursor: wait;
}

.editor-status {
    color: #555;
}

/* Admonitions - shared between the public/preview rendering and the live editor
   (ScripLeaf.Markdown.MarkdownRenderer's wrapper HTML / lib/tiptap/admonition-node.js) */

.admonition {
    border-left: 4px solid var(--accent);
    background: var(--accent-soft);
    color: var(--text);
    padding: 0.5rem 1rem;
    margin: 1rem 0;
    border-radius: 0 8px 8px 0;
}

.admonition-title {
    font-weight: bold;
    margin: 0 0 0.25rem 0;
    color: var(--accent-dark);
}

/* danger/warning are tinted off the current theme's own --surface with color-mix() (rather than a
   second hardcoded light/dark pair per color) so they - like .admonition above - adapt to dark mode
   automatically: mixing red into a light --surface gives a light pink, into a dark --surface a dark,
   muted red, without ever needing an explicit :root[data-theme="dark"] override. Before this, these
   three rules had no dark-mode variant at all - a light-mode-only leftover from before app.css's
   redesign into CSS custom properties, unnoticed because the checked-in sample content only exercises
   the default (unnamed) admonition type. */
.admonition-danger {
    border-left-color: #b3261e;
    background: color-mix(in srgb, #b3261e 14%, var(--surface));
}
.admonition-danger .admonition-title {
    color: #b3261e;
}

.admonition-warning {
    border-left-color: #a15c00;
    background: color-mix(in srgb, #a15c00 14%, var(--surface));
}
.admonition-warning .admonition-title {
    color: #a15c00;
}

/* Code blocks (fenced ```code``` in Markdown, the editor's "Code-Block" toolbar button) previously
   rendered with no styling of their own - just the browser's bare monospace default, easy to miss
   among regular paragraphs. Shares .admonition's background tint (an explicit, deliberate choice:
   admin asked for "the same background color as a Hinweis, just without a title") rather than a
   neutral gray, but skips the colored left border - that's a Hinweis-specific "this is a callout"
   marker, not a general highlighted-block one. Applied to both the published rendering
   (.scripleaf-doc, MarkdownRenderer's output) and the WYSIWYG editor (.page-content-editor, TipTap's
   own codeBlock node) so what you type looks like what gets published. */
.scripleaf-doc pre,
.page-content-editor pre {
    margin: 1rem 0;
    padding: 14px 16px;
    overflow-x: auto;
    border-radius: 8px;
    background: var(--accent-soft);
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
}
.scripleaf-doc pre code,
.page-content-editor pre code {
    padding: 0;
    background: none;
    color: var(--text);
    font-size: .85em;
}
.scripleaf-doc code,
.page-content-editor code {
    padding: .15em .4em;
    border-radius: 5px;
    background: var(--accent-soft);
    color: var(--text);
    font-size: .88em;
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
}

/* Application shell and public library */
:root {
    color-scheme: light;
    --bg: #f4f7f6;
    --surface: #ffffff;
    --surface-soft: #edf4f1;
    --text: #17333a;
    --text-soft: #607379;
    /* Body text on a published page (.scripleaf-doc p/li) reads better stronger than --text-soft's
       muted gray-teal, without going all the way to full-strength --text everywhere else uses. */
    --doc-text: #242728;
    --border: #dce6e2;
    --accent: #177147;
    --accent-dark: #0f5535;
    --accent-soft: #dff1e8;
    --header: rgba(255, 255, 255, .92);
    --shadow: 0 12px 32px rgba(16, 54, 48, .08);
    --radius: 16px;
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #101817;
    --surface: #172220;
    --surface-soft: #1d2c29;
    --text: #e6f0ed;
    --text-soft: #9db1ab;
    --doc-text: var(--text);
    --border: #2c3d39;
    --accent: #62c695;
    --accent-dark: #8edbb2;
    --accent-soft: #213e32;
    --header: rgba(23, 34, 32, .92);
    --shadow: 0 16px 40px rgba(0, 0, 0, .24);
}

* { box-sizing: border-box; }
html { background: var(--bg); }
body { margin: 0; background: var(--bg); color: var(--text); line-height: 1.55; }
a { color: inherit; }
button, input { font: inherit; }

.app-header {
    position: sticky; top: 0; z-index: 50; height: 74px; display: flex; align-items: center;
    justify-content: space-between; padding: 0 28px; background: var(--header); border-bottom: 1px solid var(--border);
    backdrop-filter: blur(14px);
}
.brand { display: flex; width: 174px; height: 48px; align-items: center; }
.brand img { display: block; width: 100%; height: auto; }
/* Two logos are always rendered (MainLayout/AdminLayout.razor); only one is ever visible - CSS just
   toggles which, the same pattern the sun/moon theme-toggle icons below use. When no dark logo is
   configured, both <img> point at the same URL, so this is a no-op. */
.brand .brand-logo-dark { display: none; }
:root[data-theme="dark"] .brand .brand-logo-light { display: none; }
:root[data-theme="dark"] .brand .brand-logo-dark { display: block; }
/* Header search box (MainLayout.razor) - a plain HTML GET form to /suche (Components/Pages/Search.razor)
   rather than a bound MudBlazor field: DocPage.razor and this layout render statically (no
   @rendermode InteractiveServer), so a form submit is the only reliably working way to search from
   every page, not just an interactive one. */
.header-search { display: flex; align-items: center; gap: 6px; flex: 1 1 auto; max-width: 340px; margin: 0 20px; padding: 0 4px 0 14px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); }
.header-search input { flex: 1 1 auto; min-width: 0; padding: 9px 0; border: 0; background: transparent; color: var(--text); }
.header-search input:focus { outline: none; }
.header-search input::placeholder { color: var(--text-soft); }
.header-search button { width: 34px; height: 34px; display: grid; place-items: center; flex: none; border: 0; border-radius: 50%; color: var(--text-soft); background: transparent; cursor: pointer; }
.header-search button:hover { color: var(--accent); background: var(--accent-soft); }
.header-actions { display: flex; align-items: center; gap: 18px; }
.header-link, .scripleaf-auth-status { color: var(--text-soft); text-decoration: none; font-size: .88rem; font-weight: 650; }
.header-link:hover, .scripleaf-auth-status:hover { color: var(--accent); }
.theme-toggle { width: 42px; height: 42px; display: grid; place-items: center; border: 1px solid var(--border); border-radius: 12px; color: var(--text); background: var(--surface); cursor: pointer; }
.theme-toggle:hover { border-color: var(--accent); background: var(--accent-soft); }
/* Admin/AdminSettings.razor's "Dunkelmodus aktivieren" switch - no point offering a toggle for a theme
   the site can never actually switch to (theme.js's own preferredTheme() already forces light
   regardless, this just keeps a dead-end button off the header). */
:root[data-dark-mode-enabled="false"] .theme-toggle { display: none; }
.theme-moon, :root[data-theme="dark"] .theme-sun { display: none; }
:root[data-theme="dark"] .theme-moon { display: inline; font-size: 1.35rem; }

.workspace { display: grid; grid-template-columns: 254px minmax(0, 1fr) 276px; min-height: calc(100vh - 74px); }
.left-sidebar, .right-sidebar { padding: 28px 20px; background: var(--surface); }
/* Sticks to the viewport instead of scrolling away with the (usually much longer) main content -
   same pattern as .admin-nav below. overflow-y lets its own list scroll internally if it's ever
   taller than the viewport, rather than growing past it. */
.left-sidebar { display: flex; flex-direction: column; position: sticky; top: 74px; align-self: start; height: calc(100vh - 74px); overflow-y: auto; border-right: 1px solid var(--border); }
.right-sidebar { border-left: 1px solid var(--border); }
.sidebar-heading { display: flex; justify-content: space-between; align-items: center; margin: 0 4px 17px; color: var(--text-soft); font-size: .73rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.count-pill { min-width: 24px; padding: 2px 7px; border-radius: 999px; text-align: center; color: var(--accent); background: var(--accent-soft); }
.book-nav, .recent-list { display: grid; gap: 7px; }
.book-nav-item, .recent-item { display: flex; align-items: center; gap: 11px; padding: 9px; border-radius: 12px; text-decoration: none; min-width: 0; }
.book-nav-item:hover, .recent-item:hover { background: var(--surface-soft); }
.book-nav-item > span:last-child, .recent-item > span:last-child { min-width: 0; }
.book-nav-item strong, .recent-item strong { display: block; overflow: hidden; color: var(--text); font-size: .86rem; text-overflow: ellipsis; white-space: nowrap; }
.book-nav-item small, .recent-item small { display: block; overflow: hidden; color: var(--text-soft); font-size: .72rem; text-overflow: ellipsis; white-space: nowrap; }
/* Same 355:188 crop as .book-cover in the book grid (the "header" image) - aspect-ratio rather than a
   fixed height keeps the two in exact proportion at any size, so an uploaded cover is framed the same
   way here as it is there, just scaled down for the sidebar. */
.book-nav-cover { position: relative; flex: 0 0 64px; aspect-ratio: 355 / 188; display: grid; place-items: center; overflow: hidden; border-radius: 7px; background: linear-gradient(145deg, #153f44, #177147); box-shadow: 0 4px 10px rgba(15, 85, 53, .2); }
.book-nav-cover img { width: 34px; filter: brightness(0) invert(1); }
.book-nav-cover img.uploaded-cover { width: 100%; height: 100%; object-fit: cover; filter: none; }
.all-books-link { display: flex; justify-content: space-between; margin: 18px 9px 0; padding-top: 16px; color: var(--accent); border-top: 1px solid var(--border); font-size: .78rem; font-weight: 750; text-decoration: none; }
/* Bottom-left legal links + version (Konzept: Impressum/Datenschutz/Version unten links). margin-top:
   auto pins this to the bottom of .left-sidebar regardless of how many books/recent items are above it
   - .left-sidebar is a flex column (above) specifically to make that possible. */
.sidebar-legal { margin-top: auto; padding: 16px 9px 0; border-top: 1px solid var(--border); }
.sidebar-legal-links { display: flex; gap: 14px; margin-bottom: 6px; }
.sidebar-legal-links a { color: var(--text-soft); font-size: .74rem; font-weight: 650; text-decoration: none; }
.sidebar-legal-links a:hover { color: var(--accent); }
.sidebar-legal-version { display: block; color: var(--text-soft); font-size: .68rem; opacity: .75; }
.recent-icon, .child-icon { flex: 0 0 auto; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; color: var(--accent); background: var(--accent-soft); font-size: .72rem; font-weight: 850; overflow: hidden; }
.child-icon-cover img { width: 100%; height: 100%; object-fit: cover; }
.sidebar-empty { margin: 14px 9px; color: var(--text-soft); font-size: .78rem; }
.main-content { min-width: 0; padding: 42px clamp(28px, 4vw, 64px) 72px; }

.page-intro { position: relative; display: flex; justify-content: space-between; overflow: hidden; max-width: 1180px; margin: 0 auto 44px; padding: clamp(28px, 5vw, 54px); border: 1px solid var(--border); border-radius: 24px; background: linear-gradient(130deg, var(--surface) 45%, var(--accent-soft)); box-shadow: var(--shadow); }
.page-intro h1 { max-width: 700px; margin: 4px 0 10px; color: var(--text); font-size: clamp(2rem, 4vw, 3.25rem); letter-spacing: -.045em; line-height: 1.06; }
.page-intro p { max-width: 620px; margin: 0; color: var(--text-soft); font-size: 1.05rem; }
.eyebrow, .content-type { color: var(--accent); font-size: .7rem; font-weight: 850; letter-spacing: .13em; text-transform: uppercase; }
.section-block { max-width: 1180px; margin: 0 auto; }
.section-title-row { display: flex; align-items: end; justify-content: space-between; margin-bottom: 20px; }
.section-title-row h2 { margin: 1px 0 0; font-size: 1.65rem; letter-spacing: -.025em; }
.result-count { color: var(--text-soft); font-size: .82rem; }
.book-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
.book-card { overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: 0 5px 18px rgba(16, 54, 48, .04); transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease; }
.book-card:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); box-shadow: var(--shadow); }
/* aspect-ratio, not a fixed height (same reasoning/ratio as .book-nav-cover above): .book-grid's
   columns (minmax(0, 1fr)) narrow continuously as the window shrinks, well before either responsive
   breakpoint below actually drops the column count. A fixed height against that shrinking width kept
   distorting the crop window away from 355:188 - the narrower the card, the taller-relative-to-width
   it became, so object-fit: cover (.book-cover.uploaded img below) had to crop away more and more of
   an uploaded cover's sides to fill it, up to the point of cropping into the cover's own text/logo.
   aspect-ratio keeps that crop window's proportions constant at any card width - the thumbnail gets
   smaller as a whole, exactly like the rest of the card, instead of effectively zooming in. */
.book-cover { position: relative; display: grid; place-items: center; aspect-ratio: 355 / 188; overflow: hidden; background: linear-gradient(145deg, #103840, #177147 65%, #63a27f); text-decoration: none; }
.book-cover::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(0,0,0,.22), transparent 14%, transparent 88%, rgba(0,0,0,.12)); }
/* Fixed size, not a percentage of .book-cover's own width: .book-grid's columns (minmax(0, 1fr))
   narrow continuously as the window shrinks, well before either responsive breakpoint below actually
   drops the column count - a percentage-sized logo shrank right along with them. This is just the
   placeholder mark for a book with no uploaded cover (.book-cover.uploaded img below is sized
   entirely differently, to fill the card edge-to-edge), so it has no reason to track card width at
   all; max-width is only a safety cap for a card so narrow this shouldn't normally happen. */
.book-cover img { position: relative; z-index: 2; width: 130px; max-width: 80%; filter: brightness(0) invert(1); }
.book-cover.uploaded img { width: 100%; height: 100%; max-width: none; object-fit: cover; filter: none; }
.book-cover.uploaded .cover-pattern { display: none; }
.cover-pattern { position: absolute; inset: -50%; background-image: radial-gradient(circle, rgba(255,255,255,.13) 1px, transparent 1px); background-size: 18px 18px; transform: rotate(12deg); }
.book-card-body { padding: 23px; }
.book-card h3 { min-height: 2.4em; margin: 5px 0 8px; font-size: 1.3rem; line-height: 1.2; letter-spacing: -.02em; }
.book-card h3 a { text-decoration: none; }
.book-card h3 a:hover { color: var(--accent); }
.book-card-body > p { min-height: 3.9em; margin: 0 0 22px; color: var(--text-soft); font-size: .86rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.card-meta { display: flex; align-items: center; gap: 10px; padding-top: 17px; border-top: 1px solid var(--border); }
.avatar { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; color: white; background: var(--accent); font-size: .65rem; font-weight: 800; }
.card-meta strong, .card-meta small { display: block; }
.card-meta strong { font-size: .76rem; }.card-meta small { color: var(--text-soft); font-size: .68rem; }

.breadcrumbs { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; max-width: 900px; margin: 0 auto 20px; color: var(--text-soft); font-size: .78rem; }
.breadcrumbs a { color: var(--text-soft); text-decoration: none; }.breadcrumbs a:hover { color: var(--accent); }.breadcrumbs .current { color: var(--text); font-weight: 700; }
/* Wraps "⬇ Als PDF exportieren" (Book only) and "✎ Bearbeiten" (whenever the current user may edit
   this node) - a single margin-left: auto on the wrapper rather than on each button individually, so
   showing both together doesn't split the flex row's free space between two separate auto margins
   (which would shove them apart from each other instead of just away from the breadcrumb trail). */
.breadcrumb-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.scripleaf-doc { max-width: 900px; margin: 0 auto; padding: clamp(25px, 5vw, 54px); color: var(--text); border: 1px solid var(--border); border-radius: 20px; background: var(--surface); box-shadow: var(--shadow); }
.scripleaf-doc h1 { margin-top: 0; color: var(--text); font-size: clamp(2rem, 4vw, 2.8rem); letter-spacing: -.04em; line-height: 1.12; }
.scripleaf-doc h2 { margin-top: 2em; color: var(--text); letter-spacing: -.025em; }
.scripleaf-doc h3, .scripleaf-doc h4, .scripleaf-doc h5, .scripleaf-doc h6 { margin: 1.6em 0 .6em; color: var(--text); letter-spacing: -.015em; }
.page-content-editor h2 { margin: 1.4em 0 .5em; }
.page-content-editor h3, .page-content-editor h4, .page-content-editor h5, .page-content-editor h6 { margin: 1.2em 0 .5em; }
/* MudBlazor.min.css (loaded globally in App.razor for the admin UI) zeroes out the browser's default
   block-level margins/padding site-wide - both here on the published rendering AND inside the
   WYSIWYG editor (.page-content-editor, same TipTap/ProseMirror surface as .content-editor-card
   above) - without this, Markdown-rendered paragraphs, lists and blockquotes run together with no
   visible gap between them wherever they appear, including while editing (hence the shared selector,
   same pattern as the pre/code rules above). Text color is deliberately NOT shared: .scripleaf-doc
   dims body text to --text-soft for the published read view, but the editor already sets its own
   full-contrast --text base color (line ~851) - dimming it there would just make editing harder. */
.scripleaf-doc p, .scripleaf-doc ul, .scripleaf-doc ol, .scripleaf-doc blockquote,
.page-content-editor p, .page-content-editor ul, .page-content-editor ol, .page-content-editor blockquote { margin: 0 0 1em; }
.scripleaf-doc li, .page-content-editor li { margin: 0 0 .3em; }
.scripleaf-doc p, .scripleaf-doc li { color: var(--doc-text); }
.scripleaf-doc ul, .scripleaf-doc ol, .page-content-editor ul, .page-content-editor ol { padding-left: 1.4em; }
.scripleaf-doc blockquote, .page-content-editor blockquote { padding-left: 1em; border-left: 3px solid var(--border); }
.scripleaf-doc blockquote { color: var(--text-soft); }
.scripleaf-doc hr { margin: 2em 0; border: none; border-top: 1px solid var(--border); }
.scripleaf-doc > :last-child { margin-bottom: 0; }
.scripleaf-doc a { color: var(--accent); }
/* .btn/.btn-primary links (e.g. the "+ Neues Kapitel" button in .child-section) must keep their own
   button colors, not the blanket in-content link color above - ".scripleaf-doc a" otherwise wins on
   specificity over ".btn-primary" alone (2 selectors vs. 1), leaving white-on-accent text invisible. */
.scripleaf-doc a.btn { color: var(--text); }
.scripleaf-doc a.btn-primary { color: white; }
.doc-header { padding-bottom: 28px; border-bottom: 1px solid var(--border); }.doc-header p { max-width: 650px; margin-bottom: 0; font-size: 1.02rem; }
/* Canonical page heading (ContentNode.Title) shown above "Zuletzt bearbeitet..." on every Page -
   independent of whatever heading (if any) the page's own Markdown body happens to start with. */
.page-title { margin: 0 0 6px; }
.page-last-edited { margin: -8px 0 22px; color: var(--text-soft); font-size: .78rem; }
.page-last-edited strong { color: var(--text); font-weight: 650; }
/* Prev/next page nav (DocPage.razor's _prevPage/_nextPage) - .doc-pagination-next is pinned to the
   right grid column explicitly so a lone next link (no prev on the first page of a book) still lands on
   the right rather than sliding into the empty left column. */
.doc-pagination { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 900px; margin: 28px auto 0; }
.doc-pagination-link { display: flex; flex-direction: column; gap: 4px; padding: 16px 18px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); text-decoration: none; transition: border-color .15s ease, transform .15s ease; }
.doc-pagination-link:hover { border-color: var(--accent); transform: translateY(-2px); }
.doc-pagination-next { grid-column: 2; align-items: flex-end; text-align: right; }
.doc-pagination-label { color: var(--accent); font-size: .7rem; font-weight: 750; letter-spacing: .05em; text-transform: uppercase; }
.doc-pagination-link strong { color: var(--text); font-size: 1rem; }
.child-section { margin-top: 32px; }
.child-section h2 { margin: 0; font-size: 1.15rem; }
.child-section-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.child-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.child-card { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 13px; min-height: 74px; padding: 14px 15px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); text-decoration: none; transition: border-color .16s ease, background-color .16s ease, box-shadow .16s ease, transform .16s ease; }
.child-card-page { position: relative; grid-template-columns: minmax(0, 1fr) auto; overflow: hidden; padding-left: 19px; }
.child-card-page::before { content: ""; position: absolute; inset: 13px auto 13px 0; width: 3px; border-radius: 0 3px 3px 0; background: var(--accent); opacity: .45; transition: inset .16s ease, opacity .16s ease; }
.child-card:hover, .child-card:focus-visible { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: var(--surface-soft); box-shadow: 0 7px 18px rgba(16, 54, 48, .07); transform: translateY(-2px); }
.child-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.child-card-page:hover::before, .child-card-page:focus-visible::before { inset-block: 0; opacity: 1; }
.child-card-content { min-width: 0; }
.child-card strong, .child-card small { display: block; }
.child-card strong { overflow: hidden; color: var(--text); font-size: .92rem; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
.child-card small { overflow: hidden; margin-top: 4px; color: var(--text-soft); font-size: .75rem; line-height: 1.35; text-overflow: ellipsis; white-space: nowrap; }
.child-card .arrow { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; color: var(--accent); font-size: .9rem; transition: color .16s ease, background-color .16s ease, transform .16s ease; }
.child-card:hover .arrow, .child-card:focus-visible .arrow { color: white; background: var(--accent); transform: translateX(2px); }
.empty-state, .loading-state { max-width: 700px; margin: 60px auto; padding: 50px; text-align: center; color: var(--text-soft); border: 1px dashed var(--border); border-radius: 18px; background: var(--surface); }
.empty-state > span { color: var(--accent); font-size: 1.5rem; font-weight: 850; }.empty-state h1, .empty-state h3 { color: var(--text); }.not-found { margin-top: 12vh; }
.primary-button { display: inline-block; margin-top: 10px; padding: 10px 16px; color: white; border-radius: 10px; background: var(--accent); text-decoration: none; font-weight: 700; }

/* Search results page (Components/Pages/Search.razor) - reached from the header search box
   (.header-search above) or by navigating to /suche?q=... directly. */
.search-page { max-width: 760px; margin: 0 auto; }
.search-page h1 { margin: 0 0 18px; }
.search-page-form { display: flex; gap: 10px; margin-bottom: 22px; }
.search-page-form input { flex: 1 1 auto; min-width: 0; padding: 11px 16px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--text); }
.search-page-form input:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.search-page-hint, .search-page-count { color: var(--text-soft); font-size: .88rem; }
.search-results { display: flex; flex-direction: column; gap: 12px; margin: 18px 0 0; padding: 0; list-style: none; }
.search-result a { display: block; padding: 16px 18px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); text-decoration: none; transition: border-color .16s ease, background-color .16s ease, transform .16s ease; }
.search-result a:hover, .search-result a:focus-visible { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: var(--surface-soft); transform: translateY(-2px); }
.search-result strong { display: block; color: var(--text); font-size: 1rem; }
.search-result-breadcrumb { display: block; margin-top: 2px; color: var(--text-soft); font-size: .78rem; }
.search-result-snippet { display: block; margin-top: 8px; color: var(--text-soft); font-size: .88rem; line-height: 1.5; }
.search-result-snippet mark { border-radius: 3px; padding: 0 2px; color: var(--text); background: var(--accent-soft); }

@media (max-width: 1180px) {
    .workspace { grid-template-columns: 226px minmax(0, 1fr); }
    .right-sidebar { display: none; }
    .book-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
    .app-header { height: 64px; padding: 0 16px; }.brand { width: 132px; }.header-link { display: none; }.header-search { max-width: none; margin: 0 10px; }
    .workspace { display: block; }.left-sidebar { display: block; position: static; height: auto; padding: 12px 16px; overflow-x: auto; overflow-y: visible; border-right: 0; border-bottom: 1px solid var(--border); }.sidebar-heading, .all-books-link, .sidebar-legal { display: none; }.book-nav { display: flex; }.book-nav-item { flex: 0 0 190px; }.book-nav-cover { flex-basis: 56px; height: auto; }
    .main-content { padding: 24px 16px 52px; }.book-grid { grid-template-columns: 1fr; }.child-grid { grid-template-columns: 1fr; }.scripleaf-doc { padding: 25px 20px; }.header-actions { gap: 10px; }.scripleaf-auth-status { font-size: .76rem; }.doc-pagination { grid-template-columns: 1fr; }.doc-pagination-next { grid-column: 1; align-items: flex-start; text-align: left; }
}

/* Admin (AdminLayout.razor + Components/Pages/Admin/*) - Konzept Abschnitt 10.2: "Administrator:
   Benutzer, Rechte, Repository und Systemeinstellungen verwalten". Reuses the app shell's CSS custom
   properties (--surface, --border, --accent, ...) so it inherits dark mode for free instead of
   maintaining a second palette. */

.admin-shell { display: flex; min-height: calc(100vh - 74px); }
.admin-nav { flex: 0 0 220px; align-self: stretch; position: sticky; top: 74px; min-height: calc(100vh - 74px); padding: 28px 16px; background: var(--surface); border-right: 1px solid var(--border); }
.admin-nav a { display: block; margin-bottom: 4px; padding: 9px 12px; border-radius: 10px; color: var(--text-soft); font-size: .86rem; font-weight: 650; text-decoration: none; }
.admin-nav a:hover { background: var(--surface-soft); color: var(--text); }
.admin-nav a.active { background: var(--accent-soft); color: var(--accent); }
.admin-main { flex: 1; min-width: 0; padding: 32px clamp(20px, 4vw, 48px) 64px; }
.admin-title-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-bottom: 22px; }
.admin-title-row h1 { margin: 0; font-size: 1.7rem; letter-spacing: -.025em; }
.admin-subtitle { margin: 4px 0 0; color: var(--text-soft); font-size: .88rem; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 30px; }
.stat-card { padding: 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.stat-card .stat-value { font-size: 1.9rem; font-weight: 800; color: var(--text); }
.stat-card .stat-label { color: var(--text-soft); font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.stat-card a { color: var(--accent); font-size: .78rem; font-weight: 650; text-decoration: none; }

/* Admin/AdminMedia.razor - the shared media library's browse/delete grid and folder breadcrumb. */
.media-breadcrumbs { margin-bottom: 16px; }
.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 16px; }
.media-grid-item { display: flex; flex-direction: column; gap: 4px; padding: 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.media-grid-item img { width: 100%; height: 120px; object-fit: cover; border-radius: 8px; background: var(--surface-soft); }
.media-grid-name { overflow: hidden; color: var(--text); font-size: .82rem; text-overflow: ellipsis; white-space: nowrap; }
.media-grid-date { color: var(--text-soft); font-size: .7rem; }
.media-grid-item .button-row, .media-grid-item .btn { margin-top: 4px; }
.media-grid-folder-open { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 14px 0 6px; text-decoration: none; }
.media-grid-folder-icon { font-size: 2rem; }
.media-grid-folder .media-grid-name { text-align: center; }

.data-table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.data-table { width: 100%; border-collapse: collapse; }
.data-table th, .data-table td { padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: .85rem; text-align: left; vertical-align: middle; }
.data-table th { color: var(--text-soft); font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; background: var(--surface-soft); }
.data-table tr:last-child td { border-bottom: none; }
.data-table td.actions { display: flex; gap: 6px; flex-wrap: wrap; }

.badge { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: .68rem; font-weight: 700; white-space: nowrap; }
.badge-accent { background: var(--accent-soft); color: var(--accent); }
.badge-warn { background: #fdf3e3; color: #a15c00; }
.badge-danger { background: #fbeceb; color: #b3261e; }
/* The actual PdfExportJobState.Error text (Admin/AdminBooks.razor's "Fehlgeschlagen" PDF-status cell) -
   shown directly under the badge rather than only in a title="" tooltip, which is too easy to never
   think to hover over a small pill for. */
.pdf-job-error { display: block; margin-top: 4px; max-width: 22em; color: var(--text-soft); font-size: .72rem; }
.badge-neutral { background: var(--surface-soft); color: var(--text-soft); }

.admin-form { display: grid; gap: 12px; max-width: 30rem; }
.admin-form label { display: flex; flex-direction: column; gap: 4px; font-size: .82rem; font-weight: 650; color: var(--text); }
.admin-form input, .admin-form select, .admin-form textarea { padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text); }
.admin-form-row { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: end; }
.legal-editor-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 20px; align-items: start; }
.legal-editor-grid label { display: flex; flex-direction: column; gap: 4px; font-size: .82rem; font-weight: 650; color: var(--text); }
.legal-editor-preview { border: 1px solid var(--border); border-radius: 8px; background: var(--surface-soft); padding: 10px 14px; max-height: 260px; overflow-y: auto; }
.legal-editor-preview-label { display: block; font-size: .72rem; font-weight: 650; text-transform: uppercase; letter-spacing: .04em; color: var(--text-soft); margin-bottom: 6px; }
.legal-editor-preview p, .legal-editor-preview ul, .legal-editor-preview ol, .legal-editor-preview blockquote { margin: 0 0 .7em; }
.legal-editor-preview li { margin: 0 0 .2em; }
.legal-editor-preview p, .legal-editor-preview li { color: var(--text-soft); font-size: .88rem; }
.legal-editor-preview ul, .legal-editor-preview ol { padding-left: 1.3em; }
.legal-editor-preview h1, .legal-editor-preview h2, .legal-editor-preview h3 { margin: 0 0 .4em; font-size: 1em; color: var(--text); }
.legal-editor-preview > :last-child { margin-bottom: 0; }
@media (max-width: 860px) { .legal-editor-grid { grid-template-columns: 1fr; } }

.button-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.btn { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface); color: var(--text); font-size: .82rem; font-weight: 650; text-decoration: none; cursor: pointer; }
.btn:hover { border-color: var(--accent); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: white; }
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.btn-danger { color: #b3261e; border-color: color-mix(in srgb, #b3261e 40%, var(--border)); }
.btn-danger:hover { background: #fbeceb; }
.btn:disabled { opacity: .5; cursor: wait; }
.add-button { min-height: 40px; padding-inline: 16px; box-shadow: 0 5px 14px color-mix(in srgb, var(--accent) 22%, transparent); }
.add-button > span { display: grid; place-items: center; width: 20px; height: 20px; font-size: 1.25rem; font-weight: 400; line-height: 1; }

.dialog-backdrop { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 20px; background: rgba(6, 18, 15, .58); backdrop-filter: blur(5px); animation: dialog-fade-in .16s ease-out; }
.admin-dialog { width: min(560px, 100%); max-height: min(760px, calc(100vh - 40px)); overflow-y: auto; padding: 24px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); box-shadow: 0 24px 70px rgba(0, 0, 0, .3); animation: dialog-slide-in .18s ease-out; }
.dialog-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.dialog-header h2 { margin: 2px 0 0; color: var(--text); font-size: 1.4rem; letter-spacing: -.025em; }
.dialog-kicker { color: var(--accent); font-size: .66rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase; }
.dialog-close { display: grid; flex: 0 0 auto; place-items: center; width: 34px; height: 34px; padding: 0; border: 1px solid var(--border); border-radius: 9px; color: var(--text-soft); background: var(--surface-soft); font-size: 1.35rem; line-height: 1; cursor: pointer; }
.dialog-close:hover { color: var(--text); border-color: var(--accent); }
.dialog-description { margin: 10px 0 22px; color: var(--text-soft); font-size: .84rem; }
.dialog-form { max-width: none; }
.dialog-form label small { color: var(--text-soft); font-size: .7rem; font-weight: 450; }
.dialog-form textarea { min-height: 86px; resize: vertical; }
.dialog-form input:focus, .dialog-form textarea:focus, .dialog-form select:focus { outline: 3px solid color-mix(in srgb, var(--accent) 16%, transparent); border-color: var(--accent); }
.dialog-form .required { color: #c23d32; }
.dialog-form .checkbox-field { flex-direction: row; align-items: flex-start; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-soft); }
.dialog-form .cover-upload-field { gap: 7px; }
.cover-upload { position: relative; display: flex; align-items: center; gap: 12px; padding: 11px; border: 1px dashed color-mix(in srgb, var(--accent) 55%, var(--border)); border-radius: 11px; background: var(--accent-soft); cursor: pointer; }
.cover-upload:hover { border-style: solid; }.cover-upload > span:nth-child(2) { min-width: 0; }.cover-upload strong, .cover-upload small { display: block; }.cover-upload strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .78rem; }.cover-upload input[type="file"] { position: absolute; inset: 0; width: 100%; height: 100%; padding: 0; opacity: 0; cursor: pointer; }
.cover-preview { display: grid; flex: 0 0 54px; place-items: center; height: 42px; overflow: hidden; border-radius: 7px; color: var(--accent); background: var(--surface); font-size: 1.25rem; }
.cover-library-btn { justify-self: start; margin-top: -4px; }
.chapter-icon-field { display: flex; flex-direction: column; gap: 4px; }
.chapter-icon-field > small { color: var(--text-soft); font-weight: 500; }
.chapter-icon-field > small a { color: var(--accent); }
.chapter-icon-input-row { display: flex; align-items: center; gap: 10px; }
.chapter-icon-input-row .mud-input-control { flex: 1; }
.chapter-icon-preview { display: grid; flex: 0 0 40px; place-items: center; width: 40px; height: 40px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--accent); }
.cover-preview img { width: 100%; height: 100%; object-fit: cover; }

/* Admin – Einstellungen (AdminSettings.razor) */
.settings-accent-row { display: flex; align-items: center; gap: 12px; margin: 14px 0; }
.settings-accent-row input[type="color"] { width: 48px; height: 40px; padding: 2px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer; }
.settings-accent-hex { width: 140px; padding: 9px 10px; border: 1px solid var(--border); border-radius: 8px; color: var(--text); background: var(--surface); font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
.settings-accent-preview { width: 40px; height: 40px; border: 1px solid var(--border); border-radius: 50%; }
.settings-logo-row { display: flex; align-items: center; gap: 18px; margin: 14px 0; }
.settings-logo-preview { display: grid; flex: 0 0 88px; place-items: center; height: 88px; overflow: hidden; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); }
.settings-logo-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }
.settings-logo-row > span:last-child { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.checkbox-field input { margin-top: 3px; accent-color: var(--accent); }.checkbox-field strong, .checkbox-field small { display: block; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 8px; margin: 10px -24px -24px; padding: 16px 24px; border-top: 1px solid var(--border); background: var(--surface-soft); }
@keyframes dialog-fade-in { from { opacity: 0; } }
@keyframes dialog-slide-in { from { opacity: 0; transform: translateY(10px) scale(.985); } }

.admin-callout { margin-bottom: 18px; padding: 12px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-soft); font-size: .85rem; }
.admin-callout.success { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-dark); }
.admin-callout.error { border-color: #e3b7b2; background: #fbeceb; color: #b3261e; }

.admin-card { padding: 18px 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); margin-bottom: 16px; }
.admin-card-subsection { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--border); }
.admin-card h3 { margin: 0 0 4px; font-size: 1.02rem; }
.admin-card .admin-card-meta { color: var(--text-soft); font-size: .78rem; margin-bottom: 12px; }

.admin-chapter-card { padding: 18px 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); margin-bottom: 16px; }
.admin-chapter-header { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.admin-chapter-header h2 { margin: 0; font-size: 1.05rem; }
.admin-chapter-header .admin-subtitle { margin: 0; }
.admin-chapter-heading { display: flex; align-items: center; gap: 12px; min-width: 0; }
.admin-chapter-cover { flex: 0 0 44px; width: 44px; height: 44px; border-radius: 8px; object-fit: cover; background: var(--surface-soft); }
.admin-chapter-icon { display: grid; place-items: center; color: var(--accent); }
.admin-chapter-card .admin-form-row { margin-top: 12px; }
.status-select { min-width: 118px; padding: 6px 28px 6px 9px; border: 1px solid var(--border); border-radius: 999px; color: var(--text); background: var(--surface); font-size: .72rem; font-weight: 700; cursor: pointer; }
.status-select.status-published { color: var(--accent-dark); border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); background: var(--accent-soft); }
.status-select.status-draft { color: #8a5a08; background: #fdf3e3; }
.status-select.status-archived { color: var(--text-soft); background: var(--surface-soft); }
.status-select:disabled { opacity: .55; cursor: wait; }
.field-label, .field-label .required { display: inline; }
.admin-danger-zone { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); }
.admin-danger-zone p { margin: 0 0 10px; color: var(--text-soft); font-size: .82rem; }
.page-editor-title { align-items: flex-end; }.page-editor-form { display: grid; gap: 16px; max-width: 1100px; }.page-meta-card { margin: 0; }.page-meta-grid { display: grid; grid-template-columns: minmax(220px, 2fr) minmax(180px, 1.3fr) minmax(150px, .8fr) 110px; gap: 14px; }.page-meta-grid label { display: flex; flex-direction: column; gap: 4px; color: var(--text); font-size: .78rem; font-weight: 650; }.page-meta-grid input, .page-meta-grid select { padding: 9px 10px; border: 1px solid var(--border); border-radius: 8px; color: var(--text); background: var(--surface); }.page-meta-grid small { color: var(--text-soft); font-size: .68rem; font-weight: 450; }.page-tags-field { grid-column: 1 / -1; }
/* No overflow: hidden here (unlike most .admin-card uses) - it would also clip the sticky toolbar's
   own stickiness, since overflow: hidden makes its element the toolbar's scroll/positioning container
   instead of the actual page scroll area (see .content-editor-card .editor-toolbar below). Corners are
   rounded on the first/last child directly instead, for the same visually-clipped look. */
.content-editor-card { margin: 0; padding: 0; }
.content-editor-card > .content-editor-heading:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.content-editor-card > .page-content-editor:last-child { border-radius: 0 0 var(--radius) var(--radius); }
.content-editor-heading { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px; border-bottom: 1px solid var(--border); }.content-editor-heading h2 { margin: 0; font-size: 1rem; }.content-editor-heading p { margin: 2px 0 0; color: var(--text-soft); font-size: .73rem; }.page-content-input { display: block; width: 100%; min-height: 430px; padding: 22px; resize: vertical; border: 0; outline: 0; color: var(--text); background: var(--surface); font: .9rem/1.65 ui-monospace, SFMono-Regular, Consolas, monospace; }.page-editor-actions { position: sticky; bottom: 0; display: flex; justify-content: flex-end; gap: 8px; padding: 14px 0; background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(10px); }

/* Admin page editor: themed override of the WYSIWYG editor spike styles above, so the TipTap toolbar
   and editing surface follow the admin light/dark palette instead of the spike's fixed colors. */
/* Sticky (top: 82px = --mud-appbar-height below) so the toolbar stays reachable while scrolling a long
   page's metadata form above it, on top of .page-content-editor's own bounded height/scroll below -
   between the two, reaching the toolbar should never need scrolling the whole admin page back up. */
.content-editor-card .editor-toolbar { position: sticky; top: 82px; z-index: 5; padding: 12px 18px; margin-bottom: 0; background: var(--surface); border-bottom: 1px solid var(--border); }
.content-editor-card .editor-toolbar button { border-color: var(--border); background: var(--surface); color: var(--text); }
.content-editor-card .editor-toolbar button:hover { background: var(--surface-soft); border-color: var(--accent); }
/* Bounded height with its own scrollbar - a long page's body scrolls inside this box instead of
   growing the whole admin page taller, which is what used to carry the toolbar (and everything else
   on the page) out of view along with it. */
.content-editor-card .page-content-editor { border: 0; border-radius: 0; min-height: 430px; max-height: 60vh; overflow-y: auto; padding: 22px; color: var(--text); background: var(--surface); }
.content-editor-card .page-content-editor .ProseMirror { min-height: 386px; }
.content-editor-card .page-content-editor .ProseMirror:focus { outline: none; }
.conflict-versions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 12px 0; }
.conflict-versions h4 { margin: 0 0 6px; font-size: .78rem; text-transform: uppercase; letter-spacing: .05em; color: var(--text-soft); }
.conflict-versions pre { max-height: 240px; margin: 0; padding: 10px; overflow: auto; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-soft); font-size: .72rem; white-space: pre-wrap; word-break: break-word; }

@media (max-width: 900px) {
    .admin-shell { display: block; }
    .admin-nav { position: static; display: flex; overflow-x: auto; width: auto; border-right: 0; border-bottom: 1px solid var(--border); }
    .conflict-versions { grid-template-columns: 1fr; }
    .page-meta-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
    .dialog-backdrop { align-items: end; padding: 0; }
    .admin-dialog { width: 100%; max-height: 92vh; padding: 20px; border-radius: 18px 18px 0 0; }
    .dialog-actions { margin: 10px -20px -20px; padding: 14px 20px; }
    .page-meta-grid { grid-template-columns: 1fr; }.page-tags-field { grid-column: auto; }.page-content-input { min-height: 320px; padding: 16px; }
}
/* MudBlazor shell --------------------------------------------------------- */
/* Dark mode: translucent surface bar (unchanged). Light mode gets its own solid-accent treatment
   below instead - kept as a separate, dark-only rule rather than an override so the two never fight
   over the same properties. */
:root[data-theme="dark"] .mud-public-shell .mud-appbar,
:root[data-theme="dark"] .mud-admin-layout .mud-appbar { border-bottom: 1px solid var(--border); background: color-mix(in srgb, var(--surface) 92%, transparent); color: var(--text); backdrop-filter: blur(18px); }
/* Light mode: a solid accent-colored bar (admin request: "kräftiger Farbbalken") rather than a neutral
   one, so the configured brand color actually shows up somewhere prominent in light mode too. Text,
   icons and the brand logo switch to white for contrast - .mud-button-root's Color="Inherit" (set in
   MainLayout/AdminLayout.razor) is what makes MudButton follow this rule's `color` instead of its own
   default text color; .scripleaf-auth-status/.theme-toggle get an explicit override below since
   they're plain HTML, not MudBlazor components. */
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar { background: var(--accent); color: white; }
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .brand img,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .brand img { filter: brightness(0) invert(1); }
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .header-link,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .header-link,
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .scripleaf-auth-status,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .scripleaf-auth-status { color: white; }
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .header-link:hover,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .header-link:hover,
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .scripleaf-auth-status:hover,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .scripleaf-auth-status:hover,
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .scripleaf-link-button,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .scripleaf-link-button { color: white; text-decoration: underline; }
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .theme-toggle,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .theme-toggle { border-color: rgba(255, 255, 255, .5); background: rgba(255, 255, 255, .15); color: white; }
:root:not([data-theme="dark"]) .mud-public-shell .mud-appbar .theme-toggle:hover,
:root:not([data-theme="dark"]) .mud-admin-layout .mud-appbar .theme-toggle:hover { border-color: white; background: rgba(255, 255, 255, .25); }
.mud-public-shell .workspace { padding: 0; }
.mud-public-shell .left-sidebar,
.mud-public-shell .right-sidebar { padding-top: 44px; padding-bottom: 44px; }
/* MudAppBar defaults to position:fixed (out of flow), which is why .workspace previously had to fake
   its own height with "min-height: calc(100vh - <header height>)" - duplicated across three rules and
   easy to drift out of sync with the header's real height, leaving the sidebars a few pixels short of
   the page height and exposing the content area's background under them. Making the appbar sticky
   instead keeps it in normal flow: .app-shell just needs to be a full-height flex column and
   .workspace (flex: 1) fills exactly what's left, so the CSS Grid's default row-stretch always keeps
   both sidebars exactly as tall as .main-content, however tall that ends up being. */
.mud-public-shell .mud-appbar { position: sticky; top: 0; height: 72px; }
.mud-public-shell { display: flex; flex-direction: column; min-height: 100vh; }
.mud-public-shell .workspace { flex: 1 1 auto; min-height: 0; }
/* MudBlazor sizes the appbar's own toolbar off the theme's --mud-appbar-height custom property, which
   ScripLeafMudTheme.cs sets to 72px for the whole app. The admin header renders 10px taller than that
   (82px, to fit its wider nav), but nothing told Mud's internal CSS about it: the toolbar kept sizing
   itself to the stale 72px inside an 82px-tall bar, leaving an unfilled strip at the bottom of the
   header (the "squished together" look). Overriding the variable in this scope keeps every Mud calc
   reading the same real number. */
.mud-admin-layout { --mud-appbar-height: 82px; }
.mud-admin-layout .mud-appbar { height: var(--mud-appbar-height); }
.mud-appbar .mud-toolbar { width: min(100%, 1280px); min-height: inherit; margin-inline: auto; padding-inline: 32px; }
.mud-admin-layout { min-height: 100vh; background: var(--bg); }
/* A persistent MudDrawer's default layout has the drawer run the FULL page height, with the appbar
   shrinking (margin-left) to sit beside it instead of on top of it - that's what MudBlazor's own CSS
   (".mud-drawer-open-persistent-left.mud-drawer-left-clipped-never .mud-appbar") already does here.
   The old rule below fought that by shoving the drawer's top down to 82px, as if the header sat above
   a full-width drawer - but the header had already vacated that top-left corner horizontally, so
   nothing was left to paint it and the layout's plain background showed through in a block the size of
   the drawer width by the header height. Leaving the drawer at Mud's own top:0/height:100% lets its
   own background fill that corner, matching how the appbar is actually laid out beside it. */
.mud-admin-layout .mud-drawer { border-right: 1px solid var(--border); background: var(--surface); }
.mud-admin-layout .mud-main-content { background: var(--bg); }
.mud-admin-layout .admin-main { padding: 118px clamp(24px, 4vw, 52px) 72px; }
.admin-nav-heading { padding: 24px 24px 8px; color: var(--text-soft); font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.mud-admin-drawer .admin-nav { position: static; min-height: 0; padding: 8px 12px; border: 0; background: transparent; }
.mud-admin-drawer .mud-nav-link { display: flex; flex-direction: row; align-items: center; margin: 3px 0; border-radius: 10px; color: var(--text-soft); }
.mud-admin-drawer .mud-nav-link-text { margin-left: 12px; }
.mud-admin-drawer .mud-nav-link.active { background: var(--accent-soft); color: var(--accent); }
.mud-admin-drawer .mud-nav-link-icon { color: currentColor; }
.mud-button-root { border-radius: 10px; }
.mud-paper { color: var(--text); background-color: var(--surface); }
.dialog-form label { display: block; }
.dialog-form label > input,
.dialog-form label > textarea,
.dialog-form label > .cover-upload { display: flex; width: 100%; margin-top: 4px; }
.dialog-form label > input,
.dialog-form label > textarea { display: block; }
.settings-color-picker { width: min(100%, 420px); margin: 8px 0 12px; }

:root[data-theme="dark"] {
    --mud-palette-background: #101512;
    --mud-palette-surface: #171e1a;
    --mud-palette-appbar-background: #141a17;
    --mud-palette-drawer-background: #131916;
    --mud-palette-text-primary: rgba(237,244,239,1);
    --mud-palette-text-secondary: rgba(168,183,174,1);
    --mud-palette-divider: rgba(43,55,48,1);
    --mud-palette-action-default: rgba(237,244,239,.65);
    --mud-palette-action-default-hover: rgba(237,244,239,.08);
}

@media (max-width: 900px) {
    .mud-admin-layout .mud-drawer { display: none; }
    .mud-admin-layout .mud-main-content { margin-left: 0 !important; }
}
