/* 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); } /* 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; 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; }