Bring every tool's header in line with archive's pattern: [logo] [title] [version] [Add Local Directory] [⟳] ............... [◐] [?] ------------- header-left --------------- ----- header-right - Changes per tool: * browse: rename "Select Directory" → "Add Local Directory"; add the red-non-stable wrap to the build label (was missing); add a help panel + bundle shared/help.js. * classifier: rename selectDirectoryBtn → addDirectoryBtn, refreshBtn → refreshHeaderBtn for consistency. Update all JS callers and welcome-screen copy to the new label. * mdedit: same id rename. Move the previously-in-pane refresh button into the header. Stop renaming the dir button to "Directory: <name>" once a folder is loaded — instead use the shared btn--subtle variant to de-emphasize while keeping the standard label. * transmittal: convert non-standard <div class="app-header"> with spacer/icons containers to <header class="app-header"> with the canonical header-left/header-right pair. Move the publish split- button into header-left (Transmittal-specific primary action). Remove dead .app-header__spacer/__icons/header-icon-btn CSS now that nothing references those classes. * landing, form: add help-btn + help-panel + bundle shared/help.js. Each panel is tool-specific (project picker docs for landing, schema-driven form docs for form). Cross-cutting: * shared/base.css: promote .btn--subtle from browse/css/tree.css so any tool with an online mode can de-emphasize Add Local Directory consistently. Verified all 7 tools in headless Chromium: header structure correct, build label red on non-stable cuts, help panel opens + closes via button + Esc.
518 lines
13 KiB
CSS
518 lines
13 KiB
CSS
/* ==========================================================================
|
|
ZDDC Shared Base — single source of truth for tokens and primitives
|
|
Included first by every tool's build.sh via ../shared/base.css
|
|
========================================================================== */
|
|
|
|
/* ── CSS custom properties ────────────────────────────────────────────────── */
|
|
:root {
|
|
/* Brand / accent (matches zddc.varasys.io website --accent) */
|
|
--primary: #2a5a8a;
|
|
--primary-hover: #1d4060;
|
|
--primary-active: #163352;
|
|
--primary-light: #e8f0f7;
|
|
|
|
/* Semantic colours */
|
|
--success: #28a745;
|
|
--warning: #d97706;
|
|
--danger: #dc3545;
|
|
--info: #17a2b8;
|
|
|
|
/* Backgrounds */
|
|
--bg: #ffffff;
|
|
--bg-secondary: #f8f9fa;
|
|
--bg-hover: #f0f4f8;
|
|
--bg-selected: var(--primary-light);
|
|
|
|
/* Text */
|
|
--text: #212529;
|
|
--text-muted: #6c757d;
|
|
--text-light: #ffffff;
|
|
|
|
/* Borders */
|
|
--border: #dee2e6;
|
|
--border-dark: #adb5bd;
|
|
|
|
/* Shape */
|
|
--radius: 4px;
|
|
|
|
/* Typography */
|
|
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
--font-mono: 'SF Mono', 'Fira Code', 'Consolas', 'Courier New', monospace;
|
|
}
|
|
|
|
/* ── Dark mode tokens ─────────────────────────────────────────────────────── */
|
|
/* Applied via: OS preference (auto) or [data-theme="dark"] on <html> */
|
|
/* The [data-theme="light"] selector locks light mode regardless of OS pref. */
|
|
@media (prefers-color-scheme: dark) {
|
|
:root:not([data-theme="light"]) {
|
|
--primary: #4a90c4;
|
|
--primary-hover: #5ba3d9;
|
|
--primary-active: #6ab5e8;
|
|
--primary-light: #1a3550;
|
|
|
|
--bg: #1e1e1e;
|
|
--bg-secondary: #252526;
|
|
--bg-hover: #2d2d30;
|
|
--bg-selected: #1a3550;
|
|
|
|
--text: #d4d4d4;
|
|
--text-muted: #9d9d9d;
|
|
--text-light: #ffffff;
|
|
|
|
--border: #3e3e42;
|
|
--border-dark: #6e6e72;
|
|
}
|
|
}
|
|
|
|
/* Manual dark override — wins over media query */
|
|
[data-theme="dark"] {
|
|
--primary: #4a90c4;
|
|
--primary-hover: #5ba3d9;
|
|
--primary-active: #6ab5e8;
|
|
--primary-light: #1a3550;
|
|
|
|
--bg: #1e1e1e;
|
|
--bg-secondary: #252526;
|
|
--bg-hover: #2d2d30;
|
|
--bg-selected: #1a3550;
|
|
|
|
--text: #d4d4d4;
|
|
--text-muted: #9d9d9d;
|
|
--text-light: #ffffff;
|
|
|
|
--border: #3e3e42;
|
|
--border-dark: #6e6e72;
|
|
}
|
|
|
|
/* ── Reset ────────────────────────────────────────────────────────────────── */
|
|
*, *::before, *::after {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
/* ── Base document ────────────────────────────────────────────────────────── */
|
|
html, body {
|
|
height: 100%;
|
|
font-family: var(--font);
|
|
font-size: 16px;
|
|
line-height: 1.5;
|
|
color: var(--text);
|
|
background-color: var(--bg-secondary);
|
|
}
|
|
|
|
/* ── Typography ───────────────────────────────────────────────────────────── */
|
|
h1, h2, h3, h4, h5, h6 {
|
|
font-weight: 600;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
a {
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
}
|
|
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* ── Utility ──────────────────────────────────────────────────────────────── */
|
|
.hidden {
|
|
display: none !important;
|
|
}
|
|
|
|
.truncate {
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
/* ── Scrollbars (webkit) ──────────────────────────────────────────────────── */
|
|
::-webkit-scrollbar {
|
|
width: 7px;
|
|
height: 7px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: #c1c1c1;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #a0a0a0;
|
|
}
|
|
|
|
/* ── Button primitive ─────────────────────────────────────────────────────── */
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.25rem;
|
|
padding: 0.4rem 0.85rem;
|
|
font-family: var(--font);
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
vertical-align: middle;
|
|
cursor: pointer;
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius);
|
|
transition: background 0.15s, box-shadow 0.15s, border-color 0.15s, color 0.15s;
|
|
background: var(--bg-secondary);
|
|
color: var(--text);
|
|
}
|
|
|
|
.btn:disabled,
|
|
.btn[disabled] {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.btn:not(:disabled):hover {
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
|
|
}
|
|
|
|
.btn:not(:disabled):active {
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* Variants */
|
|
.btn-primary {
|
|
background: var(--primary);
|
|
color: var(--text-light);
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.btn-primary:not(:disabled):hover {
|
|
background: var(--primary-hover);
|
|
border-color: var(--primary-hover);
|
|
color: var(--text-light);
|
|
}
|
|
|
|
.btn-primary:not(:disabled):active {
|
|
background: var(--primary-active);
|
|
border-color: var(--primary-active);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
border-color: var(--border);
|
|
}
|
|
|
|
.btn-secondary:not(:disabled):hover {
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
/* Subdued / de-emphasized variant.
|
|
Used on the "Add Local Directory" button when a tool is operating
|
|
in server (online) mode — the local-dir affordance is still
|
|
available but visually quieter, since the typical user already
|
|
has the directory loaded from the server. */
|
|
.btn.btn--subtle {
|
|
background: transparent;
|
|
color: var(--text-muted);
|
|
border-color: var(--border);
|
|
box-shadow: none;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.btn.btn--subtle:not(:disabled):hover {
|
|
color: var(--text);
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
.btn-success {
|
|
background: var(--success);
|
|
color: var(--text-light);
|
|
border-color: var(--success);
|
|
}
|
|
|
|
.btn-danger {
|
|
background: var(--danger);
|
|
color: var(--text-light);
|
|
border-color: var(--danger);
|
|
}
|
|
|
|
/* Sizes */
|
|
.btn-sm {
|
|
padding: 0.25rem 0.5rem;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.btn-lg {
|
|
padding: 0.6rem 1.4rem;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.btn-link {
|
|
background: transparent;
|
|
border-color: transparent;
|
|
color: var(--primary);
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
}
|
|
|
|
.btn-link:not(:disabled):hover {
|
|
text-decoration: underline;
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* ── App header chrome ────────────────────────────────────────────────────── */
|
|
.app-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.35rem 1rem;
|
|
background: var(--bg-secondary);
|
|
border-bottom: 1px solid var(--border);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Tool name inside the header */
|
|
.app-header__title {
|
|
font-size: 17px;
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
letter-spacing: 0.01em;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* Brand logo — sits left of the title in every tool's app-header.
|
|
Self-contained: the SVG provides its own dark blue rounded background,
|
|
so no extra wrapper styling is needed. */
|
|
.app-header__logo {
|
|
width: 26px;
|
|
height: 26px;
|
|
flex-shrink: 0;
|
|
display: block;
|
|
}
|
|
|
|
/* ── Build timestamp ──────────────────────────────────────────────────────── */
|
|
.build-timestamp {
|
|
font-size: 0.55rem;
|
|
color: var(--text-muted);
|
|
opacity: 0.7;
|
|
font-weight: 300;
|
|
white-space: nowrap;
|
|
padding-top: 0.15rem;
|
|
}
|
|
|
|
/* Title + timestamp stacked vertically on the left side of the header */
|
|
.header-title-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0;
|
|
line-height: 1;
|
|
}
|
|
|
|
/* ── Icon buttons (help, theme, refresh) ─────────────────────────────────── */
|
|
/* Square, centered — overrides the asymmetric text-button padding/line-height */
|
|
#help-btn,
|
|
#theme-btn,
|
|
#refreshHeaderBtn {
|
|
width: 2rem;
|
|
height: 2rem;
|
|
padding: 0;
|
|
line-height: 1;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
/* Toast CSS lives in classifier/css/base.css — only that tool uses toasts. */
|
|
|
|
/* ── Theme and help icon buttons ─────────────────────────────────────────── */
|
|
#theme-btn,
|
|
#help-btn {
|
|
font-size: 1rem;
|
|
}
|
|
|
|
/* ── Help panel (shared slide-out drawer) ─────────────────────────────────── */
|
|
/* Used by all four tools. Toggle open/close via shared/help.js. */
|
|
|
|
.help-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
width: min(420px, 85vw);
|
|
height: 100vh;
|
|
z-index: 1000;
|
|
background: var(--bg);
|
|
border-left: 1px solid var(--border);
|
|
box-shadow: -2px 0 12px rgba(0, 0, 0, 0.08);
|
|
display: flex;
|
|
flex-direction: column;
|
|
transform: translateX(100%);
|
|
transition: transform 0.25s ease;
|
|
}
|
|
|
|
.help-panel:not([hidden]) {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
.help-panel[hidden] {
|
|
display: flex;
|
|
transform: translateX(100%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.help-panel__header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0.75rem 1rem;
|
|
border-bottom: 1px solid var(--border);
|
|
flex-shrink: 0;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.help-panel__title {
|
|
font-size: 1rem;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
margin: 0;
|
|
}
|
|
|
|
.help-panel__close {
|
|
background: none;
|
|
border: none;
|
|
color: var(--text-muted);
|
|
font-size: 1.35rem;
|
|
cursor: pointer;
|
|
padding: 0.25rem 0.5rem;
|
|
border-radius: var(--radius);
|
|
line-height: 1;
|
|
transition: background 0.15s, color 0.15s;
|
|
}
|
|
|
|
.help-panel__close:hover {
|
|
color: var(--text);
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
.help-panel__body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 1rem 1rem 2rem;
|
|
font-size: 0.85rem;
|
|
line-height: 1.6;
|
|
color: var(--text);
|
|
}
|
|
|
|
.help-panel__body h3 {
|
|
font-size: 0.95rem;
|
|
font-weight: 700;
|
|
margin: 1.25rem 0 0.35rem;
|
|
color: var(--text);
|
|
border-bottom: 1px solid var(--border);
|
|
padding-bottom: 0.15rem;
|
|
}
|
|
|
|
.help-panel__body h3:first-child {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.help-panel__body h4 {
|
|
font-size: 0.7rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
margin: 1.25rem 0 0.3rem;
|
|
padding-left: 0.5rem;
|
|
border-left: 3px solid var(--border-dark);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.help-panel__body p {
|
|
margin: 0 0 0.5rem;
|
|
}
|
|
|
|
.help-panel__body ol,
|
|
.help-panel__body ul {
|
|
padding-left: 1.5rem;
|
|
margin: 0.3rem 0 0.5rem;
|
|
}
|
|
|
|
.help-panel__body li {
|
|
margin-bottom: 0.3rem;
|
|
}
|
|
|
|
.help-panel__body dl {
|
|
margin: 0.3rem 0;
|
|
}
|
|
|
|
.help-panel__body dt {
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
|
|
.help-panel__body dd {
|
|
margin: 0 0 0.5rem 1rem;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.help-panel__body code {
|
|
font-family: var(--font-mono);
|
|
font-size: 0.8em;
|
|
background: var(--bg-secondary);
|
|
padding: 0.1em 0.3em;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.help-badge {
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
padding: 0.1rem 0.35rem;
|
|
border-radius: var(--radius);
|
|
vertical-align: middle;
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
.help-badge--draft {
|
|
color: #2563eb;
|
|
background: #eff6ff;
|
|
}
|
|
|
|
.help-badge--published {
|
|
color: #7c3aed;
|
|
background: #f5f3ff;
|
|
}
|
|
|
|
/* Shrink main content when help panel is open */
|
|
body.help-open .app-header {
|
|
margin-right: min(420px, 85vw);
|
|
}
|
|
|
|
/* ── Column filter inputs (shared across archive, classifier, transmittal) ─── */
|
|
.column-filter {
|
|
display: block;
|
|
width: 100%;
|
|
box-sizing: border-box;
|
|
margin-top: 0.25rem;
|
|
padding: 0.2rem 0.4rem;
|
|
font-size: 0.8rem;
|
|
font-family: var(--font);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
transition: border-color 0.15s;
|
|
}
|
|
|
|
.column-filter:focus {
|
|
border-color: var(--primary);
|
|
outline: none;
|
|
box-shadow: 0 0 0 1px rgba(42, 90, 138, 0.35);
|
|
}
|
|
|
|
.column-filter::placeholder {
|
|
color: var(--text-muted);
|
|
}
|