Files
dev-puppeteer/my-deepagent/static/style.css
chungyeong ed694c9821 polish(my-deepagent): switch Web GUI to Claude/Anthropic design language
Earlier polish landed a dark dev-tool aesthetic (Linear / Vercel /
Resend). The user reminded that we agreed on the Claude / Anthropic
design language — cream paper background, warm charcoal ink, serif
display type, rust/terracotta accent. Pivoting accordingly.

Changes (style.css; HTML headers gain h1 → home link)
- Surface palette
  - bg: #f5f0e8 (warm cream paper)
  - surface-1/2/3: cream → light tan progression
  - border / border-strong: soft warm tan
- Ink palette (warm-tinted neutral, not blue-tinted gray)
  - text-primary: #1b1916
  - text-secondary: #54514a
  - text-muted: #8a857a
  - text-faint: #b6b0a3
- Accent rust palette
  - accent: #c14a1a (terracotta) / hover #a73d12
  - success: olive green #4a6f2a
  - warning: mustard #a86c1f
  - danger: rust red #a33419
  - info: muted slate blue #4a5d8c
- Typography: serif/sans/mono trio
  - --font-serif: "Tiempos Headline", "Source Serif Pro", "IBM Plex Serif",
                  Georgia, "Apple SD Gothic Neo", "Noto Serif KR"
  - --font-sans:  "Styrene B", "Styrene A", "Inter", "Pretendard", system stack
  - --font-mono:  JetBrains Mono / SF Mono / Menlo
  - Body font-size bumped 14 → 15 px for paper readability
  - h1, page-title h2, h2 section titles all serif now (no uppercase /
    letterspaced caps — Claude aesthetic favors true serif headlines)
  - budget-card amount uses serif numerals
- Component tweaks
  - Buttons: cream surface default; primary = rust filled; danger = outlined
  - Inputs: 3 px rgba accent ring on focus (Claude form style)
  - Badges: warm pill background + 1 px tinted border for definition on cream
  - Cards: soft 1 px shadow-card token, no heavy elevation
  - Scrollbar: themed thumb against surface-1
  - Empty-state icon: serif character in accent color
- Page-title row gains a bottom border (paper-rule separator)

XSS policy comment + textContent-only contract unchanged. No build system.

Tests
- ruff check / mypy --strict / 5 static smoke tests: PASS

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:34:29 +09:00

781 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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 612 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; }
}