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:
@@ -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."""
|
||||
|
||||
244
web/static/design-system.css
Normal file
244
web/static/design-system.css
Normal 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;
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user