@blundergoat/goat-flow
Version:
AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.
2,314 lines (2,253 loc) • 125 kB
CSS
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600;700&display=swap");
/* ═══════════════════════════════════════════════════════════
GOAT Flow Dashboard - Design Tokens & Component Styles
═══════════════════════════════════════════════════════════ */
/* ═══ Color Palette ═══ */
/* Every color in the dashboard defined once. Change here, changes everywhere. */
:root {
/* Typography */
--font-body:
"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-mono:
"Cascadia Code", "JetBrains Mono", "Fira Code", Consolas, monospace;
/* Zinc (neutral) */
--zinc-950: #0d0d10;
--zinc-900: #111114;
--zinc-850: #1a1a1e;
--zinc-825: #1e1e22;
--zinc-800: #27272a;
--zinc-750: #2a2a2e;
--zinc-700: #3f3f46;
--zinc-600: #52525b;
--zinc-500: #71717a;
--zinc-400: #a1a1aa;
--zinc-300: #d4d4d8;
--zinc-200: #e4e4e7;
--zinc-100: #f4f4f5;
--zinc-50: #fafafa;
/* Green (healthy/passing status) */
--green-950: #0d1a0d;
--green-900: #14532d;
--green-800: #166534;
--green-700: #15803d;
--green-600: #16a34a;
--green-500: #22c55e;
--green-400: #4ade80;
--green-300: #86efac;
--green-200: #bbf7d0;
--green-100: #dcfce7;
--green-50: #f0fdf4;
/* Red (danger) */
--red-950: #450a0a;
--red-900: #7f1d1d;
--red-800: #991b1b;
--red-700: #dc2626;
--red-400: #f87171;
--red-300: #fca5a5;
--red-200: #fecaca;
--red-100: #fee2e2;
/* Amber (warning) */
--amber-950: #422006;
--amber-700: #b45309;
--amber-600: #d97706;
--amber-400: #fbbf24;
--amber-300: #facc15;
--amber-100: #fef9c3;
--amber-50: #fef3c7;
/* Orange (high severity) */
--orange-950: #451a03;
--orange-700: #c2410c;
--orange-400: #fb923c;
--orange-100: #ffedd5;
/* Blue / Indigo / Purple */
--blue-400: #60a5fa;
--indigo-950: #1e3a5f;
--indigo-700: #4338ca;
--indigo-600: #4f46e5;
--indigo-400: #818cf8;
--indigo-100: #e0e7ff;
--purple-400: #c084fc;
}
/* ═══ Semantic Tokens (dark theme = default) ═══ */
:root {
--text-primary: #e2e8f0;
--text-secondary: #cbd5e1;
--text-muted: #94a3b8;
--text-disabled: #64748b;
--surface-deep: #0b0f14;
--surface-base: #11161d;
--surface-page: #0d1218;
--surface-elevated: #1a212c;
--border-faint: rgba(148, 163, 184, 0.08);
--border-subtle: rgba(148, 163, 184, 0.16);
--border-default: rgba(148, 163, 184, 0.28);
--accent: #818cf8;
--accent-hover: #a5b4fc;
--accent-bg: rgba(129, 140, 248, 0.12);
--accent-strong: #4f46e5;
--accent-contrast: #ffffff;
--accent-border: rgba(129, 140, 248, 0.36);
--status-pass: var(--green-400);
--status-pass-bg: rgba(34, 197, 94, 0.1);
--status-pass-border: rgba(34, 197, 94, 0.28);
--status-running: var(--accent);
--status-running-bg: rgba(129, 140, 248, 0.12);
--status-running-border: rgba(129, 140, 248, 0.32);
--status-waiting: var(--amber-400);
/* Saturated orange for partial-score signals on the Skills/Quality pages.
Distinct from --status-waiting (amber yellow) so partial bars don't
read as the same colour as caution-state pills. */
--orange-warn: #f59e0b;
--orange-warn-bg: rgba(245, 158, 11, 0.1);
--orange-warn-border: rgba(245, 158, 11, 0.28);
--status-recent: var(--zinc-400);
--status-danger: var(--red-400);
--amber-bg: rgba(245, 158, 11, 0.1);
--amber-border: rgba(245, 158, 11, 0.3);
--red-bg: rgba(248, 113, 113, 0.1);
--red-border: rgba(248, 113, 113, 0.3);
--neutral-bg: rgba(148, 163, 184, 0.08);
--neutral-border: rgba(148, 163, 184, 0.22);
--ui-workflow-text: #38bdf8;
--ui-workflow-bg: rgba(14, 165, 233, 0.12);
--ui-workflow-border: rgba(56, 189, 248, 0.4);
}
/* ═══ Light Theme Token Overrides ═══ */
:root:not(.dark) {
--text-primary: #0f172a;
--text-secondary: #334155;
--text-muted: #475569;
--text-disabled: #64748b;
--surface-deep: #fafbfc;
--surface-base: #ffffff;
--surface-page: #f1f5f9;
--surface-elevated: #e2e8f0;
--border-faint: rgba(15, 23, 42, 0.06);
--border-subtle: rgba(15, 23, 42, 0.08);
--border-default: rgba(15, 23, 42, 0.18);
--accent: #4f46e5;
--accent-hover: #4338ca;
--accent-bg: rgba(79, 70, 229, 0.08);
--accent-strong: #4f46e5;
--accent-contrast: #ffffff;
--accent-border: rgba(79, 70, 229, 0.3);
--status-pass: var(--green-600);
--status-pass-bg: rgba(22, 163, 74, 0.08);
--status-pass-border: rgba(22, 163, 74, 0.28);
--status-running: var(--accent);
--status-running-bg: rgba(79, 70, 229, 0.08);
--status-running-border: rgba(79, 70, 229, 0.28);
--status-waiting: var(--amber-600);
--orange-warn: #d97706;
--orange-warn-bg: rgba(217, 119, 6, 0.08);
--orange-warn-border: rgba(217, 119, 6, 0.32);
--status-recent: var(--zinc-500);
--status-danger: var(--red-700);
--amber-bg: rgba(217, 119, 6, 0.1);
--amber-border: rgba(217, 119, 6, 0.3);
--red-bg: rgba(220, 38, 38, 0.08);
--red-border: rgba(220, 38, 38, 0.28);
--neutral-bg: rgba(15, 23, 42, 0.05);
--neutral-border: rgba(15, 23, 42, 0.14);
--ui-workflow-text: #0369a1;
--ui-workflow-bg: #e0f2fe;
--ui-workflow-border: rgba(2, 132, 199, 0.28);
}
/* ═══ Global Resets ═══ */
[x-cloak] {
display: none !important;
}
button,
select,
summary,
label,
[role="button"] {
cursor: pointer;
}
body {
font-family: var(--font-body);
font-size: 14px;
line-height: 1.5;
}
.terminal-container {
width: 100%;
height: 100%;
}
.terminal-container .xterm {
height: 100%;
}
.terminal-session-shell {
background: #0f1729;
}
.terminal-loading-overlay {
position: absolute;
inset: 0;
z-index: 4;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: #0f1729;
color: #cbd5e1;
font-family: var(--font-mono);
}
.terminal-loading-card {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
max-width: min(440px, 100%);
text-align: center;
}
.terminal-loading-row {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
min-height: 22px;
font-size: 13px;
}
.terminal-loading-spinner::before {
display: inline-block;
width: 1.1em;
content: "⠋";
animation: terminal-loading-spinner 0.8s steps(10, end) infinite;
}
.terminal-loading-hint {
max-width: 34rem;
margin: 0;
color: #94a3b8;
font-family: var(--font-body);
font-size: 12px;
}
.terminal-loading-overlay-error {
color: #fecaca;
}
.terminal-overlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.6);
z-index: 10;
border-radius: 0.75rem;
}
@keyframes terminal-loading-spinner {
0% {
content: "⠋";
}
10% {
content: "⠙";
}
20% {
content: "⠹";
}
30% {
content: "⠸";
}
40% {
content: "⠼";
}
50% {
content: "⠴";
}
60% {
content: "⠦";
}
70% {
content: "⠧";
}
80% {
content: "⠇";
}
90%,
100% {
content: "⠏";
}
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.gf-icon-sprite {
display: none;
}
.gf-preset-badge {
display: inline-flex;
align-items: center;
height: 18px;
padding: 1px 6px;
border-radius: 3px;
border: 1px solid var(--border-subtle);
font-size: 10px;
line-height: 1;
color: var(--text-secondary);
background: rgba(148, 163, 184, 0.08);
white-space: nowrap;
}
.gf-preset-badge-good {
color: var(--status-pass);
border-color: var(--status-pass-border);
background: var(--status-pass-bg);
}
.gf-preset-badge-warn {
color: #f59e0b;
border-color: rgba(245, 158, 11, 0.35);
background: rgba(245, 158, 11, 0.1);
}
.gf-preset-badge-danger {
color: #f87171;
border-color: rgba(248, 113, 113, 0.35);
background: rgba(248, 113, 113, 0.1);
}
.gf-preset-badge-ui {
color: var(--ui-workflow-text);
border-color: var(--ui-workflow-border);
background: var(--ui-workflow-bg);
}
.gf-check-row {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 24px;
color: var(--text-secondary);
font-size: 12px;
}
.gf-check-row input {
width: 13px;
height: 13px;
flex-shrink: 0;
}
:focus-visible {
outline: 2px solid var(--blue-400);
outline-offset: 3px;
border-radius: 4px;
box-shadow: 0 0 0 4px rgba(96, 165, 250, 0.3);
}
/* ═══ Tailwind Dark Mode Fallback ═══ */
/* Patches Tailwind utility colors for dark mode */
.dark {
background-color: var(--zinc-850) !important;
color: var(--zinc-200);
}
.dark .bg-white {
background-color: var(--zinc-900) !important;
}
.dark .bg-gray-50,
.dark .bg-gray-100 {
background-color: var(--zinc-850) !important;
}
.dark .bg-gray-800 {
background-color: var(--zinc-900) !important;
}
.dark .bg-gray-700 {
background-color: var(--zinc-800) !important;
}
.dark .bg-gray-900 {
background-color: var(--zinc-850) !important;
}
.dark .border-gray-200,
.dark .border-gray-100 {
border-color: var(--zinc-750) !important;
}
.dark .border-gray-300 {
border-color: var(--zinc-700) !important;
}
.dark .border-gray-600 {
border-color: var(--zinc-700) !important;
}
.dark .border-gray-700 {
border-color: var(--zinc-750) !important;
}
.dark .text-gray-900 {
color: var(--zinc-200) !important;
}
.dark .text-gray-700 {
color: var(--zinc-300) !important;
}
.dark .text-gray-600 {
color: var(--zinc-400) !important;
}
.dark .text-gray-500 {
color: var(--zinc-400) !important;
}
.dark .text-gray-400 {
color: var(--zinc-500) !important;
}
.dark .text-gray-300 {
color: var(--zinc-400) !important;
}
.dark input,
.dark textarea {
background-color: var(--zinc-850) !important;
color: var(--zinc-200) !important;
border-color: var(--zinc-700) !important;
}
.dark pre {
color: var(--zinc-300) !important;
}
.dark .stroke-gray-700,
.dark path[stroke="#e5e7eb"] {
stroke: var(--zinc-750) !important;
}
.dark .border-l-blue-400 {
border-left-color: var(--blue-400) !important;
}
.dark .border-l-purple-400 {
border-left-color: var(--purple-400) !important;
}
.dark .border-l-amber-400 {
border-left-color: var(--amber-400) !important;
}
.dark .border-l-green-400 {
border-left-color: var(--green-400) !important;
}
.dark .border-l-red-400 {
border-left-color: var(--red-400) !important;
}
.dark .border-l-emerald-400 {
border-left-color: #34d399 !important;
}
.dark .border-l-gray-400 {
border-left-color: #9ca3af !important;
}
/* ═══ Print ═══ */
@media print {
.no-print {
display: none !important;
}
body {
background: white !important;
color: black !important;
}
.shadow {
box-shadow: none !important;
border: 1px solid var(--zinc-200);
}
main {
padding: 0 !important;
}
* {
break-inside: avoid;
}
svg path {
stroke-width: 4 !important;
}
[role="tabpanel"] {
page-break-before: auto;
}
h3 {
page-break-after: avoid;
}
.rounded-full {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
span[class*="bg-"] {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
}
/* ═══ Scrollbars ═══ */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
.dark ::-webkit-scrollbar-thumb {
background: var(--zinc-700);
border-radius: 3px;
}
.dark ::-webkit-scrollbar-thumb:hover {
background: var(--zinc-600);
}
:root:not(.dark) ::-webkit-scrollbar-thumb {
background: var(--zinc-300);
border-radius: 3px;
}
:root:not(.dark) ::-webkit-scrollbar-thumb:hover {
background: var(--zinc-400);
}
* {
scrollbar-width: thin;
scrollbar-color: var(--zinc-700) transparent;
}
:root:not(.dark) * {
scrollbar-color: var(--zinc-300) transparent;
}
/* ═══════════════════════════════════════════════════════════
GOAT Flow Components
All classes use semantic tokens → no light mode overrides needed
═══════════════════════════════════════════════════════════ */
/* --- Text helpers --- */
.gf-text-primary {
color: var(--text-primary);
}
.gf-text-secondary {
color: var(--text-secondary);
}
.gf-text-muted {
color: var(--text-muted);
}
.gf-text-disabled {
color: var(--text-disabled);
}
.section-label,
.gf-section-label {
color: var(--text-muted);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
line-height: 1.2;
text-transform: uppercase;
}
.gf-section-count {
color: var(--text-disabled);
font-family: var(--font-mono);
font-weight: 500;
letter-spacing: 0.04em;
}
/* --- Empty states --- */
.gf-empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
padding: 22px 16px;
text-align: center;
color: var(--text-muted);
}
.gf-empty-mark {
display: inline-grid;
place-items: center;
width: 36px;
height: 36px;
border-radius: 8px;
color: var(--text-muted);
background: var(--neutral-bg);
border: 1px solid var(--neutral-border);
font-family: var(--font-mono);
font-size: 12px;
font-weight: 700;
}
.gf-empty-state p {
margin: 0;
max-width: 360px;
color: var(--text-muted);
font-size: 13px;
}
/* --- Status marks --- */
.gf-status-dot {
display: inline-grid;
place-items: center;
width: 14px;
height: 14px;
border-radius: 999px;
flex: 0 0 auto;
font-family: var(--font-mono);
font-size: 8px;
font-weight: 700;
line-height: 1;
color: var(--surface-deep);
background: var(--status-recent);
}
.gf-status-pass {
background: var(--status-pass);
box-shadow: 0 0 0 3px var(--status-pass-bg);
}
.gf-status-running {
background: var(--status-running);
box-shadow: 0 0 0 3px var(--status-running-bg);
}
.gf-status-waiting {
background: var(--status-waiting);
box-shadow: 0 0 0 3px var(--amber-bg);
}
.gf-status-recent {
background: var(--status-recent);
color: var(--surface-base);
box-shadow: 0 0 0 3px var(--neutral-bg);
}
.gf-status-danger {
background: var(--status-danger);
box-shadow: 0 0 0 3px var(--red-bg);
}
/* --- Workspace session rail --- */
.workspace-session-rail {
--workspace-rail-inset: 16px;
padding: 0;
}
.workspace-session-rail.is-collapsed {
padding: 8px 8px 12px;
overflow: visible;
}
.workspace-session-expanded {
display: flex;
min-height: 0;
flex: 1 1 auto;
flex-direction: column;
padding-top: 20px;
}
.workspace-session-heading,
.workspace-session-launch,
.workspace-session-footer {
padding-right: var(--workspace-rail-inset);
padding-left: var(--workspace-rail-inset);
}
.workspace-session-heading {
flex: 0 0 auto;
margin-bottom: 10px;
}
.workspace-session-list-scroll {
display: flex;
min-height: 0;
flex: 1 1 auto;
flex-direction: column;
gap: 24px;
overflow-y: auto;
padding: 0 var(--workspace-rail-inset) 2px;
scrollbar-width: none;
}
.workspace-session-list-scroll::-webkit-scrollbar {
display: none;
}
.workspace-session-card-stack {
display: flex;
flex-direction: column;
gap: 8px;
}
.workspace-session-card {
position: relative;
padding: 12px;
border-left-width: 3px;
border-left-color: transparent;
cursor: pointer;
}
.workspace-session-card.is-active {
border-color: var(--accent-border);
border-left-color: var(--accent);
background: var(--accent-bg);
}
.workspace-session-card.is-waiting:not(.is-active) {
border-color: var(--amber-border);
background: var(--amber-bg);
}
.workspace-session-card-body {
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
gap: 4px;
}
.workspace-session-title-row {
display: flex;
min-width: 0;
align-items: center;
gap: 7px;
}
.workspace-session-title {
min-width: 0;
overflow: hidden;
flex: 1 1 auto;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
font-weight: 600;
}
.workspace-agent-chip {
display: inline-flex;
max-width: 76px;
flex: 0 0 auto;
align-items: center;
justify-content: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 1px 6px;
border: 1px solid var(--workspace-agent-border, var(--border-subtle));
border-radius: 999px;
background: var(--workspace-agent-bg, var(--neutral-bg));
color: var(--workspace-agent-color, var(--text-secondary));
font-family: var(--font-mono);
font-size: 10px;
font-weight: 700;
line-height: 1.35;
}
.workspace-agent-claude {
--workspace-agent-color: var(--purple-400);
--workspace-agent-bg: color-mix(in srgb, var(--purple-400) 12%, transparent);
--workspace-agent-border: color-mix(
in srgb,
var(--purple-400) 34%,
transparent
);
}
.workspace-agent-codex {
--workspace-agent-color: var(--green-400);
--workspace-agent-bg: var(--status-pass-bg);
--workspace-agent-border: var(--status-pass-border);
}
.workspace-agent-antigravity {
--workspace-agent-color: var(--blue-400);
--workspace-agent-bg: color-mix(in srgb, var(--blue-400) 12%, transparent);
--workspace-agent-border: color-mix(
in srgb,
var(--blue-400) 34%,
transparent
);
}
.workspace-agent-copilot {
--workspace-agent-color: var(--ui-workflow-text);
--workspace-agent-bg: var(--ui-workflow-bg);
--workspace-agent-border: var(--ui-workflow-border);
}
.workspace-action-btn {
font-size: 11px;
}
.workspace-danger-ghost {
border-color: transparent;
background: transparent;
color: var(--red-400);
font-size: 11px;
}
.workspace-danger-ghost:hover {
border-color: var(--red-border);
background: var(--red-bg);
color: var(--red-400);
}
.workspace-session-confirm {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
margin-top: 8px;
font-size: 11px;
}
.workspace-session-empty {
align-items: flex-start;
justify-content: flex-start;
padding: 10px 0 2px;
text-align: left;
}
.workspace-session-launch {
flex: 0 0 auto;
margin-top: 24px;
}
.workspace-session-collapsed {
position: relative;
display: flex;
min-height: 0;
flex: 1 1 auto;
flex-direction: column;
align-items: center;
overflow: visible;
padding-top: 8px;
}
.workspace-collapsed-launch {
width: 36px;
height: 36px;
padding: 0;
justify-content: center;
margin-bottom: 12px;
}
.workspace-collapsed-divider {
width: 28px;
height: 1px;
flex: 0 0 auto;
margin-bottom: 12px;
background: var(--border-subtle);
}
.workspace-collapsed-stack {
display: flex;
width: 100%;
min-height: 0;
flex: 1 1 auto;
flex-direction: column;
align-items: center;
gap: 10px;
overflow-y: auto;
overflow-x: visible;
padding: 4px 0;
}
.workspace-session-dot-btn {
position: relative;
display: inline-grid;
place-items: center;
width: 38px;
height: 38px;
padding: 0;
border: 1px solid transparent;
border-radius: 10px;
background: transparent;
color: var(--text-secondary);
}
.workspace-session-dot-btn:hover {
background: var(--neutral-bg);
}
.workspace-session-dot-btn.is-active {
border-color: transparent;
box-shadow: 0 0 0 2px var(--accent);
}
.workspace-session-dot {
position: relative;
display: inline-block;
width: 26px;
height: 26px;
border: 2px solid var(--workspace-agent-border, var(--border-default));
border-radius: 999px;
background: var(--workspace-agent-color, var(--text-muted));
box-shadow: inset 0 0 0 1px
color-mix(in srgb, var(--surface-base) 28%, transparent);
}
.workspace-session-pip {
position: absolute;
right: -2px;
bottom: -2px;
width: 9px;
height: 9px;
border: 2px solid var(--surface-base);
border-radius: 999px;
background: var(--status-recent);
}
.workspace-session-pip.is-running {
background: var(--green-400);
animation: workspace-session-pulse 1.6s ease-in-out infinite;
}
.workspace-session-pip.is-waiting {
background: var(--amber-400);
}
.workspace-session-pip.is-error {
background: var(--red-400);
}
.workspace-session-pip.is-idle {
background: var(--status-recent);
}
.workspace-session-tooltip {
white-space: normal;
}
.workspace-floating-dot-tooltip {
bottom: auto;
z-index: 60;
opacity: 0;
visibility: hidden;
}
.workspace-floating-dot-tooltip.is-visible {
opacity: 1;
visibility: visible;
transform: translate(0, -50%);
transition:
opacity 0.14s ease 0.22s,
transform 0.14s ease 0.22s,
visibility 0s linear 0.22s;
}
.workspace-session-footer {
flex: 0 0 auto;
margin-top: auto;
padding-top: 24px;
padding-bottom: 12px;
}
.workspace-session-rail.is-collapsed .workspace-session-footer {
padding: 12px 0 0;
}
.workspace-footer-tooltip-wrap,
.workspace-session-toggle {
width: 100%;
}
.workspace-session-toggle {
justify-content: flex-start;
}
.workspace-session-rail.is-collapsed .workspace-session-toggle {
width: 40px;
height: 36px;
justify-content: center;
padding: 0;
}
.workspace-session-toggle-glyph {
display: inline-flex;
width: 16px;
justify-content: center;
flex: 0 0 auto;
font-family: var(--font-mono);
font-size: 15px;
font-weight: 700;
}
@keyframes workspace-session-pulse {
0%,
100% {
box-shadow: 0 0 0 0 var(--status-pass-bg);
}
50% {
box-shadow: 0 0 0 4px var(--status-pass-bg);
}
}
@media (prefers-reduced-motion: reduce) {
.workspace-session-pip.is-running {
animation: none;
}
}
/* --- Tags --- */
.gf-tags {
display: flex !important;
flex-wrap: wrap;
gap: 6px;
margin-top: 7px;
}
.gf-tag {
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
background: var(--surface-elevated);
color: var(--text-secondary);
border: none;
}
/* --- Custom prompt form --- */
.gf-custom-prompt-form {
display: flex;
flex-direction: column;
gap: 16px;
min-height: 420px;
}
.gf-custom-form-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
padding-bottom: 12px;
border-bottom: 1px solid var(--border-subtle);
}
.gf-custom-form-head h3 {
margin: 4px 0 0;
font-size: 16px;
font-weight: 600;
}
.gf-custom-form-head-actions {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-end;
gap: 8px 10px;
min-width: 0;
}
.gf-custom-form-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: flex-end;
gap: 8px;
}
.gf-custom-form-actions .gf-btn {
white-space: nowrap;
}
.gf-start-picker {
position: relative;
display: flex;
justify-content: flex-end;
}
.gf-start-picker-trigger {
padding: 5px 8px;
border-radius: 6px;
}
.gf-start-picker-trigger:hover {
background: var(--neutral-bg);
}
.gf-start-picker-panel {
position: absolute;
right: 0;
top: calc(100% + 6px);
z-index: 30;
display: grid;
grid-template-columns: minmax(220px, 1fr) auto;
gap: 8px;
min-width: min(460px, calc(100vw - 48px));
padding: 10px;
border: 1px solid var(--border-default);
border-radius: 8px;
background: var(--surface-base);
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.24);
}
.gf-validation-summary {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 10px;
padding: 10px 12px;
border: 1px solid var(--red-border);
border-radius: 8px;
background: var(--red-bg);
color: var(--red-400);
font-size: 12px;
}
.gf-validation-title {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.gf-validation-summary a {
color: var(--red-400);
text-decoration: underline;
text-underline-offset: 2px;
}
.gf-prompt-list-card {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 12px;
border-left-width: 3px;
cursor: pointer;
text-align: left;
}
.gf-prompt-favorite {
margin-top: 2px;
padding: 0;
border: 0;
background: transparent;
color: var(--text-dim);
cursor: pointer;
line-height: 1;
}
.gf-prompt-favorite-preview {
cursor: default;
}
.gf-prompt-card-content {
min-width: 0;
flex: 1;
}
.gf-prompt-card-title {
font-size: 13px;
font-weight: 500;
}
.gf-prompt-card-desc {
margin: 2px 0 6px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
}
.gf-prompt-card-meta {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
}
.gf-prompt-route-chip {
padding: 1px 6px;
border-radius: 3px;
background: rgba(148, 163, 184, 0.08);
font-family: var(--font-mono);
font-size: 10px;
}
.gf-prompt-category-label {
font-size: 10px;
}
.gf-prompt-placeholder {
font-style: italic;
}
.gf-custom-form-body {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(220px, 280px);
gap: 18px;
align-items: start;
min-height: 100%;
}
.gf-custom-form-main {
min-width: 0;
}
.gf-custom-section {
padding: 0 0 18px;
border-bottom: 1px solid var(--border-subtle);
}
.gf-custom-section + .gf-custom-section {
padding-top: 18px;
}
.gf-custom-section-title,
.gf-flag-group-title {
color: var(--text-muted);
font-size: 12px;
font-weight: 700;
letter-spacing: 0.09em;
line-height: 1.2;
text-transform: uppercase;
}
.gf-custom-section-title {
margin: 0 0 12px;
}
.gf-custom-grid-2 {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.gf-field {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 0;
}
.gf-field + .gf-field,
.gf-custom-grid-2 + .gf-field {
margin-top: 12px;
}
.gf-field .gf-input {
width: 100%;
box-sizing: border-box;
padding: 9px 11px;
border-radius: 6px;
font-size: 13px;
}
.gf-field-help,
.gf-field-error,
.gf-field-warning,
.gf-count-line {
font-size: 11px;
line-height: 1.4;
}
.gf-field-help,
.gf-count-line {
color: var(--text-dim);
}
.gf-field-error {
color: var(--red-400);
}
.gf-field-warning {
color: var(--amber-400);
}
.gf-count-line {
align-self: flex-end;
font-family: var(--font-mono);
}
.gf-route-pills {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.gf-route-pill,
.gf-suggestion-chip {
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border-default);
border-radius: 999px;
background: transparent;
color: var(--text-secondary);
cursor: pointer;
font-size: 12px;
font-weight: 500;
}
.gf-route-pill {
padding: 5px 10px;
}
.gf-route-pill:hover,
.gf-suggestion-chip:hover {
background: var(--neutral-bg);
color: var(--text-primary);
}
.gf-route-pill.is-active {
background: var(--accent-bg);
color: var(--accent);
border-color: var(--accent-border);
}
.gf-custom-prompt-textarea {
min-height: 210px;
resize: vertical;
font-family: var(--font-mono);
font-size: 12.5px !important;
line-height: 1.55;
}
.gf-flag-groups {
display: grid;
gap: 14px;
}
.gf-flag-group {
display: grid;
gap: 8px;
}
.gf-flag-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px 12px;
}
.gf-flag-row {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 5px;
min-width: 0;
}
.gf-flag-row .gf-check-row {
flex: 0 1 auto;
min-width: 0;
}
.gf-flag-default-badge {
padding: 1px 5px;
border: 1px solid var(--accent-border);
border-radius: 999px;
background: var(--accent-bg);
color: var(--accent);
font-size: 9px;
font-weight: 700;
line-height: 1.2;
text-transform: uppercase;
}
.gf-tooltip-wrap {
position: relative;
display: inline-flex;
flex: 0 0 auto;
}
.gf-info-button {
display: inline-grid;
place-items: center;
width: 18px;
height: 18px;
border: 1px solid var(--border-default);
border-radius: 999px;
background: transparent;
color: var(--text-secondary);
cursor: help;
font-size: 11px;
line-height: 1;
}
.gf-tooltip {
position: absolute;
left: 0;
bottom: calc(100% + 8px);
z-index: 20;
width: 240px;
padding: 6px 10px;
border: 1px solid var(--border-default);
border-radius: 8px;
background: var(--surface-base);
color: var(--text-primary);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.28);
font-size: 12px;
line-height: 1.4;
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(4px);
transition:
opacity 0.14s ease,
transform 0.14s ease,
visibility 0s linear 0.14s;
}
.gf-tooltip-wrap:hover .gf-tooltip,
.gf-tooltip-wrap:focus-within .gf-tooltip {
opacity: 1;
visibility: visible;
transform: translateY(0);
transition:
opacity 0.14s ease 0.22s,
transform 0.14s ease 0.22s,
visibility 0s linear 0.22s;
}
.gf-tooltip-right {
left: calc(100% + 8px);
top: 50%;
bottom: auto;
width: max-content;
min-width: 0;
max-width: 260px;
transform: translate(-4px, -50%);
white-space: nowrap;
}
.gf-tooltip-right::before {
content: "";
position: absolute;
left: -5px;
top: 50%;
width: 8px;
height: 8px;
transform: translateY(-50%) rotate(45deg);
border-left: 1px solid var(--border-default);
border-bottom: 1px solid var(--border-default);
background: var(--surface-base);
}
.gf-tooltip-wrap:hover .gf-tooltip-right,
.gf-tooltip-wrap:focus-within .gf-tooltip-right {
transform: translate(0, -50%);
}
.gf-tooltip-secondary {
display: block;
margin-top: 2px;
color: var(--text-muted);
font-size: 11px;
line-height: 1.35;
}
@media (prefers-reduced-motion: reduce) {
.gf-tooltip,
.gf-tooltip-wrap:hover .gf-tooltip,
.gf-tooltip-wrap:focus-within .gf-tooltip {
transition: none;
}
}
.gf-tag-input {
display: flex;
min-height: 40px;
flex-wrap: wrap;
align-items: center;
gap: 6px;
padding: 6px;
border: 0.5px solid var(--border-default);
border-radius: 6px;
background: var(--surface-page);
}
.gf-tag-input input {
min-width: 110px;
flex: 1 1 120px;
border: 0;
outline: 0;
background: transparent;
color: var(--text-secondary);
font-size: 13px;
}
.gf-tag-chip {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 3px 7px;
border: 1px solid var(--accent-border);
border-radius: 999px;
background: var(--accent-bg);
color: var(--accent);
font-size: 11px;
}
.gf-tag-chip button {
border: 0;
background: transparent;
color: inherit;
cursor: pointer;
font-size: 12px;
line-height: 1;
padding: 0;
}
.gf-surface-suggestions {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.gf-suggestion-chip {
padding: 3px 8px;
}
.gf-custom-notes {
min-height: 82px;
resize: vertical;
}
.gf-custom-preview-pane {
position: sticky;
top: 12px;
display: grid;
gap: 8px;
align-self: start;
}
.gf-custom-preview-card {
cursor: default;
}
.gf-custom-preview-card:hover {
background: var(--surface-base);
}
.gf-custom-save-secondary {
min-width: 78px;
}
.gf-custom-run-primary {
padding-inline: 16px;
font-weight: 700;
box-shadow: 0 8px 22px rgba(59, 130, 246, 0.18);
}
/* --- Surfaces --- */
.gf-surface {
background: var(--surface-base);
border: 0.5px solid var(--border-subtle);
}
.gf-bg-elevated {
background: var(--surface-elevated);
}
.gf-bg-page {
background: var(--surface-page);
}
.gf-code-inline {
background: var(--surface-elevated);
}
/* --- Health banner --- */
.gf-banner-row {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
gap: 12px;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
}
.gf-banner-pass {
background: var(--status-pass-bg);
border: 0.5px solid var(--status-pass-border);
}
.gf-banner-pass .gf-banner-icon {
background: var(--status-pass-border);
color: var(--green-400);
}
.gf-banner-pass .gf-banner-title {
color: var(--green-300);
}
.gf-banner-pass .gf-banner-sub {
color: var(--green-200);
}
.gf-banner-pass .gf-banner-ts {
color: var(--green-400);
}
.gf-banner-fail {
background: var(--red-950);
border: 0.5px solid var(--red-900);
}
.gf-banner-fail .gf-banner-icon {
background: var(--red-900);
color: var(--red-400);
}
.gf-banner-fail .gf-banner-title {
color: var(--red-300);
}
.gf-banner-fail .gf-banner-sub {
color: var(--red-200);
}
.gf-banner-fail .gf-banner-ts {
color: var(--red-400);
}
/* --- Metric cards --- */
.gf-metric {
border-radius: 8px;
padding: 14px 12px;
text-align: center;
background: var(--surface-elevated);
border: none;
}
.gf-metric-value {
font-size: 22px;
font-weight: 500;
color: var(--text-primary);
font-family: var(--font-mono);
}
.gf-metric-label {
font-size: 12px;
margin-top: 2px;
color: var(--text-muted);
}
.gf-grade-text {
color: var(--status-pass) !important;
}
/* --- Card --- */
.gf-card {
background: var(--surface-base);
border: 0.5px solid var(--border-subtle);
border-radius: 8px;
padding: 16px 20px;
text-align: left;
}
.gf-card-header {
border-bottom: 0.5px solid var(--border-subtle);
}
.gf-card:hover {
border-color: var(--border-default);
}
/* --- Links --- */
.gf-link {
color: var(--accent);
font-size: 12px;
font-weight: 500;
}
.gf-link:hover {
opacity: 0.8;
}
/* --- Table --- */
.gf-th {
text-align: left;
font-size: 11px;
font-weight: 500;
padding: 6px 16px;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
border-bottom: 0.5px solid var(--border-subtle);
}
.gf-td {
padding: 10px 16px;
}
.gf-tr td {
border-bottom: 0.5px solid var(--border-faint);
}
.gf-tr:last-child td {
border-bottom: none;
}
.gf-tr-clickable {
cursor: pointer;
}
.gf-tr-clickable:hover td {
background: var(--surface-page);
}
/* --- Status dots --- */
.gf-dot {
width: 7px;
height: 7px;
border-radius: 50%;
display: inline-block;
}
.gf-dot-on {
background: var(--accent);
}
.gf-dot-off {
background: var(--border-default);
}
/* --- Grade badge --- */
.gf-grade {
display: inline-flex;
align-items: center;
justify-content: center;
width: 26px;
height: 26px;
border-radius: 5px;
font-size: 14px;
font-weight: 600;
font-family: var(--font-mono);
}
.gf-grade-a {
background: rgba(74, 222, 128, 0.12);
color: var(--green-400);
}
.gf-grade-b {
background: rgba(250, 204, 21, 0.12);
color: var(--amber-300);
}
.gf-grade-c,
.gf-grade-d,
.gf-grade-f {
background: rgba(248, 113, 113, 0.12);
color: var(--red-400);
}
.gf-grade-na {
background: var(--surface-elevated);
color: var(--text-disabled);
font-size: 12px;
}
/* --- Tier bars --- */
.gf-tier-label {
font-size: 9px;
width: 8px;
color: var(--text-muted);
}
.gf-tier-bar {
height: 3px;
border-radius: 2px;
background: var(--status-pass);
}
/* --- Quick actions --- */
.gf-action-btn {
border-radius: 8px;
padding: 12px;
text-align: center;
background: var(--surface-base);
border: 0.5px solid var(--border-subtle);
cursor: pointer;
transition:
background 0.1s,
border-color 0.1s;
}
.gf-action-btn:hover {
background: var(--surface-page);
border-color: var(--border-default);
}
.gf-play-icon {
flex-shrink: 0;
width: 28px;
height: 28px;
border-radius: 50%;
border: 0.5px solid var(--border-default);
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--text-disabled);
transition:
color 0.1s,
border-color 0.1s;
}
.gf-action-btn:hover .gf-play-icon {
color: var(--accent) !important;
border-color: var(--accent-border) !important;
}
.gf-action-title {
font-size: 13px;
font-weight: 500;
color: var(--text-primary);
}
.gf-action-desc {
font-size: 12px;
margin-top: 2px;
color: var(--text-muted);
}
/* --- Footer --- */
.gf-footer {
color: var(--text-muted);
}
.gf-footer-link {
color: var(--accent);
text-decoration: none;
}
.gf-footer-link:hover {
text-decoration: underline;
}
/* --- Severity badges --- */
.gf-badge-critical {
background: var(--red-950);
color: var(--red-400);
}
.gf-badge-high {
background: var(--orange-950);
color: var(--orange-400);
}
.gf-badge-medium {
background: var(--amber-950);
color: var(--amber-400);
}
.gf-badge-low {
background: var(--indigo-950);
color: var(--indigo-400);
}
.gf-badge-ap {
background: var(--red-950);
color: var(--red-400);
}
.gf-badge-pass {
background: var(--green-950);
color: var(--green-400);
}
.gf-badge-warn {
background: var(--amber-950);
color: var(--amber-400);
}
.gf-badge-info {
background: var(--indigo-950);
color: var(--indigo-400);
}
.gf-badge-muted {
background: var(--surface-elevated);
color: var(--text-muted);
}
/* --- Progress bars --- */
.gf-bar-track {
background: var(--border-default);
}
.gf-bar-fill {
background: var(--status-pass);
}
/* --- Inputs --- */
.gf-input {
background: var(--surface-page);
border: 0.5px solid var(--border-default);
color: var(--text-secondary);
}
.gf-input-btn {
background: var(--surface-elevated);
border: 0.5px solid var(--border-default);
color: var(--text-secondary);
}
.gf-dropdown {
background: var(--surface-page);
border: 0.5px solid var(--border-default);
}
.gf-dropdown-row:hover {
background: var(--surface-elevated);
}
/* ═══════════════════════════════════════════════════════════
Button System - 3 sizes × 5 variants
═══════════════════════════════════════════════════════════ */
/* Base reset */
.gf-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
cursor: pointer;
white-space: nowrap;
font-family: var(--font-body);
border: 1px solid var(--border-default);
background: transparent;
color: var(--text-primary);
transition:
background 0.15s,
border-color 0.15s,
color 0.15s;
}
.gf-btn:hover {
background: rgba(148, 163, 184, 0.06);
border-color: rgba(148, 163, 184, 0.35);
}
/* Size: Small - table inline actions */
.gf-btn-sm {
font-size: 12px;
font-weight: 500;
padding: 4px 10px;
border-radius: 6px;
}
/* Size: Medium - toolbar buttons */
.gf-btn-md {
font-size: 13px;
font-weight: 500;
padding: 6px 12px;
border-radius: 6px;
}
/* Size: Large - primary CTAs */
.gf-btn-lg {
font-size: 14px;
font-weight: 600;
padding: 10px 24px;
border-radius: 6px;
}
/* Variant: Primary (filled accent) */
.gf-btn-primary {
background: var(--accent-strong);
color: var(--accent-contrast);
border-color: var(--accent-strong);
}
.gf-btn-primary:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
color: var(--accent-contrast);
}
.gf-btn-primary:disabled,
.gf-btn-primary:disabled:hover {
background: var(--surface-elevated);
color: var(--text-muted);
border-color: var(--border-default);
cursor: not-allowed;
}
/* Variant: Audit/secondary accent */
.gf-btn-audit {
border: 1px solid var(--accent-border);
background: var(--accent-bg);
color: var(--accent);
transition:
background 0.15s,
border-color 0.15s;
}
.gf-btn-audit:hover {
background: var(--accent-bg);
border-color: var(--accent);
}
/* Variant: Ghost (no border, no bg) */
.gf-btn-ghost {
background: none;
color: var(--accent);
border-color: transparent;
}
.gf-btn-ghost:hover {
opacity: 0.8;
}
/* Variant: Muted (gray) */
.gf-btn-muted {
background: var(--surface-elevated);
color: var(--text-secondary);
border-color: var(--border-default);
transition:
background 0.1s,
color 0.1s;
}
.gf-btn-muted:hover {
background: var(--border-default);
color: var(--text-primary);
}
.gf-btn-secondary {
background: transparent;
color: var(--text-secondary);
border-color: var(--border-default);
}
.gf-btn-secondary:hover {
background: var(--neutral-bg);
color: var(--text-primary);
}
.gf-btn-text {
padding-left: 4px;
padding-right: 4px;
background: transparent;
border-color: transparent;
color: var(--text-muted);
}
.gf-btn-text:hover {
background: transparent;
border-color: transparent;
color: var(--text-primary);
}
.gf-btn-icon {
width: 30px;
height: 30px;
padding: 0;
border-radius: 6px;
}
.btn-warn {
color: var(--amber-400) !important;
border-color: var(--amber-border) !important;
background: var(--amber-bg) !important;
}
.btn-warn:hover {
border-color: var(--amber-400) !important;
background: rgba(245, 158, 11, 0.16) !important;
}
/* Variant: Danger (red ghost) */
.gf-btn-danger {
background: var(--red-bg);
color: var(--red-400);
border-color: var(--red-border);
}
.gf-btn-danger:hover {
background: rgba(248, 113, 113, 0.18);
border-color: rgba(248, 113, 113, 0.45);
}
.gf-btn-danger-solid {
background: var(--red-700);
color: white;
border-color: var(--red-700);
}
.gf-btn-danger-solid:hover {
background: var(--red-800);
border-color: var(--red-800);
color: white;
}
/* Convenience: green indicator badge */
.gf-btn-green {
background: var(--accent-bg);
color: var(--accent);
}
.gf-check-pass {
background: var(--accent-border);
color: var(--accent);
}
/* Convenience: Copy button (small muted) */
.gf-btn-copy {
font-size: 13px;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
background: transparent;
color: var(--text-primary);
border: 1px solid var(--border-default);
transition:
background 0.15s,
border-color 0.15s;
}
.gf-btn-copy:hover {
background: rgba(148, 163, 184, 0.06);
border-color: rgba(148, 163, 184, 0.35);
}
/* Convenience: Terminal button (small primary) */
.gf-btn-terminal {
font-size: 13px;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
background: var(--accent-bg);
color: var(--accent);
font-weight: 500;
border: 1px solid var(--accent-border);
transition:
background 0.15s,
border-color 0.15s;
}
.gf-btn-terminal:hover {
background: var(--accent-bg);
border-color: var(--accent);
}
/* Convenience: Regenerate (small ghost) */
.gf-btn-regen {
font-size: 13px;
padding: 6px 12px;
border-radius: 6px;
cursor: pointer;
color: var(--text-primary);
background: transparent;
border: 1px solid var(--border-default);
}
.gf-btn-regen:hover {
background: rgba(148, 163, 184, 0.06);
border-color: rgba(148, 163, 184, 0.35);
}
/* Convenience: Terminal CTA (large primary) */
.gf-terminal-cta {
background: var(--accent-bg);
border-bottom: 1px solid var(--border-subtle);
}
.gf-btn-terminal-cta {
padding: 10px 24px;
background: var(--accent-strong);
color: var(--accent-contrast);
border: 1px solid var(--accent-strong);
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: background 0.15s;
}
.gf-btn-terminal-cta:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
}
/* ═══════════════════════════════════════════════════════════
Dashboard Shell
═══════════════════════════════════════════════════════════ */
.gf-app-shell {
display: flex;
height: 100vh;
min-width: 1060px;
background: var(--surface-page);
}
.gf-side-nav {
display: flex;
width: 204px;
flex: 0 0 204px;
flex-direction: column;
gap: 16px;
overflow-y: auto;
padding: 14px 10px;
background: var(--surface-base);
border-right: 1px solid var(--border-subtle);
transition:
width 0.16s ease,
flex-basis 0.16s ease,
padding 0.16s ease;
}
.gf-side-collapsed .gf-side-nav {
width: 64px;
flex-basis: 64px;
padding: 14px 8px;
overflow: visible;
}
.gf-side-top {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
}
.gf-side-logo {
display: flex;
align-items: center;
gap: 7px;
min-width: 0;
flex: 1 1 auto;
padding: 4px 8px 10px;
border: 0;
background: transparent;
color: var(--text-primary);
font-size: 15px;
font-weight: 700;
letter-spacing: 0;
text-align: left;
}
.gf-side-collapsed .gf-side-logo {
flex: 0 0 auto;
justify-content: center;
padding: 2px 0 8px;
}
.gf-side-logo-emoji {
display: inline-grid;
place-items: center;
width: 24px;
height: 24px;
flex: 0 0 auto;
font-size: 19px;
line-height: 1;
}
.gf-side-logo-text,
.gf-side-link-label,
.gf-side-group-label {
transition:
opacity 0.12s ease,
transform 0.12s ease;
}
.gf-side-collapse-btn {
display: inline-grid;
place-items: center;
width: 28px;
height: 28px;
flex: 0 0 auto;
border: 1px solid var(--border-subtle);
border-radius: 6px;
background: rgba(148, 163, 184, 0.05);
color: var(--text-muted);
}
.gf-side-collapse-btn:hover {
background: var(--neutral-bg);
color: var(--text-primary);
border-color: var(--border-default);
}
.gf-side-collapse-btn svg {
width: 16px;
height: 16px;
transition: transform 0.16s ease;
}
.gf-side-collapsed .gf-side-collapse-btn svg {
transform: rotate(180deg);
}
.gf-side-nav-groups {
display: flex;
flex-direction: column;
gap: 14px;
}
.gf-side-nav-group {
display: grid;
gap: 3px;
}
.gf-side-group-label {
padding: 0 10px 5px;
color: var(--text-disabled);
font-size: 10px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.gf-side-link {
display: flex;
align-items: center;
justify-content: flex-start;
gap: 9px;
min-height: 31px;
width: 100%;
padding: 6px 10px;
border: 1px solid transparent;
border-radius: 6px;
background: transparent;
color: var(--text-secondary);
font-size: 13px;
font-weight: 500;
line-height: 1.25;
text-align: left;
}
.gf-side-link::before {
content: "";
display: none;
}
.gf-side-icon {
width: 16px;
height: 16px;
flex: 0 0 auto;
color: var(--text-muted);
fill: none;
stroke: currentColor;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
transition:
color 0.12s ease,
transform 0.12s ease;
}
.gf-side-link:hover .gf-side-icon,
.gf-side-link-active .gf-side-icon {
color: currentColor;
}
.gf-side-link .gf-status-dot {
margin-left: auto;
}
.gf-side-link:hover {
background: var(--neutral-bg);
color: var(--text-primary);
}
.gf-side-link-active {
background: var(--accent-bg);
border-color: var(--accent-border);
color: var(--accent);
}
.gf-side-collapsed .gf-side-top {
flex-direction: column;
justify-content: center;
gap: 6px;
}
.gf-side-collapsed .gf-side-collapse-btn {
width: 34px;
}
.gf-side-collapsed .gf-side-logo-emoji {
width: 34px;
height: 28px;
font-size: 20px;
}
.gf-side-collapsed .gf-side-logo-text,
.gf-side-collapsed .gf-side-link-label,
.gf-side-collapsed .gf-side-group-label {
display: none;
}
.gf-side-collapsed .gf-side-nav-groups {
gap: 10px;
}
.gf-side-collapsed .gf-side-nav-group {
gap: 5px;
}
.gf-side-collapsed .gf-side-link {
position: relative;
justify-content: center;
min-height: 32px;
padding: 6px 4px;
}
.gf-side-collapsed .gf-side-icon {
width: 17px;
height: 17px;
}
.gf-side-collapsed .gf-side-link .gf-status-dot {
position: absolute;
top: 4px;
right: 4px;
width: 7px;
height: 7px;
font-size: 0;
box-shadow: none;
}
/* Tooltips on collapsed side-nav icons - uses aria-label for content
so it stays in sync with the screen-reader name. */
.gf-side-collapsed .gf-side-link::after {
content: attr(aria-label);
position: absolute;
left: calc(100% + 12px);
top: 50%;
transform: translateY(-50%) translateX(-4px);
padding: 6px 10px;
border-radius: 6px;
background: var(--surface-elevated);
border: 1px solid var(--border-default);
color: var(--text-primary);
font-size: 12px;
font-weight: 500;
line-height: 1.2;
letter-spacing: 0.01em;
white-space: nowrap;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 1000;
transition:
opacity 0.14s ease,
transform 0.14s ease,
visibility 0s linear 0.14s;
}
.gf-side-collapsed .gf-side-link::before {
content: "";
display: block;
position: absolute;
left: calc(100% + 7px);
top: 50%;
width: 8px;
height: 8px;
transform: translateY(-50%) translateX(-4px) rotate(45deg);
background: var(--surface-elevated);
border-left: 1px solid var(--border-default);
border-bottom: 1px solid var(--border-default);
opacity: 0;
visibility: hidden;
pointer-events: none;
z-index: 1001;
transition:
opacity 0.14s ease,
transform 0.14s ease,
visibility 0s linear 0.14s;
}
.gf-side-collapsed .gf-side-link:hover::after,
.gf-side-collapsed .gf-side-link:focus-visible::after {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0);
transition:
opacity 0.14s ease 0.18s,
transform 0.14s ease 0.18s,
visibility 0s linear 0.18s;
}
.gf-side-collapsed .gf-side-link:hover::before,
.gf-side-collapsed .gf-side-link:focus-visible::before {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0) rotate(45deg);
transition:
opacity 0.14s ease 0.18s,
transform 0.14s ease 0.18s,
visibility 0s linear 0.18s;
}
@media (prefers-reduced-motion: reduce) {
.gf-side-collapsed .gf-side-link::after,
.gf-side-collapsed .gf-side-link::before,
.gf-side-collapsed .gf-side-link:hover::after,
.gf-side-collapsed .gf-side-link:hover::before,
.gf-side-collapsed .gf-side-link:focus-visible::after,
.gf-side-collapsed .gf-side-link:focus-visible::before {
transition: none;
}
}
.gf-main-shell {
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
height: 100vh;
}
.gf-header {
display: flex;
align-items: center;
padding: 14px 24px;
gap: 12px;
position: relative;
background: var(--surface-base);
border: none;
border-bottom: 1px solid var(--border-subtle);
}
.gf-header-spacer {
flex: 1 1 auto;
min-width: 20px;
}
.gf-logo {
font-weight: 500;
font-size: 15px;
color: var(--text-primary);
cursor: pointer;
border: none;
background: none;
padding: 0;
display: flex;
align-items: center;
gap: 8px;
}
.gf-header-ver {
font-size: 11px;
margin-left: 2px;
color: var(--text-disabled);
}
.gf-header-proj {
font-size: 14px;
font-weight: 400;
color: var(--text-secondary);
max-width: 320px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.gf-header-proj-edit {
background: transparent;
border: 1px solid var(--border-subtle, rgba(148, 163, 184, 0.3));
border-radius: 4px;
padding: 2px 6px;
color: var(--text-primary);
font: inherit;
font-size: 14px;
outline: none;
min-width: 120px;
}
.gf-header-proj-edit:focus {
border-color: var(--accent, #60a5fa);
}
.gf-header-proj-edit-btn {
background: transparent;
border: none;
border-radius: 4px;
color: var(--text-disabled