Editorial/Judicial design system — Phase B visual overhaul

- New design-system.css: CSS variables for Navy/Cream/Gold palette,
  Frank Ruhl Libre (display) + Assistant (body) typography via Google Fonts,
  spacing/shadow/motion tokens, RTL-safe utilities
- All body paragraphs justify to both sides (text-align: justify, inter-word)
- Existing inline <style> migrated from hardcoded #e94560/#1a1a2e/#27ae60 to
  CSS variables
- Header: deep navy with gold accent rule under, display-font brand mark,
  active nav link marked with gold underline
- Buttons: navy primary, gold-wash focus rings, elevation on hover
- Case cards: gold right-border, hairline top glow on hover, display font
  on case number
- Home dashboard: new hero with eyebrow/title/subtitle, 4 KPI cards with
  gold-rule side marker, loadKPIs() fetches case count, corpus size,
  pattern count, processing queue
- Style report: larger hero h1, ornamental pull-quote headline with
  drop-cap open quote, gold divider under section titles
- Toast, status bar, form inputs: navy/gold palette, serif italics for
  subtitles and empty states

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-11 11:47:13 +00:00
parent 858333b386
commit d5164e2875
3 changed files with 833 additions and 124 deletions

View File

@@ -69,6 +69,11 @@ async def index():
return FileResponse(STATIC_DIR / "index.html")
@app.get("/design-system.css")
async def design_system_css():
return FileResponse(STATIC_DIR / "design-system.css", media_type="text/css")
@app.post("/api/upload")
async def upload_file(file: UploadFile = File(...)):
"""Upload a file to the temporary uploads directory."""

View File

@@ -0,0 +1,244 @@
/* ════════════════════════════════════════════════════════════
* Ezer Mishpati — Design System
* Editorial/Judicial aesthetic for a Hebrew RTL judicial tool.
*
* Typography: Frank Ruhl Libre (display) + Assistant (body)
* Palette: Navy #0f172a + Cream #f5f1e8 + Gold #a97d3a
* ════════════════════════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=Frank+Ruhl+Libre:wght@400;500;700;900&family=Assistant:wght@300;400;500;600;700&display=swap');
:root {
/* ── Colors ─────────────────────────────────────────── */
--color-navy: #0f172a;
--color-navy-soft: #1e293b;
--color-navy-dim: #334155;
--color-cream: #f5f1e8;
--color-cream-deep: #ede8d8;
--color-parchment: #fbf8f0;
--color-gold: #a97d3a;
--color-gold-deep: #8b6428;
--color-gold-soft: #c89a56;
--color-gold-wash: #fdf6e8;
--color-ink: #1a1a2e;
--color-ink-soft: #3a3a52;
--color-ink-muted: #6b7280;
--color-ink-light: #9ca3af;
--color-rule: #e5dfd0; /* cream-toned hairline */
--color-rule-soft: #f0ead8;
--color-surface: #ffffff;
--color-surface-raised: #fbf8f0;
--color-bg: var(--color-cream);
/* Status colors — tuned to the palette */
--color-success: #4a7c59;
--color-success-bg: #e8efe7;
--color-warn: #b8894a;
--color-warn-bg: #faf0dc;
--color-danger: #a54242;
--color-danger-bg: #f5e6e6;
--color-info: #4e6a8c;
--color-info-bg: #e6ecf3;
/* ── Typography ─────────────────────────────────────── */
--font-display: 'Frank Ruhl Libre', 'David Libre', Georgia, serif;
--font-body: 'Assistant', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-mono: ui-monospace, 'Cascadia Code', 'SF Mono', Menlo, monospace;
--text-xs: 0.75rem;
--text-sm: 0.85rem;
--text-base: 0.95rem;
--text-md: 1.05rem;
--text-lg: 1.2rem;
--text-xl: 1.45rem;
--text-2xl: 1.8rem;
--text-3xl: 2.3rem;
--text-4xl: 2.9rem;
--leading-tight: 1.25;
--leading-snug: 1.4;
--leading-body: 1.65;
--leading-prose: 1.8;
--weight-light: 300;
--weight-normal: 400;
--weight-medium: 500;
--weight-semi: 600;
--weight-bold: 700;
--weight-display: 900;
/* ── Spacing scale (8px grid) ───────────────────────── */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-7: 32px;
--space-8: 40px;
--space-9: 56px;
--space-10: 72px;
/* ── Radii ──────────────────────────────────────────── */
--radius-sm: 4px;
--radius: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-pill: 999px;
/* ── Shadows — soft, editorial ──────────────────────── */
--shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.05);
--shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
--shadow: 0 2px 6px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
--shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08), 0 2px 4px rgba(15, 23, 42, 0.04);
--shadow-lg: 0 10px 30px rgba(15, 23, 42, 0.12), 0 2px 6px rgba(15, 23, 42, 0.05);
--shadow-gold: 0 0 0 3px var(--color-gold-wash);
/* ── Transitions ────────────────────────────────────── */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--t-fast: 120ms var(--ease-out);
--t: 180ms var(--ease-out);
--t-slow: 280ms var(--ease-out);
}
/* ── Base overrides ──────────────────────────────────── */
html { font-size: 16px; }
body {
font-family: var(--font-body);
font-weight: var(--weight-normal);
font-size: var(--text-base);
line-height: var(--leading-body);
color: var(--color-ink);
background: var(--color-bg);
direction: rtl;
text-align: right;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-feature-settings: "kern", "liga", "clig", "calt";
}
/* Display typography — serif for headings */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-display);
font-weight: var(--weight-bold);
line-height: var(--leading-tight);
color: var(--color-navy);
letter-spacing: -0.01em;
}
h1 { font-size: var(--text-3xl); font-weight: var(--weight-display); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }
h5 { font-size: var(--text-md); }
h6 { font-size: var(--text-base); }
/* Prose paragraphs — justify both sides for Hebrew legal text */
p,
.prose {
text-align: justify;
text-justify: inter-word;
hyphens: auto;
line-height: var(--leading-body);
}
/* Text that should NOT justify (short labels, meta) */
.no-justify, .meta, .label, .caption,
th, td, button, input, select, label, nav {
text-align: right;
}
/* Links */
a {
color: var(--color-gold-deep);
text-decoration: none;
transition: color var(--t-fast);
}
a:hover { color: var(--color-gold); }
/* Focus rings — gold, subtle */
*:focus-visible {
outline: 2px solid var(--color-gold);
outline-offset: 2px;
border-radius: var(--radius-sm);
}
/* Selection */
::selection {
background: var(--color-gold-wash);
color: var(--color-navy);
}
/* ── Utility classes ─────────────────────────────────── */
.text-display { font-family: var(--font-display); }
.text-body { font-family: var(--font-body); }
.text-mono { font-family: var(--font-mono); }
.text-xs { font-size: var(--text-xs); }
.text-sm { font-size: var(--text-sm); }
.text-base { font-size: var(--text-base); }
.text-md { font-size: var(--text-md); }
.text-lg { font-size: var(--text-lg); }
.text-xl { font-size: var(--text-xl); }
.text-2xl { font-size: var(--text-2xl); }
.text-3xl { font-size: var(--text-3xl); }
.text-muted { color: var(--color-ink-muted); }
.text-light { color: var(--color-ink-light); }
.text-gold { color: var(--color-gold-deep); }
.text-navy { color: var(--color-navy); }
.weight-light { font-weight: var(--weight-light); }
.weight-normal { font-weight: var(--weight-normal); }
.weight-medium { font-weight: var(--weight-medium); }
.weight-bold { font-weight: var(--weight-bold); }
.justify { text-align: justify; text-justify: inter-word; }
.start { text-align: right; } /* RTL start */
.end { text-align: left; } /* RTL end */
.center { text-align: center; }
.ornament {
display: block;
text-align: center;
color: var(--color-gold);
font-family: var(--font-display);
letter-spacing: 0.3em;
margin: var(--space-6) 0;
}
.ornament::before { content: "❦"; font-size: 1.3em; }
.divider {
border: 0;
height: 1px;
background: linear-gradient(
to left,
transparent 0%,
var(--color-rule) 20%,
var(--color-rule) 80%,
transparent 100%
);
margin: var(--space-6) 0;
}
.divider-gold {
border: 0;
height: 2px;
background: linear-gradient(
to left,
transparent 0%,
var(--color-gold) 50%,
transparent 100%
);
margin: var(--space-6) 0;
}

View File

@@ -4,101 +4,402 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>עוזר משפטי — ניהול תיקים</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="/design-system.css">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #f5f5f5;
color: #1a1a2e;
font-family: var(--font-body);
background: var(--color-bg);
color: var(--color-ink);
direction: rtl;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* Header */
/* Header — editorial navy with gold accent rule */
header {
background: #1a1a2e;
color: #ffffff;
padding: 14px 32px;
background: var(--color-navy);
color: var(--color-parchment);
padding: 18px 40px;
display: flex;
align-items: center;
gap: 12px;
gap: 16px;
border-bottom: 3px solid var(--color-gold);
box-shadow: var(--shadow-md);
position: relative;
z-index: 10;
}
header h1 { font-size: 1.25em; font-weight: 600; cursor: pointer; }
header .sep { width: 2px; height: 20px; background: rgba(255,255,255,0.2); border-radius: 1px; }
header .subtitle { font-size: 0.85em; opacity: 0.6; }
header nav { margin-right: auto; display: flex; gap: 8px; }
header h1 {
font-family: var(--font-display);
font-size: 1.45em;
font-weight: 700;
color: var(--color-parchment);
letter-spacing: 0.02em;
cursor: pointer;
transition: color var(--t);
}
header h1:hover { color: var(--color-gold-soft); }
header .sep {
width: 1px; height: 24px;
background: var(--color-gold);
opacity: 0.5;
border-radius: 1px;
}
header .subtitle {
font-family: var(--font-display);
font-size: 0.95em;
font-style: italic;
color: var(--color-gold-soft);
opacity: 0.85;
}
header nav { margin-right: auto; display: flex; gap: 4px; }
header nav a {
color: rgba(255,255,255,0.7); text-decoration: none; font-size: 0.82em;
padding: 4px 12px; border-radius: 4px; transition: all 0.15s;
color: rgba(245, 241, 232, 0.7);
text-decoration: none;
font-size: 0.88em;
font-weight: 500;
padding: 8px 16px;
border-radius: var(--radius);
transition: all var(--t);
position: relative;
}
header nav a:hover {
color: var(--color-parchment);
background: rgba(169, 125, 58, 0.15);
}
header nav a.active {
color: var(--color-gold-soft);
background: rgba(169, 125, 58, 0.2);
}
header nav a.active::after {
content: '';
position: absolute;
bottom: -19px; right: 50%;
transform: translateX(50%);
width: 30px; height: 3px;
background: var(--color-gold);
border-radius: 2px 2px 0 0;
}
header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,255,0.1); }
/* Main */
.main { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 28px 24px; }
.page { display: none; }
.main { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: var(--space-7) var(--space-6); }
.page { display: none; animation: fadeSlideIn 0.35s var(--ease-out); }
.page.active { display: block; }
/* Cards */
@keyframes fadeSlideIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
/* Cards — editorial surfaces */
.card {
background: #ffffff; border-radius: 10px;
box-shadow: 0 1px 4px rgba(0,0,0,0.06), 0 0 1px rgba(0,0,0,0.08);
overflow: hidden; margin-bottom: 16px;
background: var(--color-surface);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
border: 1px solid var(--color-rule-soft);
overflow: hidden;
margin-bottom: var(--space-4);
transition: box-shadow var(--t), transform var(--t);
}
.card-header {
padding: 14px 20px; font-size: 0.9em; font-weight: 600; color: #1a1a2e;
border-bottom: 1px solid #eee; display: flex; align-items: center; gap: 8px;
padding: 16px 24px;
font-family: var(--font-display);
font-size: 1.05em;
font-weight: 600;
color: var(--color-navy);
border-bottom: 1px solid var(--color-rule);
background: var(--color-parchment);
display: flex;
align-items: center;
gap: 10px;
}
.card-body { padding: 20px; }
.card-body { padding: 24px; }
/* Buttons */
/* Buttons — editorial with gold */
.btn {
padding: 8px 20px; border: none; border-radius: 6px; font-size: 0.88em;
font-family: inherit; cursor: pointer; transition: all 0.15s; font-weight: 500;
padding: 10px 22px;
border: 1px solid transparent;
border-radius: var(--radius);
font-size: 0.9em;
font-family: var(--font-body);
cursor: pointer;
transition: all var(--t);
font-weight: 600;
letter-spacing: 0.01em;
}
.btn-primary {
background: var(--color-navy);
color: var(--color-parchment);
border-color: var(--color-navy);
}
.btn-primary:hover {
background: var(--color-navy-soft);
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.btn-primary:disabled {
background: var(--color-ink-light);
border-color: var(--color-ink-light);
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.btn-secondary {
background: var(--color-cream-deep);
color: var(--color-navy);
border-color: var(--color-rule);
}
.btn-secondary:hover {
background: var(--color-rule);
}
.btn-outline, .btn-ghost {
background: transparent;
color: var(--color-navy);
border: 1px solid var(--color-navy);
}
.btn-outline:hover, .btn-ghost:hover {
background: var(--color-gold-wash);
border-color: var(--color-gold-deep);
color: var(--color-gold-deep);
}
.btn-gold {
background: var(--color-gold);
color: var(--color-parchment);
border-color: var(--color-gold);
}
.btn-gold:hover {
background: var(--color-gold-deep);
box-shadow: var(--shadow-md);
transform: translateY(-1px);
}
.btn-sm { padding: 6px 14px; font-size: 0.8em; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn-success {
background: var(--color-success);
color: #fff;
border-color: var(--color-success);
}
.btn-primary { background: #e94560; color: #fff; }
.btn-primary:hover { background: #d6304a; }
.btn-secondary { background: #eee; color: #1a1a2e; }
.btn-secondary:hover { background: #ddd; }
.btn-outline { background: transparent; color: #e94560; border: 1px solid #e94560; }
.btn-outline:hover { background: #fff0f3; }
.btn-sm { padding: 4px 12px; font-size: 0.78em; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn-success { background: #27ae60; color: #fff; }
/* Form Elements */
.form-row { display: flex; gap: 12px; flex-wrap: wrap; align-items: end; margin-bottom: 14px; }
.form-row { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: end; margin-bottom: var(--space-4); }
.form-group { flex: 1; min-width: 160px; }
.form-group label { display: block; font-size: 0.78em; color: #888; margin-bottom: 4px; font-weight: 500; }
.form-group select, .form-group input[type="text"], .form-group input[type="date"], .form-group textarea {
width: 100%; padding: 8px 10px; border: 1px solid #ddd; border-radius: 6px;
font-size: 0.88em; font-family: inherit; direction: rtl; background: #fff; transition: border-color 0.15s;
.form-group label {
display: block;
font-size: 0.78em;
color: var(--color-ink-muted);
margin-bottom: 6px;
font-weight: var(--weight-medium);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.form-group select,
.form-group input[type="text"],
.form-group input[type="date"],
.form-group textarea {
width: 100%;
padding: 10px 14px;
border: 1px solid var(--color-rule);
border-radius: var(--radius);
font-size: 0.92em;
font-family: var(--font-body);
direction: rtl;
background: var(--color-surface);
transition: border-color var(--t), box-shadow var(--t);
color: var(--color-ink);
}
.form-group textarea {
resize: vertical;
min-height: 80px;
line-height: var(--leading-body);
}
.form-group select:focus,
.form-group input:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--color-gold);
box-shadow: 0 0 0 3px var(--color-gold-wash);
}
.form-group textarea { resize: vertical; min-height: 60px; }
.form-group select:focus, .form-group input:focus, .form-group textarea:focus { outline: none; border-color: #e94560; }
/* ── Case List ─────────────────────────────────────────── */
.case-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.case-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: var(--space-5);
}
.case-card {
background: #fff; border-radius: 10px; padding: 20px; cursor: pointer;
box-shadow: 0 1px 4px rgba(0,0,0,0.06); transition: box-shadow 0.2s, transform 0.15s;
border-right: 4px solid #e94560;
background: var(--color-surface);
border-radius: var(--radius-lg);
padding: var(--space-6);
cursor: pointer;
box-shadow: var(--shadow-sm);
transition: box-shadow var(--t), transform var(--t), border-color var(--t);
border: 1px solid var(--color-rule-soft);
border-right: 4px solid var(--color-gold);
position: relative;
}
.case-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 1px;
background: linear-gradient(to left, transparent, var(--color-gold-soft), transparent);
opacity: 0;
transition: opacity var(--t);
}
.case-card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
border-right-color: var(--color-gold-deep);
}
.case-card:hover::before { opacity: 1; }
.case-card .case-number {
font-family: var(--font-display);
font-size: 1.2em;
font-weight: 700;
color: var(--color-navy);
letter-spacing: 0.01em;
}
.case-card .case-title {
font-size: 0.95em;
color: var(--color-ink-soft);
margin: 8px 0;
line-height: var(--leading-snug);
font-weight: var(--weight-medium);
}
.case-card .case-meta {
font-size: 0.78em;
color: var(--color-ink-muted);
display: flex;
gap: 14px;
flex-wrap: wrap;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid var(--color-rule-soft);
}
.case-card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.1); transform: translateY(-2px); }
.case-card .case-number { font-size: 1.1em; font-weight: 700; color: #e94560; }
.case-card .case-title { font-size: 0.9em; color: #555; margin: 6px 0; line-height: 1.4; }
.case-card .case-meta { font-size: 0.78em; color: #999; display: flex; gap: 16px; flex-wrap: wrap; }
.case-card .badge {
display: inline-block; padding: 2px 8px; border-radius: 4px;
font-size: 0.72em; font-weight: 600; background: #f0f0f0; color: #666;
display: inline-block;
padding: 3px 10px;
border-radius: var(--radius-pill);
font-size: 0.72em;
font-weight: 600;
background: var(--color-cream-deep);
color: var(--color-ink-muted);
letter-spacing: 0.02em;
}
.case-card .badge.new { background: #e3f2fd; color: #1976d2; }
.case-card .badge.in_progress { background: #fff3e0; color: #f57c00; }
.case-card .badge.drafted { background: #e8f5e9; color: #388e3c; }
.case-card .badge.new { background: var(--color-info-bg); color: var(--color-info); }
.case-card .badge.in_progress { background: var(--color-warn-bg); color: var(--color-warn); }
.case-card .badge.drafted, .case-card .badge.final { background: var(--color-success-bg); color: var(--color-success); }
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
.page-header h2 { font-size: 1.2em; font-weight: 600; }
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-6);
padding-bottom: var(--space-4);
border-bottom: 2px solid var(--color-gold);
}
.page-header h2 {
font-family: var(--font-display);
font-size: var(--text-2xl);
font-weight: 700;
color: var(--color-navy);
}
/* ── Home Dashboard Hero ───────────────────────────── */
.home-hero {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: var(--space-8) 0 var(--space-6);
margin-bottom: var(--space-6);
border-bottom: 1px solid var(--color-rule);
}
.home-hero-eyebrow {
font-size: var(--text-xs);
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--color-gold-deep);
font-weight: 600;
margin-bottom: var(--space-2);
}
.home-hero-title {
font-family: var(--font-display);
font-size: var(--text-4xl);
font-weight: 900;
color: var(--color-navy);
line-height: 1;
letter-spacing: -0.02em;
margin-bottom: var(--space-2);
}
.home-hero-subtitle {
font-family: var(--font-display);
font-style: italic;
color: var(--color-ink-muted);
font-size: 1.05em;
text-align: right;
}
/* KPI cards */
.kpi-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--space-4);
margin-bottom: var(--space-7);
}
.kpi-card {
background: var(--color-surface);
border: 1px solid var(--color-rule-soft);
border-radius: var(--radius-lg);
padding: var(--space-5) var(--space-6);
position: relative;
overflow: hidden;
transition: all var(--t);
}
.kpi-card::before {
content: '';
position: absolute;
top: 0; right: 0; bottom: 0;
width: 3px;
background: var(--color-gold);
opacity: 0.7;
transition: width var(--t), opacity var(--t);
}
.kpi-card:hover::before { width: 5px; opacity: 1; }
.kpi-card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
.kpi-label {
font-size: var(--text-xs);
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--color-ink-muted);
font-weight: 600;
margin-bottom: var(--space-2);
}
.kpi-value {
font-family: var(--font-display);
font-size: var(--text-4xl);
font-weight: 900;
color: var(--color-navy);
line-height: 1;
letter-spacing: -0.02em;
}
.kpi-caption {
font-size: var(--text-xs);
color: var(--color-ink-light);
margin-top: var(--space-2);
font-family: var(--font-display);
font-style: italic;
}
@media (max-width: 800px) {
.kpi-row { grid-template-columns: repeat(2, 1fr); }
.home-hero { flex-direction: column; align-items: flex-start; gap: var(--space-4); }
}
/* ── Wizard ────────────────────────────────────────────── */
.wizard-steps {
@@ -110,8 +411,8 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
flex: 1; padding: 12px 16px; text-align: center; font-size: 0.82em; color: #999;
border-bottom: 3px solid transparent; transition: all 0.2s;
}
.wizard-step.active { color: #e94560; border-bottom-color: #e94560; font-weight: 600; }
.wizard-step.done { color: #27ae60; border-bottom-color: #27ae60; }
.wizard-step.active { color: var(--color-gold); border-bottom-color: var(--color-gold); font-weight: 600; }
.wizard-step.done { color: var(--color-success); border-bottom-color: var(--color-success); }
.wizard-panel { display: none; }
.wizard-panel.active { display: block; }
.wizard-nav { display: flex; justify-content: space-between; margin-top: 20px; }
@@ -121,7 +422,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
.dynamic-list .item { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.dynamic-list .item input { flex: 1; }
.dynamic-list .remove-btn {
background: none; border: none; color: #e94560; cursor: pointer; font-size: 1.1em; padding: 4px;
background: none; border: none; color: var(--color-gold); cursor: pointer; font-size: 1.1em; padding: 4px;
}
/* ── Case View ─────────────────────────────────────────── */
@@ -137,7 +438,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
font-size: 0.78em; padding: 4px 10px; border-radius: 4px;
text-decoration: none; border: 1px solid #ddd; color: #555; transition: all 0.15s;
}
.case-header-bar .links a:hover { border-color: #e94560; color: #e94560; }
.case-header-bar .links a:hover { border-color: var(--color-gold); color: var(--color-gold); }
.doc-group { margin-bottom: 16px; }
.doc-group-header {
@@ -154,21 +455,21 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
.doc-item .doc-icon { color: #999; }
.doc-item .doc-name { flex: 1; }
.doc-item .doc-status { font-size: 0.75em; color: #999; }
.doc-status.completed { color: #27ae60; font-weight: 700; font-size: 1em; }
.doc-status.processing { display: inline-block; width: 14px; height: 14px; border: 2px solid #e94560; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; }
.doc-status.completed { color: var(--color-success); font-weight: 700; font-size: 1em; }
.doc-status.processing { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--color-gold); border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; }
.doc-status.pending { color: #ccc; }
.doc-status.failed { color: #e94560; font-weight: 700; }
.btn-retry { background: none; border: 1px solid #e94560; color: #e94560; border-radius: 4px; padding: 2px 8px; font-size: 0.75em; cursor: pointer; margin-right: 6px; }
.btn-retry:hover { background: #e94560; color: #fff; }
.processing-badge { display: inline-flex; align-items: center; gap: 4px; color: #e94560; font-size: 0.78em; font-weight: 500; }
.mini-spinner { display: inline-block; width: 10px; height: 10px; border: 1.5px solid #e94560; border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; }
.doc-status.failed { color: var(--color-gold); font-weight: 700; }
.btn-retry { background: none; border: 1px solid var(--color-gold); color: var(--color-gold); border-radius: 4px; padding: 2px 8px; font-size: 0.75em; cursor: pointer; margin-right: 6px; }
.btn-retry:hover { background: var(--color-gold); color: #fff; }
.processing-badge { display: inline-flex; align-items: center; gap: 4px; color: var(--color-gold); font-size: 0.78em; font-weight: 500; }
.mini-spinner { display: inline-block; width: 10px; height: 10px; border: 1.5px solid var(--color-gold); border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite; }
/* Upload zone (reusable) */
.upload-zone {
border: 2px dashed #ccc; border-radius: 10px; padding: 40px 24px;
text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s; background: #fafafa;
}
.upload-zone:hover, .upload-zone.dragover { border-color: #e94560; background: #fff5f7; }
.upload-zone:hover, .upload-zone.dragover { border-color: var(--color-gold); background: #fff5f7; }
.upload-zone h3 { font-size: 0.95em; font-weight: 500; color: #555; margin-bottom: 4px; }
.upload-zone p { font-size: 0.78em; color: #aaa; }
.upload-zone input[type="file"] { display: none; }
@@ -188,11 +489,11 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
border: 1px solid #eee; border-radius: 8px; margin-bottom: 8px; background: #fafafa;
}
.task-item .spinner {
width: 20px; height: 20px; border: 2.5px solid #eee; border-top-color: #e94560;
width: 20px; height: 20px; border: 2.5px solid #eee; border-top-color: var(--color-gold);
border-radius: 50%; animation: spin 0.8s linear infinite; flex-shrink: 0;
}
.task-item.done .spinner { border-color: #27ae60; border-top-color: #27ae60; animation: none; }
.task-item.failed .spinner { border-color: #e94560; border-top-color: #e94560; animation: none; }
.task-item.done .spinner { border-color: var(--color-success); border-top-color: var(--color-success); animation: none; }
.task-item.failed .spinner { border-color: var(--color-gold); border-top-color: var(--color-gold); animation: none; }
@keyframes spin { to { transform: rotate(360deg); } }
.task-info { flex: 1; min-width: 0; }
.task-info .task-name { font-size: 0.85em; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -203,27 +504,57 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
.creation-steps li { padding: 8px 0; font-size: 0.88em; display: flex; align-items: center; gap: 8px; }
.creation-steps li .step-icon { width: 20px; text-align: center; }
.creation-steps li.pending .step-icon { color: #ccc; }
.creation-steps li.running .step-icon { color: #e94560; }
.creation-steps li.done .step-icon { color: #27ae60; }
.creation-steps li.error .step-icon { color: #e94560; }
.creation-steps li.running .step-icon { color: var(--color-gold); }
.creation-steps li.done .step-icon { color: var(--color-success); }
.creation-steps li.error .step-icon { color: var(--color-gold); }
/* Status Bar */
.status-bar {
background: #1a1a2e; color: rgba(255,255,255,0.5); font-size: 0.75em;
padding: 8px 32px; display: flex; gap: 24px; align-items: center;
background: var(--color-navy);
color: rgba(245, 241, 232, 0.55);
font-size: 0.78em;
font-family: var(--font-body);
padding: 10px 40px;
display: flex;
gap: var(--space-7);
align-items: center;
border-top: 1px solid var(--color-gold-deep);
letter-spacing: 0.02em;
}
.status-bar .stat { display: flex; align-items: center; gap: 8px; }
.status-bar .stat-value {
color: var(--color-gold-soft);
font-weight: 700;
font-family: var(--font-display);
font-size: 1.1em;
}
.status-bar .stat { display: flex; align-items: center; gap: 6px; }
.status-bar .stat-value { color: rgba(255,255,255,0.85); font-weight: 600; }
/* Toast */
.toast {
position: fixed; bottom: 60px; left: 50%; transform: translateX(-50%) translateY(10px);
background: #1a1a2e; color: white; padding: 10px 24px; border-radius: 8px;
font-size: 0.85em; z-index: 1000; opacity: 0; transition: opacity 0.3s, transform 0.3s; pointer-events: none;
position: fixed; bottom: 70px; left: 50%;
transform: translateX(-50%) translateY(10px);
background: var(--color-navy);
color: var(--color-parchment);
padding: 14px 28px;
border-radius: var(--radius-md);
font-size: 0.9em;
font-weight: 500;
z-index: 1000;
opacity: 0;
transition: opacity var(--t-slow), transform var(--t-slow);
pointer-events: none;
box-shadow: var(--shadow-lg);
border: 1px solid var(--color-gold);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.error { background: #e94560; }
.toast.success { background: #27ae60; }
.toast.error {
background: var(--color-danger);
border-color: var(--color-danger);
}
.toast.success {
background: var(--color-success);
border-color: var(--color-success);
}
/* ── Local files (research, drafts, proofread) ───────── */
.local-file-group { margin-bottom: 12px; }
@@ -250,17 +581,25 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
.export-item .export-name { font-size: 0.88em; font-weight: 600; }
.export-item .export-meta { font-size: 0.75em; color: #999; margin-top: 2px; }
.export-item .export-actions { display: flex; gap: 6px; flex-shrink: 0; }
.export-item.final { border-color: #27ae60; background: #f0faf3; }
.export-item.final .export-icon { color: #27ae60; }
.export-item.final { border-color: var(--color-success); background: #f0faf3; }
.export-item.final .export-icon { color: var(--color-success); }
.export-upload-zone {
border: 2px dashed #ccc; border-radius: 8px; padding: 16px;
text-align: center; cursor: pointer; transition: border-color 0.2s, background 0.2s;
background: #fafafa; font-size: 0.85em; color: #888; margin-top: 8px;
}
.export-upload-zone:hover { border-color: #e94560; background: #fff5f7; }
.export-upload-zone:hover { border-color: var(--color-gold); background: #fff5f7; }
.export-upload-zone input[type="file"] { display: none; }
.empty { text-align: center; color: #bbb; padding: 40px 20px; font-size: 0.88em; line-height: 1.6; }
.empty {
text-align: center;
color: var(--color-ink-light);
padding: var(--space-8) var(--space-5);
font-size: 0.9em;
line-height: var(--leading-body);
font-family: var(--font-display);
font-style: italic;
}
/* ── Skills Management ───────────────────────────────── */
.skill-list { display: flex; flex-direction: column; gap: 10px; }
@@ -293,7 +632,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
padding-bottom: 10px; margin-bottom: 12px;
border-bottom: 1px solid #eee;
}
.training-review .review-header strong { font-size: 0.95em; color: #1a1a2e; flex: 1; }
.training-review .review-header strong { font-size: 0.95em; color: var(--color-ink); flex: 1; }
.training-review .review-meta { font-size: 0.78em; color: #888; }
.training-review .btn-icon {
background: transparent; border: none; color: #aaa; cursor: pointer;
@@ -312,7 +651,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
font-size: 0.88em; font-family: inherit;
}
.training-review .review-fields input:focus {
outline: none; border-color: #e94560;
outline: none; border-color: var(--color-gold);
}
.training-review .review-cats { margin-bottom: 10px; }
.training-review .review-cats-label {
@@ -327,7 +666,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
}
.cat-chip:hover { background: #f0f0f0; }
.cat-chip input[type="checkbox"] { margin: 0; cursor: pointer; }
.cat-chip:has(input:checked) { background: #ffe4ea; border-color: #e94560; color: #c62828; }
.cat-chip:has(input:checked) { background: #ffe4ea; border-color: var(--color-gold); color: #c62828; }
.review-preview {
margin-top: 6px; border: 1px solid #eee; border-radius: 6px;
@@ -390,7 +729,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
padding: 10px 14px; background: #fff; border: 1px solid #eee;
border-radius: 6px; font-size: 0.84em;
}
.pattern-text { color: #1a1a2e; font-weight: 500; }
.pattern-text { color: var(--color-ink); font-weight: 500; }
.pattern-context { color: #666; font-size: 0.88em; margin-top: 4px; }
.pattern-meta {
color: #999; font-size: 0.78em; margin-top: 6px;
@@ -398,24 +737,85 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
}
/* ── Style Report (Dafna's Portrait) ────────────────── */
.style-report-header { text-align: center; margin-bottom: 32px; padding-top: 16px; }
.style-report-header h1 { font-size: 2em; font-weight: 600; color: #1a1a2e; margin-bottom: 6px; }
.style-report-header .subtitle-muted { color: #888; font-size: 0.95em; }
.style-report-header {
text-align: center;
margin-bottom: var(--space-9);
padding-top: var(--space-5);
position: relative;
}
.style-report-header::after {
content: '';
display: block;
width: 80px;
height: 3px;
background: linear-gradient(to left, transparent, var(--color-gold), transparent);
margin: var(--space-4) auto 0;
}
.style-report-header h1 {
font-family: var(--font-display);
font-size: var(--text-4xl);
font-weight: 900;
color: var(--color-navy);
margin-bottom: var(--space-2);
letter-spacing: -0.02em;
}
.style-report-header .subtitle-muted {
color: var(--color-ink-muted);
font-size: 1.05em;
font-family: var(--font-display);
font-style: italic;
}
.portrait-card {
background: #fff; border-radius: 12px; padding: 28px 32px;
margin-bottom: 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.06), 0 0 1px rgba(0,0,0,0.08);
background: var(--color-surface);
border-radius: var(--radius-lg);
padding: var(--space-8) var(--space-9);
margin-bottom: var(--space-6);
box-shadow: var(--shadow-sm);
border: 1px solid var(--color-rule-soft);
position: relative;
}
.portrait-card::before {
content: '';
position: absolute;
top: 0; right: var(--space-9); left: var(--space-9);
height: 3px;
background: linear-gradient(to left, transparent, var(--color-gold-soft), transparent);
border-radius: 0 0 2px 2px;
opacity: 0.6;
}
.portrait-section-title {
font-size: 1.3em; font-weight: 600; color: #1a1a2e;
margin-bottom: 8px; padding-bottom: 10px;
border-bottom: 2px solid #f0f0f0;
font-family: var(--font-display);
font-size: var(--text-2xl);
font-weight: 700;
color: var(--color-navy);
margin-bottom: var(--space-3);
padding-bottom: var(--space-3);
border-bottom: 1px solid var(--color-rule);
letter-spacing: -0.01em;
}
.portrait-headline {
font-size: 1.05em; color: #555; line-height: 1.6;
margin-bottom: 20px; padding: 12px 16px;
background: #fff9ed; border-right: 3px solid #e9a13f;
border-radius: 4px;
font-family: var(--font-display);
font-size: 1.15em;
font-style: italic;
color: var(--color-navy);
line-height: 1.65;
margin-bottom: 24px;
padding: 16px 22px;
background: var(--color-gold-wash);
border-right: 4px solid var(--color-gold);
border-radius: var(--radius);
position: relative;
}
.portrait-headline::before {
content: '"';
font-size: 3em;
font-family: var(--font-display);
color: var(--color-gold-soft);
position: absolute;
top: -8px; right: 16px;
opacity: 0.3;
font-weight: 700;
}
/* Hero section */
@@ -425,7 +825,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
}
.hero-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.hero-stat { text-align: center; padding: 14px; background: #fafafa; border-radius: 8px; }
.hero-stat-value { font-size: 1.9em; font-weight: 700; color: #1a1a2e; line-height: 1; }
.hero-stat-value { font-size: 1.9em; font-weight: 700; color: var(--color-ink); line-height: 1; }
.hero-stat-label { font-size: 0.8em; color: #888; margin-top: 6px; }
.hero-donut-wrap { display: flex; align-items: center; gap: 20px; }
@@ -463,7 +863,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
}
.hero-timeline-dot {
position: absolute; top: 50%; width: 10px; height: 10px;
border-radius: 50%; background: #e94560; transform: translate(50%, -50%);
border-radius: 50%; background: var(--color-gold); transform: translate(50%, -50%);
cursor: pointer; transition: transform 0.15s;
box-shadow: 0 0 0 2px #fff;
}
@@ -505,7 +905,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
}
.phrase-filter:hover { background: #f5f5f5; }
.phrase-filter.active {
background: #1a1a2e; color: #fff; border-color: #1a1a2e;
background: var(--color-ink); color: #fff; border-color: var(--color-ink);
}
.phrase-wall {
display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
@@ -517,7 +917,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
display: flex; flex-direction: column; gap: 6px;
}
.phrase-card:hover { background: #fff; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.phrase-card-text { font-weight: 500; color: #1a1a2e; line-height: 1.4; }
.phrase-card-text { font-weight: 500; color: var(--color-ink); line-height: 1.4; }
.phrase-card-meta {
display: flex; justify-content: space-between; font-size: 0.75em; color: #999;
margin-top: auto;
@@ -534,9 +934,9 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
background: linear-gradient(to bottom, #fafafa, #fff);
border-radius: 6px;
}
.growth-curve-path { fill: none; stroke: #e94560; stroke-width: 2.5; }
.growth-curve-path { fill: none; stroke: var(--color-gold); stroke-width: 2.5; }
.growth-curve-area { fill: #fce4e9; opacity: 0.6; }
.growth-curve-dot { fill: #e94560; cursor: pointer; transition: r 0.15s; }
.growth-curve-dot { fill: var(--color-gold); cursor: pointer; transition: r 0.15s; }
.growth-curve-dot:hover { r: 6; }
.contribution-grid {
@@ -553,7 +953,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 8px; font-size: 0.82em; color: #555;
}
.contribution-card-number { font-weight: 600; color: #1a1a2e; font-size: 1em; }
.contribution-card-number { font-weight: 600; color: var(--color-ink); font-size: 1em; }
.contribution-badges { display: flex; gap: 8px; margin: 10px 0; }
.contribution-badge {
padding: 4px 10px; border-radius: 10px; font-size: 0.78em; font-weight: 600;
@@ -564,7 +964,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
font-size: 0.82em; color: #666; margin-top: 8px; padding-top: 8px;
border-top: 1px dashed #e5e5e5; line-height: 1.5;
}
.contribution-highlight strong { color: #1a1a2e; }
.contribution-highlight strong { color: var(--color-ink); }
/* Modal */
.phrase-modal {
@@ -582,7 +982,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
letter-spacing: 0.05em;
}
.phrase-modal-text {
font-size: 1.1em; font-weight: 600; color: #1a1a2e;
font-size: 1.1em; font-weight: 600; color: var(--color-ink);
margin-bottom: 12px; line-height: 1.5;
}
.phrase-modal-context {
@@ -593,7 +993,7 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
max-height: 300px; overflow-y: auto;
}
.phrase-modal-example {
padding: 10px 14px; background: #fafafa; border-right: 3px solid #e94560;
padding: 10px 14px; background: #fafafa; border-right: 3px solid var(--color-gold);
font-size: 0.86em; line-height: 1.5; color: #333; border-radius: 4px;
}
@@ -623,11 +1023,45 @@ header nav a:hover, header nav a.active { color: #fff; background: rgba(255,255,
</header>
<div class="main">
<!-- ══ Page: Case List ══ -->
<!-- ══ Page: Case List (Dashboard) ══ -->
<div class="page" id="page-home">
<div class="home-hero">
<div class="home-hero-text">
<p class="home-hero-eyebrow">עוזר משפטי · ועדת ערר ירושלים</p>
<h1 class="home-hero-title">לוח הבית</h1>
<p class="home-hero-subtitle">ניהול תיקי ערר, קורפוס הסגנון והחלטות בתהליך</p>
</div>
<div class="home-hero-actions">
<button class="btn btn-primary" onclick="navigate('/new')">+ תיק חדש</button>
</div>
</div>
<div class="kpi-row" id="kpiRow">
<div class="kpi-card">
<div class="kpi-label">תיקי ערר</div>
<div class="kpi-value" id="kpiCases"></div>
</div>
<div class="kpi-card">
<div class="kpi-label">קורפוס סגנון</div>
<div class="kpi-value" id="kpiCorpus"></div>
<div class="kpi-caption">החלטות שנלמדו</div>
</div>
<div class="kpi-card">
<div class="kpi-label">דפוסי סגנון</div>
<div class="kpi-value" id="kpiPatterns"></div>
<div class="kpi-caption">ביטויים שחולצו</div>
</div>
<div class="kpi-card">
<div class="kpi-label">בעיבוד</div>
<div class="kpi-value" id="kpiProcessing"></div>
<div class="kpi-caption">מסמכים פעילים</div>
</div>
</div>
<div class="divider-gold"></div>
<div class="page-header">
<h2>תיקי ערר</h2>
<button class="btn btn-primary" onclick="navigate('/new')">+ תיק חדש</button>
<h2>תיקים פעילים</h2>
</div>
<div class="case-grid" id="caseGrid">
<div class="empty">טוען תיקים...</div>
@@ -1051,6 +1485,7 @@ function handleRoute() {
document.getElementById('page-home').classList.add('active');
document.getElementById('navHome').classList.add('active');
loadCaseList();
loadKPIs();
} else if (hash === '#/new') {
document.getElementById('page-new').classList.add('active');
document.getElementById('navNew').classList.add('active');
@@ -1675,7 +2110,7 @@ function setupExportUpload(caseNumber) {
const newInput = newZone.querySelector('input[type="file"]');
newZone.addEventListener('click', () => newInput.click());
newZone.addEventListener('dragover', e => { e.preventDefault(); newZone.style.borderColor = '#e94560'; });
newZone.addEventListener('dragover', e => { e.preventDefault(); newZone.style.borderColor = 'var(--color-gold)'; });
newZone.addEventListener('dragleave', () => { newZone.style.borderColor = '#ccc'; });
newZone.addEventListener('drop', e => {
e.preventDefault();
@@ -1833,6 +2268,31 @@ async function loadStatus() {
} catch (e) {}
}
async function loadKPIs() {
// Home dashboard KPI tiles
const casesEl = document.getElementById('kpiCases');
const corpusEl = document.getElementById('kpiCorpus');
const patternsEl = document.getElementById('kpiPatterns');
const procEl = document.getElementById('kpiProcessing');
if (!casesEl) return;
try {
const [statusRes, corpusRes, patternsRes] = await Promise.all([
fetch(API + '/processing-status').then(r => r.json()).catch(() => ({})),
fetch(API + '/training/corpus').then(r => r.json()).catch(() => []),
fetch(API + '/training/patterns').then(r => r.json()).catch(() => ({total: 0})),
]);
casesEl.textContent = statusRes.cases ?? '0';
corpusEl.textContent = corpusRes.length || '0';
patternsEl.textContent = patternsRes.total || '0';
// Count decisions currently being processed
const procCount = (statusRes.processing_documents ?? statusRes.processing ?? 0);
procEl.textContent = procCount || '0';
} catch (e) {
console.error('KPI load failed', e);
}
}
// ── Helpers ──────────────────────────────────────────────
function esc(s) {
if (!s) return '';
@@ -1875,7 +2335,7 @@ async function loadSkillList() {
actions.push(`<button class="btn btn-sm btn-secondary" onclick="syncSkill('${esc(s.slug)}')">Re-sync</button>`);
}
if (inDb) {
actions.push(`<button class="btn btn-sm btn-outline" style="color:#e94560;border-color:#e94560" onclick="deleteSkill('${esc(s.slug)}')">Delete from DB</button>`);
actions.push(`<button class="btn btn-sm btn-outline" style="color:var(--color-gold);border-color:var(--color-gold)" onclick="deleteSkill('${esc(s.slug)}')">Delete from DB</button>`);
}
return `
<div class="skill-item">
@@ -2009,16 +2469,16 @@ async function restartPaperclip() {
const data = await res.json();
if (!res.ok) {
status.textContent = 'Error: ' + (data.detail || 'failed');
status.style.color = '#e94560';
status.style.color = 'var(--color-gold)';
toast('Restart failed', 'error');
} else {
status.textContent = 'Restarted successfully';
status.style.color = '#27ae60';
status.style.color = 'var(--color-success)';
toast('Paperclip restarted', 'success');
}
} catch (e) {
status.textContent = 'Network error';
status.style.color = '#e94560';
status.style.color = 'var(--color-gold)';
toast('Network error', 'error');
} finally {
btn.disabled = false;
@@ -2389,7 +2849,7 @@ const SECTION_COLORS = {
conclusion: '#b8894a',
};
const DONUT_COLORS = ['#e94560', '#5e9a6e', '#4e7cb3', '#a7547c', '#c87533', '#7e5c9a', '#b8894a'];
const DONUT_COLORS = ['var(--color-gold)', '#5e9a6e', '#4e7cb3', '#a7547c', '#c87533', '#7e5c9a', '#b8894a'];
let _styleReportData = null;
let _activeFilter = 'all';