/* my-deepagent Web GUI — v0.2 PR #3 (Claude design pass). * * Visual reference: Anthropic / Claude design language * - Warm cream paper background (#F5F0E8 family) * - Charcoal warm-tinted ink for body * - Tiempos / Source Serif headings (serif heads, sans body) * - Rust / terracotta accent (#CC5500 family) * - Generous whitespace, soft 1px borders, minimal shadow * - Rounded corners 6–12 px, no heavy elevation * * Vanilla CSS only. No framework, no build system. */ /* ---------- Reset + tokens ---------- */ *, *::before, *::after { box-sizing: border-box; } :root { /* Paper / surface */ --bg: #f5f0e8; --surface-1: #fbfaf6; --surface-2: #efe9de; --surface-3: #e7e0d3; --surface-hover: #eee7da; /* Borders */ --border: #e2dccf; --border-strong: #cfc7b6; /* Ink */ --text-primary: #1b1916; --text-secondary: #54514a; --text-muted: #8a857a; --text-faint: #b6b0a3; /* Accents (rust + supporting palette) */ --accent: #c14a1a; --accent-hover: #a73d12; --accent-bg: rgba(193, 74, 26, 0.1); --success: #4a6f2a; --success-bg: rgba(74, 111, 42, 0.1); --warning: #a86c1f; --warning-bg: rgba(168, 108, 31, 0.12); --danger: #a33419; --danger-bg: rgba(163, 52, 25, 0.1); --info: #4a5d8c; --info-bg: rgba(74, 93, 140, 0.1); /* Type */ --font-serif: "Tiempos Headline", "Source Serif Pro", "IBM Plex Serif", "Georgia", "Apple SD Gothic Neo", "Noto Serif KR", serif; --font-sans: "Styrene B", "Styrene A", "Inter", "Pretendard", -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo", "Noto Sans KR", "Segoe UI", Helvetica, Arial, sans-serif; --font-mono: "JetBrains Mono", "SF Mono", "Menlo", "Monaco", "Consolas", monospace; /* Geometry */ --radius-sm: 6px; --radius: 8px; --radius-lg: 12px; --shadow-card: 0 1px 0 rgba(28, 25, 22, 0.04); } /* ---------- Base ---------- */ html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text-primary); font-family: var(--font-sans); font-size: 15px; line-height: 1.55; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-variant-numeric: tabular-nums; } body { min-height: 100vh; display: flex; flex-direction: column; } a { color: var(--accent); text-decoration: none; transition: color 0.15s ease; } a:hover { color: var(--accent-hover); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; } code, kbd, .mono { font-family: var(--font-mono); font-size: 0.86em; letter-spacing: -0.005em; } ::selection { background: var(--accent); color: var(--surface-1); } /* ---------- Header / nav ---------- */ header { background: transparent; border-bottom: 1px solid var(--border); padding: 20px 36px; display: flex; justify-content: space-between; align-items: baseline; gap: 24px; } header h1 { margin: 0; font-family: var(--font-serif); font-size: 22px; font-weight: 500; letter-spacing: -0.02em; color: var(--text-primary); } header h1 a { color: inherit; } header h1 a:hover { text-decoration: none; color: var(--accent); } header nav { display: flex; gap: 4px; align-self: center; } header nav a { color: var(--text-secondary); padding: 6px 12px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 400; transition: all 0.15s ease; } header nav a:hover { color: var(--text-primary); background: var(--surface-2); text-decoration: none; } header nav a.active { color: var(--accent); background: var(--accent-bg); } /* ---------- Main ---------- */ main { flex: 1; max-width: 1180px; width: 100%; margin: 0 auto; padding: 40px 36px 64px; } .page-title { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 28px; border-bottom: 1px solid var(--border); padding-bottom: 16px; } .page-title h2 { margin: 0; font-family: var(--font-serif); font-size: 30px; font-weight: 500; letter-spacing: -0.02em; text-transform: none; color: var(--text-primary); } .page-subtitle { color: var(--text-muted); font-size: 14px; } h2 { margin: 36px 0 14px; font-family: var(--font-serif); font-size: 18px; font-weight: 500; letter-spacing: -0.01em; color: var(--text-primary); text-transform: none; } h2.section-title { display: flex; align-items: baseline; gap: 10px; } h2.section-title .hint { font-family: var(--font-sans); font-size: 13px; color: var(--text-muted); font-weight: 400; margin-left: 4px; } /* ---------- Cards / tables ---------- */ .card { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-card); overflow: hidden; } table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 14px; } th, td { text-align: left; padding: 14px 18px; border-bottom: 1px solid var(--border); vertical-align: middle; } tbody tr:last-child td { border-bottom: none; } tbody tr { transition: background 0.12s ease; } tbody tr:hover { background: var(--surface-2); } th { background: var(--surface-2); color: var(--text-secondary); font-weight: 500; font-size: 12px; letter-spacing: 0.03em; text-transform: uppercase; padding-top: 11px; padding-bottom: 11px; border-bottom: 1px solid var(--border-strong); } td .mono { color: var(--text-secondary); } td a { font-weight: 500; } /* ---------- State badges (pill) ---------- */ .badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 11px; border-radius: 999px; font-size: 12px; font-weight: 500; letter-spacing: 0.01em; border: 1px solid transparent; font-variant-numeric: tabular-nums; } .badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; } .badge.state-completed, .badge.state-ok { color: var(--success); background: var(--success-bg); border-color: rgba(74, 111, 42, 0.2); } .badge.state-running, .badge.state-executing, .badge.state-validating, .badge.state-awaiting_artifact, .badge.state-awaiting_approval { color: var(--warning); background: var(--warning-bg); border-color: rgba(168, 108, 31, 0.22); } .badge.state-failed, .badge.state-aborted { color: var(--danger); background: var(--danger-bg); border-color: rgba(163, 52, 25, 0.2); } .badge.state-pending, .badge.state-created, .badge.state-bound, .badge.state-planning, .badge.state-paused, .badge.state-skipped { color: var(--info); background: var(--info-bg); border-color: rgba(74, 93, 140, 0.2); } .badge.state-running::before, .badge.state-executing::before, .badge.state-validating::before, .badge.state-awaiting_artifact::before { animation: pulse 1.6s ease-in-out infinite; } @keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.45; transform: scale(0.85); } } /* ---------- Buttons ---------- */ button, .button { appearance: none; background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); padding: 8px 16px; font-family: inherit; font-size: 13.5px; font-weight: 500; letter-spacing: -0.005em; cursor: pointer; transition: all 0.15s ease; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; } button:hover:not(:disabled), .button:hover { background: var(--surface-hover); border-color: var(--text-faint); color: var(--text-primary); text-decoration: none; } button:active:not(:disabled) { transform: translateY(0.5px); } button:disabled { opacity: 0.4; cursor: not-allowed; } button.primary { background: var(--accent); border-color: var(--accent); color: var(--surface-1); font-weight: 500; } button.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--surface-1); } button.danger { background: transparent; color: var(--danger); border-color: rgba(163, 52, 25, 0.32); } button.danger:hover:not(:disabled) { background: var(--danger-bg); border-color: var(--danger); } /* ---------- Forms ---------- */ label { display: block; margin: 0 0 6px; color: var(--text-secondary); font-size: 13px; font-weight: 500; } label .hint { color: var(--text-muted); font-weight: 400; margin-left: 6px; font-size: 12.5px; } input[type="text"], input[type="number"], textarea, select { width: 100%; background: var(--surface-1); color: var(--text-primary); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 13px; font-family: inherit; font-size: 14px; line-height: 1.5; transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; } input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-bg); } input::placeholder, textarea::placeholder { color: var(--text-faint); } textarea { resize: vertical; min-height: 110px; font-family: var(--font-mono); font-size: 13px; line-height: 1.6; } select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%2354514a' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 36px; } .form-row { margin-bottom: 18px; } .form-grid { display: grid; grid-template-columns: 1fr 220px; gap: 16px; } .action-bar { display: flex; gap: 8px; margin: 28px 0 0; padding-top: 18px; border-top: 1px solid var(--border); } .action-bar.no-top-border { border-top: none; padding-top: 0; } /* ---------- Meta panel (key/value lists) ---------- */ .meta-panel { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); padding: 4px 0; box-shadow: var(--shadow-card); } .meta-row { display: grid; grid-template-columns: 150px 1fr; gap: 18px; padding: 12px 18px; border-bottom: 1px solid var(--border); align-items: center; } .meta-row:last-child { border-bottom: none; } .meta-row .key { color: var(--text-muted); font-size: 12.5px; font-weight: 500; letter-spacing: 0.02em; text-transform: uppercase; } .meta-row .value { color: var(--text-primary); font-size: 14px; word-break: break-all; } .meta-row .value.mono { font-family: var(--font-mono); font-size: 12.5px; color: var(--text-secondary); } .meta-row .value.dim { color: var(--text-muted); } /* ---------- Budget summary cards ---------- */ .budget-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; } .budget-card { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow-card); } .budget-card .scope { color: var(--text-muted); font-size: 12px; font-weight: 500; letter-spacing: 0.04em; text-transform: uppercase; margin-bottom: 8px; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .budget-card .amount { font-family: var(--font-serif); font-size: 26px; font-weight: 500; letter-spacing: -0.02em; color: var(--text-primary); } .budget-card .amount.warn { color: var(--warning); } .budget-card .amount.over { color: var(--danger); } .budget-card .cap { font-family: var(--font-sans); color: var(--text-muted); font-size: 13px; font-weight: 400; margin-left: 6px; } .budget-card .bar { height: 4px; background: var(--surface-3); border-radius: 2px; margin-top: 12px; overflow: hidden; } .budget-card .bar > div { height: 100%; background: var(--success); transition: width 0.3s ease; } .budget-card .bar.warn > div { background: var(--warning); } .budget-card .bar.over > div { background: var(--danger); } /* ---------- Event log (SSE) ---------- */ .events { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); max-height: 60vh; overflow-y: auto; padding: 8px 0; font-family: var(--font-mono); font-size: 12.5px; box-shadow: var(--shadow-card); } .event-line { display: grid; grid-template-columns: 80px 1fr; gap: 14px; padding: 6px 18px; border-bottom: 1px solid transparent; } .event-line:hover { background: var(--surface-2); } .event-line .ts { color: var(--text-faint); font-size: 11.5px; } .event-line .body .type { color: var(--accent); font-weight: 500; } .event-line .body .payload { color: var(--text-muted); margin-left: 8px; font-size: 11.5px; word-break: break-all; } .event-line.run-completed .body .type { color: var(--success); } .event-line.run-failed .body .type, .event-line.run-aborted .body .type { color: var(--danger); } .event-line.run-resumed .body .type { color: var(--warning); } .events::-webkit-scrollbar { width: 10px; } .events::-webkit-scrollbar-track { background: transparent; } .events::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 5px; border: 2px solid var(--surface-1); } /* ---------- Empty / error states ---------- */ .empty { padding: 56px 24px; text-align: center; color: var(--text-muted); font-size: 14px; } .empty .empty-icon { font-family: var(--font-serif); font-size: 30px; margin-bottom: 10px; opacity: 0.5; color: var(--accent); } .empty .cta { margin-top: 18px; } .error-banner { background: var(--danger-bg); border: 1px solid rgba(163, 52, 25, 0.28); border-radius: var(--radius); padding: 12px 16px; margin-bottom: 16px; color: var(--danger); font-size: 13.5px; display: flex; align-items: center; gap: 10px; } .error-banner::before { content: "!"; display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; background: var(--danger); color: var(--surface-1); border-radius: 50%; font-weight: 700; font-size: 11px; flex-shrink: 0; font-family: var(--font-sans); } /* ---------- Tag chip (per-role override input) ---------- */ .chips { display: grid; grid-template-columns: 160px 1fr; gap: 14px; padding: 14px 18px; border-bottom: 1px solid var(--border); align-items: center; } .chips:last-child { border-bottom: none; } .chips .role { font-size: 13px; color: var(--text-secondary); font-weight: 500; } .chips .role .hint { display: block; font-size: 12px; color: var(--text-muted); font-weight: 400; margin-top: 2px; } .chips input { font-family: var(--font-mono); font-size: 12.5px; } /* ---------- Responsive ---------- */ @media (max-width: 720px) { main { padding: 24px 16px 40px; } header { padding: 16px 16px; } .page-title h2 { font-size: 24px; } .form-grid { grid-template-columns: 1fr; } .meta-row { grid-template-columns: 1fr; gap: 4px; padding: 12px 14px; } .event-line { grid-template-columns: 1fr; gap: 2px; } .chips { grid-template-columns: 1fr; gap: 6px; } } /* ================================================================= v0.3 PR #8 — Conversation page ================================================================= */ .conversation-main { display: flex; flex-direction: column; min-height: calc(100vh - 80px); padding-bottom: 0; } .conv-topbar { display: flex; align-items: center; gap: 12px; padding: 12px 16px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 12px; flex-wrap: wrap; } .conv-label { font-size: 13px; color: var(--text-muted); font-weight: 600; } .conv-picker { flex: 1; min-width: 240px; padding: 6px 10px; font-family: var(--font-mono); font-size: 13px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); } .conv-action-btn { padding: 6px 14px; font-size: 13px; background: var(--accent); color: white; border: none; border-radius: 6px; cursor: pointer; } .conv-action-btn:hover { filter: brightness(1.08); } .conv-session-state { font-size: 11px; padding: 2px 8px; border-radius: 999px; text-transform: lowercase; letter-spacing: 0.04em; } .conv-session-state.state-active { background: rgba(34,197,94,0.12); color: rgb(22,163,74); } .conv-session-state.state-ended { background: rgba(100,116,139,0.12); color: rgb(71,85,105); } .messages-thread { flex: 1; overflow-y: auto; padding: 16px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg); margin-bottom: 12px; display: flex; flex-direction: column; gap: 12px; } .conv-empty { color: var(--text-muted); text-align: center; padding: 40px 16px; font-size: 13px; } .msg-bubble { max-width: 80%; padding: 10px 14px; border-radius: 12px; font-size: 14px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; } .msg-bubble.role-user { align-self: flex-end; background: var(--accent); color: white; } .msg-bubble.role-assistant { align-self: flex-start; background: var(--bg-card); border: 1px solid var(--border); } .msg-bubble.role-system { align-self: center; max-width: 90%; font-style: italic; font-size: 12.5px; background: rgba(245,158,11,0.08); border: 1px dashed rgba(245,158,11,0.4); color: rgb(120,53,15); } .msg-bubble.pending { opacity: 0.6; font-size: 20px; padding: 6px 14px; } .msg-meta { display: flex; align-items: center; gap: 8px; font-size: 11px; opacity: 0.6; margin-bottom: 4px; } .msg-role { font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; } .conv-input-bar { display: flex; gap: 8px; padding: 12px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; } .conv-input-bar textarea { flex: 1; font-family: var(--font-body); font-size: 14px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px; resize: vertical; min-height: 44px; } .conv-input-bar textarea:disabled { background: var(--bg); opacity: 0.5; } .conv-input-bar button { padding: 0 18px; font-size: 13px; background: var(--accent); color: white; border: none; border-radius: 6px; cursor: pointer; } .conv-input-bar button:disabled { opacity: 0.4; cursor: not-allowed; }