dorfteich/apps/web/src/styles/base.css
Claude Fable 5 31557f09e5 Sidebar: pin the action icon row to the visible bottom (#129)
.sidebar is itself the scroll container, so the footer's margin-top:
auto only pinned the icon row to the end of the CONTENT — behind the
fold on long page lists. The row is now position: sticky with negative
bottom/side margins undoing the sidebar padding, a background, and a
top border, so the list scrolls away beneath it and the four actions
stay visible at any list length. The import progress list keeps
floating above the row (absolute within the sticky footer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fb2VzvcoBPHkjh8bZ6PzQn
2026-07-16 12:02:40 +02:00

3501 lines
65 KiB
CSS

*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body,
#root {
height: 100%;
margin: 0;
}
body {
font-family: var(--font-body);
font-weight: var(--font-weight-body);
color: var(--color-text);
background: var(--color-bg);
line-height: 1.6;
}
h1,
h2,
h3,
h4 {
font-family: var(--font-heading);
font-weight: var(--font-weight-heading);
line-height: 1.25;
}
code,
pre {
font-family: var(--font-mono);
font-weight: var(--font-weight-mono);
}
/* A pond's content root (ADR 0016): sets --font-* (via PondFontScope) so its
* body text uses the pond's body font; headings and code re-resolve the same
* variables through the global rules above. */
.pond-font-scope {
font-family: var(--font-body);
font-weight: var(--font-weight-body);
}
a {
color: var(--color-accent);
}
button {
font: inherit;
}
/* Layout skeleton */
.app {
display: grid;
grid-template-rows: var(--topbar-height) 1fr;
height: 100%;
}
.app-body {
display: flex;
min-height: 0;
/* Grid items default to a min-content minimum; without this the row can
force the whole app wider than the viewport (issue #100). */
min-width: 0;
}
.topbar {
display: flex;
align-items: center;
gap: var(--space-4);
padding: 0 var(--space-4);
border-bottom: 1px solid var(--color-border);
background: var(--color-bg);
}
.topbar__brand {
font-family: var(--font-heading);
font-size: 1.1rem;
color: var(--color-text);
text-decoration: none;
}
.topbar__spacer {
flex: 1;
}
.sidebar {
width: var(--sidebar-width);
flex-shrink: 0;
/* Column flex so the trash footer can pin to the bottom (margin-top: auto). */
display: flex;
flex-direction: column;
border-right: 1px solid var(--color-border);
background: var(--color-bg-subtle);
padding: var(--space-4);
overflow-y: auto;
transition:
margin-left 0.18s ease-out,
opacity 0.15s ease-out;
}
.sidebar--collapsed {
margin-left: calc(-1 * var(--sidebar-width));
opacity: 0;
}
/* Drag handle on the sidebar's right edge (issue #99). */
.sidebar-resizer {
flex-shrink: 0;
width: 6px;
margin-left: -3px;
cursor: col-resize;
touch-action: none;
background: transparent;
}
.sidebar-resizer:hover,
.sidebar-resizer:focus-visible {
background: var(--color-accent);
outline: none;
}
.sidebar__hint {
color: var(--color-text-muted);
font-size: 0.9rem;
}
.sidebar__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.sidebar__pond-name {
font-size: 1rem;
margin: 0;
}
.sidebar__sort {
font: inherit;
font-size: 0.85rem;
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
padding: var(--space-1) var(--space-2);
}
.sidebar__pages {
list-style: none;
margin: 0 0 var(--space-3);
padding: 0;
}
/* Folder view (issue #108): the page tree with collapsible nodes. */
.sidebar__view-toggle {
display: flex;
gap: var(--space-1);
margin-bottom: var(--space-2);
}
.sidebar__view-btn {
font: inherit;
font-size: 0.8rem;
padding: var(--space-1) var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
color: var(--color-text-muted);
cursor: pointer;
}
.sidebar__view-btn--active {
color: var(--color-text);
font-weight: 600;
background: var(--color-surface);
}
.sidebar__tree-row {
display: flex;
align-items: center;
gap: var(--space-1);
min-width: 0;
}
.sidebar__tree-row .sidebar__page {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* In the tree, the nested children <ul> is a SECOND flex item of the
.sidebar__page-item <li>. Stack it below the parent row (#122) — the
base rule's flex row centered the parent vertically BESIDE its children. */
.sidebar__pages--tree .sidebar__page-item {
flex-direction: column;
align-items: stretch;
gap: 0;
}
.sidebar__tree-children {
/* Per-level indent: about two characters is plenty (#122). */
margin: 0 0 0 1.25em;
}
.sidebar__caret {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 1rem;
border: 0;
background: none;
padding: 0;
cursor: pointer;
color: var(--color-text-muted);
transform: rotate(90deg);
transition: transform 0.12s ease;
}
.sidebar__caret svg {
width: 0.9rem;
height: 0.9rem;
}
.sidebar__caret--collapsed {
transform: rotate(0deg);
}
.sidebar__caret--leaf {
cursor: default;
}
/* Folder pages vs. leaf pages read differently at a glance (#122). */
.sidebar__page-icon {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
color: var(--color-text-muted);
}
.sidebar__page-icon svg {
width: 0.875rem;
height: 0.875rem;
}
/* Label view (issue #108): pages grouped under the label tree. */
.sidebar__label-group {
margin-bottom: var(--space-2);
}
.sidebar__label-heading {
display: flex;
align-items: center;
gap: var(--space-1);
margin: 0 0 var(--space-1);
font-size: 0.8rem;
font-weight: 600;
color: var(--color-text-muted);
text-transform: uppercase;
letter-spacing: 0.03em;
}
.sidebar__label-group .sidebar__pages {
margin-bottom: 0;
}
.sidebar__new-page-parent {
margin: 0 0 var(--space-2);
font-size: 0.8rem;
color: var(--color-text-muted);
}
/* Drop-into cue while dragging a page onto another (reparent, issue #109). */
.sidebar__page-item--drop-into > .sidebar__tree-row {
outline: 2px solid var(--color-accent);
outline-offset: -2px;
border-radius: var(--radius);
}
/* Minimal modal (issue #109: "Move to…" and the delete-choice dialog). */
.modal-overlay {
position: fixed;
inset: 0;
z-index: 1100;
background: rgb(0 0 0 / 40%);
display: flex;
align-items: center;
justify-content: center;
padding: var(--space-4);
}
.modal {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
padding: var(--space-4);
max-width: 28rem;
width: 100%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 8px 24px rgb(0 0 0 / 20%);
}
.modal__title {
margin: 0 0 var(--space-3);
font-size: 1.1rem;
}
.modal__actions {
display: flex;
align-items: center;
gap: var(--space-3);
margin-top: var(--space-3);
}
.modal__actions--stacked {
flex-direction: column;
align-items: stretch;
gap: var(--space-2);
}
.move-dialog__options {
list-style: none;
margin: 0;
padding: 0;
max-height: 40vh;
overflow-y: auto;
}
.move-dialog__option {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) 0;
cursor: pointer;
}
.move-dialog__option:has(input:disabled) {
color: var(--color-text-muted);
cursor: not-allowed;
}
.sidebar__page {
display: block;
/* Compact rows (#122): deep imported trees need to fit on one screen. */
padding: 0.125rem var(--space-2);
border-radius: var(--radius);
color: var(--color-text);
text-decoration: none;
font-size: 0.875rem;
}
.sidebar__page:hover {
background: var(--color-bg);
}
.sidebar__page--active {
background: var(--color-bg);
font-weight: 600;
}
.sidebar__new-page-form {
margin-top: var(--space-2);
}
.sidebar__new-page-form .field {
margin-bottom: var(--space-2);
}
.sidebar__new-page-actions {
display: flex;
align-items: center;
gap: var(--space-3);
}
/* The import control sits in the pinned footer icon row (#124); its
progress list floats ABOVE the row so the icons stay put. */
.sidebar__import {
position: relative;
display: inline-flex;
}
.sidebar__import-list {
list-style: none;
position: absolute;
bottom: calc(100% + var(--space-1));
left: 0;
width: 14rem;
margin: 0;
padding: var(--space-2);
display: flex;
flex-direction: column;
gap: var(--space-2);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: 0 4px 12px rgb(0 0 0 / 10%);
z-index: 30;
}
.sidebar__import-item {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: var(--space-2);
font-size: 0.85rem;
}
.sidebar__import-name {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sidebar__import-status {
color: var(--color-text-muted);
}
.sidebar__import-item--failed .sidebar__import-status {
color: var(--color-danger);
}
.sidebar__import-actions {
display: flex;
gap: var(--space-2);
}
.pond-home {
max-width: 36rem;
}
.main-column {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
.main {
flex: 1;
min-height: 0;
min-width: 0;
overflow-y: auto;
padding: var(--space-6) var(--space-8);
}
.icon-button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
border: 1px solid transparent;
border-radius: var(--radius);
background: transparent;
cursor: pointer;
color: var(--color-text);
}
.icon-button svg {
width: 1.15rem;
height: 1.15rem;
}
.icon-button--active {
color: var(--color-accent);
background: var(--color-bg-subtle);
}
.icon-button:disabled {
opacity: 0.5;
cursor: default;
}
/* Page actions in the TopBar (issue #101). */
.topbar__page-actions {
display: flex;
align-items: center;
}
/* Live presence next to the page actions (issue #102). */
.topbar__presence {
display: flex;
align-items: center;
}
.page-actions {
display: flex;
align-items: center;
gap: var(--space-1);
}
.icon-button .comments-unread-badge {
position: absolute;
top: -4px;
right: -6px;
margin-left: 0;
line-height: 1.1rem;
padding: 0 0.3rem;
}
.page-actions__more {
position: relative;
}
.page-actions__menu {
position: absolute;
right: 0;
top: calc(100% + 4px);
min-width: 14rem;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: 0 4px 12px rgb(0 0 0 / 0.08);
display: flex;
flex-direction: column;
z-index: 10;
}
.page-actions__menu a,
.page-actions__menu button {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-2) var(--space-3);
text-align: left;
background: none;
border: none;
color: var(--color-text);
text-decoration: none;
cursor: pointer;
font: inherit;
}
.page-actions__menu svg {
width: 1rem;
height: 1rem;
flex-shrink: 0;
}
.page-actions__menu a:hover,
.page-actions__menu button:hover:not(:disabled) {
background: var(--color-bg-subtle);
}
.page-actions__menu button:disabled {
color: var(--color-text-muted);
cursor: default;
}
.page-actions__menu button.page-actions__menu-danger {
color: var(--color-danger);
}
.icon-button:hover {
background: var(--color-bg-subtle);
border-color: var(--color-border);
}
.icon-button:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 1px;
}
.status-pill {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) var(--space-3);
border-radius: 999px;
border: 1px solid var(--color-border);
font-size: 0.9rem;
}
.status-pill--ok {
color: var(--color-ok);
}
.status-pill--error {
color: var(--color-danger);
}
/* Forms */
.field {
display: block;
margin-bottom: var(--space-4);
}
.field__label {
display: block;
margin-bottom: var(--space-1);
font-size: 0.9rem;
color: var(--color-text-muted);
}
.field input,
.field select {
width: 100%;
padding: var(--space-2) var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
font: inherit;
background: var(--color-bg);
}
.field input:focus-visible,
.field select:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 1px;
}
.field__hint,
.field__error {
display: block;
margin-top: var(--space-1);
font-size: 0.85rem;
}
.field__hint {
color: var(--color-text-muted);
}
.field__error {
color: var(--color-danger);
}
.button {
display: inline-block;
padding: var(--space-2) var(--space-4);
border: none;
border-radius: var(--radius);
background: var(--color-accent);
color: var(--color-accent-contrast);
cursor: pointer;
text-decoration: none;
font: inherit;
}
.button:disabled {
opacity: 0.6;
cursor: default;
}
.linklike {
background: none;
border: none;
padding: 0;
color: var(--color-accent);
text-decoration: underline;
cursor: pointer;
font: inherit;
}
.form-banner {
padding: var(--space-2) var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
margin-bottom: var(--space-4);
font-size: 0.95rem;
}
.form-banner--error {
border-color: var(--color-danger);
color: var(--color-danger);
}
.form-banner--ok {
border-color: var(--color-ok);
color: var(--color-ok);
}
/* Auth pages */
.auth-card {
max-width: 24rem;
margin: var(--space-8) auto;
}
.auth-card__links {
margin-top: var(--space-4);
font-size: 0.95rem;
}
/* Legal pages + footer (issue #82) */
.app-footer {
display: flex;
align-items: center;
gap: var(--space-2);
flex-shrink: 0;
padding: var(--space-2) var(--space-8);
border-top: 1px solid var(--color-border);
background: var(--color-bg);
color: var(--color-text-muted);
font-size: 0.85rem;
}
.app-footer__spacer {
flex: 1;
}
.app-footer__status {
display: flex;
align-items: center;
}
/* Instance version next to the connection status (#126). */
.app-footer__version {
font-size: 0.8rem;
white-space: nowrap;
}
.legal-page {
max-width: 44rem;
}
.legal-page__placeholder {
color: var(--color-text-muted);
}
.legal-editor,
.markdown-field {
margin-bottom: var(--space-4);
}
.legal-editor textarea,
.markdown-field textarea {
width: 100%;
font-family: var(--font-mono);
font-size: 0.9rem;
}
.legal-editor__preview,
.markdown-field__preview {
margin-top: var(--space-3);
padding: var(--space-3);
border: 1px dashed var(--color-border);
border-radius: var(--radius);
}
/* First-run setup wizard (issue #81) */
.setup-shell {
min-height: 100vh;
padding: var(--space-4);
}
.setup-wizard {
max-width: 28rem;
}
.setup-progress {
margin-bottom: var(--space-1);
color: var(--color-text-muted);
font-size: 0.9rem;
}
.setup-progress-steps {
display: flex;
flex-wrap: wrap;
gap: var(--space-1) var(--space-3);
margin: 0 0 var(--space-6);
padding: 0;
list-style: none;
color: var(--color-text-muted);
font-size: 0.85rem;
}
.setup-progress-steps li[aria-current='step'] {
color: inherit;
font-weight: 600;
}
.setup-progress-steps__done {
color: var(--color-accent);
}
.setup-language-buttons {
display: flex;
gap: var(--space-3);
}
.button--outline {
background: transparent;
color: var(--color-accent);
box-shadow: inset 0 0 0 1px var(--color-accent);
}
.setup-actions {
display: flex;
align-items: center;
gap: var(--space-3);
margin-top: var(--space-4);
}
.setup-actions__spacer {
flex: 1;
}
.setup-choice {
display: flex;
align-items: flex-start;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.setup-choice__hint {
display: block;
}
.setup-smtp-detail {
color: var(--color-danger);
font-family: var(--font-mono);
font-size: 0.85rem;
overflow-wrap: anywhere;
}
.setup-summary dt {
margin-top: var(--space-3);
color: var(--color-text-muted);
font-size: 0.9rem;
}
.setup-summary dd {
margin: 0;
}
/* Settings */
.settings-section {
max-width: 36rem;
margin-bottom: var(--space-8);
padding-bottom: var(--space-6);
border-bottom: 1px solid var(--color-border);
}
.table {
width: 100%;
border-collapse: collapse;
margin-bottom: var(--space-4);
}
.table th,
.table td {
text-align: left;
padding: var(--space-2) var(--space-3);
border-bottom: 1px solid var(--color-border);
font-size: 0.95rem;
}
.table th {
color: var(--color-text-muted);
font-weight: 400;
}
.badge {
display: inline-block;
margin-left: var(--space-2);
padding: 0 var(--space-2);
border-radius: 999px;
background: var(--color-bg-subtle);
border: 1px solid var(--color-border);
font-size: 0.8rem;
color: var(--color-text-muted);
}
/* User menu */
.user-menu {
position: relative;
}
.user-menu__trigger {
background: none;
border: 1px solid transparent;
border-radius: var(--radius);
padding: var(--space-1) var(--space-3);
cursor: pointer;
}
.user-menu__trigger:hover {
border-color: var(--color-border);
}
.user-menu__list {
position: absolute;
right: 0;
top: calc(100% + 4px);
min-width: 12rem;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: 0 4px 12px rgb(0 0 0 / 0.08);
display: flex;
flex-direction: column;
z-index: 10;
}
.user-menu__list a,
.user-menu__list button {
padding: var(--space-2) var(--space-3);
text-align: left;
background: none;
border: none;
color: var(--color-text);
text-decoration: none;
cursor: pointer;
font: inherit;
}
.user-menu__list a:hover,
.user-menu__list button:hover {
background: var(--color-bg-subtle);
}
.topbar__nav {
display: flex;
gap: var(--space-4);
}
/* Page editor (issue #25). Fills the content area — no width cap (issue
#100); the public read view keeps its own narrow reading layout. */
.editor-page {
min-width: 0;
}
.editor-page__header {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-4);
margin-bottom: var(--space-4);
}
.editor-page__title {
flex: 1;
border: none;
background: none;
font-family: var(--font-heading);
font-weight: var(--font-weight-heading);
font-size: 1.6rem;
padding: var(--space-1) 0;
}
.editor-page__title:disabled {
color: var(--color-text);
opacity: 1;
}
.editor-page__title:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
/* The export entries flow inline with the other overflow-menu items. */
.editor-page__export {
display: contents;
}
.pond-export__hint {
color: var(--color-text-muted);
margin-bottom: var(--space-2);
}
/* Pond appearance (fonts) settings — issue #66 */
.appearance__intro {
color: var(--color-text-muted);
}
.appearance__slot {
display: flex;
flex-wrap: wrap;
align-items: end;
gap: var(--space-3);
padding: var(--space-3) 0;
border-top: 1px solid var(--color-border);
}
.appearance__slot-label {
flex-basis: 100%;
font-weight: 600;
}
.appearance__field {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.appearance__preview {
flex: 1 1 16rem;
margin: 0;
font-size: 1.1rem;
}
.appearance__actions {
display: flex;
align-items: center;
gap: var(--space-4);
margin-top: var(--space-3);
}
.font-catalog__table {
border-collapse: collapse;
width: 100%;
}
.font-catalog__table th,
.font-catalog__table td {
text-align: left;
padding: var(--space-2) var(--space-3);
border-bottom: 1px solid var(--color-border);
}
.editor-shell {
border: 1px solid var(--color-border);
border-radius: var(--radius);
}
/* Read mode drops the frame and its inner padding — the rendered page sits
directly in the content area (M10 follow-up). */
.editor-shell--reading {
border: none;
border-radius: 0;
}
.editor-shell--reading > .editor-content {
padding: 0;
}
.editor-toolbar {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
padding: var(--space-2) var(--space-3);
border-bottom: 1px solid var(--color-border);
background: var(--color-bg-subtle);
/* Long articles: the toolbar pins to the top of the scrolling content
area instead of scrolling away. */
position: sticky;
top: 0;
z-index: 20;
}
.editor-toolbar__group {
display: flex;
gap: var(--space-1);
padding-right: var(--space-3);
border-right: 1px solid var(--color-border);
}
.editor-toolbar__group:last-child {
border-right: none;
padding-right: 0;
}
.editor-toolbar__section-select {
height: 1.75rem;
max-width: 12rem;
padding: 0 var(--space-1);
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
color: var(--color-text);
font-size: 0.85rem;
}
/* A section whose plugin is disabled/removed is an invisible wrapper (its
* dt-style-… class matches no stylesheet). While writing, a faint dashed
* hint keeps every section findable, so "unwrap" has a visible target. */
.editor-content .dt-section {
border-radius: var(--radius);
outline: 1px dashed transparent;
outline-offset: 2px;
}
.editor-content:focus-within .dt-section {
outline-color: var(--color-border);
}
/* The page-tools panel (issue #77): active pageTool plugin surfaces behind
* disclosures; each iframe mounts lazily on first open. */
.page-tools {
margin: var(--space-2) var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
}
.page-tools__tool + .page-tools__tool {
border-top: 1px solid var(--color-border);
}
.page-tools__toggle {
display: block;
width: 100%;
padding: var(--space-2) var(--space-3);
border: none;
background: var(--color-bg-subtle);
color: var(--color-text);
text-align: left;
font-size: 0.9rem;
cursor: pointer;
}
.page-tools__tool .plugin-frame-host {
padding: var(--space-2) var(--space-3);
}
/* A plugin-owned block (issue #76): a framed island in the content column.
* The sandbox iframe sizes itself via ui.resize; the bar carries the plugin
* name and the edit affordance. */
.plugin-block {
margin: 0.75rem 0;
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
}
.plugin-block--selected {
outline: 2px solid var(--color-accent);
outline-offset: 1px;
}
.plugin-block__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
padding: var(--space-1) var(--space-2);
border-bottom: 1px solid var(--color-border);
background: var(--color-bg-subtle);
font-size: 0.8rem;
color: var(--color-text-muted);
}
.plugin-block__mount .plugin-frame {
display: block;
width: 100%;
border: none;
}
/* Read mode integrates plugin output like normal content: no frame, no
name bar — same principle as the frameless reading shell (M10). */
.editor-shell--reading .plugin-block {
border: none;
border-radius: 0;
background: transparent;
/* No selection outline either — reading is not editing. */
outline: none;
}
.editor-shell--reading .plugin-block__bar {
display: none;
}
.plugin-block__fallback {
padding: var(--space-2) var(--space-3);
}
.plugin-block__fallback-text {
margin: 0;
}
.plugin-block__fallback-note {
margin: var(--space-1) 0 0;
font-size: 0.8rem;
color: var(--color-text-muted);
}
.toolbar-button {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1.75rem;
height: 1.75rem;
padding: 0 var(--space-1);
border: 1px solid transparent;
border-radius: var(--radius);
background: transparent;
cursor: pointer;
color: var(--color-text);
font-size: 0.9rem;
}
.toolbar-button:hover:not(:disabled) {
background: var(--color-bg);
border-color: var(--color-border);
}
.toolbar-button:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 1px;
}
.toolbar-button--active {
background: var(--color-accent);
color: var(--color-accent-contrast);
}
.toolbar-button:disabled {
opacity: 0.4;
cursor: default;
}
.editor-link-form {
display: flex;
gap: var(--space-1);
align-items: center;
}
.editor-link-form input {
padding: var(--space-1) var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--radius);
font: inherit;
font-size: 0.9rem;
}
.editor-link-form__error {
flex-basis: 100%;
font-size: 0.8rem;
color: var(--color-danger);
}
.editor-link-menu {
padding: var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
}
.editor-link-menu__actions {
display: flex;
gap: var(--space-1);
}
/* The connection-status icon in the content footer (left half). */
.editor-connection {
display: inline-flex;
align-items: center;
color: var(--color-text-muted);
}
.editor-connection svg {
width: 1rem;
height: 1rem;
}
.editor-connection[data-status='connected'] {
color: var(--color-accent);
}
.editor-connection[data-status='offline'] {
color: var(--color-danger);
}
.presence-strip {
display: flex;
gap: calc(-1 * var(--space-1));
align-items: center;
padding: var(--space-1) var(--space-3);
}
.presence-avatar {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
margin-left: -0.4rem;
border: 2px solid var(--color-bg);
border-radius: 50%;
color: #ffffff;
font-size: 0.7rem;
font-weight: 600;
}
.presence-avatar:first-child {
margin-left: 0;
}
.presence-avatar--overflow {
background: var(--color-text-muted);
}
.presence-avatar__ro {
position: absolute;
right: -0.15rem;
bottom: -0.15rem;
font-size: 0.75rem;
line-height: 1;
}
/* Remote collaboration carets and selections (issue #37). */
.collab-caret {
position: relative;
margin-left: -1px;
margin-right: -1px;
border-left: 1px solid;
border-right: 1px solid;
word-break: normal;
pointer-events: none;
}
.collab-caret--hidden {
display: none;
}
.collab-caret__label {
position: absolute;
top: -1.4em;
left: -1px;
padding: 0.05rem 0.3rem;
border-radius: 3px 3px 3px 0;
color: #ffffff;
font-size: 0.7rem;
font-weight: 600;
white-space: nowrap;
user-select: none;
}
.collab-selection {
border-radius: 2px;
}
.editor-banner {
margin: var(--space-1) var(--space-3);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm, 4px);
font-size: 0.9rem;
}
.editor-banner--info {
background: var(--color-bg-subtle);
border: 1px solid var(--color-border);
color: var(--color-text-muted);
}
.editor-banner--error {
background: var(--color-bg-subtle);
border: 1px solid var(--color-danger);
color: var(--color-danger);
}
.editor-page__body {
display: flex;
gap: var(--space-4);
align-items: flex-start;
}
.editor-page__body > .editor-shell {
flex: 1 1 auto;
min-width: 0;
}
/* Column holding the open side panels next to the editor; each panel takes
the column's full width and they stack vertically (M10 follow-up). */
.editor-page__panels {
display: flex;
flex-direction: column;
gap: var(--space-4);
flex: 0 0 22rem;
max-width: 22rem;
}
.editor-page__panels > .label-picker,
.editor-page__panels > .history-panel {
flex: none;
max-width: none;
}
.history-panel {
flex: 0 0 22rem;
max-width: 22rem;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm, 4px);
padding: var(--space-3);
max-height: 80vh;
overflow-y: auto;
}
.history-panel__header {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--space-2);
}
.history-panel__header h2 {
font-size: 1rem;
margin: 0;
}
.history-panel__list {
list-style: none;
margin: var(--space-2) 0;
padding: 0;
}
.history-panel__item {
display: flex;
flex-direction: column;
width: 100%;
text-align: left;
gap: 2px;
padding: var(--space-2);
border: 1px solid transparent;
border-radius: var(--radius-sm, 4px);
background: none;
cursor: pointer;
color: inherit;
}
.history-panel__item:hover {
background: var(--color-bg-subtle);
}
.history-panel__item[aria-current='true'] {
border-color: var(--color-border);
background: var(--color-bg-subtle);
}
/* Owner-facing quick label management inside the picker (M10 follow-up). */
.label-picker__manage {
margin-top: var(--space-3);
padding-top: var(--space-3);
border-top: 1px solid var(--color-border);
font-size: 0.85rem;
}
.label-picker__create {
display: flex;
align-items: center;
gap: var(--space-2);
margin-bottom: var(--space-2);
}
.label-picker__create input {
flex: 1;
min-width: 0;
}
.label-picker__error {
color: var(--color-danger);
font-size: 0.85rem;
}
/* Contributor names under each version entry (M10 follow-up). */
.history-panel__contributors {
display: block;
padding: 0 var(--space-2) var(--space-1);
font-size: 0.8rem;
color: var(--color-text-muted);
}
.history-panel__contributors-more {
font: inherit;
}
.history-panel__when {
font-weight: 600;
font-size: 0.9rem;
}
.history-panel__meta {
font-size: 0.8rem;
color: var(--color-text-muted);
}
.history-panel__error {
color: var(--color-danger);
}
.history-panel__diff {
white-space: pre-wrap;
word-break: break-word;
font-size: 0.85rem;
background: var(--color-bg-subtle);
padding: var(--space-2);
border-radius: var(--radius-sm, 4px);
}
.diff--added {
background: color-mix(in srgb, green 22%, transparent);
text-decoration: none;
}
.diff--removed {
background: color-mix(in srgb, red 22%, transparent);
text-decoration: line-through;
}
.history-panel__preview {
border-top: 1px solid var(--color-border);
padding-top: var(--space-2);
}
.access-revoked__title {
font-weight: 600;
margin: 0 0 var(--space-1);
}
.access-revoked__description {
margin: 0 0 var(--space-2);
}
.access-revoked__actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
}
.editor-content {
padding: var(--space-4) var(--space-6);
min-height: 12rem;
}
.editor-content .ProseMirror {
outline: none;
}
.editor-content h1,
.editor-content h2,
.editor-content h3,
.editor-content h4 {
margin-top: var(--space-6);
margin-bottom: var(--space-2);
}
.editor-content blockquote {
margin: var(--space-4) 0;
padding-left: var(--space-4);
border-left: 3px solid var(--color-border);
color: var(--color-text-muted);
}
.editor-content pre {
padding: var(--space-3);
border-radius: var(--radius);
background: var(--color-bg-subtle);
overflow-x: auto;
}
.editor-content code {
background: var(--color-bg-subtle);
border-radius: 3px;
padding: 0 0.25em;
}
.editor-content pre code {
background: none;
padding: 0;
}
.editor-content ul[data-type='task_list'] {
list-style: none;
padding-left: var(--space-2);
}
.editor-content ul[data-type='task_list'] li {
display: flex;
align-items: flex-start;
gap: var(--space-2);
}
.editor-content table {
border-collapse: collapse;
margin: var(--space-4) 0;
width: 100%;
}
.editor-content table td,
.editor-content table th {
border: 1px solid var(--color-border);
padding: var(--space-2) var(--space-3);
}
.editor-content table th {
background: var(--color-bg-subtle);
text-align: left;
}
.editor-content hr {
border: none;
border-top: 1px solid var(--color-border);
margin: var(--space-6) 0;
}
.editor-image {
position: relative;
display: inline-block;
max-width: 100%;
vertical-align: bottom;
}
.editor-image img {
max-width: 100%;
border-radius: var(--radius);
}
.editor-image__controls {
display: flex;
flex-direction: column;
gap: var(--space-2);
position: absolute;
top: 100%;
left: 0;
z-index: 1;
margin-top: var(--space-1);
padding: var(--space-2) var(--space-3);
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-bg);
box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
white-space: nowrap;
}
.editor-image__alt {
display: flex;
flex-direction: column;
gap: var(--space-1);
font-size: 0.85rem;
color: var(--color-text-muted);
}
.editor-image__alt input {
padding: var(--space-1) var(--space-2);
border: 1px solid var(--color-border);
border-radius: var(--radius);
font: inherit;
font-size: 0.9rem;
}
.editor-image__widths {
display: flex;
gap: var(--space-1);
}
.editor-image-upload {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 3rem;
min-height: 2rem;
padding: var(--space-1) var(--space-2);
border: 1px dashed var(--color-border);
border-radius: var(--radius);
background: var(--color-bg-subtle);
color: var(--color-text-muted);
font-size: 0.85rem;
}
.editor-image-upload--error {
border-color: var(--color-danger);
color: var(--color-danger);
}
/* Pond trash (issue #31) */
.trash-page {
max-width: 48rem;
margin: 0 auto;
}
.trash-page__list {
list-style: none;
margin: var(--space-4) 0 0;
padding: 0;
}
.trash-page__item {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-2) 0;
border-bottom: 1px solid var(--color-border);
}
.trash-page__title {
flex: 1;
font-weight: var(--font-weight-heading);
}
.trash-page__deleted-at {
color: var(--color-text-muted);
font-size: 0.85rem;
}
/* Labels (issue #44) --------------------------------------------------- */
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* Colored chips on sidebar page entries. */
.label-chips {
display: flex;
flex-wrap: wrap;
gap: var(--space-1);
margin: var(--space-1) 0 0 var(--space-2);
}
.label-chip {
display: inline-block;
padding: 0 var(--space-2);
border-radius: 999px;
font-size: 0.72rem;
line-height: 1.5;
white-space: nowrap;
}
.label-chip__swatch {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
border: 1px solid var(--color-border);
flex: 0 0 auto;
}
/* Sidebar label filter. */
.sidebar__filter {
margin-bottom: var(--space-3);
font-size: 0.9rem;
}
.sidebar__filter > summary {
cursor: pointer;
color: var(--color-text-muted);
padding: var(--space-1) 0;
}
.sidebar__filter-list {
list-style: none;
margin: var(--space-1) 0;
padding: 0;
max-height: 14rem;
overflow-y: auto;
}
.sidebar__filter-option {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) 0;
cursor: pointer;
}
.sidebar__footer {
/* #129: .sidebar is the scroll container, so margin-top: auto alone only
pins the row to the END of the content — behind the fold on long page
lists. Sticky keeps it visible; the negative bottom/side margins undo
the sidebar padding so the bar sits flush and covers the scrolling
list across the full width. */
position: sticky;
bottom: calc(-1 * var(--space-4));
margin: auto calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
padding: var(--space-2) var(--space-4);
background: var(--color-bg-subtle);
border-top: 1px solid var(--color-border);
display: flex;
align-items: center;
gap: var(--space-1);
}
/* Knowledge graph (issue #112) + local graph panel (#113). */
.graph-page__header {
display: flex;
align-items: baseline;
gap: var(--space-3);
flex-wrap: wrap;
}
.graph-page__counts {
margin: 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
.graph-page__hint {
color: var(--color-text-muted);
font-size: 0.9rem;
}
.graph-page__canvas {
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-surface);
overflow: hidden;
}
/* Physics/rendering sliders (#123). */
.graph-controls {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-3);
margin-bottom: var(--space-2);
font-size: 0.85rem;
color: var(--color-text-muted);
}
.graph-controls__field {
display: inline-flex;
align-items: center;
gap: var(--space-1);
}
.graph-controls__field input[type='range'] {
width: 7rem;
}
.force-graph {
display: block;
width: 100%;
height: auto;
touch-action: none;
cursor: grab;
}
.force-graph__edge {
stroke: var(--color-border);
stroke-width: 1.2;
}
.force-graph__node {
cursor: pointer;
}
.force-graph__dot {
stroke-width: 2;
}
.force-graph__node--phantom .force-graph__dot {
stroke-dasharray: 3 3;
}
.force-graph__node--phantom .force-graph__label {
fill: var(--color-text-muted);
font-style: italic;
}
.force-graph__ring {
fill: none;
stroke: var(--color-accent);
stroke-width: 2;
}
.force-graph__label {
font-size: 11px;
fill: var(--color-text);
pointer-events: none;
user-select: none;
}
.graph-legend {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
margin-top: var(--space-3);
font-size: 0.85rem;
color: var(--color-text-muted);
}
.graph-legend__entry {
display: inline-flex;
align-items: center;
gap: var(--space-1);
}
.graph-legend__phantom-swatch {
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
border: 2px dashed var(--color-text-muted);
}
/* Obsidian vault import dialog (issue #118). */
.vault-import__hint {
color: var(--color-text-muted);
font-size: 0.9rem;
}
.vault-import-dialog__field {
display: block;
border: 0;
padding: 0;
margin: 0 0 var(--space-3);
}
.vault-import-dialog__field > legend,
.vault-import-dialog__field > span {
display: block;
font-weight: 600;
font-size: 0.9rem;
margin-bottom: var(--space-1);
}
.vault-import-dialog__field .move-dialog__options {
max-height: 12rem;
}
.vault-import-dialog__labels-empty {
color: var(--color-text-muted);
font-size: 0.9rem;
margin: 0 0 var(--space-1);
}
/* Inline label creation (#121): input + button side by side. */
.vault-import-dialog__label-create {
display: flex;
gap: var(--space-2);
margin-top: var(--space-1);
}
.vault-import-dialog__label-create input {
flex: 1;
min-width: 0;
}
/* "Create this page" on the not-found screen (issue #115). */
.create-missing-page {
margin-top: var(--space-3);
}
.create-missing-page__hint {
color: var(--color-text-muted);
font-size: 0.9rem;
margin: 0 0 var(--space-2);
}
/* Local neighborhood graph below the page content (issue #113). */
.local-graph {
margin-top: var(--space-4);
}
.local-graph > summary {
cursor: pointer;
font-weight: 600;
font-size: 0.9rem;
}
.local-graph__controls {
display: flex;
gap: var(--space-1);
margin: var(--space-2) 0;
}
/* Hop-depth slider (#123): replaces the two fixed depth buttons. */
.local-graph__hops {
display: inline-flex;
align-items: center;
gap: var(--space-2);
font-size: 0.85rem;
color: var(--color-text-muted);
}
.local-graph__hops input[type='range'] {
width: 7rem;
}
.local-graph__canvas {
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: var(--color-surface);
max-width: 36rem;
overflow: hidden;
}
/* Pond settings page + label manager. */
.pond-settings-page {
max-width: 48rem;
}
/* Member management (issue #54) */
.member-manager__intro,
.member-manager__note,
.member-manager__empty {
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.member-seats {
list-style: none;
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin: 0 0 var(--space-3);
padding: 0;
}
.member-seats__item {
background: var(--color-surface-muted, rgba(127, 127, 127, 0.12));
border-radius: var(--radius-sm, 0.375rem);
padding: var(--space-1) var(--space-2);
font-size: 0.875rem;
}
.member-add {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.member-add__field {
display: flex;
flex-direction: column;
gap: var(--space-1);
font-size: 0.875rem;
}
.member-add__quota-full {
flex-basis: 100%;
color: var(--color-danger);
margin: 0;
font-size: 0.875rem;
}
.member-search {
width: 100%;
margin-bottom: var(--space-3);
}
.member-group {
margin-bottom: var(--space-4);
}
.member-group__title {
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-muted);
margin: 0 0 var(--space-2);
}
.member-group__list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.member-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
padding: var(--space-2);
border: 1px solid var(--color-border, rgba(127, 127, 127, 0.25));
border-radius: var(--radius-sm, 0.375rem);
}
.member-row__username,
.member-row__owner-badge {
color: var(--color-text-muted);
}
.member-row__actions {
display: flex;
align-items: center;
gap: var(--space-2);
}
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.label-manager__description {
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.label-manager__new-root {
display: flex;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.label-manager__error {
color: var(--color-danger);
margin-bottom: var(--space-3);
}
.label-manager__empty {
color: var(--color-text-muted);
}
.label-tree {
list-style: none;
margin: 0;
padding: 0;
}
.label-tree .label-tree {
margin-left: var(--space-4);
border-left: 1px solid var(--color-border);
padding-left: var(--space-3);
}
.label-node {
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
padding: var(--space-1) 0;
}
.label-node__swatch {
display: inline-block;
width: 0.9rem;
height: 0.9rem;
border-radius: 50%;
border: 1px solid var(--color-border);
flex: 0 0 auto;
}
.label-node__name {
font-weight: 600;
}
.label-node__actions {
display: flex;
align-items: center;
gap: var(--space-2);
margin-left: auto;
}
.label-node__color {
width: 1.75rem;
height: 1.5rem;
padding: 0;
border: 1px solid var(--color-border);
border-radius: var(--radius);
background: none;
cursor: pointer;
}
.label-node__delete {
color: var(--color-danger);
}
.label-tree__child-form {
display: flex;
gap: var(--space-2);
margin: var(--space-1) 0 var(--space-2) var(--space-4);
}
/* Page label picker panel. */
.label-picker {
flex: 0 0 20rem;
max-width: 20rem;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm, 4px);
padding: var(--space-3);
max-height: 80vh;
overflow-y: auto;
}
.label-picker__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--space-2);
}
.label-picker__search {
width: 100%;
margin-bottom: var(--space-2);
}
.label-picker__list {
list-style: none;
margin: 0;
padding: 0;
}
.label-picker__option {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) 0;
cursor: pointer;
}
.label-picker__empty {
color: var(--color-text-muted);
}
/* Manual page reordering (issue #45) ----------------------------------- */
.sidebar__page-item {
display: flex;
align-items: center;
gap: var(--space-1);
}
.sidebar__page-item .sidebar__page {
flex: 1 1 auto;
min-width: 0;
}
.sidebar__page-item--draggable {
cursor: grab;
}
.sidebar__reorder {
display: inline-flex;
gap: 2px;
flex: 0 0 auto;
}
.sidebar__reorder-btn {
border: 1px solid var(--color-border);
background: var(--color-bg);
border-radius: var(--radius);
color: var(--color-text-muted);
width: 1.4rem;
height: 1.4rem;
line-height: 1;
cursor: pointer;
padding: 0;
}
.sidebar__reorder-btn:disabled {
opacity: 0.35;
cursor: default;
}
.sidebar__reorder-btn:not(:disabled):hover {
background: var(--color-bg-subtle);
color: var(--color-text);
}
/* Wikilinks (issue #46) ------------------------------------------------- */
.wikilink-nodeview {
display: inline;
}
.wikilink {
color: var(--color-accent);
text-decoration: none;
border-bottom: 1px solid transparent;
cursor: pointer;
}
.wikilink:hover {
border-bottom-color: currentColor;
}
/* A link to a page that does not exist yet. */
.wikilink--phantom {
color: var(--color-text-muted);
border-bottom: 1px dashed currentColor;
}
.wikilink-suggest {
list-style: none;
margin: 0;
padding: var(--space-1);
min-width: 14rem;
max-width: 22rem;
max-height: 16rem;
overflow-y: auto;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: 0 4px 16px rgb(0 0 0 / 12%);
z-index: 30;
}
.wikilink-suggest__item {
display: block;
width: 100%;
text-align: left;
padding: var(--space-1) var(--space-2);
border: 0;
border-radius: var(--radius);
background: none;
color: var(--color-text);
cursor: pointer;
font-size: 0.95rem;
}
.wikilink-suggest__item.is-active,
.wikilink-suggest__item:hover {
background: var(--color-bg-subtle);
}
/* Backlinks + missing pages (issue #48) --------------------------------- */
.backlinks {
margin-top: var(--space-6);
border-top: 1px solid var(--color-border);
padding-top: var(--space-3);
}
.backlinks > summary {
cursor: pointer;
font-weight: 600;
color: var(--color-text-muted);
}
.backlinks__list {
list-style: none;
margin: var(--space-2) 0 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.backlinks__link {
font-weight: 600;
}
.backlinks__snippet {
margin: 2px 0 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
.phantom-pages__description {
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.phantom-pages__empty {
color: var(--color-text-muted);
}
.phantom-pages__list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.phantom-pages__head {
display: flex;
align-items: center;
gap: var(--space-3);
}
.phantom-pages__slug {
font-family: var(--font-mono);
background: var(--color-bg-subtle);
padding: 2px var(--space-2);
border-radius: var(--radius);
}
.phantom-pages__referrers {
margin: var(--space-1) 0 0;
color: var(--color-text-muted);
font-size: 0.9rem;
}
/* Search palette (issue #50) -------------------------------------------- */
.topbar__search {
display: inline-flex;
align-items: center;
gap: var(--space-1);
border: 1px solid var(--color-border);
background: var(--color-bg-subtle);
border-radius: var(--radius);
padding: var(--space-1) var(--space-3);
color: var(--color-text-muted);
cursor: pointer;
font-size: 0.9rem;
}
.topbar__search:hover {
background: var(--color-bg);
color: var(--color-text);
}
.search-overlay {
position: fixed;
inset: 0;
z-index: 100;
display: flex;
justify-content: center;
align-items: flex-start;
padding-top: 10vh;
}
.search-backdrop {
position: absolute;
inset: 0;
background: rgb(0 0 0 / 35%);
}
.search-palette {
position: relative;
width: min(40rem, 92vw);
max-height: 75vh;
overflow-y: auto;
background: var(--color-bg);
border: 1px solid var(--color-border);
border-radius: var(--radius);
box-shadow: 0 12px 40px rgb(0 0 0 / 25%);
padding: var(--space-3);
}
.search-palette__input {
width: 100%;
font-size: 1.1rem;
padding: var(--space-2);
}
.search-palette__scope {
display: flex;
align-items: center;
gap: var(--space-4);
margin: var(--space-2) 0;
font-size: 0.9rem;
color: var(--color-text-muted);
}
.search-palette__labels ul {
list-style: none;
margin: var(--space-1) 0 0;
padding: 0;
max-height: 10rem;
overflow-y: auto;
}
.search-palette__labels label {
display: flex;
align-items: center;
gap: var(--space-2);
padding: 2px 0;
}
.search-palette__hint {
color: var(--color-text-muted);
padding: var(--space-3);
text-align: center;
}
.search-palette__recent ul {
list-style: none;
margin: 0;
padding: 0;
}
.search-palette__recent li {
padding: var(--space-1) var(--space-2);
}
.search-results {
list-style: none;
margin: 0;
padding: 0;
}
.search-result {
display: block;
width: 100%;
text-align: left;
border: 0;
background: none;
border-radius: var(--radius);
padding: var(--space-2);
cursor: pointer;
color: var(--color-text);
}
.search-result--active,
.search-result:hover {
background: var(--color-bg-subtle);
}
.search-result__title {
font-weight: 600;
margin-right: var(--space-2);
}
.search-result__pond {
color: var(--color-text-muted);
font-size: 0.85rem;
}
.search-result__snippet {
display: block;
margin-top: 2px;
color: var(--color-text-muted);
font-size: 0.9rem;
}
.search-result__snippet mark {
background: var(--color-accent);
color: var(--color-accent-contrast);
border-radius: 2px;
padding: 0 2px;
}
/* Access rules (issue #55) */
.access-rules__intro,
.access-rules__empty {
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.rule-add {
border: 1px solid var(--color-border, rgba(127, 127, 127, 0.25));
border-radius: var(--radius-sm, 0.375rem);
padding: var(--space-3);
margin-bottom: var(--space-4);
}
.rule-add__title {
margin: 0 0 var(--space-2);
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-muted);
}
.rule-add__row {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-bottom: var(--space-2);
}
.rule-add__field {
display: flex;
flex-direction: column;
gap: var(--space-1);
font-size: 0.875rem;
}
.rule-add__public-warning {
display: flex;
align-items: center;
gap: var(--space-2);
}
.rule-groups,
.rule-group__list {
list-style: none;
margin: 0;
padding: 0;
}
.rule-group {
margin-bottom: var(--space-3);
}
.rule-group__subject {
margin: 0 0 var(--space-1);
font-size: 0.9375rem;
}
.rule-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
padding: var(--space-1) 0;
}
/* Public read-only page view (issue #56) */
.public-page {
max-width: 48rem;
margin: 0 auto;
}
.public-page__badge {
display: inline-block;
padding: var(--space-1) var(--space-2);
border-radius: 999px;
background: var(--color-bg-subtle);
border: 1px solid var(--color-border);
font-size: 0.8rem;
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.public-page__pond {
color: var(--color-text-muted);
font-size: 0.9rem;
margin: 0;
}
.public-page__body img {
max-width: 100%;
height: auto;
}
/* Effective-permissions inspector (issue #57) */
.inspector__intro {
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.inspector__controls {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
margin-bottom: var(--space-3);
}
.inspector__field {
display: flex;
flex-direction: column;
gap: var(--space-1);
font-size: 0.875rem;
}
.inspector__result {
margin: 0;
}
.inspector__outcome {
display: flex;
gap: var(--space-2);
padding: var(--space-2);
border-left: 3px solid var(--color-border);
margin-bottom: var(--space-2);
}
.inspector__outcome dt {
min-width: 5rem;
font-weight: 600;
}
.inspector__outcome dd {
margin: 0;
}
.inspector__outcome--allow {
border-left-color: var(--color-ok);
}
.inspector__outcome--deny {
border-left-color: var(--color-danger);
}
.inspector__reason {
color: var(--color-text-muted);
}
/* Quota override manager (issue #58) */
.quota-manager__lookup {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.quota-manager__subject {
font-weight: 600;
margin-bottom: var(--space-2);
}
.quota-row__override {
display: flex;
align-items: center;
gap: var(--space-2);
}
.quota-row__input {
width: 8rem;
}
.quota-row--over .quota-row__usage {
color: var(--color-danger);
}
.quota-row__flag {
color: var(--color-danger);
}
/* User management (issue #59) */
.user-manager__search {
width: 100%;
margin-bottom: var(--space-3);
}
.user-row__username,
.user-row__email {
color: var(--color-text-muted);
font-size: 0.85rem;
}
.user-row__actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
}
.user-row__delete-confirm {
color: var(--color-danger);
font-weight: 600;
}
.user-manager__pager {
display: flex;
align-items: center;
gap: var(--space-3);
margin-top: var(--space-3);
}
/* Attachments: page section + pond file manager (issue #61) */
.attachments-panel {
border: 1px solid var(--color-border);
border-radius: var(--radius-sm, 0.375rem);
padding: var(--space-3);
margin-bottom: var(--space-3);
background: var(--color-surface-muted, rgba(127, 127, 127, 0.06));
}
.attachments-panel__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-2);
margin-bottom: var(--space-2);
}
.attachments-panel__header h3 {
margin: 0;
}
.attachments-panel__upload {
display: flex;
align-items: center;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.attachments-panel__input {
display: none;
}
.attachments-panel__empty,
.pond-file-manager__empty {
color: var(--color-text-muted);
}
.attachments-panel__list,
.pond-file-manager__list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.attachments-item {
display: flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-1) 0;
flex-wrap: wrap;
}
.attachments-item__glyph {
font-size: 1.1rem;
}
.attachments-item__name {
font-weight: 600;
}
.attachments-item__meta {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.attachments-item__orphan {
color: var(--color-danger, #b91c1c);
font-style: italic;
}
.attachments-item__actions {
margin-left: auto;
display: flex;
gap: var(--space-2);
}
.pond-file-manager__usage {
color: var(--color-text-muted);
margin-bottom: var(--space-2);
}
/* --- Plugin sandbox frames (issue #73) ------------------------------------ */
.plugin-frame-host__mount .plugin-frame {
display: block;
width: 100%;
height: 120px;
border: none;
background: transparent;
}
.plugin-frame-host[data-state='failed'] .plugin-frame-host__mount {
display: none;
}
.plugin-frame-host__status {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.plugin-frame-host__status--failed {
color: var(--color-danger, #b91c1c);
border: 1px dashed var(--color-danger, #b91c1c);
border-radius: 4px;
padding: var(--space-2);
}
.plugin-preview__version {
color: var(--color-text-muted);
font-size: 1rem;
font-weight: 400;
}
.plugin-preview__surface {
margin-top: var(--space-4);
}
/* --- Plugin administration (issue #72) ------------------------------------ */
.plugin-manager__upload-input {
display: none;
}
.plugin-manager__list {
list-style: none;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.plugin-manager__item {
border: 1px solid var(--color-border);
border-radius: 6px;
padding: var(--space-3);
}
.plugin-manager__head {
display: flex;
align-items: baseline;
gap: var(--space-2);
}
.plugin-manager__name {
font-weight: 600;
}
.plugin-manager__version,
.plugin-manager__kind {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.plugin-manager__permissions {
margin: var(--space-2) 0;
font-size: 0.875rem;
}
.plugin-manager__permission {
margin-right: var(--space-1);
}
.plugin-manager__controls {
display: flex;
align-items: center;
gap: var(--space-3);
flex-wrap: wrap;
}
.plugin-manager__mode-hint {
color: var(--color-text-muted);
font-size: 0.8125rem;
}
.pond-plugins__list {
list-style: none;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.pond-plugins__version {
color: var(--color-text-muted);
font-size: 0.875rem;
}
/* Site-Admin system panel (issue #86) */
.system-badge {
display: inline-block;
padding: 0.1rem 0.5rem;
border-radius: 999px;
font-size: 0.8125rem;
background: var(--color-surface-muted, #e2e8f0);
margin-left: var(--space-1);
}
.system-badge--ok {
background: #d6f2df;
color: #1d6f42;
}
.system-badge--error {
background: #fbe3e0;
color: #a02818;
}
.system-badge--warn {
background: #fdf0d4;
color: #8a5a00;
}
.system-jobs__notice {
color: var(--color-text-muted);
}
.system-backup__facts dt {
font-weight: 600;
margin-top: var(--space-2);
}
.system-backup__facts dd {
margin: 0;
}
.system-backup__retention,
.system-backup__unavailable {
color: var(--color-text-muted);
}
/* Backup settings + in-app restore (issue #103) */
.system-backup__settings,
.system-backup__restore {
margin-top: var(--space-4);
padding-top: var(--space-3);
border-top: 1px solid var(--color-border, #cbd5e1);
}
.system-backup__settings label,
.system-backup__confirm label {
display: block;
margin-top: var(--space-2);
font-weight: 600;
}
.system-backup__settings input[type='text'],
.system-backup__settings input[type='url'],
.system-backup__settings input[type='password'],
.system-backup__settings input[type='number'],
.system-backup__settings select,
.system-backup__confirm input[type='text'] {
display: block;
margin-top: var(--space-1);
width: min(28rem, 100%);
}
.system-backup__checkbox,
.system-backup__settings .system-backup__checkbox {
font-weight: 600;
}
.system-backup__checkbox input {
margin-right: var(--space-1);
}
.system-backup__nextcloud {
border: none;
padding: 0;
margin: 0;
}
.system-backup__nextcloud:disabled {
opacity: 0.5;
}
.system-backup__hint {
color: var(--color-text-muted);
font-size: 0.875rem;
margin: var(--space-1) 0;
}
.system-backup__notice--error {
color: var(--color-danger);
}
.system-backup__warning {
color: var(--color-danger);
font-weight: 600;
}
.system-backup__sets {
list-style: none;
padding: 0;
margin: var(--space-1) 0;
}
.system-backup__save,
.system-backup__test {
margin-top: var(--space-3);
}
.system-backup__restore-status--failed {
color: var(--color-danger);
}
.button--danger {
border-color: var(--color-danger);
background: var(--color-danger);
color: var(--color-accent-contrast);
}
.button--danger:hover:not(:disabled) {
background: #8a0718;
}
/* Pond creation form in the switcher + pond danger zone */
.pond-switcher__create {
display: block;
width: 100%;
text-align: left;
border: none;
border-top: 1px solid var(--color-border);
background: none;
padding: var(--space-2) var(--space-3);
cursor: pointer;
font: inherit;
color: var(--color-accent);
}
.pond-switcher__form {
padding: var(--space-3);
min-width: 18rem;
}
.pond-switcher__form label {
display: block;
margin-top: var(--space-2);
font-weight: 600;
}
.pond-switcher__form input {
display: block;
width: 100%;
margin-top: var(--space-1);
box-sizing: border-box;
}
.pond-switcher__hint {
color: var(--color-text-muted);
font-size: 0.85rem;
}
.pond-switcher__actions {
display: flex;
gap: var(--space-2);
margin-top: var(--space-2);
}
.pond-delete {
border-top: 1px solid var(--color-border);
margin-top: var(--space-6);
padding-top: var(--space-4);
}
.pond-delete__hint {
color: var(--color-text-muted);
}
.pond-delete label {
display: block;
font-weight: 600;
margin: var(--space-2) 0;
}
.pond-delete input {
display: block;
margin-top: var(--space-1);
width: min(24rem, 100%);
}
.pond-delete__submit {
margin-top: var(--space-2);
}
/* API tokens (issue #104) */
.api-tokens__create label {
display: block;
margin-top: var(--space-2);
font-weight: 600;
}
.api-tokens__create input[type='text'],
.api-tokens__create input[type='date'],
.api-tokens__create select {
display: block;
margin-top: var(--space-1);
width: min(24rem, 100%);
}
.api-tokens__ponds {
border: none;
padding: 0;
margin: var(--space-2) 0;
}
.api-tokens__ponds legend {
font-weight: 600;
padding: 0;
}
.api-tokens__pond {
display: block;
font-weight: 400 !important;
margin-top: var(--space-1) !important;
}
.api-tokens__pond input {
margin-right: var(--space-1);
}
.api-tokens__create .button {
margin-top: var(--space-2);
}
.api-tokens__created {
margin-top: var(--space-3);
padding: var(--space-3);
border: 1px solid var(--color-border, #cbd5e1);
border-radius: 8px;
}
.api-tokens__secret {
display: block;
margin: var(--space-2) 0;
word-break: break-all;
user-select: all;
}
.api-tokens__intro,
.api-tokens__hint,
.api-opt-in__hint {
color: var(--color-text-muted);
}
.api-tokens__table {
margin-top: var(--space-3);
}
.api-opt-in__label input {
margin-right: var(--space-1);
}
/* Fullscreen plugin surface (ui.enterFullscreen — drawio-class editors):
covers the whole viewport, above every app layer, until the plugin exits
or the surface is destroyed. */
.plugin-block__mount .plugin-frame.plugin-frame--fullscreen,
.plugin-frame.plugin-frame--fullscreen {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh !important;
z-index: 1000;
border: none;
border-radius: 0;
background: var(--color-surface, #fff);
}
/* Maintenance screen during an in-app restore (issue #103) */
.maintenance-page {
max-width: 32rem;
margin: 15vh auto 0;
padding: var(--space-4);
text-align: center;
}
.maintenance-page__error {
color: var(--color-danger);
}
.system-audit__filters {
display: flex;
gap: var(--space-2);
flex-wrap: wrap;
margin-bottom: var(--space-3);
}
.system-audit__table code,
.system-storage__table code {
font-size: 0.8125rem;
word-break: break-all;
}
.system-audit__pager {
display: flex;
align-items: center;
gap: var(--space-3);
margin-top: var(--space-3);
}
/* Comments panel (issue #92) */
.comments-panel {
border: 1px solid var(--color-border, #cbd5e1);
border-radius: 8px;
padding: var(--space-3);
margin: var(--space-3) 0;
background: var(--color-surface, #fff);
}
.comments-panel__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-2);
}
.comments-panel__header h2 {
margin: 0;
font-size: 1.1rem;
}
.comments-panel__count {
margin-left: var(--space-2);
font-size: 0.8125rem;
background: var(--color-surface-muted, #e2e8f0);
border-radius: 999px;
padding: 0.05rem 0.5rem;
}
.comments-panel__policy-hint,
.comments-panel__empty {
color: var(--color-text-muted);
}
.comments-panel__threads {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.comments-panel__resolved {
margin-top: var(--space-3);
}
.comments-panel__resolved > summary {
cursor: pointer;
color: var(--color-text-muted);
}
.comments-panel__resolved > .comments-panel__threads {
margin-top: var(--space-2);
}
.comments-thread {
border-top: 1px solid var(--color-border, #e2e8f0);
padding-top: var(--space-2);
}
.comments-thread--resolved {
opacity: 0.75;
}
.comments-thread__replies {
list-style: none;
margin: var(--space-2) 0 0;
padding-left: var(--space-4);
border-left: 2px solid var(--color-border, #e2e8f0);
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.comment__meta {
display: flex;
gap: var(--space-2);
align-items: baseline;
font-size: 0.8125rem;
color: var(--color-text-muted);
}
.comment__author {
font-weight: 600;
color: var(--color-text, inherit);
}
.comment__body p {
margin: var(--space-1) 0;
}
.comment__actions {
display: flex;
gap: var(--space-3);
}
.comments-link-button {
background: none;
border: none;
padding: 0;
color: var(--color-primary, #2f6f4f);
cursor: pointer;
font-size: 0.8125rem;
text-decoration: underline;
}
.comments-composer textarea {
width: 100%;
resize: vertical;
}
.comments-composer__footer {
display: flex;
align-items: center;
gap: var(--space-3);
margin-top: var(--space-1);
}
.comments-composer__hint {
flex: 1;
font-size: 0.75rem;
color: var(--color-text-muted);
}
.comments-unread-badge {
margin-left: var(--space-1);
font-size: 0.75rem;
background: var(--color-primary, #2f6f4f);
color: #fff;
border-radius: 999px;
padding: 0.05rem 0.45rem;
}
.comment-policy__label {
display: flex;
align-items: center;
gap: var(--space-2);
}
.comment-policy__hint {
color: var(--color-text-muted);
font-size: 0.8125rem;
}
/* Watches (issue #93) */
.watch-toggle--active {
background: var(--color-primary, #2f6f4f);
color: #fff;
}
.watches-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.watches-list li {
display: flex;
align-items: center;
gap: var(--space-3);
}
.watches-list__type {
color: var(--color-text-muted);
font-size: 0.8125rem;
}
.settings-checkbox {
display: flex;
align-items: center;
gap: var(--space-2);
margin: var(--space-2) 0;
}
.pond-settings-page__header {
display: flex;
align-items: center;
gap: var(--space-3);
}
/* Notification center (issue #94) */
.notifications-bell {
position: relative;
}
.notifications-bell__button {
background: none;
border: none;
cursor: pointer;
font-size: 1.1rem;
position: relative;
padding: var(--space-1);
}
.notifications-bell__badge {
position: absolute;
top: -2px;
right: -4px;
background: #a02818;
color: #fff;
border-radius: 999px;
font-size: 0.7rem;
padding: 0 0.35rem;
line-height: 1.2rem;
}
.notifications-bell__dropdown {
position: absolute;
right: 0;
top: 100%;
z-index: 30;
width: 22rem;
max-height: 24rem;
overflow-y: auto;
background: var(--color-surface, #fff);
border: 1px solid var(--color-border, #cbd5e1);
border-radius: 8px;
box-shadow: 0 6px 24px rgb(0 0 0 / 0.12);
padding: var(--space-2);
}
.notifications-bell__header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-2);
font-weight: 600;
}
.notifications-bell__empty {
color: var(--color-text-muted);
margin: var(--space-2) 0;
}
.notifications-bell__list {
list-style: none;
margin: 0;
padding: 0;
}
.notifications-bell__entry {
display: flex;
flex-direction: column;
gap: 2px;
width: 100%;
text-align: left;
background: none;
border: none;
border-top: 1px solid var(--color-border, #e2e8f0);
padding: var(--space-2);
cursor: pointer;
}
.notifications-bell__entry--unread {
font-weight: 600;
}
.notifications-bell__entry time {
color: var(--color-text-muted);
font-size: 0.75rem;
font-weight: 400;
}