feat: Legal Tools v1 — multilingual landing, dashboard, SSO bridge

- Public landing page at / for unauthenticated users (EN/NO/UK/PL)
- Authenticated / shows Case Workbench dashboard with manifesto strip,
  stats, and launched-tool grid (Transcribe, Timeline, BVJ, Advocate,
  Deep Research, Corpus)
- Added includes/i18n.php with full 4-language translation layer
- Extended layout.php to Case Workbench shell with tool rail, lang switcher
- AI output language normalization extended to en/no/uk/pl in PHP agents
- SSO token validation in bootstrap.php / index.php (dobetternorge.no bridge)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 22:53:27 +02:00
parent ba6c197f1b
commit a3d46f9756
19 changed files with 1149 additions and 238 deletions
+498
View File
@@ -14,6 +14,461 @@
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
/* Do Better Norge v1 workbench */
:root {
--dbn-paper: #f6f2ea;
--dbn-ink: #16130f;
--dbn-blue: #00205b;
--dbn-red: #ba0c2f;
--dbn-teal: #0f766e;
--dbn-line: rgba(22, 19, 15, 0.16);
}
body {
background:
linear-gradient(90deg, rgba(0, 32, 91, 0.055) 1px, transparent 1px),
linear-gradient(180deg, rgba(186, 12, 47, 0.04), transparent 38rem),
var(--dbn-paper);
background-size: 44px 44px, auto, auto;
}
.app-shell {
padding: 18px clamp(14px, 2vw, 28px) 34px;
}
.topbar {
align-items: flex-start;
border-bottom: 2px solid rgba(22, 19, 15, 0.14);
padding-bottom: 16px;
}
.topbar h1 {
color: var(--dbn-ink);
font-size: clamp(1.8rem, 2.8vw, 3.2rem);
line-height: 0.95;
letter-spacing: 0;
}
.title-mark {
color: var(--dbn-red);
}
.case-no {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
margin-top: 9px;
color: #5d574e;
font-size: 0.86rem;
font-weight: 700;
}
.case-sep {
opacity: 0.45;
}
.pulse {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--dbn-teal);
box-shadow: 0 0 0 5px rgba(15, 118, 110, 0.12);
}
.shell-lang-switcher {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px;
border: 1px solid var(--dbn-line);
border-radius: 8px;
background: rgba(255, 255, 255, 0.64);
}
.shell-lang-switcher a {
display: inline-flex;
min-width: 36px;
min-height: 30px;
align-items: center;
justify-content: center;
border-radius: 6px;
color: var(--dbn-blue);
font-size: 0.78rem;
font-weight: 900;
text-decoration: none;
}
.shell-lang-switcher a.is-active,
.shell-lang-switcher a:hover {
background: var(--dbn-blue);
color: #fff;
}
.manifesto {
max-width: 1500px;
margin: 0 auto 12px;
display: grid;
grid-template-columns: minmax(0, 1.15fr) minmax(360px, 0.85fr);
gap: 14px;
border: 1px solid rgba(22, 19, 15, 0.18);
border-radius: 8px;
background:
linear-gradient(135deg, rgba(186, 12, 47, 0.14), transparent 44%),
linear-gradient(90deg, rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0.42));
overflow: hidden;
}
.manifesto-copy {
padding: clamp(20px, 3vw, 36px);
}
.manifesto-eyebrow {
margin: 0 0 8px;
color: var(--dbn-red);
font-size: 0.78rem;
font-weight: 900;
letter-spacing: 0;
text-transform: uppercase;
}
.manifesto-title {
max-width: 780px;
margin: 0;
color: var(--dbn-ink);
font-size: clamp(2rem, 5vw, 5.4rem);
line-height: 0.92;
letter-spacing: 0;
}
.manifesto-sub {
max-width: 760px;
margin: 14px 0 0;
color: #3f3932;
font-size: clamp(1rem, 1.3vw, 1.18rem);
line-height: 1.45;
}
.manifesto-stats {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
border-left: 1px solid rgba(22, 19, 15, 0.16);
}
.manifesto-stat {
min-height: 120px;
padding: 20px;
border: 0 solid rgba(22, 19, 15, 0.13);
border-bottom-width: 1px;
border-right-width: 1px;
background: rgba(255, 255, 255, 0.38);
}
.manifesto-stat strong {
display: block;
color: var(--dbn-blue);
font-size: clamp(1.8rem, 3vw, 3.2rem);
line-height: 1;
}
.manifesto-stat span {
display: block;
margin-top: 8px;
color: #4b453d;
font-size: 0.82rem;
font-weight: 800;
text-transform: uppercase;
}
.workspace {
grid-template-columns: 204px minmax(0, 1fr) 370px;
}
.tool-rail,
.tool-panel,
.reasoning-panel,
.gate-panel,
.cap-card,
.dashboard-tool-card {
border-color: rgba(22, 19, 15, 0.15);
box-shadow: 0 18px 45px rgba(22, 19, 15, 0.08);
}
.tool-tab {
position: relative;
min-height: 74px;
overflow: hidden;
}
.tool-tab em {
position: absolute;
right: 10px;
bottom: 8px;
color: rgba(0, 32, 91, 0.22);
font-size: 1.25rem;
font-style: normal;
font-weight: 900;
}
.tool-tab.is-active {
background: #fdf8ef;
border-color: rgba(186, 12, 47, 0.28);
color: var(--dbn-ink);
}
.tool-tab.is-active::before {
content: "";
position: absolute;
inset: 0 auto 0 0;
width: 4px;
background: var(--dbn-red);
}
.dashboard-shell .disclaimer {
margin-bottom: 18px;
}
.tool-dashboard-grid {
max-width: 1500px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
}
.dashboard-tool-card {
position: relative;
min-height: 250px;
padding: 22px;
border: 1px solid var(--dbn-line);
border-radius: 8px;
background: rgba(255, 255, 255, 0.82);
color: var(--dbn-ink);
text-decoration: none;
overflow: hidden;
}
.dashboard-tool-card:hover {
transform: translateY(-2px);
border-color: rgba(186, 12, 47, 0.36);
}
.dashboard-tool-card__icon {
color: rgba(0, 32, 91, 0.14);
font-size: 4.8rem;
font-weight: 900;
line-height: 1;
}
.dashboard-tool-card__badge {
position: absolute;
top: 20px;
right: 18px;
color: var(--dbn-red);
font-size: 0.75rem;
font-weight: 900;
text-transform: uppercase;
}
.dashboard-tool-card h2 {
margin: 12px 0 8px;
font-size: 1.45rem;
}
.dashboard-tool-card p {
color: #514b43;
line-height: 1.48;
}
.dashboard-tool-card strong {
position: absolute;
bottom: 20px;
color: var(--dbn-blue);
}
.dbn-public-tools {
min-height: 100vh;
}
.showcase-header {
background: rgba(255, 255, 255, 0.72);
border-bottom: 1px solid var(--dbn-line);
}
.showcase-header-inner {
align-items: flex-start;
padding-top: 22px;
padding-bottom: 22px;
}
.showcase-header-actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 10px;
}
.showcase-title {
max-width: 980px;
color: var(--dbn-ink);
font-size: clamp(2.4rem, 6vw, 6.4rem);
line-height: 0.9;
letter-spacing: 0;
}
.showcase-tagline {
max-width: 780px;
color: #403a33;
font-size: clamp(1.05rem, 1.6vw, 1.32rem);
}
.landing-hero {
max-width: 1500px;
margin: 18px auto;
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(280px, 420px);
gap: 14px;
padding: clamp(22px, 4vw, 54px);
border: 1px solid var(--dbn-line);
border-radius: 8px;
background:
linear-gradient(135deg, rgba(0, 32, 91, 0.12), transparent 34%),
linear-gradient(315deg, rgba(186, 12, 47, 0.16), transparent 40%),
#fffaf2;
}
.landing-hero h2 {
max-width: 840px;
margin: 0;
font-size: clamp(2rem, 5vw, 5.3rem);
line-height: 0.92;
letter-spacing: 0;
}
.landing-hero p {
max-width: 740px;
color: #403a33;
font-size: 1.08rem;
line-height: 1.5;
}
.landing-hero__stats {
display: grid;
gap: 10px;
align-content: center;
}
.landing-hero__stats div {
padding: 18px;
border: 1px solid rgba(0, 32, 91, 0.16);
border-radius: 8px;
background: rgba(255, 255, 255, 0.7);
}
.landing-hero__stats strong {
display: block;
color: var(--dbn-blue);
font-size: 2.5rem;
}
.landing-hero__stats span {
color: #514b43;
font-weight: 800;
}
.cap-grid--six {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.evidence-inner {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.evidence-inner article {
padding: 20px;
border-left: 4px solid rgba(186, 12, 47, 0.45);
background: rgba(255, 255, 255, 0.58);
}
.google-access-button {
display: flex;
align-items: center;
justify-content: center;
min-height: 48px;
margin: 18px 0;
border-radius: 8px;
background: var(--dbn-blue);
color: #fff;
font-weight: 900;
text-decoration: none;
}
.fallback-login {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid var(--dbn-line);
}
.fallback-login summary {
cursor: pointer;
color: #655d53;
font-weight: 800;
}
@media (max-width: 1120px) {
.workspace {
grid-template-columns: 1fr;
}
.tool-rail {
flex-direction: row;
overflow-x: auto;
}
.tool-tab {
min-width: 170px;
}
.manifesto,
.landing-hero {
grid-template-columns: 1fr;
}
.manifesto-stats {
border-left: 0;
}
.tool-dashboard-grid,
.cap-grid--six,
.evidence-inner {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 680px) {
.topbar,
.showcase-header-inner {
flex-direction: column;
}
.topbar-actions,
.showcase-header-actions {
width: 100%;
justify-content: flex-start;
}
.manifesto-stats,
.tool-dashboard-grid,
.cap-grid--six,
.evidence-inner {
grid-template-columns: 1fr;
}
.dashboard-tool-card {
min-height: 220px;
}
}
* {
box-sizing: border-box;
}
@@ -3712,3 +4167,46 @@ a.dr-source-title-link:hover {
position: relative;
top: -1px;
}
/* v1 final cascade overrides */
body {
background:
linear-gradient(90deg, rgba(0, 32, 91, 0.055) 1px, transparent 1px),
linear-gradient(180deg, rgba(186, 12, 47, 0.04), transparent 38rem),
var(--dbn-paper);
background-size: 44px 44px, auto, auto;
color: var(--dbn-ink);
}
.app-shell { padding: 18px clamp(14px, 2vw, 28px) 34px; }
.topbar { align-items: flex-start; border-bottom: 2px solid rgba(22, 19, 15, 0.14); padding-bottom: 16px; }
.topbar h1 { color: var(--dbn-ink); font-size: clamp(1.8rem, 2.8vw, 3.2rem); line-height: .95; letter-spacing: 0; }
.workspace { grid-template-columns: 204px minmax(0, 1fr) 370px; }
.tool-rail, .tool-panel, .reasoning-panel, .gate-panel, .cap-card, .dashboard-tool-card {
border-color: rgba(22, 19, 15, 0.15);
box-shadow: 0 18px 45px rgba(22, 19, 15, 0.08);
}
.tool-tab { position: relative; min-height: 74px; overflow: hidden; }
.tool-tab em { position: absolute; right: 10px; bottom: 8px; color: rgba(0, 32, 91, .22); font-size: 1.25rem; font-style: normal; font-weight: 900; }
.tool-tab.is-active { background: #fdf8ef; border-color: rgba(186, 12, 47, .28); color: var(--dbn-ink); }
.tool-tab.is-active::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--dbn-red); }
.showcase-title { max-width: 980px; color: var(--dbn-ink); font-size: clamp(2.4rem, 6vw, 6.4rem); line-height: .9; letter-spacing: 0; }
.showcase-tagline { max-width: 780px; color: #403a33; font-size: clamp(1.05rem, 1.6vw, 1.32rem); }
.cap-grid--six { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.evidence-inner { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.google-access-button { display: flex; align-items: center; justify-content: center; min-height: 48px; margin: 18px 0; border-radius: 8px; background: var(--dbn-blue); color: #fff; font-weight: 900; text-decoration: none; }
.fallback-login { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--dbn-line); }
.fallback-login summary { cursor: pointer; color: #655d53; font-weight: 800; }
@media (max-width: 1120px) {
.workspace { grid-template-columns: 1fr; }
.tool-rail { flex-direction: row; overflow-x: auto; }
.tool-tab { min-width: 170px; }
.tool-dashboard-grid, .cap-grid--six, .evidence-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
.topbar, .showcase-header-inner { flex-direction: column; }
.topbar-actions, .showcase-header-actions { width: 100%; justify-content: flex-start; }
.manifesto-stats, .tool-dashboard-grid, .cap-grid--six, .evidence-inner { grid-template-columns: 1fr; }
}