Files
webflash/frontend/css/style.css
2026-05-17 03:27:30 +09:00

388 lines
10 KiB
CSS
Raw Permalink 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.

/* ──────────────────────────────────────────────────────────────
ESP32 Web Flasher style.css
────────────────────────────────────────────────────────────── */
:root {
--bg: #0d1117;
--surface: #161b22;
--surface2: #21262d;
--border: #30363d;
--accent: #00c896;
--accent-dim: #00a07a;
--danger: #f85149;
--warn: #e3b341;
--text: #e6edf3;
--text-muted: #8b949e;
--radius: 8px;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* ── Header ─────────────────────────────────────────────────── */
header {
background: var(--surface);
border-bottom: 1px solid var(--border);
padding: 0 24px;
height: 56px;
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
z-index: 100;
}
.logo {
display: flex;
align-items: center;
gap: 10px;
font-weight: 700;
font-size: 18px;
color: var(--accent);
text-decoration: none;
}
.logo svg { width: 28px; height: 28px; }
.header-badge {
font-size: 11px;
background: var(--accent);
color: #000;
padding: 2px 8px;
border-radius: 20px;
font-weight: 600;
}
/* ── Layout ──────────────────────────────────────────────────── */
main {
flex: 1;
max-width: 960px;
width: 100%;
margin: 0 auto;
padding: 32px 16px 64px;
display: flex;
flex-direction: column;
gap: 24px;
}
/* ── Cards ───────────────────────────────────────────────────── */
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
}
.card-header {
padding: 14px 20px;
background: var(--surface2);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
gap: 10px;
}
.card-header h2 {
font-size: 15px;
font-weight: 600;
}
.step-badge {
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--accent);
color: #000;
font-size: 12px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.step-badge.done { background: #238636; color: #fff; }
.step-badge.locked { background: var(--border); color: var(--text-muted); }
.card-body { padding: 20px; }
/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
border: 1px solid transparent;
transition: opacity .15s, filter .15s;
text-decoration: none;
}
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn:not(:disabled):hover { filter: brightness(1.1); }
.btn-primary { background: var(--accent); color: #000; border-color: var(--accent); }
.btn-secondary { background: transparent; color: var(--text); border-color: var(--border); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-sm { padding: 5px 12px; font-size: 12px; }
/* ── Status indicator ────────────────────────────────────────── */
.status-row {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
border-radius: 6px;
background: var(--surface2);
border: 1px solid var(--border);
font-size: 14px;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
flex-shrink: 0;
}
.dot-idle { background: var(--border); }
.dot-ok { background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.dot-error { background: var(--danger); box-shadow: 0 0 6px var(--danger); }
.dot-loading { background: var(--warn); animation: pulse 1s infinite; }
@keyframes pulse { 0%,100%{ opacity:1 } 50%{ opacity:.3 } }
/* ── Forms ───────────────────────────────────────────────────── */
.form-group { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.form-group label { font-size: 13px; color: var(--text-muted); }
input[type="text"],
input[type="file"],
select,
textarea {
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
border-radius: 6px;
padding: 8px 12px;
font-size: 14px;
width: 100%;
outline: none;
}
input:focus, select:focus, textarea:focus {
border-color: var(--accent);
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px;
}
@media (max-width: 600px) { .form-grid { grid-template-columns: 1fr; } }
/* ── File drop zone ──────────────────────────────────────────── */
.drop-zone {
border: 2px dashed var(--border);
border-radius: 6px;
padding: 28px;
text-align: center;
cursor: pointer;
transition: border-color .2s, background .2s;
color: var(--text-muted);
font-size: 14px;
}
.drop-zone:hover, .drop-zone.dragover {
border-color: var(--accent);
background: rgba(0,200,150,.05);
}
.drop-zone input { display: none; }
.drop-zone .icon { font-size: 32px; margin-bottom: 8px; }
.drop-zone .file-selected {
color: var(--accent);
font-weight: 600;
word-break: break-all;
}
/* ── Progress bar ────────────────────────────────────────────── */
.progress-wrap {
background: var(--surface2);
border-radius: 20px;
height: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg, var(--accent), var(--accent-dim));
border-radius: 20px;
width: 0%;
transition: width .3s;
}
.progress-label {
font-size: 12px;
color: var(--text-muted);
margin-top: 6px;
display: flex;
justify-content: space-between;
}
/* ── Serial monitor ──────────────────────────────────────────── */
#monitor {
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
font-size: 12px;
background: #0d1117;
color: #58a6ff;
border: 1px solid var(--border);
border-radius: 6px;
padding: 12px;
height: 200px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
line-height: 1.6;
}
#monitor .line-ok { color: var(--accent); }
#monitor .line-err { color: var(--danger); }
#monitor .line-warn { color: var(--warn); }
#monitor .line-info { color: var(--text-muted); }
/* ── Firmware list ───────────────────────────────────────────── */
.fw-list { display: flex; flex-direction: column; gap: 10px; }
.fw-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 14px;
background: var(--surface2);
border: 1px solid var(--border);
border-radius: 6px;
cursor: pointer;
transition: border-color .15s;
}
.fw-item:hover { border-color: var(--accent); }
.fw-item.selected { border-color: var(--accent); background: rgba(0,200,150,.08); }
.fw-item .fw-icon {
font-size: 28px;
flex-shrink: 0;
}
.fw-item .fw-info { flex: 1; overflow: hidden; }
.fw-item .fw-name {
font-weight: 600;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fw-item .fw-meta {
font-size: 12px;
color: var(--text-muted);
margin-top: 2px;
}
.fw-item .fw-actions { display: flex; gap: 6px; flex-shrink: 0; }
.chip-badge {
background: var(--surface);
border: 1px solid var(--border);
color: var(--text-muted);
font-size: 11px;
padding: 2px 8px;
border-radius: 20px;
}
/* ── Alert banner ────────────────────────────────────────────── */
.alert {
padding: 10px 16px;
border-radius: 6px;
font-size: 13px;
display: flex;
align-items: flex-start;
gap: 10px;
line-height: 1.5;
}
.alert-info { background: rgba(56,139,253,.1); border: 1px solid rgba(56,139,253,.3); }
.alert-warn { background: rgba(227,179,65,.1); border: 1px solid rgba(227,179,65,.3); }
/* ── esp-web-install-button override ────────────────────────── */
esp-web-install-button {
display: block;
margin-top: 14px;
}
esp-web-install-button[active] > button {
background: var(--accent);
color: #000;
border: none;
padding: 10px 22px;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
}
/* ── Tabs ────────────────────────────────────────────────────── */
.tab-bar {
display: flex;
gap: 4px;
border-bottom: 1px solid var(--border);
padding: 0 20px;
background: var(--surface2);
}
.tab-btn {
padding: 10px 16px;
font-size: 13px;
color: var(--text-muted);
background: none;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: color .15s;
margin-bottom: -1px;
}
.tab-btn:hover { color: var(--text); }
.tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab-panel { display: none; padding: 20px; }
.tab-panel.active { display: block; }
/* ── Empty state ─────────────────────────────────────────────── */
.empty-state {
text-align: center;
padding: 32px;
color: var(--text-muted);
}
.empty-state .icon { font-size: 40px; margin-bottom: 12px; }