        :root {
            --mono: 'IBM Plex Mono', 'SFMono-Regular', Consolas, monospace;
            --sans: 'Inter', -apple-system, sans-serif;
        }
        * { box-sizing: border-box; }

        /* Breakout: lifts the viewer out of the Bootstrap .container from
           _Layout.cshtml, so its chrome (toolbar/sidebar/preview pane) uses the
           full window width and height — same trick as Editor.cshtml's
           #editor-root. Only the document content rendered inside the preview
           iframe is width-constrained (see wrapDocument's body max-width), not
           the surrounding UI. */
        #viewer-root {
            position: relative;
            left: 50%; right: 50%;
            margin-left: -50vw; margin-right: -50vw;
            width: 100vw;
        }
        #app {
            display: flex; flex-direction: column;
            /* Height is set exactly to the available space between navbar and
               footer via JS (fitAppHeight); min-height is just the floor. */
            min-height: 480px;
            background: var(--bg); color: var(--text); font-family: var(--sans);
        }

        /* -- Presentation mode fullscreens #viewer-root (not just the iframe) so the
           TOC strip — a sibling of #app, outside the iframe entirely — stays usable.
           Hide the toolbar/file-panel chrome for a clean, distraction-free view;
           fitAppHeight() already accounts for the header/footer no longer being part
           of the fullscreened subtree. Escape (native fullscreen exit) is the only
           way out, same as the existing video/audio fullscreen. -- */
        #viewer-root:fullscreen { background: var(--bg); }
        #viewer-root:fullscreen .toolbar,
        #viewer-root:fullscreen .files-panel {
            display: none;
        }

        .toolbar {
            display: flex; align-items: center; gap: 12px;
            padding: 10px 16px; background: var(--panel);
            border-bottom: 1px solid var(--border); flex-shrink: 0;
        }
        .brand { font-family: var(--mono); font-size: 13px; color: var(--text-dim); letter-spacing: 0.5px; }
        .brand b { color: var(--accent); }
        .toolbar-filename {
            flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
            font-size: 13px; color: var(--text-dim);
        }
        .open-editor-btn {
            display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
            background: var(--accent); color: var(--accent-contrast); text-decoration: none;
            border: none; border-radius: 7px; padding: 7px 13px;
            font-family: var(--sans); font-size: 12.5px; font-weight: 600; cursor: pointer; transition: opacity .15s;
        }
        .open-editor-btn:hover { opacity: .85; color: var(--accent-contrast); }
        .open-editor-btn[hidden] { display: none; }

        /* Shown only to a (mock-)logged-in user (see updatePdfButtonVisibility) —
           prints the preview iframe, letting the browser's print dialog save it
           as a PDF, same button in Editor.cshtml. */
        .pdf-btn {
            display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
            background: var(--panel-alt); border: 1px solid var(--border); color: var(--text);
            border-radius: 7px; padding: 7px 13px;
            font-family: var(--sans); font-size: 12.5px; font-weight: 600; cursor: pointer; transition: .15s;
        }
        .pdf-btn:hover { border-color: var(--accent); color: var(--accent); }
        .pdf-btn[hidden] { display: none; }

        /* Toggles the currently viewed file's favorite status — mirrors the
           file-tree row's star (see toggleFavorite) but discoverable without
           opening the Dateien panel. */
        .favorite-toggle-btn {
            display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
            width: 32px; height: 32px;
            background: var(--panel-alt); border: 1px solid var(--border); color: var(--text-dim);
            border-radius: 7px; cursor: pointer; transition: .15s;
        }
        .favorite-toggle-btn:hover { border-color: #f5a623; color: #f5a623; }
        .favorite-toggle-btn.active { color: #f5a623; border-color: #f5a623; background: rgba(245,166,35,.12); }
        .favorite-toggle-btn.active svg { fill: currentColor; }
        .favorite-toggle-btn[hidden] { display: none; }

        .presentation-btn {
            display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
            background: var(--panel-alt); border: 1px solid var(--border); color: var(--text);
            border-radius: 7px; padding: 7px 13px;
            font-family: var(--sans); font-size: 12.5px; font-weight: 600; cursor: pointer; transition: .15s;
        }
        .presentation-btn:hover { border-color: var(--accent); color: var(--accent); }
        .presentation-btn.active { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }

        .work { flex: 1; display: flex; min-height: 0; }
        .pane { flex: 1; min-width: 0; display: flex; flex-direction: column; }

        /* File browser: same visual language as the editor's, but view-only — no
           add/upload button, no drag-and-drop, and the "…" menu only offers
           non-mutating actions (copy link / download). */
        .files-panel { display: flex; flex-shrink: 0; border-right: 1px solid var(--border); background: var(--panel); }
        .files-backdrop { display: none; }
        .files-toggle {
            width: 34px; flex-shrink: 0; display: flex; flex-direction: column; align-items: center;
            gap: 10px; padding-top: 12px;
            background: transparent; border: none; border-right: 1px solid var(--border);
            color: var(--text-dim); cursor: pointer;
        }
        .files-toggle:hover { color: var(--text); background: var(--panel-alt); }
        .files-toggle-icon { flex-shrink: 0; display: inline-flex; transition: transform .15s; }
        .files-toggle.expanded .files-toggle-icon { transform: rotate(180deg); }
        .files-toggle-label {
            writing-mode: vertical-rl;
            font-family: var(--mono); font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase;
            white-space: nowrap;
        }
        .files-body {
            width: 260px; min-width: 0; display: flex; flex-direction: column;
            background: var(--panel);
        }
        .files-body[hidden] { display: none; }
        .files-head {
            display: flex; align-items: center; justify-content: space-between;
            padding: 8px 10px; border-bottom: 1px solid var(--border); flex-shrink: 0;
            font-family: var(--mono); font-size: 11px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 1px;
        }
        .files-tree { flex: 1; overflow-y: auto; padding: 6px 0; }

        /* Vault switcher, anchored at the bottom edge of the file panel — same
           layout/behavior as Editor.cshtml's. Only shown to a (mock-)logged-in
           user; see updateVaultBarVisibility. */
        .vault-bar {
            display: flex; align-items: center; gap: 2px; flex-shrink: 0;
            padding: 6px; border-top: 1px solid var(--border); background: var(--panel);
        }
        .vault-bar[hidden] { display: none; }
        .vault-bar-current {
            flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px;
            background: transparent; border: none; color: var(--text); font-family: var(--sans);
            font-size: 12.5px; font-weight: 600; padding: 5px 6px; border-radius: 6px; cursor: pointer;
        }
        .vault-bar-current:hover { background: var(--panel-alt); }
        .vault-bar-current .vault-icon { flex-shrink: 0; display: flex; color: var(--text-dim); }
        .vault-bar-current span:not(.vault-icon) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
        .vault-bar-current svg:last-child { flex-shrink: 0; color: var(--text-dim); }
        .vault-bar-more {
            flex-shrink: 0; width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
            background: transparent; border: none; color: var(--text-dim); cursor: pointer; border-radius: 5px;
        }
        .vault-bar-more:hover { background: var(--panel-alt); color: var(--text); }

        .vault-menu {
            position: fixed; z-index: 50; width: 220px; max-height: 320px; overflow-y: auto;
            background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
            box-shadow: 0 10px 28px rgba(0,0,0,.28); padding: 6px; display: none;
        }
        .vault-menu[data-open] { display: block; }
        .vault-menu-label {
            font-family: var(--mono); font-size: 10.5px; color: var(--text-dim);
            text-transform: uppercase; letter-spacing: .5px; margin: 8px 6px 4px;
        }
        .vault-menu-label:first-child { margin-top: 2px; }
        .vault-item {
            display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
            background: transparent; border: none; color: var(--text); font-family: var(--sans);
            padding: 6px 8px; border-radius: 6px; font-size: 12.5px; cursor: pointer;
        }
        .vault-item:hover { background: var(--panel-alt); }
        .vault-item.active { background: var(--accent); color: var(--accent-contrast); }
        .vault-item svg { flex-shrink: 0; }
        .vault-item span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .vault-menu-sep { height: 1px; background: var(--border); margin: 6px 2px; }
        .vault-menu-create {
            display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
            background: transparent; border: none; color: var(--accent); font-family: var(--sans);
            padding: 6px 8px; border-radius: 6px; font-size: 12.5px; font-weight: 600; cursor: pointer;
        }
        .vault-menu-create:hover { background: var(--panel-alt); }

        /* Vault sharing modal — same mock pattern as the editor's per-file share
           modal: a public link (non-resolving, no real backend) plus a fake
           invite list stored on the vault object itself. */
        .share-backdrop {
            position: fixed; inset: 0; z-index: 60; background: rgba(0,0,0,.45);
            display: flex; align-items: center; justify-content: center; padding: 16px;
        }
        .share-backdrop[hidden] { display: none; }
        .share-modal {
            width: 420px; max-width: 100%; max-height: calc(100vh - 64px); overflow-y: auto;
            background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
            box-shadow: 0 20px 60px rgba(0,0,0,.4); padding: 20px;
        }
        .share-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
        .share-modal-head h3 { margin: 0; font-size: 16px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .share-modal-sub { font-size: 12px; color: var(--text-dim); margin: 4px 0 0; }
        .share-modal-close {
            width: 26px; height: 26px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
            background: transparent; border: none; color: var(--text-dim); cursor: pointer; border-radius: 6px;
        }
        .share-modal-close:hover { background: var(--panel-alt); color: var(--text); }
        .share-section { padding: 14px 0; border-top: 1px solid var(--border); }
        .share-section:first-of-type { border-top: none; padding-top: 12px; }
        .share-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
        .share-row-title { font-size: 13px; color: var(--text); font-weight: 600; }
        .share-row-sub { font-size: 11.5px; color: var(--text-dim); margin-top: 2px; }
        .share-switch { position: relative; display: inline-block; width: 36px; height: 20px; flex-shrink: 0; }
        .share-switch input { opacity: 0; width: 0; height: 0; position: absolute; }
        .share-switch-track {
            position: absolute; inset: 0; background: var(--border); border-radius: 999px; cursor: pointer; transition: .15s;
        }
        .share-switch-track::before {
            content: ''; position: absolute; width: 14px; height: 14px; left: 3px; top: 3px;
            background: var(--panel); border-radius: 50%; transition: .15s;
        }
        .share-switch input:checked + .share-switch-track { background: var(--accent); }
        .share-switch input:checked + .share-switch-track::before { transform: translateX(16px); }
        .share-link-row { display: flex; gap: 6px; margin-top: 10px; }
        .share-link-row input {
            flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text-dim); font-family: var(--mono); font-size: 11.5px;
        }
        .share-link-row.disabled input { opacity: .5; }
        .share-link-row select {
            padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 12px; font-family: var(--sans); flex-shrink: 0;
        }
        .share-link-row.disabled select { opacity: .5; }
        .share-link-row button {
            padding: 6px 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel-alt);
            color: var(--text); font-size: 12px; cursor: pointer; white-space: nowrap; font-family: var(--sans);
        }
        .share-link-row button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
        .share-link-row button:disabled { opacity: .5; cursor: not-allowed; }
        .share-link-email-row.disabled { opacity: .5; pointer-events: none; }
        .share-listed-row {
            display: flex; align-items: flex-start; gap: 8px; margin-top: 10px; cursor: pointer;
            font-size: 12px; color: var(--text-dim);
        }
        .share-listed-row input { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; accent-color: var(--accent); }
        .share-listed-row.disabled { opacity: .5; pointer-events: none; }
        .share-link-password-row { display: flex; gap: 6px; margin-top: 10px; }
        .share-link-password-row input {
            flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 12.5px; font-family: var(--sans);
        }
        .share-link-password-row button {
            padding: 6px 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel-alt);
            color: var(--text); font-size: 12px; cursor: pointer; white-space: nowrap; font-family: var(--sans);
        }
        .share-link-password-row button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
        .share-link-password-row button:disabled { opacity: .5; cursor: not-allowed; }
        .share-link-password-row.disabled { opacity: .5; pointer-events: none; }
        .share-link-password-status { color: var(--accent); font-size: 11.5px; margin: 6px 0 0; }
        .share-invite-row { display: flex; gap: 6px; margin-top: 10px; }
        .share-invite-row input[type="email"], .share-invite-row input[type="text"] {
            flex: 1; min-width: 0; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 12.5px; font-family: var(--sans);
        }
        .share-invite-message { margin: 6px 0 0; font-size: 11.5px; color: #c0392b; }
        .share-invite-row select {
            padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 12px; font-family: var(--sans);
        }
        .share-invite-row button {
            padding: 6px 12px; border: none; border-radius: 6px; background: var(--accent);
            color: var(--accent-contrast); font-size: 12px; font-weight: 600; cursor: pointer; font-family: var(--sans);
        }
        .share-category-input {
            width: 100%; margin-top: 8px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 12.5px; font-family: var(--sans); box-sizing: border-box;
        }
        .share-people { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
        .share-person { display: flex; align-items: center; gap: 8px; font-size: 12.5px; }
        .share-person .share-person-email { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
        .share-person select {
            padding: 4px 6px; border: 1px solid var(--border); border-radius: 5px;
            background: var(--panel-alt); color: var(--text-dim); font-size: 11.5px; font-family: var(--sans);
        }
        .share-person .share-person-remove {
            width: 22px; height: 22px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
            background: transparent; border: none; color: var(--text-dim); cursor: pointer; border-radius: 5px;
        }
        .share-person .share-person-remove:hover { background: var(--panel-alt); color: #d9534f; }

        .file-row {
            display: flex; align-items: center; gap: 5px; padding: 4px 6px;
            cursor: pointer; border-radius: 5px; margin: 0 4px; font-size: 12.5px; color: var(--text);
        }
        .file-row:hover { background: var(--panel-alt); }
        .file-row.active { background: var(--accent); color: var(--accent-contrast); }
        .file-row .file-chevron {
            width: 12px; flex-shrink: 0; display: flex; align-items: center; justify-content: center;
            color: var(--text-dim); transition: transform .15s;
        }
        .file-row .file-chevron.open { transform: rotate(90deg); }
        .file-row.active .file-chevron { color: var(--accent-contrast); }
        .file-row .file-icon { flex-shrink: 0; display: flex; }
        .file-row .file-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .file-row .file-share { flex-shrink: 0; display: flex; opacity: .8; cursor: pointer; border-radius: 4px; }
        .file-row .file-share:hover { opacity: 1; background: rgba(127,127,127,.25); }
        /* Same color token as the "Öffentlich" badges on Browse/the homepage
           (.browse-badge-public/.badge-public) — a public-link file gets a
           visually distinct (warm) icon color instead of the plain share icon's
           inherited text color, so it reads as "public" at a glance in the tree. */
        .file-row .file-share.file-share-public { color: var(--accent-warm); opacity: 1; }
        .file-row .file-favorite { flex-shrink: 0; display: flex; align-items: center; justify-content: center; opacity: .6; cursor: pointer; border-radius: 4px; color: var(--text-dim); padding: 2px; }
        .file-row .file-favorite:hover { opacity: 1; background: rgba(127,127,127,.25); color: var(--text); }
        .file-row .file-favorite.active { opacity: 1; color: #f5a623; }
        .file-row .file-favorite.active:hover { color: #f5a623; background: rgba(245,166,35,.18); }
        .file-row .file-more {
            flex-shrink: 0; visibility: hidden; display: flex; align-items: center; justify-content: center;
            background: transparent; border: none; color: inherit;
            cursor: pointer; padding: 2px; border-radius: 4px;
        }
        .file-row:hover .file-more, .file-row.menu-open .file-more { visibility: visible; }
        .file-row .file-more:hover { background: rgba(127,127,127,.25); }

        .file-menu {
            position: fixed; z-index: 50; min-width: 160px; display: none;
            background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
            box-shadow: 0 10px 28px rgba(0,0,0,.28); padding: 6px;
        }
        .file-menu[data-open] { display: block; }
        .file-menu button {
            display: block; width: 100%; text-align: left; background: transparent; border: none; color: var(--text);
            padding: 6px 8px; border-radius: 5px; font-size: 12.5px; cursor: pointer;
        }
        .file-menu button:hover { background: var(--panel-alt); }

        .pane-head {
            font-family: var(--mono); font-size: 11px; color: var(--text-dim);
            padding: 6px 14px; border-bottom: 1px solid var(--border); background: var(--panel);
            text-transform: uppercase; letter-spacing: 1px; flex-shrink: 0;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
        }
        #preview { flex: 1; width: 100%; border: none; background: var(--bg); min-height: 420px; }

        /* Video/audio preview, rendered directly in the app page instead of inside
           #preview's sandboxed iframe — a server-streamed (GridFS) file's <video src>
           needs the auth cookie, which a sandboxed cross-origin iframe (no
           allow-same-origin) never sends, since it has no "site" the cookie's
           SameSite=Lax policy considers same-site with the top page. A plain
           <video>/<audio> element can't execute script either way, so there's
           nothing the iframe sandbox was actually protecting here. See
           showMediaPreview in viewer.js. */
        .media-preview {
            flex: 1; width: 100%; display: none; align-items: center; justify-content: center;
            background: var(--bg); overflow: auto; min-height: 420px;
        }
        .media-preview[data-active] { display: flex; }
        .media-preview video { max-width: 100%; max-height: 100%; border-radius: 8px; background: #000; }
        .media-preview audio { width: min(480px, 90%); }
        .media-preview-missing { color: var(--text-dim); font-size: 13px; font-family: var(--sans); }

        /* Custom right-click menu for the video/audio preview above — replaces the
           browser's native context menu (which offers "Save video/audio as…") with a
           small set of playback actions. */
        .video-menu {
            position: fixed; z-index: 50; min-width: 160px; display: none;
            background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
            box-shadow: 0 10px 28px rgba(0,0,0,.28); padding: 6px;
        }
        .video-menu[data-open] { display: block; }
        .video-menu button {
            display: block; width: 100%; text-align: left; background: transparent; border: none; color: var(--text);
            padding: 6px 8px; border-radius: 5px; font-size: 12.5px; cursor: pointer; font-family: var(--sans);
        }
        .video-menu button:hover { background: var(--panel-alt); }
        .empty-state {
            flex: 1; display: flex; align-items: center; justify-content: center;
            color: var(--text-dim); font-size: 13px; font-family: var(--sans);
        }

        /* Outline strip — same as the editor's, minus the source-highlight tie-in
           (there is no editor pane here to highlight). */
        .toc-strip {
            position: fixed; right: 10px; z-index: 25; pointer-events: none;
            display: flex; flex-direction: column; align-items: flex-end; justify-content: center;
        }
        .toc-strip[hidden] { display: none; }
        .toc-hover-zone { display: inline-flex; pointer-events: auto; }
        .toc-ticks { display: flex; flex-direction: column; align-items: flex-end; gap: 7px; }
        .toc-tick {
            height: 2px; border-radius: 1px; background: var(--border); cursor: pointer;
            transition: background-color .15s;
        }
        .toc-tick.active { background: var(--accent); }
        .toc-panel {
            display: none;
            min-width: 190px; max-width: 280px; max-height: 70vh; overflow-y: auto;
            background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
            box-shadow: 0 10px 28px rgba(0,0,0,.28); padding: 6px;
        }
        .toc-panel-item { display: flex; align-items: center; gap: 4px; width: 100%; border-radius: 5px; }
        .toc-panel-item:hover { background: var(--panel-alt); }
        .toc-panel-item-label {
            flex: 1; min-width: 0; background: transparent; border: none; color: var(--text);
            padding: 5px 8px; font-size: 12.5px; text-align: left; cursor: pointer;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
        }

        @media (max-width: 768px) {
            .files-panel { border-right: none; border-top: 1px solid var(--border); }
            .work { flex-direction: column-reverse; }
            .files-toggle {
                flex-direction: row; width: 100%; height: 36px;
                padding: 0 14px; gap: 8px; justify-content: flex-start;
                border-right: none;
            }
            .files-toggle-label { writing-mode: horizontal-tb; }
            /* position:fixed (not absolute/static) so the panel overlays the page
               as a true fixed sheet instead of pushing content down and needing a
               scroll to reach it — top/bottom are set via JS (fitAppHeight) to the
               same header/footer band as everything else, matching Editor.cshtml. */
            .files-body {
                position: fixed; left: 0; z-index: 45;
                width: 260px; max-width: 80vw;
                box-shadow: 4px 0 24px rgba(0,0,0,.35);
            }
            .files-backdrop {
                display: block; position: fixed; inset: 0; z-index: 44; background: rgba(0,0,0,.4);
            }
            .files-backdrop[hidden] { display: none; }
            /* Safety net matching Editor.cshtml's — see the equivalent rule in
               editor.css for why: any one element overflowing the screen width
               (rather than wrapping/shrinking) balloons the whole layout viewport,
               breaking every 100vw/fixed-position calculation on the page, not
               just the offending element. */
            html, body { overflow-x: hidden; }

            .toolbar { flex-wrap: wrap; row-gap: 8px; padding: 8px 10px; }
            /* On desktop .toolbar-filename's flex:1 sits between the brand and the
               action buttons, pushing the latter to the right edge for free. On
               mobile it's pulled onto its own row (below), so nothing is left in
               the first row to push against — without this the buttons just sit
               left-aligned right after the brand instead of at the right edge,
               unlike Editor.cshtml's .seg/.pdf-btn/.open-viewer-btn group (whose
               .brand already carries this same margin-right:auto). */
            .toolbar-filename { order: 3; flex-basis: 100%; }
            .brand { margin-right: auto; }
            /* pdf/presentation/open-editor buttons drop their text label and become
               icon-only on mobile — same treatment as Editor.cshtml's pdf/viewer-
               open buttons — so the brand + all of them fit on one row instead of
               each wrapping onto its own line. */
            .pdf-btn .btn-label, .presentation-btn .btn-label, .open-editor-btn .btn-label { display: none; }
            .pdf-btn, .presentation-btn, .open-editor-btn { padding: 7px 9px; }
        }

        /* Shown in place of the whole app shell when a /v/{id} route resolves to a
           document/vault the caller has no rights to, or a session that's expired —
           see showAccessError in viewer.js. */
        .access-error {
            display: flex; flex-direction: column; align-items: center; justify-content: center;
            gap: 10px; height: 100%; min-height: 60vh; text-align: center; padding: 24px;
        }
        .access-error h2 { margin: 0; font-size: 20px; color: var(--text); }
        .access-error p { margin: 0; color: var(--text-dim); font-size: 14px; max-width: 420px; }
        .access-error-btn {
            margin-top: 10px; padding: 8px 18px; border-radius: 6px; background: var(--accent);
            color: var(--accent-contrast); font-size: 13px; font-weight: 600; text-decoration: none;
        }
        button.access-error-btn { border: none; cursor: pointer; font-family: inherit; }
        .access-error-btn:hover { opacity: .9; }
        .access-error-password-form { display: flex; gap: 8px; margin-top: 4px; }
        .access-error-password-form input {
            padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px;
            background: var(--panel-alt); color: var(--text); font-size: 13px; font-family: var(--sans);
        }
        .access-error-password-error { margin: 0; color: #d9534f; font-size: 13px; }
