Files
backlog/web/styles.css
T
2026-08-28 19:47:46 +02:00

1514 lines
57 KiB
CSS

/* Personal Backlog — paper-like editor aesthetic */
:root {
--accent-hue: 35;
--accent: oklch(0.62 0.13 var(--accent-hue));
--accent-soft: oklch(0.62 0.13 var(--accent-hue) / 0.10);
--accent-edge: oklch(0.62 0.13 var(--accent-hue) / 0.35);
--accent-deep: oklch(0.48 0.14 var(--accent-hue));
--bg: oklch(0.985 0.005 80);
--bg-2: oklch(0.97 0.006 80);
--paper: oklch(0.99 0.004 80);
--ink: oklch(0.22 0.012 60);
--ink-2: oklch(0.42 0.012 60);
--ink-3: oklch(0.62 0.012 60);
--rule: oklch(0.91 0.008 70);
--rule-2: oklch(0.95 0.006 70);
--status-open: oklch(0.55 0.005 60);
--status-progress: oklch(0.55 0.13 220);
--status-blocked: oklch(0.58 0.16 25);
--status-postponed: oklch(0.68 0.15 60);
--status-done: oklch(0.55 0.12 145);
--status-cancelled: oklch(0.5 0.012 60);
--warn: oklch(0.7 0.13 80);
--warn-bg: oklch(0.94 0.05 85);
--ok: oklch(0.6 0.12 145);
--danger: oklch(0.58 0.16 25);
--danger-soft: oklch(0.58 0.16 25 / 0.08);
--font-sans: "Inter", system-ui, -apple-system, "Helvetica Neue", Helvetica, Arial, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
--radius: 6px;
--radius-lg: 10px;
--shadow-1: 0 1px 0 oklch(0.91 0.008 70);
--shadow-2: 0 1px 2px oklch(0.22 0.012 60 / 0.06), 0 4px 14px oklch(0.22 0.012 60 / 0.05);
--shadow-pop: 0 8px 24px oklch(0.22 0.012 60 / 0.14), 0 2px 6px oklch(0.22 0.012 60 / 0.08);
--row-h: 36px;
--row-pad-y: 7px;
}
html[data-density="compact"] { --row-h: 28px; --row-pad-y: 4px; }
/* ---------- Dark theme ---------- */
html[data-theme="dark"] {
--bg: oklch(0.19 0.008 60);
--bg-2: oklch(0.23 0.009 60);
--paper: oklch(0.215 0.008 60);
--ink: oklch(0.93 0.006 70);
--ink-2: oklch(0.74 0.006 70);
--ink-3: oklch(0.56 0.008 70);
--rule: oklch(0.32 0.012 70);
--rule-2: oklch(0.27 0.010 70);
--status-open: oklch(0.72 0.008 60);
--status-progress: oklch(0.68 0.13 220);
--status-blocked: oklch(0.66 0.16 25);
--status-postponed: oklch(0.74 0.14 60);
--status-done: oklch(0.66 0.12 145);
--status-cancelled: oklch(0.55 0.012 60);
--warn: oklch(0.78 0.13 80);
--warn-bg: oklch(0.30 0.06 80);
--ok: oklch(0.7 0.12 145);
--danger: oklch(0.66 0.16 25);
--danger-soft: oklch(0.66 0.16 25 / 0.14);
--shadow-1: 0 1px 0 oklch(0 0 0 / 0.4);
--shadow-2: 0 1px 2px oklch(0 0 0 / 0.4), 0 4px 14px oklch(0 0 0 / 0.35);
--shadow-pop: 0 8px 24px oklch(0 0 0 / 0.55), 0 2px 6px oklch(0 0 0 / 0.45);
}
html[data-theme="dark"] .header { background: oklch(0.19 0.008 60 / 0.86); }
html[data-theme="dark"] .row:hover { background: oklch(0.27 0.010 60 / 0.6); }
html[data-theme="dark"] .btn-primary:hover:not(:disabled),
html[data-theme="dark"] .row-btn.primary:hover { background: oklch(0.85 0.008 70); color: var(--bg); }
html[data-theme="dark"] .banner.info { background: oklch(0.30 0.06 220); color: oklch(0.85 0.04 220); }
html[data-theme="dark"][data-paper="true"] body {
background-image: radial-gradient(oklch(0.55 0.008 70 / 0.18) 1px, transparent 1px);
}
html[data-theme="dark"] .restore-warn {
background: oklch(0.28 0.06 80);
border-color: oklch(0.45 0.10 80 / 0.6);
color: oklch(0.85 0.06 75);
}
html[data-theme="dark"] .restore-warn svg { color: oklch(0.78 0.13 70); }
html[data-theme="dark"] .restore-warn-title { color: oklch(0.92 0.05 75); }
html[data-theme="dark"] .restore-warn-body { color: oklch(0.78 0.04 70); }
html[data-theme="dark"] .restore-warn-body code { background: oklch(0 0 0 / 0.30); }
html[data-theme="dark"] .drag-handle { color: oklch(0.50 0.005 60); }
html[data-theme="dark"] .rte-toolbar { background: oklch(0.25 0.010 60); }
html[data-theme="dark"] .rte-code-block,
html[data-theme="dark"] .rte-inline-code { background: oklch(0.25 0.010 60); }
html[data-theme="dark"] .rte-table th { background: oklch(0.25 0.010 60); }
html[data-theme="dark"] .rte-table td { background: oklch(0.22 0.008 60); }
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
font-family: var(--font-sans);
color: var(--ink);
background: var(--bg);
font-size: 14px;
line-height: 1.45;
-webkit-font-smoothing: antialiased;
}
html[data-paper="true"] body {
background-image: radial-gradient(oklch(0.91 0.008 70 / 0.35) 1px, transparent 1px);
background-size: 22px 22px;
}
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
button:focus-visible { outline: 2px solid var(--accent-edge); outline-offset: 2px; border-radius: 3px; }
button:disabled { cursor: not-allowed; opacity: 0.4; }
input { font: inherit; color: inherit; }
.mono { font-family: var(--font-mono); }
.small { font-size: 12px; }
.muted { color: var(--ink-3); }
/* ---------- App shell ---------- */
.app { min-height: 100vh; height: 100vh; display: flex; flex-direction: column; }
/* ---------- Header ---------- */
.header {
display: grid;
grid-template-columns: auto auto 1fr auto;
gap: 24px;
align-items: center;
padding: 14px 24px;
border-bottom: 1px solid var(--rule);
background: oklch(0.985 0.005 80 / 0.86);
backdrop-filter: saturate(1.4) blur(8px);
flex-shrink: 0;
z-index: 50;
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand-glyph { display: inline-flex; align-items: center; color: var(--accent); }
.brand-name { font-weight: 600; font-size: 15px; letter-spacing: -0.01em; }
.brand-sub {
font-size: 12px; color: var(--ink-3);
padding-left: 10px; border-left: 1px solid var(--rule); margin-left: 4px;
}
.tabs { display: flex; gap: 2px; }
.tab {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 12px; border-radius: var(--radius);
font-size: 13px; color: var(--ink-2); font-weight: 500;
}
.tab:hover { background: var(--bg-2); color: var(--ink); }
.tab.active { background: var(--ink); color: var(--bg); }
.search-wrap {
display: flex; align-items: center; gap: 8px;
padding: 7px 12px;
background: var(--paper);
border: 1px solid var(--rule); border-radius: var(--radius);
color: var(--ink-3);
max-width: 480px; width: 100%; justify-self: start;
}
.search-wrap:focus-within {
border-color: var(--accent-edge);
box-shadow: 0 0 0 3px var(--accent-soft);
color: var(--ink);
}
.search-input { flex: 1; border: 0; background: transparent; outline: 0; color: var(--ink); font-size: 13px; }
.search-input::placeholder { color: var(--ink-3); }
.search-clear {
width: 18px; height: 18px;
display: grid; place-items: center;
border-radius: 50%; color: var(--ink-3); font-size: 14px; line-height: 1;
}
.search-clear:hover { background: var(--bg-2); color: var(--ink); }
.header-right { display: flex; align-items: center; gap: 14px; }
.header-btn {
display: inline-flex; align-items: center; gap: 6px;
padding: 6px 10px; border-radius: var(--radius);
font-size: 12.5px; color: var(--ink-2);
border: 1px solid var(--rule); background: var(--paper);
}
.header-btn:hover { background: var(--bg-2); color: var(--ink); }
.save-indicator { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-3); font-family: var(--font-mono); }
.save-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); }
.save-dot.saving { background: var(--accent); animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: 0.4; } }
/* ---------- Banner ---------- */
.banner { display: flex; align-items: center; gap: 10px; padding: 9px 24px; font-size: 13px; border-bottom: 1px solid var(--rule); }
.banner.warn { background: var(--warn-bg); color: oklch(0.35 0.12 60); }
.banner.info { background: oklch(0.96 0.01 220); color: oklch(0.35 0.05 220); }
.banner-close { margin-left: auto; font-size: 12px; color: inherit; text-decoration: underline; text-underline-offset: 3px; }
/* ---------- Main layout ---------- */
.main { display: grid; grid-template-columns: 240px 1fr; flex: 1; min-height: 0; }
/* ---------- Filter panel ---------- */
.filter-panel {
border-right: 1px solid var(--rule);
padding: 22px 18px;
display: flex; flex-direction: column; gap: 22px;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.filter-section { display: flex; flex-direction: column; gap: 8px; }
.filter-label {
font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--ink-3); font-weight: 600;
}
.filter-list { display: flex; flex-direction: column; gap: 2px; }
.filter-list-row { flex-direction: row; gap: 6px; }
.filter-list-row.wrap { flex-wrap: wrap; }
.filter-chip {
display: flex; align-items: center; gap: 8px;
padding: 5px 8px; border-radius: 5px;
font-size: 13px; color: var(--ink-2); text-align: left;
}
.filter-chip:hover { background: var(--bg-2); color: var(--ink); }
.filter-chip.active { background: var(--accent-soft); color: var(--accent-deep); }
.filter-chip .filter-name { flex: 1; }
.filter-chip .filter-count { font-family: var(--font-mono); font-size: 11px; color: var(--ink-3); }
.filter-chip.active .filter-count { color: var(--accent-deep); }
.filter-chip.mini {
padding: 4px 10px; font-family: var(--font-mono); font-size: 12px; font-weight: 500;
border: 1px solid var(--rule); background: var(--paper);
}
.filter-chip.mini.active { border-color: var(--accent); background: var(--accent); color: var(--bg); }
.filter-chip.mini.pri-P0.active { background: var(--accent-deep); border-color: var(--accent-deep); }
.tag-chip {
font-family: var(--font-mono); font-size: 11.5px;
padding: 3px 8px; border-radius: 99px;
background: var(--bg-2); color: var(--ink-2);
border: 1px solid var(--rule);
display: inline-flex; align-items: center; gap: 3px;
}
.tag-chip:hover { background: var(--paper); color: var(--ink); }
.tag-chip.active { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.tag-chip .hl { color: var(--accent-deep); font-weight: 600; }
.tag-chip.active .hl { color: var(--bg); }
.tag-x { font-family: var(--font-sans); font-size: 13px; line-height: 1; opacity: 0.6; margin-left: 1px; }
.tag-chip:hover .tag-x { opacity: 1; }
.tag-total {
font-size: 10.5px; font-weight: 500;
color: var(--ink-3);
padding: 1px 6px; border-radius: 99px;
background: var(--bg-2); border: 1px solid var(--rule);
margin-left: 4px;
letter-spacing: 0;
}
.tag-selected { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 2px; }
.tag-search {
display: flex; align-items: center; gap: 6px;
padding: 6px 9px;
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--bg-2); color: var(--ink-3);
margin-bottom: 6px;
}
.tag-search.focused { border-color: var(--accent-edge); background: var(--paper); box-shadow: 0 0 0 3px var(--accent-soft); color: var(--ink); }
.tag-search-input { flex: 1; border: 0; background: transparent; outline: 0; font-size: 12.5px; color: var(--ink); padding: 0; min-width: 0; }
.tag-search-input::placeholder { color: var(--ink-3); }
.tag-search-clear { width: 16px; height: 16px; display: grid; place-items: center; border-radius: 50%; color: var(--ink-3); font-size: 14px; line-height: 1; flex-shrink: 0; }
.tag-search-clear:hover { background: var(--paper); color: var(--ink); }
.tag-results { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; max-height: 220px; overflow-y: auto; padding: 2px 0; }
.tag-empty { font-size: 11.5px; color: var(--ink-3); font-style: italic; padding: 4px 0; }
.tag-more { font-size: 10.5px; color: var(--ink-3); padding: 2px 4px; }
.clear-btn { padding: 6px 0; font-size: 12px; color: var(--accent-deep); text-align: left; text-decoration: underline; text-underline-offset: 3px; }
/* ---------- Content ---------- */
.content { min-width: 0; height: 100%; display: flex; flex-direction: column; overflow: hidden; }
.content-sticky {
flex-shrink: 0;
padding: 28px 32px 14px;
background: var(--bg);
border-bottom: 1px solid var(--rule-2);
}
.content-scroll {
flex: 1;
overflow-y: auto;
padding: 18px 32px 80px;
min-height: 0;
}
.content-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 14px; }
.content-head-actions { display: flex; align-items: center; gap: 12px; }
.eyebrow { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); font-weight: 600; margin-bottom: 4px; }
.content-title { font-size: 26px; font-weight: 600; letter-spacing: -0.015em; margin: 0; }
.btn-primary, .btn-secondary, .btn-danger {
display: inline-flex; align-items: center; gap: 6px;
padding: 8px 14px; border-radius: var(--radius);
font-size: 13px; font-weight: 500;
}
.btn-primary { background: var(--ink); color: var(--bg); }
.btn-primary:hover:not(:disabled) { background: oklch(0.15 0.012 60); }
.btn-secondary { background: var(--paper); color: var(--ink); border: 1px solid var(--rule); }
.btn-secondary:hover { background: var(--bg-2); }
.btn-danger { background: var(--danger); color: white; }
.btn-danger:hover { background: oklch(0.5 0.16 25); }
/* segmented control */
.seg { display: inline-flex; padding: 2px; background: var(--bg-2); border: 1px solid var(--rule); border-radius: var(--radius); }
.seg-mini { padding: 2px; }
.seg-btn {
padding: 5px 10px; border-radius: 4px;
font-size: 12px; color: var(--ink-2);
font-family: var(--font-mono); font-weight: 500;
transition: background 0.12s, color 0.12s;
}
.seg-btn:hover { color: var(--ink); }
.seg-btn.active { background: var(--paper); color: var(--ink); box-shadow: 0 1px 2px oklch(0.22 0.012 60 / 0.08); }
/* in dialogs the segmented control should fill the row + have a stronger active state */
.field .seg { width: 100%; height: 38px; padding: 3px; align-items: stretch; }
.field .seg .seg-btn { flex: 1; padding: 0 12px; display: inline-flex; align-items: center; justify-content: center; gap: 5px; }
.field .seg .seg-btn.active {
background: var(--paper);
color: var(--ink);
box-shadow: 0 0 0 1px var(--ink) inset, 0 1px 2px oklch(0.22 0.012 60 / 0.08);
font-weight: 600;
}
.field .seg .seg-btn.pri-P0.active {
background: var(--accent);
color: var(--bg);
box-shadow: 0 0 0 1px var(--accent) inset;
}
.field .seg .seg-btn.pri-P0.active .p0-dot { background: var(--bg); box-shadow: 0 0 0 2px oklch(0.62 0.13 var(--accent-hue) / 0.4); }
.legend {
display: flex; flex-wrap: wrap; align-items: center;
gap: 14px; padding: 10px 12px; margin-bottom: 0;
font-size: 12px; color: var(--ink-3);
border: 1px dashed var(--rule); border-radius: var(--radius);
background: var(--paper);
}
/* Saved view chips */
.view-chips {
display: flex; flex-wrap: wrap; gap: 4px;
margin: 12px 0 10px;
}
.view-chip {
padding: 6px 12px;
border-radius: 99px;
font-size: 12.5px; font-weight: 500;
color: var(--ink-2);
border: 1px solid var(--rule);
background: var(--paper);
transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.view-chip:hover { background: var(--bg-2); color: var(--ink); border-color: oklch(0.85 0.008 70); }
.view-chip.active {
background: var(--ink);
color: var(--bg);
border-color: var(--ink);
}
.legend-cap { font-weight: 600; color: var(--ink-2); letter-spacing: 0.04em; }
.legend-item { display: inline-flex; align-items: center; gap: 5px; color: var(--ink-2); }
.legend-sep { color: var(--rule); }
.legend-hint { margin-left: auto; }
.legend kbd {
font-family: var(--font-mono); font-size: 11px;
padding: 1px 6px;
border: 1px solid var(--rule); border-bottom-width: 2px; border-radius: 4px;
background: var(--paper); color: var(--ink-2);
}
/* ---------- Status icons (3 styles) ---------- */
.glyph-flat { display: inline-block; vertical-align: middle; }
.glyph-flat.status-open { color: var(--status-open); }
.glyph-flat.status-in-progress { color: var(--status-progress); }
.glyph-flat.status-blocked { color: var(--status-blocked); }
.glyph-flat.status-postponed { color: var(--status-postponed); }
.glyph-flat.status-done { color: var(--status-done); }
.glyph-flat.status-cancelled { color: var(--status-cancelled); }
.glyph-ascii {
font-family: var(--font-mono); font-size: 13px; font-weight: 500;
letter-spacing: -0.04em; display: inline-block; min-width: 26px; text-align: center;
}
.glyph-ascii.status-open { color: var(--status-open); }
.glyph-ascii.status-in-progress { color: var(--status-progress); font-weight: 600; }
.glyph-ascii.status-blocked { color: var(--status-blocked); font-weight: 600; }
.glyph-ascii.status-postponed { color: var(--status-postponed); }
.glyph-ascii.status-done { color: var(--status-done); }
.glyph-ascii.status-cancelled { color: var(--status-cancelled); text-decoration: line-through; text-decoration-thickness: 1px; }
.glyph-emoji {
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
line-height: 1;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
/* normalize size of the variation-selector pictographs */
font-variant-emoji: emoji;
}
.glyph-color { display: inline-block; vertical-align: middle; }
.restore-warn {
display: flex; gap: 10px;
margin-top: 12px;
padding: 10px 12px;
border-radius: var(--radius);
border: 1px solid oklch(0.82 0.13 85 / 0.6);
background: oklch(0.97 0.05 85);
color: oklch(0.36 0.10 70);
}
.restore-warn svg { flex-shrink: 0; margin-top: 2px; color: oklch(0.62 0.16 70); }
.restore-warn-title { font-weight: 600; font-size: 12.5px; margin-bottom: 3px; color: oklch(0.32 0.08 70); }
.restore-warn-body { font-size: 12px; line-height: 1.45; color: oklch(0.40 0.06 70); }
.restore-warn-body code { background: oklch(1 0 0 / 0.55); padding: 0 4px; border-radius: 3px; }
/* ---------- Tree rows ---------- */
.tree {
background: var(--paper);
border: 1px solid var(--rule);
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: var(--shadow-2);
}
.row {
display: flex; align-items: center; gap: 10px;
padding: var(--row-pad-y) 16px;
min-height: var(--row-h);
border-bottom: 1px solid var(--rule-2);
position: relative;
font-size: 13.5px;
}
.row:last-child { border-bottom: 0; }
.row:hover { background: oklch(0.985 0.005 80 / 0.7); }
.row.dimmed { opacity: 0.45; }
.row.drop-target { box-shadow: inset 0 2px 0 var(--accent); background: var(--accent-soft); }
.row.p0 { background: linear-gradient(90deg, var(--accent-soft) 0%, transparent 60%); }
.row.p0::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--accent); }
.level-0 .title { font-weight: 600; font-size: 14.5px; }
.level-1 .title { font-weight: 500; }
.level-2 .title, .level-3 .title { color: var(--ink-2); }
.row-rail { align-self: stretch; flex-shrink: 0; }
.twisty { width: 16px; height: 16px; display: grid; place-items: center; color: var(--ink-3); border-radius: 3px; flex-shrink: 0; }
.twisty:hover { background: var(--bg-2); color: var(--ink); }
.twisty.empty { visibility: hidden; }
.drag-handle { width: 14px; color: oklch(0.85 0.005 60); cursor: grab; flex-shrink: 0; opacity: 0; transition: opacity 0.15s; }
.row:hover .drag-handle { opacity: 1; }
/* status button + popover */
.status-wrap { position: relative; display: inline-flex; }
.status-btn {
display: inline-flex; align-items: center; justify-content: center;
width: 24px; height: 24px;
border-radius: 5px;
flex-shrink: 0;
}
.status-btn:hover { background: var(--bg-2); }
.status-pop {
position: absolute; top: calc(100% + 4px); left: 0;
z-index: 30; min-width: 180px;
padding: 4px;
background: var(--paper); border: 1px solid var(--rule);
border-radius: var(--radius); box-shadow: var(--shadow-pop);
}
.status-pop-item {
width: 100%; display: flex; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 4px;
font-size: 13px; color: var(--ink); text-align: left;
}
.status-pop-item:hover { background: var(--bg-2); }
.status-pop-item.active { background: var(--accent-soft); color: var(--accent-deep); }
/* priority button + popover */
.pri-wrap { position: relative; display: inline-flex; }
.pri {
font-family: var(--font-mono);
font-size: 11px; font-weight: 600;
color: var(--ink-3); letter-spacing: 0.04em;
flex-shrink: 0;
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 7px; border-radius: 4px;
border: 1px solid var(--rule); background: var(--paper);
}
.pri:hover { background: var(--bg-2); border-color: oklch(0.85 0.008 70); }
.pri-P0 { color: var(--accent-deep); border-color: var(--accent-edge); background: var(--accent-soft); }
.pri-P1 { color: var(--ink); }
.pri-P2 { color: var(--ink-2); }
.pri-P3 { color: var(--ink-3); }
.p0-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.pri-pop {
position: absolute; top: calc(100% + 4px); left: 0;
z-index: 30; min-width: 160px; padding: 4px;
background: var(--paper); border: 1px solid var(--rule);
border-radius: var(--radius); box-shadow: var(--shadow-pop);
}
.pri-pop-item {
width: 100%;
display: grid; grid-template-columns: 14px 32px 1fr; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 4px;
font-family: var(--font-mono); font-size: 12px;
color: var(--ink); text-align: left;
}
.pri-pop-item:hover { background: var(--bg-2); }
.pri-pop-item.active { background: var(--accent-soft); color: var(--accent-deep); }
.pri-pop-item .p0-dot { grid-column: 1; }
.pri-pop-hint { font-family: var(--font-sans); font-size: 11.5px; color: var(--ink-3); justify-self: end; }
.title { flex-shrink: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: text; }
.title.done { color: var(--ink-3); text-decoration: line-through; text-decoration-thickness: 1px; }
.title .hl { background: var(--accent-soft); color: var(--accent-deep); padding: 0 1px; border-radius: 2px; }
/* ---------- Progress gauge ---------- */
.gauge {
display: inline-flex; align-items: center; gap: 4px;
flex-shrink: 0;
padding: 1px 6px 1px 4px;
border-radius: 99px;
background: var(--bg-2);
border: 1px solid var(--rule);
user-select: none;
line-height: 1;
}
.gauge-seg {
display: inline-block;
width: 4px; height: 8px;
border-radius: 1px;
background: oklch(0.88 0.005 60);
transition: background 0.12s;
}
.gauge-seg.on { background: var(--status-progress); }
.gauge-num {
font-family: var(--font-mono);
font-size: 10.5px;
font-variant-numeric: tabular-nums;
color: var(--ink-3);
padding-left: 3px;
min-width: 26px;
text-align: right;
}
/* state-coloring: 100 = green, 0 = neutral, mid = blue (default) */
.gauge.gauge-v-100 .gauge-seg.on { background: var(--status-done); }
.gauge.gauge-v-100 .gauge-num { color: var(--status-done); }
.gauge.gauge-v-0 { border-style: dashed; }
.gauge.gauge-v-0 .gauge-num { color: var(--ink-3); }
/* row gauge: hover-emphasize when interactive */
.gauge-interactive { cursor: pointer; transition: background 0.12s, border-color 0.12s; }
.gauge-interactive:hover { background: var(--paper); border-color: var(--accent-edge); }
.gauge-interactive:focus-visible { outline: 2px solid var(--accent-edge); outline-offset: 2px; }
/* larger size for dialog */
.gauge-md { padding: 4px 10px 4px 7px; gap: 5px; }
.gauge-md .gauge-seg { width: 5px; height: 12px; }
.gauge-md .gauge-num { font-size: 12px; min-width: 32px; padding-left: 4px; }
/* dialog progress field */
.progress-row { display: flex; align-items: center; gap: 12px; }
.progress-seg { flex: 1; }
.progress-seg .seg-btn { font-family: var(--font-mono); }
.progress-seg.locked { opacity: 0.55; }
/* row dim adjustment: lower opacity for blocked-ish stuck rows */
.row .gauge { margin-left: 2px; }
.due { font-family: var(--font-mono); font-size: 11.5px; color: var(--ink-3); padding: 1px 6px; border-radius: 99px; background: var(--bg-2); flex-shrink: 0; }
.due.overdue { color: oklch(0.95 0.005 60); background: var(--status-blocked); font-weight: 500; }
.tags { display: inline-flex; gap: 4px; flex-shrink: 0; }
.tag { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-2); padding: 1px 6px; border-radius: 99px; border: 1px solid var(--rule); background: var(--paper); }
.reason { font-style: italic; font-size: 12px; color: var(--status-blocked); flex-shrink: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 240px; }
.row-spacer { flex: 1; min-width: 0; }
/* row action toolbar — bigger, distinct, labeled on hover */
.row-actions { display: flex; gap: 2px; flex-shrink: 0; opacity: 0; transition: opacity 0.15s; align-items: center; }
.row:hover .row-actions, .row:focus-within .row-actions { opacity: 1; }
.action-sep { width: 1px; height: 16px; background: var(--rule); margin: 0 4px; }
/* custom tooltip on icon buttons (instant, branded) */
.icon-btn { position: relative; }
.icon-btn[data-tip]::after {
content: attr(data-tip);
position: absolute;
top: calc(100% + 6px);
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
background: var(--ink);
color: var(--bg);
font-family: var(--font-sans);
font-size: 11.5px;
font-weight: 500;
padding: 4px 8px;
border-radius: 4px;
pointer-events: none;
opacity: 0;
transition: opacity 0.12s 0s;
z-index: 100;
box-shadow: 0 4px 12px oklch(0.22 0.012 60 / 0.2);
}
.icon-btn[data-tip]::before {
content: "";
position: absolute;
top: calc(100% + 1px);
left: 50%;
transform: translateX(-50%);
border: 4px solid transparent;
border-bottom-color: var(--ink);
pointer-events: none;
opacity: 0;
transition: opacity 0.12s 0s;
z-index: 100;
}
.icon-btn[data-tip]:hover::after,
.icon-btn[data-tip]:hover::before,
.icon-btn[data-tip]:focus-visible::after,
.icon-btn[data-tip]:focus-visible::before {
opacity: 1;
transition-delay: 0.35s;
}
.icon-btn {
width: 28px; height: 28px;
display: inline-grid; place-items: center;
border-radius: 5px;
color: var(--ink-2);
border: 1px solid transparent;
transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.icon-btn:hover:not(:disabled) {
background: var(--paper);
color: var(--ink);
border-color: var(--rule);
}
.icon-btn.danger:hover:not(:disabled) {
color: var(--danger);
background: var(--danger-soft);
border-color: oklch(0.58 0.16 25 / 0.3);
}
.empty-state { text-align: center; padding: 60px 20px; color: var(--ink-3); background: var(--paper); border: 1px dashed var(--rule); border-radius: var(--radius-lg); }
.empty-glyph { font-family: var(--font-mono); font-size: 36px; margin-bottom: 8px; color: var(--rule); }
/* ---------- Admin ---------- */
.admin { padding: 28px 32px 80px; max-width: 1280px; margin: 0 auto; width: 100%; overflow-y: auto; height: 100%; }
.admin-head { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 24px; }
.admin-head h2 { font-size: 26px; font-weight: 600; letter-spacing: -0.015em; margin: 0; }
.admin-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.card { background: var(--paper); border: 1px solid var(--rule); border-radius: var(--radius-lg); padding: 18px 20px; box-shadow: var(--shadow-2); }
.card.span-2 { grid-column: span 2; }
.card.span-3 { grid-column: span 3; }
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; gap: 10px; }
.card-head h3 { font-size: 14px; font-weight: 600; margin: 0; letter-spacing: -0.005em; }
.card-sub { font-size: 11.5px; color: var(--ink-3); }
.pill { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: 11px; font-weight: 500; padding: 2px 8px; border-radius: 99px; border: 1px solid var(--rule); }
.pill.mini { font-size: 10.5px; padding: 1px 6px; }
.pill.ok { color: var(--ok); border-color: var(--ok); background: oklch(0.95 0.04 145); }
.pill.warn { color: oklch(0.45 0.12 60); border-color: var(--warn); background: var(--warn-bg); }
.pill.neutral { color: var(--ink-2); background: var(--bg-2); }
.kv { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; margin: 0; }
.kv > div { display: flex; flex-direction: column; gap: 1px; padding: 6px 0; border-top: 1px dashed var(--rule); }
.kv > div:first-child, .kv > div:nth-child(2) { border-top: 0; padding-top: 0; }
.kv dt { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; margin: 0; }
.kv dd { margin: 0; font-size: 13px; color: var(--ink); }
.action-list { display: flex; flex-direction: column; gap: 6px; }
.action-btn { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border-radius: var(--radius); border: 1px solid var(--rule); background: var(--bg); font-size: 13px; text-align: left; line-height: 1.35; }
.action-btn:hover { background: var(--bg-2); border-color: oklch(0.85 0.008 70); }
.action-btn svg { flex-shrink: 0; margin-top: 2px; color: var(--ink-2); }
.action-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.action-label { font-weight: 500; color: var(--ink); font-size: 13px; }
.action-meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-3); letter-spacing: 0.01em; }
/* ---- Stats overview ---- */
.stats-card { display: flex; flex-direction: column; gap: 16px; }
.stats-head { flex-wrap: wrap; gap: 12px; }
.range-switch {
display: inline-flex; flex-wrap: wrap;
background: var(--bg);
border: 1px solid var(--rule);
border-radius: var(--radius);
padding: 2px;
gap: 1px;
}
.range-btn {
padding: 5px 10px;
font-size: 11.5px; font-weight: 500;
color: var(--ink-3);
border-radius: 4px;
white-space: nowrap;
transition: background 0.12s, color 0.12s;
}
.range-btn:hover { color: var(--ink-2); background: var(--bg-2); }
.range-btn.active { background: var(--ink); color: var(--bg); }
.kpi-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 1px;
background: var(--rule);
border: 1px solid var(--rule);
border-radius: var(--radius);
overflow: hidden;
}
.kpi {
background: var(--paper);
padding: 12px 14px;
display: flex; flex-direction: column; gap: 6px;
min-width: 0;
}
.kpi-accent { background: oklch(from var(--accent) l c h / 0.04); }
.kpi-label { font-size: 10.5px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; }
.kpi-value { font-family: var(--font-mono); font-size: 24px; font-weight: 500; letter-spacing: -0.02em; line-height: 1; color: var(--ink); }
.kpi-unit { font-size: 13px; color: var(--ink-3); margin-left: 2px; font-weight: 400; }
.kpi-delta { font-family: var(--font-mono); font-size: 10.5px; display: flex; align-items: center; gap: 4px; }
.kpi-delta.up { color: oklch(0.55 0.13 145); }
.kpi-delta.down { color: oklch(0.58 0.16 30); }
.kpi-delta.flat { color: var(--ink-3); }
.kpi-arrow { font-size: 9px; }
.kpi-vs { color: var(--ink-3); font-weight: 400; }
.chart-head {
display: flex; justify-content: space-between; align-items: center;
gap: 12px; flex-wrap: wrap;
padding-top: 6px;
border-top: 1px dashed var(--rule);
padding-top: 14px;
}
.chart-legend { display: flex; flex-wrap: wrap; gap: 4px; }
.legend-chip {
display: inline-flex; align-items: center; gap: 6px;
padding: 3px 8px;
font-size: 11px; color: var(--ink-2);
border: 1px solid transparent;
border-radius: 99px;
transition: opacity 0.12s, border-color 0.12s;
}
.legend-chip:hover { border-color: var(--rule); }
.legend-chip.off { opacity: 0.4; }
.legend-chip.off .lg-swatch { filter: grayscale(0.8); }
.lg-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 2px; }
.mode-switch {
display: inline-flex;
background: var(--bg);
border: 1px solid var(--rule);
border-radius: var(--radius);
padding: 2px;
gap: 1px;
}
.mode-btn {
display: inline-flex; align-items: center; gap: 5px;
padding: 4px 9px;
font-size: 11.5px; font-weight: 500;
color: var(--ink-3);
border-radius: 4px;
}
.mode-btn:hover { color: var(--ink-2); background: var(--bg-2); }
.mode-btn.active { background: var(--paper); color: var(--ink); box-shadow: 0 0 0 1px var(--rule); }
.mode-btn svg { color: currentColor; }
.stack-bars {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
gap: 4px;
align-items: end;
height: 160px;
padding: 0 2px;
}
.stack-col { display: flex; flex-direction: column; gap: 6px; height: 100%; min-width: 0; }
.stack-stack {
position: relative;
flex: 1;
min-height: 0;
border-radius: 3px 3px 0 0;
overflow: hidden;
align-self: stretch;
}
.stack-seg {
position: absolute;
left: 0; right: 0;
width: 100%;
min-height: 1px;
transition: height 0.25s ease, bottom 0.25s ease;
box-sizing: border-box;
}
/* round the topmost segment of each stack */
.stack-seg.top { border-radius: 3px 3px 0 0; }
.cumulative-stack { border-radius: 3px 3px 0 0; }
.stack-seg.cumulative {
background: var(--accent);
border-radius: 3px 3px 0 0;
box-shadow: none;
}
.legend-chip.static { cursor: default; opacity: 1; padding: 3px 8px; }
.stack-cap {
font-size: 10.5px; color: var(--ink-3);
font-family: var(--font-mono);
text-align: center;
display: flex; flex-direction: column; align-items: center; gap: 1px;
min-height: 16px;
line-height: 1;
}
.stack-total { font-size: 9.5px; color: var(--ink-3); opacity: 0.7; }
/* dense buckets — collapse columns to fit */
.stack-bars.buckets-30 { gap: 2px; }
.stack-bars.buckets-30 .stack-cap { font-size: 9.5px; }
/* legacy stat block styles kept for any external refs but no longer used */
.stats-row, .stat-block, .bar-row, .bar-col, .bar { /* retained */ }
.stat-block { padding: 12px 14px; border-radius: var(--radius); background: var(--bg); border: 1px solid var(--rule); }
.stat-num { font-family: var(--font-mono); font-size: 28px; font-weight: 500; letter-spacing: -0.03em; line-height: 1; }
.stat-num.small { font-family: var(--font-sans); font-size: 14px; font-weight: 600; }
.stat-unit { font-size: 14px; color: var(--ink-3); margin-left: 2px; }
.stat-cap { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 6px; }
.bar-row { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; align-items: end; padding-top: 16px; border-top: 1px dashed var(--rule); }
.bar-col { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.bar { width: 100%; background: var(--accent); border-radius: 3px 3px 0 0; min-height: 4px; }
.bar-cap { font-size: 11px; color: var(--ink-3); }
.bar-num { font-family: var(--font-mono); font-size: 11px; color: var(--ink-2); }
.status-mix { display: flex; flex-direction: column; gap: 7px; }
.mix-row { display: grid; grid-template-columns: 30px 1fr 80px 30px; align-items: center; gap: 8px; font-size: 12.5px; }
.mix-label { color: var(--ink-2); }
.mix-bar { height: 6px; background: var(--bg-2); border-radius: 99px; overflow: hidden; }
.mix-fill { display: block; height: 100%; background: var(--ink-2); border-radius: 99px; }
.mix-num { font-family: var(--font-mono); font-size: 11.5px; text-align: right; color: var(--ink-2); }
.backup-table, .history-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.backup-table th, .history-table th { text-align: left; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-3); padding: 6px 8px; border-bottom: 1px solid var(--rule); }
.backup-table td, .history-table td { padding: 9px 8px; border-bottom: 1px solid var(--rule-2); }
.backup-table tr.active { background: var(--accent-soft); }
.row-actions-cell { display: flex; gap: 4px; justify-content: flex-end; }
.row-btn { display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px; border-radius: 4px; font-size: 11.5px; color: var(--ink-2); border: 1px solid var(--rule); background: var(--paper); }
.row-btn:hover { background: var(--bg-2); }
.row-btn.primary { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.row-btn.primary:hover { background: oklch(0.15 0.012 60); }
.backup-preview { margin-top: 12px; border: 1px solid var(--rule); border-radius: var(--radius); background: var(--bg); overflow: hidden; }
.preview-head { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; border-bottom: 1px solid var(--rule); background: var(--bg-2); }
.preview-body { margin: 0; padding: 14px 16px; font-family: var(--font-mono); font-size: 11.5px; line-height: 1.55; color: var(--ink-2); white-space: pre-wrap; max-height: 320px; overflow: auto; }
/* ---------- Dialog system (centered, properly scrolled) ---------- */
.dlg-backdrop {
position: fixed; inset: 0;
display: flex; align-items: center; justify-content: center;
background: oklch(0.22 0.012 60 / 0.42);
backdrop-filter: blur(3px);
z-index: 200;
padding: 24px;
animation: dlg-fade 0.15s ease;
}
@keyframes dlg-fade { from { opacity: 0; } }
.dlg {
width: 100%;
max-height: calc(100vh - 48px);
background: var(--paper);
border: 1px solid var(--rule);
border-radius: 12px;
box-shadow: 0 30px 80px oklch(0.22 0.012 60 / 0.28), 0 4px 12px oklch(0.22 0.012 60 / 0.12);
display: flex; flex-direction: column;
overflow: hidden;
animation: dlg-pop 0.18s cubic-bezier(0.2, 0.9, 0.3, 1.1);
}
@keyframes dlg-pop { from { opacity: 0; transform: translateY(8px) scale(0.985); } }
.dlg form { display: contents; }
.dlg-head {
display: flex; align-items: flex-start; justify-content: space-between;
padding: 18px 22px 14px;
border-bottom: 1px solid var(--rule-2);
gap: 16px;
}
.dlg-title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; margin: 0; color: var(--ink); }
.dlg-close {
width: 28px; height: 28px;
display: grid; place-items: center;
border-radius: 6px;
color: var(--ink-3);
flex-shrink: 0;
}
.dlg-close:hover { background: var(--bg-2); color: var(--ink); }
.dlg-body {
padding: 18px 22px;
overflow-y: auto;
flex: 1;
min-height: 0;
}
.dlg-msg { font-size: 14px; color: var(--ink); margin: 0 0 8px; }
.dlg-detail { font-size: 12.5px; color: var(--ink-3); padding: 8px 12px; background: var(--bg-2); border: 1px dashed var(--rule); border-radius: 6px; }
.dlg-foot {
display: flex; align-items: center; justify-content: space-between;
gap: 12px;
padding: 14px 22px;
border-top: 1px solid var(--rule-2);
background: var(--bg-2);
}
.dlg-foot-actions { display: flex; gap: 8px; }
.dlg-hint { font-size: 11.5px; color: var(--ink-3); font-family: var(--font-mono); }
/* dialog form fields */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field:last-child { margin-bottom: 0; }
.field-row { display: grid; grid-template-columns: 1.5fr 1fr; gap: 16px; margin-bottom: 16px; }
.field-row .field { margin-bottom: 0; }
.field-label {
font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--ink-3); font-weight: 600;
display: flex; align-items: baseline; gap: 8px;
}
.field-hint {
font-size: 11px; letter-spacing: 0; text-transform: none;
font-weight: 400; color: var(--ink-3); font-style: italic;
}
.text-input {
width: 100%;
height: 38px;
padding: 0 12px;
font-size: 13.5px;
border: 1px solid var(--rule);
border-radius: var(--radius);
background: var(--bg);
color: var(--ink);
outline: 0;
transition: border-color 0.12s, box-shadow 0.12s;
}
.text-input[type="date"] { font-family: var(--font-mono); font-size: 13px; }
.text-input::placeholder { color: var(--ink-3); }
.text-input:focus { border-color: var(--accent-edge); box-shadow: 0 0 0 3px var(--accent-soft); background: var(--paper); }
/* status grid in dialog */
.status-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
}
.status-card {
display: flex; align-items: center; gap: 8px;
padding: 9px 11px; border-radius: var(--radius);
border: 1px solid var(--rule); background: var(--bg);
font-size: 12.5px; color: var(--ink-2);
text-align: left;
transition: background 0.12s, border-color 0.12s;
}
.status-card:hover { background: var(--paper); color: var(--ink); }
.status-card.active { background: var(--paper); border-color: var(--ink); color: var(--ink); box-shadow: 0 0 0 1px var(--ink) inset; }
.status-card-icon { display: inline-flex; flex-shrink: 0; }
.status-card-label { font-weight: 500; }
/* tag input */
.tag-input {
display: flex; flex-wrap: wrap; gap: 4px;
padding: 6px 8px;
border: 1px solid var(--rule);
border-radius: var(--radius);
background: var(--bg);
min-height: 38px;
cursor: text;
}
.tag-input:hover { border-color: oklch(0.85 0.008 70); }
.tag-input:focus-within { border-color: var(--accent-edge); box-shadow: 0 0 0 3px var(--accent-soft); background: var(--paper); }
.tag-pill {
display: inline-flex; align-items: center; gap: 4px;
font-family: var(--font-mono); font-size: 11.5px;
padding: 2px 4px 2px 8px;
background: var(--paper); border: 1px solid var(--rule); border-radius: 99px;
color: var(--ink);
}
.tag-pill button {
width: 16px; height: 16px;
display: grid; place-items: center;
border-radius: 50%;
color: var(--ink-3);
font-size: 14px; line-height: 1;
}
.tag-pill button:hover { background: var(--bg-2); color: var(--danger); }
.tag-input-field { flex: 1; min-width: 80px; border: 0; outline: 0; background: transparent; padding: 4px; font-size: 13px; }
.tag-input-field::placeholder { color: var(--ink-3); }
.tag-suggest { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; align-items: center; }
.tag-suggest-cap { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; margin-right: 4px; }
.tag-suggest-chip {
font-family: var(--font-mono); font-size: 11px;
padding: 2px 8px; border-radius: 99px;
background: var(--bg); border: 1px dashed var(--rule); color: var(--ink-2);
}
.tag-suggest-chip:hover { background: var(--paper); color: var(--ink); border-style: solid; border-color: var(--accent-edge); }
/* Tag autocomplete dropdown */
.tag-ac { position: relative; }
.tag-ac-pop {
position: absolute;
top: calc(100% + 4px); left: 0; right: 0;
background: var(--paper);
border: 1px solid var(--rule);
border-radius: var(--radius);
box-shadow: var(--shadow-pop);
padding: 4px;
z-index: 50;
max-height: 280px;
overflow-y: auto;
}
.tag-ac-cap {
font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--ink-3); font-weight: 600;
padding: 6px 8px 4px;
}
.tag-ac-item {
display: flex; align-items: center; gap: 6px;
width: 100%; text-align: left;
padding: 6px 9px; border-radius: 4px;
font-family: var(--font-mono); font-size: 12.5px;
color: var(--ink); background: transparent;
}
.tag-ac-item.highlighted { background: var(--accent-soft); color: var(--accent-deep); }
.tag-ac-item .hl { color: var(--accent-deep); font-weight: 600; }
.tag-ac-item.highlighted .hl { color: var(--accent-deep); background: oklch(0.62 0.13 var(--accent-hue) / 0.18); padding: 0 1px; border-radius: 2px; }
.tag-ac-item.create { color: var(--accent-deep); }
.tag-ac-item.create strong { font-weight: 600; }
.tag-ac-foot {
display: flex; gap: 12px; justify-content: flex-end;
padding: 6px 9px 4px;
border-top: 1px dashed var(--rule);
margin-top: 4px;
font-size: 10.5px; color: var(--ink-3);
}
.tag-ac-foot kbd {
font-family: var(--font-mono); font-size: 10px;
padding: 1px 4px; margin-right: 2px;
border: 1px solid var(--rule); border-bottom-width: 2px; border-radius: 3px;
background: var(--bg-2); color: var(--ink-2);
}
/* ---------- Rich Text Editor ---------- */
.rte-wrap {
border: 1px solid var(--rule);
border-radius: var(--radius);
background: var(--bg);
overflow: hidden;
transition: border-color 0.12s, box-shadow 0.12s;
}
.rte-wrap:focus-within {
border-color: var(--accent-edge);
box-shadow: 0 0 0 3px var(--accent-soft);
background: var(--paper);
}
.rte-toolbar {
display: flex;
align-items: center;
gap: 2px;
padding: 4px 6px;
border-bottom: 1px solid var(--rule);
background: var(--bg-2);
flex-wrap: wrap;
}
.rte-toolbar button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
color: var(--ink-2);
background: transparent;
transition: background 0.1s, color 0.1s;
}
.rte-toolbar button:hover {
background: var(--paper);
color: var(--ink);
}
.rte-toolbar-sep {
width: 1px;
height: 18px;
background: var(--rule);
margin: 0 4px;
}
.rte-copy-btn {
width: auto !important;
padding: 0 6px;
gap: 3px;
font-size: 11px;
font-weight: 500;
}
.rte-copy-menu {
position: fixed;
background: var(--paper);
border: 1px solid var(--rule);
border-radius: var(--radius);
box-shadow: var(--shadow-pop);
padding: 4px;
z-index: 100;
min-width: 160px;
}
.rte-copy-menu button {
display: block;
width: 100%;
text-align: left;
padding: 7px 10px;
border-radius: 4px;
font-size: 12.5px;
color: var(--ink);
}
.rte-copy-menu button:hover {
background: var(--accent-soft);
color: var(--accent-deep);
}
.rte-editor {
min-height: 80px;
max-height: 240px;
overflow-y: auto;
padding: 10px 12px;
font-size: 13px;
line-height: 1.55;
color: var(--ink);
outline: none;
}
.rte-editor:empty::before {
content: attr(data-placeholder);
color: var(--ink-3);
pointer-events: none;
}
.rte-editor p { margin: 0 0 0.75em; }
.rte-editor p:last-child { margin-bottom: 0; }
.rte-editor h1, .rte-editor h2, .rte-editor h3 {
margin: 0.8em 0 0.4em;
font-weight: 600;
line-height: 1.3;
}
.rte-editor h1:first-child,
.rte-editor h2:first-child,
.rte-editor h3:first-child { margin-top: 0; }
.rte-editor h1 { font-size: 1.3em; }
.rte-editor h2 { font-size: 1.15em; }
.rte-editor h3 { font-size: 1em; }
.rte-editor ul, .rte-editor ol {
margin: 0.5em 0;
padding-left: 1.5em;
}
.rte-editor li { margin: 0.25em 0; }
.rte-editor a {
color: var(--accent-deep);
text-decoration: underline;
text-underline-offset: 2px;
}
.rte-editor a:hover { color: var(--accent); }
.rte-editor strong { font-weight: 600; }
.rte-editor em { font-style: italic; }
.rte-inline-code {
font-family: var(--font-mono);
font-size: 0.9em;
padding: 1px 5px;
background: var(--bg-2);
border-radius: 3px;
color: var(--ink);
}
.rte-code-block {
font-family: var(--font-mono);
font-size: 12px;
line-height: 1.5;
padding: 10px 12px;
background: var(--bg-2);
border-radius: var(--radius);
margin: 0.75em 0;
overflow-x: auto;
white-space: pre;
}
.rte-code-block code {
background: none;
padding: 0;
font-size: inherit;
}
.rte-table {
width: 100%;
border-collapse: collapse;
margin: 0.75em 0;
font-size: 12.5px;
}
.rte-table th, .rte-table td {
border: 1px solid var(--rule);
padding: 6px 10px;
text-align: left;
}
.rte-table th {
background: var(--bg-2);
font-weight: 600;
}
.rte-table td { background: var(--paper); }
.rte-img {
max-width: 100%;
height: auto;
border-radius: var(--radius);
margin: 0.5em 0;
}
/* Collapsed state */
.rte-collapsed {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
min-height: 40px;
border: 1px dashed var(--rule);
border-radius: var(--radius);
background: var(--bg);
cursor: pointer;
transition: border-color 0.12s, background 0.12s;
}
.rte-collapsed:hover {
border-color: var(--accent-edge);
background: var(--paper);
}
.rte-collapsed-placeholder {
font-size: 13px;
color: var(--ink-3);
}
/* ---------- Import / Export dialog ---------- */
.ie-tabs { display: flex; gap: 4px; margin-bottom: 12px; border-bottom: 1px solid var(--rule); align-items: stretch; }
.ie-tab {
display: inline-flex; align-items: baseline; gap: 6px;
padding: 7px 14px;
font-size: 13px; font-weight: 500; color: var(--ink-3);
border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.ie-tab:hover { color: var(--ink); }
.ie-tab.active { color: var(--ink); border-bottom-color: var(--ink); }
.ie-tab-sub { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-3); }
.ie-copy-btn {
margin-left: auto;
display: inline-flex; align-items: center; gap: 5px;
padding: 5px 10px;
font-size: 12px; font-weight: 500; color: var(--ink-2);
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--paper);
align-self: center;
margin-bottom: 4px;
transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.ie-copy-btn:hover { background: var(--bg-2); color: var(--ink); border-color: oklch(0.85 0.008 70); }
.ie-copy-btn.copied { background: var(--ok); color: white; border-color: var(--ok); }
.export-pre {
background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius);
padding: 14px 16px;
font-family: var(--font-mono); font-size: 11.5px; line-height: 1.55;
color: var(--ink-2);
max-height: 360px; overflow: auto;
white-space: pre;
margin: 0;
}
/* ---------- Toast ---------- */
.toast {
position: fixed; bottom: 24px; left: 50%;
transform: translateX(-50%);
background: var(--ink); color: var(--bg);
padding: 9px 16px; border-radius: 99px;
font-size: 13px;
display: inline-flex; align-items: center; gap: 8px;
box-shadow: 0 10px 30px oklch(0.22 0.012 60 / 0.3);
z-index: 250;
animation: toast-in 0.2s ease;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } }
@media (max-width: 900px) {
.main { grid-template-columns: 1fr; }
.filter-panel { position: static; max-height: none; border-right: 0; border-bottom: 1px solid var(--rule); }
.admin-grid { grid-template-columns: 1fr; }
.card.span-2, .card.span-3 { grid-column: span 1; }
.header { grid-template-columns: 1fr; gap: 10px; }
.stats-row { grid-template-columns: repeat(2, 1fr); }
.field-row { grid-template-columns: 1fr; }
.status-grid { grid-template-columns: repeat(2, 1fr); }
}
/* ---------- Archive Manager ---------- */
.archive-section { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--rule-2); }
.archive-section:first-of-type { margin-top: 8px; padding-top: 0; border-top: 0; }
.archive-toolbar {
display: flex; align-items: center; gap: 10px;
margin-bottom: 12px; flex-wrap: wrap;
}
.archive-label { font-size: 12px; font-weight: 600; color: var(--ink-2); }
.archive-filter {
padding: 4px 8px; font-size: 12px;
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--paper); color: var(--ink);
}
.archive-search {
padding: 4px 10px; font-size: 12px;
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--paper); color: var(--ink);
width: 160px;
}
.archive-search::placeholder { color: var(--ink-3); }
.archive-empty {
padding: 20px; text-align: center;
color: var(--ink-3); font-size: 13px;
}
.archive-list {
display: flex; flex-direction: column; gap: 4px;
max-height: 280px; overflow-y: auto;
}
.archive-item {
display: flex; align-items: center; gap: 8px;
padding: 6px 10px; background: var(--bg); border-radius: var(--radius);
font-size: 13px; cursor: pointer;
transition: background 0.12s;
}
.archive-item:hover { background: var(--bg-2); }
.archive-item.archived { cursor: default; }
.archive-item input[type="checkbox"] { flex-shrink: 0; }
.archive-item .glyph { flex-shrink: 0; width: 18px; text-align: center; }
.archive-item-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.archive-item-children {
font-size: 11px; color: var(--ink-3);
padding: 2px 6px; background: var(--rule-2); border-radius: 3px;
}
.archive-item-date { font-size: 11px; color: var(--ink-3); font-family: var(--font-mono); }
.archive-more { padding: 8px; text-align: center; font-size: 12px; color: var(--ink-3); }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-xs { padding: 2px 8px; font-size: 11px; }
/* ---------- Archive Search Results ---------- */
.archive-search-section {
margin-top: 16px; padding-top: 16px;
border-top: 1px dashed var(--rule);
}
.archive-search-toggle {
display: flex; align-items: center; gap: 6px;
padding: 6px 10px;
font-size: 12px; font-weight: 500; color: var(--ink-2);
background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius);
cursor: pointer;
transition: background 0.12s, color 0.12s;
}
.archive-search-toggle:hover { background: var(--bg-2); color: var(--ink); }
.archive-loading { color: var(--ink-3); font-style: italic; }
.archive-count { color: var(--ink-3); }
.archive-search-results {
margin-top: 8px; padding: 8px;
background: var(--bg); border: 1px solid var(--rule); border-radius: var(--radius);
}
.archive-search-empty {
padding: 12px; text-align: center;
color: var(--ink-3); font-size: 13px;
}
.archive-search-item {
display: flex; align-items: center; gap: 8px;
padding: 6px 8px;
border-radius: var(--radius);
transition: background 0.12s;
}
.archive-search-item:hover { background: var(--bg-2); }
.archive-search-item .glyph { flex-shrink: 0; width: 18px; text-align: center; }
.archive-search-title { flex: 1; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.archive-search-date { font-size: 11px; color: var(--ink-3); font-family: var(--font-mono); }
.archive-search-more { padding: 8px; text-align: center; font-size: 12px; color: var(--ink-3); }
.archive-search-header {
font-size: 12px; font-weight: 600; color: var(--ink-2);
padding: 4px 0; margin-bottom: 8px;
}
.archive-match-hint { font-size: 14px; color: var(--ink-3); font-weight: 400; }
.rte-readonly {
padding: 10px 12px; background: var(--bg); border: 1px solid var(--rule);
border-radius: var(--radius); font-size: 13px; line-height: 1.5; color: var(--ink-2);
min-height: 60px; max-height: 200px; overflow-y: auto;
}
.rte-readonly:empty::before { content: 'No details'; color: var(--ink-3); }
.tag-list-readonly { display: flex; flex-wrap: wrap; gap: 6px; }
/* ---------- Project sections (multi-project api mode) ---------- */
.project-sections { display: flex; flex-direction: column; gap: 16px; }
.project-section {
background: var(--paper);
border: 1px solid var(--rule);
border-radius: var(--radius-lg);
overflow: hidden;
}
.project-section-header {
display: flex; align-items: center; gap: 8px; padding: 10px 14px;
background: var(--bg-2); cursor: pointer; user-select: none;
border-bottom: 1px solid transparent; transition: background 0.15s;
}
.project-section-header:hover { background: var(--accent-soft); }
.project-section-header.expanded { border-bottom-color: var(--rule); }
.project-section-header.missing .project-section-name { color: var(--ink-3); }
.project-section-chevron { color: var(--ink-3); width: 14px; display: inline-flex; }
.project-section-name { font-weight: 600; font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-section-count { font-size: 12px; color: var(--ink-3); margin-left: 4px; white-space: nowrap; }
.project-section-actions {
margin-left: auto; display: flex; gap: 2px; opacity: 0; transition: opacity 0.15s;
}
.project-section-header:hover .project-section-actions,
.project-section-header:focus-within .project-section-actions { opacity: 1; }
.project-section-btn {
padding: 4px 6px; border: none; background: transparent;
color: var(--ink-3); cursor: pointer; border-radius: var(--radius); transition: background 0.15s, color 0.15s;
}
.project-section-btn:hover { background: var(--accent-soft); color: var(--accent); }
.project-section-btn-danger:hover { background: var(--danger-soft); color: var(--danger); }
.project-section-content { padding: 8px 0; }
.project-section-content.drop-target {
outline: 2px dashed var(--accent-edge);
outline-offset: -4px;
background: var(--accent-soft);
}
.project-empty { padding: 20px; text-align: center; color: var(--ink-3); font-size: 13px; }
.project-empty .mono { font-family: var(--font-mono); font-size: 12px; }
.project-missing-badge {
font-size: 11px; line-height: 1; padding: 3px 8px; border-radius: 999px;
color: var(--warn); background: var(--warn-bg);
border: 1px solid var(--warn);
white-space: nowrap;
}
.dlg-checkbox {
display: flex; align-items: center; gap: 8px; margin-top: 12px;
font-size: 13px; color: var(--ink-2); cursor: pointer;
}
.dlg-checkbox input { width: 16px; height: 16px; accent-color: var(--danger); cursor: pointer; }
/* ---- Admin Projects card + import/export target select (multi-project) ---- */
.projects-table .projects-path {
max-width: 280px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.projects-register {
display: flex; align-items: center; gap: 8px;
margin-top: 14px; flex-wrap: wrap;
}
.projects-input {
flex: 1 1 auto; min-width: 0;
font-family: var(--font-mono); font-size: 12.5px;
padding: 7px 10px;
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--paper); color: var(--ink);
}
.projects-input::placeholder { color: var(--ink-3); }
.projects-input:focus { outline: none; border-color: var(--accent-edge); }
.projects-input-name { flex: 0 1 200px; font-family: inherit; }
.ie-target-row {
display: flex; align-items: center; gap: 10px;
margin-bottom: 12px;
}
.ie-target-label {
font-size: 11px; font-weight: 600;
color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em;
white-space: nowrap;
}
.ie-target {
font: inherit; font-size: 13px;
padding: 6px 10px;
border: 1px solid var(--rule); border-radius: var(--radius);
background: var(--paper); color: var(--ink);
cursor: pointer;
}
/* ---------- Row context menu ---------- */
.ctx-menu {
position: fixed; z-index: 60;
width: 200px; padding: 4px;
background: var(--paper); border: 1px solid var(--rule);
border-radius: var(--radius-lg); box-shadow: var(--shadow-pop);
}
.ctx-menu-label {
padding: 6px 8px 4px;
font-size: 11px; font-weight: 600;
color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em;
}
.ctx-menu-item {
width: 100%; display: flex; align-items: center; gap: 8px;
padding: 6px 8px; border-radius: 4px;
font-size: 13px; color: var(--ink); text-align: left;
}
.ctx-menu-item:hover { background: var(--bg-2); }
.ctx-menu-item.active { background: var(--accent-soft); color: var(--accent-deep); }
.ctx-menu-item.danger { color: var(--danger); }
.ctx-menu-item.danger:hover { background: var(--danger-soft); }
.ctx-menu-sep { height: 1px; margin: 4px 6px; background: var(--rule-2); }