Groups allow multiple modules to be run sequentially in a defined order. Adds full CRUD (repo, engine orchestrator, web routes, templates) for grp, group_member, and group_run tables that were previously schema-only. Module index now shows group membership badges per module. Wizard default dest name now sanitizes source column names with spaces or special characters to valid identifiers rather than failing at CREATE TABLE time. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
303 lines
7.9 KiB
CSS
303 lines
7.9 KiB
CSS
/* Pipekit web — structured, bordered, terminal-inspired.
|
|
Design bar (per user feedback):
|
|
- Every logical region has a visible border + title.
|
|
- Pickers and structured lists over free-text inputs.
|
|
- Layout directs flow; nothing floats. */
|
|
|
|
:root {
|
|
--bg: #111418;
|
|
--surface: #181c22;
|
|
--border: #2a3038;
|
|
--border-strong: #3d4652;
|
|
--text: #d7dce3;
|
|
--text-muted: #8b95a2;
|
|
--accent: #6fa8dc;
|
|
--success: #78c679;
|
|
--danger: #e57373;
|
|
--warning: #e1b467;
|
|
--mono: "JetBrains Mono", "Fira Code", "Consolas", "Courier New", monospace;
|
|
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: var(--sans);
|
|
font-size: 14px;
|
|
line-height: 1.45;
|
|
}
|
|
a { color: var(--accent); text-decoration: none; }
|
|
a:hover { text-decoration: underline; }
|
|
code, pre, .mono { font-family: var(--mono); font-size: 13px; }
|
|
|
|
header.topbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.5rem;
|
|
padding: 0.6rem 1.2rem;
|
|
background: var(--surface);
|
|
border-bottom: 1px solid var(--border-strong);
|
|
}
|
|
header.topbar .brand {
|
|
font-weight: 700;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
header.topbar nav {
|
|
display: flex;
|
|
gap: 1rem;
|
|
}
|
|
header.topbar nav a {
|
|
color: var(--text-muted);
|
|
padding: 0.2rem 0.5rem;
|
|
border-radius: 3px;
|
|
}
|
|
header.topbar nav a.active,
|
|
header.topbar nav a:hover {
|
|
color: var(--text);
|
|
background: var(--border);
|
|
text-decoration: none;
|
|
}
|
|
header.topbar .right { margin-left: auto; color: var(--text-muted); font-size: 12px; }
|
|
|
|
main {
|
|
max-width: 1200px;
|
|
margin: 1rem auto;
|
|
padding: 0 1.2rem;
|
|
}
|
|
|
|
/* Bordered panels — the bread and butter. */
|
|
.panel {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.panel > header {
|
|
padding: 0.45rem 0.9rem;
|
|
border-bottom: 1px solid var(--border);
|
|
background: #1d222a;
|
|
font-weight: 600;
|
|
letter-spacing: 0.02em;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6rem;
|
|
}
|
|
.panel > header .subtitle {
|
|
color: var(--text-muted);
|
|
font-weight: 400;
|
|
font-size: 12px;
|
|
}
|
|
.panel > .body { padding: 0.8rem 0.9rem; }
|
|
.panel > .body.tight { padding: 0; }
|
|
.panel > footer {
|
|
padding: 0.5rem 0.9rem;
|
|
border-top: 1px solid var(--border);
|
|
background: #15191f;
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Tables */
|
|
table.grid {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
table.grid th, table.grid td {
|
|
padding: 0.4rem 0.7rem;
|
|
border-bottom: 1px solid var(--border);
|
|
text-align: left;
|
|
vertical-align: top;
|
|
}
|
|
table.grid th {
|
|
color: var(--text-muted);
|
|
font-weight: 500;
|
|
font-size: 12px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
background: #15191f;
|
|
border-bottom-color: var(--border-strong);
|
|
}
|
|
table.grid tr:last-child td { border-bottom: none; }
|
|
table.grid tr:hover td { background: #1c2128; }
|
|
|
|
/* Status pills */
|
|
.pill {
|
|
display: inline-block;
|
|
padding: 0.05rem 0.5rem;
|
|
border-radius: 10px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
border: 1px solid currentColor;
|
|
color: var(--text-muted);
|
|
}
|
|
.pill.ok, .pill.success { color: var(--success); }
|
|
.pill.err, .pill.error { color: var(--danger); }
|
|
.pill.running { color: var(--accent); }
|
|
.pill.disabled { color: var(--text-muted); }
|
|
.pill.warning { color: var(--warning); }
|
|
|
|
/* Group membership tags */
|
|
.tag {
|
|
display: inline-block;
|
|
padding: 0.05rem 0.45rem;
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
background: var(--border);
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
margin-right: 0.2rem;
|
|
}
|
|
.tag:hover { color: var(--accent); }
|
|
|
|
/* Labeled key-value rows (used in detail views) */
|
|
dl.keyval {
|
|
display: grid;
|
|
grid-template-columns: 10rem 1fr;
|
|
gap: 0.3rem 1rem;
|
|
margin: 0;
|
|
}
|
|
dl.keyval dt { color: var(--text-muted); }
|
|
dl.keyval dd { margin: 0; }
|
|
|
|
/* SQL blocks */
|
|
pre.sql {
|
|
background: #0f1216;
|
|
border: 1px solid var(--border);
|
|
border-radius: 3px;
|
|
padding: 0.7rem 0.9rem;
|
|
margin: 0;
|
|
white-space: pre-wrap;
|
|
overflow-x: auto;
|
|
color: #c6d0da;
|
|
}
|
|
|
|
/* Buttons and forms */
|
|
button, .btn {
|
|
background: var(--border);
|
|
border: 1px solid var(--border-strong);
|
|
color: var(--text);
|
|
padding: 0.35rem 0.9rem;
|
|
border-radius: 3px;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
}
|
|
button:hover, .btn:hover { background: var(--border-strong); }
|
|
button.primary { background: #22303f; border-color: #3d5273; color: #cfe0f5; }
|
|
button.primary:hover { background: #2b3d52; }
|
|
button.ghost { background: transparent; }
|
|
|
|
form.inline { display: inline; }
|
|
|
|
.actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
|
|
|
|
/* Empty-state */
|
|
.empty {
|
|
padding: 1.5rem;
|
|
text-align: center;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
/* Group heading inside a panel (used on the module list) */
|
|
.group-head {
|
|
padding: 0.4rem 0.9rem;
|
|
color: var(--text-muted);
|
|
background: #141820;
|
|
font-size: 12px;
|
|
letter-spacing: 0.05em;
|
|
text-transform: uppercase;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
/* Two-column layout helper */
|
|
.two-col {
|
|
display: grid;
|
|
grid-template-columns: 2fr 1fr;
|
|
gap: 1rem;
|
|
}
|
|
/* Grid items default to min-width:auto which is content-sized; let them
|
|
shrink so wide tables/inputs inside don't blow out the layout. */
|
|
.two-col > * { min-width: 0; }
|
|
@media (max-width: 900px) {
|
|
.two-col { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* Form controls — inputs, selects, textarea. Match bordered panel look. */
|
|
input[type="text"], input[type="number"], input[type="password"],
|
|
select, textarea {
|
|
background: #0f1216;
|
|
border: 1px solid var(--border-strong);
|
|
color: var(--text);
|
|
padding: 0.35rem 0.6rem;
|
|
border-radius: 3px;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
min-width: 14rem;
|
|
}
|
|
input:focus, select:focus, textarea:focus {
|
|
outline: 1px solid var(--accent);
|
|
border-color: var(--accent);
|
|
}
|
|
textarea { font-family: var(--mono); min-width: 100%; }
|
|
label.field {
|
|
display: grid;
|
|
grid-template-columns: 10rem 1fr;
|
|
align-items: center;
|
|
gap: 0.5rem 1rem;
|
|
margin-bottom: 0.6rem;
|
|
}
|
|
label.field .help { grid-column: 2; color: var(--text-muted); font-size: 12px; }
|
|
|
|
/* Step indicator */
|
|
.steps {
|
|
display: flex;
|
|
gap: 0;
|
|
margin-bottom: 1rem;
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
overflow: hidden;
|
|
background: var(--surface);
|
|
}
|
|
.steps .step {
|
|
flex: 1;
|
|
padding: 0.5rem 0.9rem;
|
|
color: var(--text-muted);
|
|
font-size: 12px;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
border-right: 1px solid var(--border);
|
|
}
|
|
.steps .step:last-child { border-right: none; }
|
|
.steps .step.active { color: var(--text); background: #1d222a; }
|
|
.steps .step.done { color: var(--success); }
|
|
.steps .step .num { font-weight: 700; margin-right: 0.4rem; }
|
|
|
|
/* Radio/checkbox-in-row tables */
|
|
table.picker { table-layout: fixed; }
|
|
table.picker td.pick { width: 2.5rem; text-align: center; }
|
|
table.picker input[type="radio"],
|
|
table.picker input[type="checkbox"] { margin: 0; }
|
|
table.picker tbody tr { cursor: pointer; }
|
|
table.picker tbody tr:hover td { background: #1c2128; }
|
|
/* Drop the global 14rem min-width for in-row text inputs so the picker
|
|
table can shrink to its container instead of pushing past it. */
|
|
table.picker input[type="text"] { min-width: 0; }
|
|
table.picker td { overflow: hidden; text-overflow: ellipsis; }
|
|
|
|
/* Flash messages */
|
|
.flash {
|
|
padding: 0.5rem 0.9rem;
|
|
margin-bottom: 1rem;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--border-strong);
|
|
background: #1d222a;
|
|
}
|
|
.flash.ok { border-color: #2f6b35; background: #16261a; color: #b6dcb8; }
|
|
.flash.err { border-color: #6b2f2f; background: #261616; color: #dcb6b6; }
|
|
.flash.warn { border-color: #6b5a2f; background: #261f16; color: #e1c98a; }
|