519 lines
16 KiB
CSS
519 lines
16 KiB
CSS
/* Shared Catppuccin palette + body typography + terminal pane styles.
|
|
Bundled in front of the page-specific rules via esbuild. */
|
|
@import "@hive/shared/base.css";
|
|
@import "@hive/shared/terminal.css";
|
|
|
|
/* ─── global typography ─────────────────────────────────────────────
|
|
Element-level rules shared across all three pages (index, flow,
|
|
logs). These must not reference page-specific chrome classes. */
|
|
|
|
h1, h2 {
|
|
color: var(--purple);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.15em;
|
|
margin-top: 2em;
|
|
text-shadow: 0 0 8px rgba(203, 166, 247, 0.4);
|
|
}
|
|
.divider {
|
|
color: var(--purple-dim);
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
ul { list-style: none; padding-left: 0; }
|
|
li { padding: 0.5em 0; }
|
|
.glyph { color: var(--purple); margin-right: 0.5em; }
|
|
a {
|
|
color: var(--cyan);
|
|
text-decoration: none;
|
|
font-weight: bold;
|
|
text-shadow: 0 0 4px rgba(137, 220, 235, 0.5);
|
|
}
|
|
a:hover {
|
|
color: var(--fg);
|
|
text-shadow: 0 0 12px rgba(137, 220, 235, 0.9);
|
|
}
|
|
code {
|
|
color: var(--amber);
|
|
background: var(--bg-elev);
|
|
padding: 0.1em 0.4em;
|
|
border: 1px solid var(--border);
|
|
border-radius: 2px;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
/* ─── shared inline labels ──────────────────────────────────────────
|
|
.meta / .id / .agent / .empty appear in message rows, build-log
|
|
toolbars, and side-panel content rendered by common.js. */
|
|
.meta { color: var(--muted); font-size: 0.85em; margin-left: 0.4em; }
|
|
.id { color: var(--pink); font-weight: bold; margin-right: 0.4em; }
|
|
.agent { color: var(--amber); font-weight: bold; margin-right: 0.6em; }
|
|
.empty { color: var(--muted); font-style: italic; }
|
|
|
|
/* ─── status badges ─────────────────────────────────────────────────
|
|
.badge base + semantic colour variants. Used on container rows
|
|
(tabs.js) and build-log rows (logs.js). */
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 0.05em 0.5em;
|
|
border: 1px solid;
|
|
border-radius: 2px;
|
|
font-size: 0.75em;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
.badge-warn {
|
|
color: var(--amber); border-color: var(--amber);
|
|
text-shadow: 0 0 6px rgba(250, 179, 135, 0.5);
|
|
}
|
|
.badge-rate-limited {
|
|
color: var(--red); border-color: var(--red);
|
|
text-shadow: 0 0 6px rgba(243, 139, 168, 0.5);
|
|
}
|
|
.badge-muted {
|
|
color: var(--muted); border-color: var(--purple-dim);
|
|
background: rgba(127, 132, 156, 0.08);
|
|
}
|
|
.badge-reminder {
|
|
color: var(--cyan); border-color: var(--cyan);
|
|
text-shadow: 0 0 6px rgba(137, 220, 235, 0.4);
|
|
}
|
|
.badge-loose-ends {
|
|
color: var(--purple); border-color: var(--purple);
|
|
text-shadow: 0 0 6px rgba(203, 166, 247, 0.4);
|
|
}
|
|
/* Context-window usage badges on dashboard container rows. */
|
|
.badge-ctx-ok {
|
|
color: var(--green); border-color: var(--green);
|
|
opacity: 0.85;
|
|
}
|
|
.badge-ctx-caution {
|
|
color: var(--amber); border-color: var(--amber);
|
|
text-shadow: 0 0 6px rgba(250, 179, 135, 0.5);
|
|
}
|
|
.badge-ctx-warn {
|
|
color: var(--red); border-color: var(--red);
|
|
text-shadow: 0 0 6px rgba(243, 139, 168, 0.5);
|
|
}
|
|
.badge-ok { background: rgba(166,227,161,0.12); color: var(--green); border-color: var(--green); }
|
|
.badge-fail { background: rgba(243,139,168,0.12); color: var(--red); border-color: var(--red); }
|
|
.badge-running { background: rgba(250,179,135,0.12); color: var(--amber); border-color: var(--amber); }
|
|
|
|
/* ─── buttons ───────────────────────────────────────────────────────
|
|
.btn base + semantic colour/size modifiers. Logs page uses
|
|
.btn-restart for the ↻ refresh buttons; dashboard uses all variants. */
|
|
.btn {
|
|
font-family: inherit;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
background: transparent;
|
|
/* Strip browser UA button chrome (solid fill, system text colour).
|
|
Without this, native <button> + <input type="submit"> elements
|
|
ignore our background:transparent and colour in some browsers. */
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
border: 1px solid;
|
|
padding: 0.25em 0.8em;
|
|
cursor: pointer;
|
|
text-shadow: 0 0 4px currentColor;
|
|
box-shadow: 0 0 0 0 currentColor;
|
|
transition: box-shadow 0.15s ease;
|
|
}
|
|
.btn:hover {
|
|
background: rgba(205, 214, 244, 0.06);
|
|
text-shadow: 0 0 10px currentColor;
|
|
box-shadow: 0 0 10px -2px currentColor;
|
|
}
|
|
.btn:disabled,
|
|
.btn[disabled] {
|
|
opacity: 0.32;
|
|
cursor: not-allowed;
|
|
text-shadow: none;
|
|
box-shadow: none;
|
|
}
|
|
.btn:disabled:hover,
|
|
.btn[disabled]:hover {
|
|
background: transparent;
|
|
text-shadow: none;
|
|
box-shadow: none;
|
|
}
|
|
.btn-approve { color: var(--green); border-color: var(--green); }
|
|
.btn-deny { color: var(--red); border-color: var(--red); }
|
|
.btn-destroy { color: var(--red); border-color: var(--red); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
.btn-rebuild { color: var(--amber); border-color: var(--amber); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
.btn-restart { color: var(--cyan); border-color: var(--cyan); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
.btn-stop { color: var(--pink); border-color: var(--pink); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
.btn-start { color: var(--green); border-color: var(--green); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
/* M0V3 affordance (selection bar) — mauve reads as "structural
|
|
change" rather than the destructive red / amber chrome of
|
|
destroy / rebuild. See docs/web-ui.md::Selection bar. */
|
|
.btn-move { color: var(--purple); border-color: var(--purple); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
|
|
.btn-talk { color: var(--cyan); border-color: var(--cyan); }
|
|
.btn-spawn { color: var(--amber); border-color: var(--amber); }
|
|
.btn-fire-now { color: var(--mauve, #cba6f7); border-color: var(--mauve, #cba6f7); }
|
|
/* Post-fire flash: report renders directly on the button for ~1.5s
|
|
so the operator sees ok/failed/missing/consumed counts inline
|
|
without a modal. Green when at least one ok; muted otherwise. */
|
|
.btn-fire-now-flashed {
|
|
color: var(--green);
|
|
border-color: var(--green);
|
|
text-shadow: 0 0 6px currentColor;
|
|
box-shadow: 0 0 8px -2px currentColor;
|
|
}
|
|
/* Inline edit button on each schedule row. Yellow reads as a
|
|
parallel destructive-adjacent action (edit changes state, but
|
|
isn't deletion). */
|
|
.btn-edit-schedule { color: var(--yellow, #f9e2af); border-color: var(--yellow, #f9e2af); }
|
|
|
|
/* ─── file-preview / diff panel (common.js Panel) ───────────────────
|
|
Side-panel content rendered by openFilePanel / buildTabbedPreview
|
|
in common.js; all three pages load the Panel singleton. */
|
|
.diff-panel { display: flex; flex-direction: column; gap: 0.6em; }
|
|
.diff-base-tabs { display: flex; flex-wrap: wrap; gap: 0.4em; }
|
|
.diff-base-tab {
|
|
background: transparent;
|
|
border: 1px solid var(--border);
|
|
color: var(--muted);
|
|
font: inherit;
|
|
font-size: 0.85em;
|
|
padding: 0.2em 0.7em;
|
|
cursor: pointer;
|
|
}
|
|
.diff-base-tab:hover { color: var(--fg); }
|
|
.diff-base-tab.active {
|
|
color: var(--purple);
|
|
border-color: var(--purple);
|
|
background: rgba(203, 166, 247, 0.08);
|
|
}
|
|
/* Image / tabbed file preview */
|
|
.preview-host { margin-top: 0.5em; }
|
|
.img-preview {
|
|
display: block;
|
|
max-width: 100%;
|
|
height: auto;
|
|
margin: 0 auto;
|
|
border: 1px solid var(--border);
|
|
border-radius: 4px;
|
|
/* checkerboard so transparent regions of the image read clearly */
|
|
background: repeating-conic-gradient(#313244 0% 25%, #1e1e2e 0% 50%) 50% / 18px 18px;
|
|
}
|
|
|
|
/* Path linkification — agents drop pointer strings into messages;
|
|
clicking the anchor opens the file in the side panel. */
|
|
.path-link {
|
|
color: var(--blue, #89b4fa);
|
|
text-decoration: underline dotted;
|
|
cursor: pointer;
|
|
}
|
|
.path-link:hover { color: var(--amber); }
|
|
/* File-preview body — rendered inside the side panel. */
|
|
.path-preview-body {
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
padding: 0.5em 0.7em;
|
|
margin: 0;
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
font-size: 0.85em;
|
|
color: var(--fg);
|
|
}
|
|
|
|
/* ─── page chrome: header + back link (flow + logs pages) ───────────
|
|
.logs-header / .logs-back / .logs-title are used by both
|
|
/flow.html and /logs.html — the same frosted sticky bar pattern. */
|
|
.logs-header {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 25;
|
|
background: rgba(30, 30, 46, 0.92);
|
|
-webkit-backdrop-filter: blur(8px) saturate(120%);
|
|
backdrop-filter: blur(8px) saturate(120%);
|
|
border-bottom: 1px solid var(--purple-dim);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1.5em;
|
|
padding: 0.5em 1.5em;
|
|
}
|
|
|
|
.logs-back {
|
|
color: var(--purple);
|
|
text-decoration: none;
|
|
font-size: 0.88em;
|
|
white-space: nowrap;
|
|
flex: none;
|
|
}
|
|
.logs-back:hover { text-decoration: underline; }
|
|
|
|
.logs-title {
|
|
color: var(--subtext0);
|
|
font-size: 0.85em;
|
|
letter-spacing: 0.05em;
|
|
flex: none;
|
|
}
|
|
|
|
/* ─── operator inbox + message rows ────────────────────────────────
|
|
.inbox and .msg-* are rendered by common.js (renderInbox) and
|
|
flow.js — both the dashboard side panel and the /flow.html page
|
|
display broker messages. */
|
|
.inbox {
|
|
background: var(--bg-elev);
|
|
border: 1px solid var(--border);
|
|
padding: 0.5em 0.8em;
|
|
/* No max-height cap — let the inbox grow to fill the
|
|
side-panel-body which already scrolls. */
|
|
}
|
|
.inbox li {
|
|
padding: 0.25em 0;
|
|
border-bottom: 1px solid var(--border);
|
|
display: grid;
|
|
grid-template-columns: auto auto auto 1fr;
|
|
gap: 0.5em;
|
|
align-items: baseline;
|
|
}
|
|
.inbox li:last-child { border-bottom: 0; }
|
|
.inbox .msg-ts { color: var(--muted); font-size: 0.85em; }
|
|
.inbox .msg-from { color: var(--amber); }
|
|
.inbox .msg-sep { color: var(--muted); }
|
|
.inbox .msg-body { color: var(--fg); white-space: pre-wrap; word-break: break-word; }
|
|
/* `#msgflow` is a shared `.live` pane inside `.terminal-wrap`. The
|
|
msgrow / msg-* rules below power both the dashboard CALL tab and
|
|
the /flow.html full-page terminal. */
|
|
.live .msgrow {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: 0.5em;
|
|
padding: 0.1em 0;
|
|
text-indent: 0;
|
|
}
|
|
.live .msgrow .msg-body {
|
|
flex: 1 1 100%;
|
|
min-width: 0;
|
|
}
|
|
.live .msgrow.sent .msg-arrow { color: var(--cyan); }
|
|
.live .msgrow.delivered .msg-arrow { color: var(--green); }
|
|
/* Reply-thread rendering: indented border-left + muted reply tag. */
|
|
.live .msgrow.msg-reply {
|
|
padding-left: 1.2em;
|
|
border-left: 2px solid var(--border);
|
|
margin-left: 0.6em;
|
|
}
|
|
.msg-reply-tag {
|
|
color: var(--muted);
|
|
font-size: 0.8em;
|
|
white-space: nowrap;
|
|
order: -1;
|
|
}
|
|
.msg-reply-tag a {
|
|
color: var(--muted);
|
|
text-shadow: none;
|
|
font-weight: normal;
|
|
}
|
|
.msg-reply-tag a:hover { color: var(--fg); }
|
|
@keyframes msg-highlight-fade {
|
|
from { background: rgba(203, 166, 247, 0.18); }
|
|
to { background: transparent; }
|
|
}
|
|
.msg-highlight { animation: msg-highlight-fade 1.5s ease-out forwards; }
|
|
.msg-ts { color: var(--muted); font-size: 0.85em; }
|
|
.msg-arrow { font-weight: bold; }
|
|
.msg-from { color: var(--amber); }
|
|
.msg-sep { color: var(--muted); }
|
|
.msg-to { color: var(--pink); }
|
|
.msg-body { color: var(--fg); white-space: pre-wrap; word-break: break-word; }
|
|
|
|
/* ─── operator compose box ──────────────────────────────────────────
|
|
Sits inside `.terminal-wrap` on both /flow.html and the dashboard
|
|
CALL tab. Dashed top separator mirrors the agent terminal prompt. */
|
|
.op-compose {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 0.6em;
|
|
padding: 0.55em 0.8em;
|
|
border-top: 1px dashed var(--purple-dim);
|
|
}
|
|
.op-compose-prompt {
|
|
color: var(--purple);
|
|
text-shadow: 0 0 4px currentColor;
|
|
font-weight: bold;
|
|
white-space: nowrap;
|
|
user-select: none;
|
|
padding-top: 0.15em;
|
|
}
|
|
.op-compose-input {
|
|
flex: 1;
|
|
background: transparent;
|
|
color: var(--fg);
|
|
border: none;
|
|
font-family: inherit;
|
|
font-size: 1em;
|
|
line-height: 1.4;
|
|
resize: none;
|
|
overflow: hidden;
|
|
max-height: 8em;
|
|
padding: 0;
|
|
}
|
|
.op-compose-input:focus { outline: none; }
|
|
.op-compose-input::placeholder { color: var(--muted); }
|
|
.op-compose-suggest {
|
|
position: absolute;
|
|
left: 3em;
|
|
bottom: 100%;
|
|
z-index: 50;
|
|
background: var(--bg-elev);
|
|
border: 1px solid var(--purple-dim);
|
|
border-radius: 4px;
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0.3em 0;
|
|
min-width: 12em;
|
|
max-height: 14em;
|
|
overflow-y: auto;
|
|
}
|
|
.op-compose-suggest .item {
|
|
padding: 0.35em 0.9em;
|
|
cursor: pointer;
|
|
font-size: 0.9em;
|
|
color: var(--muted);
|
|
}
|
|
.op-compose-suggest .item.active,
|
|
.op-compose-suggest .item:hover {
|
|
background: var(--border);
|
|
color: var(--purple);
|
|
}
|
|
|
|
/* ─── side panel ─────────────────────────────────────────────────
|
|
Long content (file previews, diffs, journald, applied config)
|
|
opens in a drawer that swipes in from the right — used by both
|
|
/flow.html and the dashboard. */
|
|
.side-panel {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 200;
|
|
pointer-events: none;
|
|
}
|
|
.side-panel-backdrop {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: rgba(17, 17, 27, 0.55);
|
|
opacity: 0;
|
|
transition: opacity 200ms ease;
|
|
}
|
|
.side-panel-drawer {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
width: min(42em, 95vw);
|
|
background: var(--bg-elev);
|
|
border-left: 1px solid var(--purple-dim);
|
|
display: flex;
|
|
flex-direction: column;
|
|
transform: translateX(100%);
|
|
transition: transform 220ms ease;
|
|
overflow: hidden;
|
|
}
|
|
.side-panel.open { pointer-events: auto; }
|
|
.side-panel.open .side-panel-backdrop { opacity: 1; }
|
|
.side-panel.open .side-panel-drawer { transform: translateX(0); }
|
|
.side-panel-resize {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 6px;
|
|
cursor: ew-resize;
|
|
opacity: 0;
|
|
transition: opacity 120ms;
|
|
background: var(--purple-dim);
|
|
}
|
|
.side-panel-resize:hover,
|
|
body.side-panel-resizing .side-panel-resize {
|
|
opacity: 1;
|
|
}
|
|
body.side-panel-resizing .side-panel-resize {
|
|
background: var(--purple);
|
|
}
|
|
body.side-panel-resizing {
|
|
user-select: none;
|
|
}
|
|
body.side-panel-resizing * { cursor: ew-resize !important; }
|
|
.side-panel-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.6em;
|
|
padding: 0.6em 1em;
|
|
border-bottom: 1px solid var(--border);
|
|
flex: none;
|
|
}
|
|
.side-panel-title {
|
|
flex: 1;
|
|
font-size: 0.88em;
|
|
color: var(--muted);
|
|
letter-spacing: 0.04em;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.side-panel-close {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: none;
|
|
border: 1px solid var(--border);
|
|
border-radius: 3px;
|
|
color: var(--muted);
|
|
font-size: 1em;
|
|
line-height: 1;
|
|
padding: 0.15em 0.4em;
|
|
cursor: pointer;
|
|
transition: border-color 0.15s ease, color 0.15s ease;
|
|
}
|
|
.side-panel-close:hover { border-color: var(--red); color: var(--red); }
|
|
.side-panel-body {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 0.8em 1em;
|
|
font-size: 0.88em;
|
|
}
|
|
.side-panel-body .md { color: var(--fg); line-height: 1.5; }
|
|
.side-panel-body .md > :first-child { margin-top: 0; }
|
|
.side-panel-body .md > :last-child { margin-bottom: 0; }
|
|
.side-panel-body .md p { margin: 0.5em 0; }
|
|
.side-panel-body .md h1,
|
|
.side-panel-body .md h2,
|
|
.side-panel-body .md h3,
|
|
.side-panel-body .md h4 { color: var(--purple); margin: 0.9em 0 0.4em; }
|
|
.side-panel-body .md code {
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 2px;
|
|
padding: 0.1em 0.3em;
|
|
font-size: 0.9em;
|
|
}
|
|
.side-panel-body .md pre {
|
|
background: var(--crust);
|
|
border: 1px solid var(--border);
|
|
padding: 0.5em 0.7em;
|
|
overflow-x: auto;
|
|
margin: 0.5em 0;
|
|
}
|
|
.side-panel-body .md pre code { background: none; border: none; padding: 0; }
|
|
.side-panel-body .md a { color: var(--cyan); }
|
|
.side-panel-body .md ul,
|
|
.side-panel-body .md ol { margin: 0.4em 0; padding-left: 1.5em; }
|
|
.side-panel-body .md blockquote {
|
|
border-left: 3px solid var(--purple-dim);
|
|
padding-left: 0.8em;
|
|
margin: 0.4em 0;
|
|
color: var(--muted);
|
|
}
|
|
.side-panel-body .md table { border-collapse: collapse; margin: 0.5em 0; }
|
|
.side-panel-body .md th,
|
|
.side-panel-body .md td {
|
|
border: 1px solid var(--border);
|
|
padding: 0.2em 0.5em;
|
|
}
|