feat: Barnevernet Analyzer — document analysis + partisan RAG brief

7-step agent pipeline: document classification, party extraction, timeline
extraction, corpus RAG (child_welfare/echr/family_core/bufdir_guidance),
and synthesis using the user's chosen engine (including dbn-legal-agent).
Progressive NDJSON streaming renders doc_meta, parties, and timeline cards
before the final advocacy brief and procedural red flags arrive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 20:49:46 +02:00
parent 343b19d0b4
commit 43cf5b8ce4
6 changed files with 2943 additions and 0 deletions
+336
View File
@@ -3376,3 +3376,339 @@ a.dr-source-title-link:hover {
color: var(--muted);
white-space: pre-wrap;
}
/* ============================================================
BVJ Analyzer — document meta, parties, timeline, red flags
============================================================ */
.bvj-doc-meta {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 10px;
padding: 16px 20px;
margin-bottom: 20px;
}
.bvj-doc-meta__head {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
}
.bvj-doc-meta__authority {
font-weight: 700;
color: var(--ink);
font-size: 1rem;
}
.bvj-doc-type-badge {
display: inline-block;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
background: var(--soft-teal);
color: var(--teal-dark);
border: 1px solid #b2dbd6;
border-radius: 20px;
padding: 2px 10px;
}
.bvj-doc-meta__fields {
display: flex;
flex-wrap: wrap;
gap: 8px 20px;
}
.bvj-doc-meta__field {
font-size: 0.84rem;
color: var(--muted);
}
.bvj-doc-meta__field strong {
color: var(--ink);
font-weight: 600;
}
/* --- Parties grid --- */
.bvj-parties-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 12px;
margin-bottom: 20px;
}
.bvj-party-card {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
padding: 12px 14px;
}
.bvj-party-card__name {
font-weight: 700;
font-size: 0.92rem;
color: var(--ink);
margin: 0 0 4px;
}
.bvj-party-card__org {
font-size: 0.8rem;
color: var(--muted);
margin: 0 0 6px;
}
.bvj-party-card__rel {
font-size: 0.8rem;
font-style: italic;
color: var(--muted);
margin: 0 0 8px;
}
.bvj-party-role {
display: inline-block;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.03em;
border-radius: 20px;
padding: 2px 9px;
}
.bvj-party-role--bvv {
background: #e8f0fe;
color: #2d5fa6;
border: 1px solid #c3d4f8;
}
.bvj-party-role--parent {
background: var(--soft-teal);
color: var(--teal-dark);
border: 1px solid #b2dbd6;
}
.bvj-party-role--child {
background: #ecfdf5;
color: #166534;
border: 1px solid #bbf7d0;
}
.bvj-party-role--third {
background: #f3f4f6;
color: #4b5563;
border: 1px solid var(--line);
}
.bvj-party-role--other {
background: #fafafa;
color: var(--muted);
border: 1px solid var(--line);
}
/* --- Timeline --- */
.bvj-timeline-wrap {
display: flex;
flex-direction: column;
gap: 4px;
margin-bottom: 20px;
}
.bvj-timeline-event {
display: grid;
grid-template-columns: 130px 1fr;
border-left: 3px solid var(--line);
border-radius: 0 6px 6px 0;
overflow: hidden;
}
.bvj-timeline-event--high { border-left-color: var(--coral); }
.bvj-timeline-event--medium { border-left-color: var(--amber); }
.bvj-timeline-event--low { border-left-color: var(--line); }
.bvj-timeline-date {
font-family: ui-monospace, "Cascadia Code", "Fira Code", monospace;
font-size: 0.78rem;
color: var(--muted);
background: #f3f4f6;
border-right: 1px solid var(--line);
padding: 10px 12px;
display: flex;
flex-direction: column;
justify-content: flex-start;
gap: 2px;
}
.bvj-timeline-time {
font-size: 0.72rem;
color: var(--muted);
opacity: 0.8;
}
.bvj-timeline-body {
background: var(--panel);
padding: 10px 14px;
display: flex;
flex-direction: column;
gap: 2px;
}
.bvj-timeline-actor {
font-size: 0.78rem;
font-weight: 700;
color: var(--teal-dark);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.bvj-timeline-action {
font-size: 0.88rem;
color: var(--ink);
line-height: 1.5;
}
/* --- Red flags --- */
.bvj-red-flags {
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 20px;
}
.bvj-red-flag {
background: var(--panel);
border: 1px solid var(--line);
border-radius: 8px;
padding: 14px 16px;
}
.bvj-red-flag--high { border-left: 3px solid var(--coral); }
.bvj-red-flag--medium { border-left: 3px solid var(--amber); }
.bvj-red-flag--low { border-left: 3px solid var(--line); }
.bvj-red-flag__head {
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 8px;
}
.bvj-red-flag__desc {
font-weight: 700;
font-size: 0.9rem;
color: var(--ink);
flex: 1;
margin: 0;
}
.bvj-red-flag__legal {
display: inline-block;
font-size: 0.75rem;
font-weight: 600;
background: var(--soft-teal);
color: var(--teal-dark);
border: 1px solid #b2dbd6;
border-radius: 20px;
padding: 2px 9px;
white-space: nowrap;
margin-top: 2px;
}
.bvj-red-flag__details {
margin-top: 6px;
}
.bvj-red-flag__details summary {
font-size: 0.8rem;
color: var(--teal);
cursor: pointer;
user-select: none;
}
.bvj-red-flag__check {
font-size: 0.84rem;
font-style: italic;
color: var(--muted);
margin: 6px 0 0;
line-height: 1.5;
}
/* --- Severity badges --- */
.bvj-severity {
display: inline-block;
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
border-radius: 20px;
padding: 2px 9px;
white-space: nowrap;
}
.bvj-severity-high {
background: var(--soft-coral);
color: var(--coral);
border: 1px solid #f9c6ae;
}
.bvj-severity-medium {
background: #fffbeb;
color: var(--amber);
border: 1px solid #fde68a;
}
.bvj-severity-low {
background: #f3f4f6;
color: var(--muted);
border: 1px solid var(--line);
}
/* --- BVJ result banner (role + doc type header) --- */
.bvj-banner {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
background: var(--soft-teal);
border: 1px solid #b2dbd6;
border-radius: 8px;
margin-bottom: 16px;
}
.bvj-banner__label {
font-size: 0.8rem;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.04em;
font-weight: 600;
}
.bvj-banner__role {
font-size: 0.88rem;
font-weight: 700;
color: var(--teal-dark);
}
/* --- [DOC] citation inline marker --- */
.dr-cite--doc {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: 700;
background: #e8f0fe;
color: #2d5fa6;
border: 1px solid #c3d4f8;
border-radius: 4px;
padding: 1px 5px;
margin: 0 1px;
cursor: default;
vertical-align: baseline;
position: relative;
top: -1px;
}
File diff suppressed because it is too large Load Diff