diff --git a/DESIGN.md b/DESIGN.md
index 60021b55..e9edf85c 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -11,50 +11,50 @@ colors:
warm-graphite: "oklch(26.78% 0.0097 355.6)"
muted-graphite: "oklch(51.33% 0.0088 345.6)"
quiet-border: "oklch(90.93% 0.0035 354.7)"
- success-mint: "oklch(75.77% 0.1581 165)"
+ success-mint: "oklch(46% 0.095 160)"
navigation-active: "oklch(92.5% 0.052 23.2)"
navigation-active-hover: "oklch(89.5% 0.071 23.2)"
navigation-active-foreground: "oklch(36.5% 0.11 23.2)"
navigation-active-border: "oklch(60% 0.135 23.2)"
- warning-amber: "oklch(85.23% 0.1386 78.9)"
- information-blue: "oklch(70.35% 0.1128 221.3)"
+ warning-amber: "oklch(48% 0.09 70)"
+ information-neutral: "oklch(51.33% 0.0088 345.6)"
typography:
display:
- fontFamily: "Fraunces, Source Serif Pro, Georgia, Times New Roman, serif"
- fontSize: "3rem"
+ fontFamily: "Manrope Variable, Manrope, system-ui, sans-serif"
+ fontSize: "1.5rem"
fontWeight: 600
lineHeight: 1.03
letterSpacing: "-0.025em"
headline:
- fontFamily: "Fraunces, Source Serif Pro, Georgia, Times New Roman, serif"
- fontSize: "1.875rem"
+ fontFamily: "Manrope Variable, Manrope, system-ui, sans-serif"
+ fontSize: "1.5rem"
fontWeight: 600
lineHeight: 1.15
letterSpacing: "-0.015em"
title:
- fontFamily: "Fraunces, Source Serif Pro, Georgia, Times New Roman, serif"
- fontSize: "1.2rem"
+ fontFamily: "Manrope Variable, Manrope, system-ui, sans-serif"
+ fontSize: "1.25rem"
fontWeight: 600
lineHeight: 1.25
letterSpacing: "-0.01em"
body:
- fontFamily: "Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, system-ui, Arial, sans-serif"
- fontSize: "0.9375rem"
+ fontFamily: "Manrope Variable, Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, system-ui, Arial, sans-serif"
+ fontSize: "1rem"
fontWeight: 400
lineHeight: 1.65
letterSpacing: "normal"
control:
- fontFamily: "Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, system-ui, Arial, sans-serif"
+ fontFamily: "Manrope Variable, Manrope, -apple-system, BlinkMacSystemFont, Segoe UI, system-ui, Arial, sans-serif"
fontSize: "0.875rem"
fontWeight: 600
lineHeight: 1.25
letterSpacing: "0.005em"
label:
- fontFamily: "ui-monospace, SF Mono, Cascadia Code, Menlo, Consolas, monospace"
- fontSize: "0.6875rem"
+ fontFamily: "Manrope Variable, Manrope, system-ui, sans-serif"
+ fontSize: "0.75rem"
fontWeight: 600
lineHeight: 1.25
- letterSpacing: "0.06em"
+ letterSpacing: "normal"
rounded:
xs: "4px"
sm: "6px"
@@ -113,6 +113,16 @@ components:
# Design System: ThothII
+## Visual review branch, September 2026
+
+The revision on `codex/ui-visual-review` is approved for implementation and Docker visual review,
+not yet for adoption on `main`. The previous look remains recoverable from the base commit and
+the preserved Docker image. Historical prototypes must remain untouched.
+
+This revision follows Impeccable's product register: one locally bundled Manrope family for the
+whole UI, five fixed size roles, red as the sole brand accent and additional color only for meaningful
+state. The primary scene remains an analyst reading data and SQL in a well-lit office.
+
## Overview
**Creative North Star: "The Clinical Workbench"**
@@ -134,7 +144,7 @@ disciplined and tactile, never playful, sluggish, or visually unstable.
**Key Characteristics:**
- Warm, restrained surfaces with one scarce red accent.
-- Editorial headings paired with highly legible operational body text.
+- One sans-serif family, with hierarchy expressed through size, weight and spacing.
- Dense information organized through hierarchy, rhythm, and progressive disclosure.
- Persisted artifacts and reviewer decisions presented as the visual source of truth.
- Fast state feedback with reduced-motion parity.
@@ -178,7 +188,8 @@ frontend uses OKLCH tokens directly.
foreground. It shares Instrument Red's hue but uses a lighter, lower-chroma fill, so location is
visible without carrying the full weight of a primary action.
- **Warning Amber** (`warning-amber`): waiting, attention, and in-progress states.
-- **Information Blue** (`information-blue`): informational state when red would imply action.
+- **Information**: neutral text and indicators for dates, protocols and ordinary status. The legacy
+ `--info` token resolves to muted foreground, not an additional blue accent.
The dark theme keeps the same semantic mapping with neutral near-black surfaces and a slightly
lighter red accent. Do not introduce a second visual identity for dark mode.
@@ -191,30 +202,29 @@ for their named states. Color is never the only state indicator.
## Typography
-**Display Font:** Fraunces, with Source Serif Pro, Georgia, and Times New Roman fallbacks
-**Body Font:** Manrope, with native system sans-serif fallbacks
-**Label/Mono Font:** SF Mono or Cascadia Code, with Menlo and Consolas fallbacks
+**UI Font:** locally bundled Manrope Variable, with Manrope and native sans-serif fallbacks.
+**Technical Font:** SF Mono or Cascadia Code, with Menlo and Consolas fallbacks.
-**Character:** Fraunces gives persisted artifacts and key headings editorial authority. Manrope
-keeps dense controls and prose calm and readable. The mono register separates machine identity,
-metadata, SQL, identifiers, and micro-labels from natural-language content.
+Manrope covers headings, labels, controls, navigation and document reading. Monospace is reserved
+for SQL, code, paths and machine identifiers, never for ordinary UI labels or status headings.
### Hierarchy
-- **Display** (600, `3rem`, `1.03`): authentication and exceptional page-level statements only.
-- **Headline** (600, `1.875rem`, `1.15`): major page or artifact titles.
-- **Title** (600, `1.2rem`, `1.25`): panel and document section hierarchy.
-- **Body** (400, `0.9375rem`, `1.65`): operational prose, with a target line length of 65 to 75
+- **Headline** (600, `1.5rem`, `1.3`): page or artifact titles, `--text-page`.
+- **Title** (600, `1.25rem`, `1.4`): section hierarchy, `--text-section`.
+- **Body** (400, `1rem`, `1.6`): operational prose, `--text-body`, with a target line length of 65 to 75
characters where the surface controls width.
-- **Control** (600, `0.875rem`, `1.25`): buttons, inputs, tabs, and compact actions.
-- **Label** (600, `0.6875rem`, `0.06em` tracking): uppercase micro-labels, state metadata, and panel
- headers. Labels use the mono family.
+- **Control** (400–600, `0.875rem`, `1.5`): buttons, inputs, tables, tabs and compact subheadings,
+ `--text-control`.
+- **Metadata** (400–600, `0.75rem`, `1.5`): secondary status, counts and timestamps, `--text-meta`.
+ Labels use sentence case and normal tracking. Ordinary operational text never falls below 12px.
Typography uses fixed sizes. Responsive changes happen at structural breakpoints, not through fluid
type scaling. Numeric data and identifiers use tabular numerals where comparison matters.
-**The Three Registers Rule.** Serif means authority, sans means interaction and reading, mono means
-machine identity. Do not exchange these roles for novelty.
+**The One Family Rule.** The UI and document readers use sans-serif throughout. The legacy
+`--font-heading` alias resolves to `--font-sans`. Preserve technical monospace without turning it
+into a second decorative hierarchy. Do not shrink text to solve layout constraints.
**The Read Once Rule.** A heading, label, and body must be distinguishable on first glance through
size and weight. Do not repeat headings in explanatory copy.
@@ -279,25 +289,26 @@ default, hover, focus, active, disabled, loading, and error behavior where those
- **Focus:** three-pixel Instrument Red ring with a clear border shift.
- **Error / Disabled:** errors combine destructive color with explanatory text; disabled controls
retain readable contrast and use 50 percent opacity.
-- **Metadata catalog model:** Database Management keeps one compact, installation-level
- metadata-generation LLM selector in the application header. The selection persists across
- database, table, column, and relationship views; when no usable profile is configured, the
- disabled control explains: “No metadata-generation LLM model is configured for this installation.”
+- **Global context:** the collapsible top shelf is the sole workspace/model selector for Core and
+ Admin. Preserve independent remembered choices, installation defaults, operation locks and unsaved
+ edit guards. Never introduce a separate metadata-generation default or selector.
### Navigation
- **Style:** compact session rows use `8px` corners and restrained vertical padding.
- **Default / Hover / Active:** porcelain at rest, Sunken Surface on hover, and a muted Navigation
Active red with a defined border when current. Exactly one top-level navigation control is current.
-- **Administrative controls:** the admin-only Administration accordion groups Database management,
- Memory management, Evidence management, a structural divider, Workspace management, and Pi
- management in that order. Its trigger exposes
+- **Administrative controls:** the admin-only Administration accordion groups Database,
+ Memory, Evidence, a structural divider, Workspace, and Pi configuration in that order. Its trigger exposes
expanded state and starts collapsed by default, while non-admin users do not receive the accordion
or its navigation actions.
- **Responsive:** collapse navigation structurally at the application breakpoint. Do not shrink
labels into illegibility. Below 768px, Memory and Evidence management use the full content
width; a Navigation button opens the shared accessible dialog. Selecting another archive
- page or pressing Escape closes it. Desktop retains the session sidebar.
+ page or pressing Escape closes it. Desktop retains the right session sidebar and its My sessions /
+ All sessions tabs. Core retains question/answer, eight phases, reviewer gates and the left log.
+ The portal owns the red header and left sidebar; ThothII must not duplicate them. Size to the
+ actual application container. Narrow session document panels may use the available width.
### Tabs
diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md
index be947785..fb502369 100644
--- a/PROJECT_STATE.md
+++ b/PROJECT_STATE.md
@@ -14,13 +14,35 @@ requirements as mandatory; do not replace the running server stack in place.
## Current product shape
+### Isolated visual review, awaiting owner acceptance
+
+The UI revision is isolated in `/Users/mp/projects/ThothII-visual-review`, branch
+`codex/ui-visual-review`, based on `2d1b714e`. The original checkout and its prototypes
+remain intact. No merge to `main` has been performed.
+
+Local Docker at `http://127.0.0.1:8080/` now runs the frontend image
+`thothii-frontend:visual-review-20260912`. Only frontend was recreated; Core and all
+data services/volumes/configurations are unchanged. The prior look is preserved as
+`thothii-frontend:before-visual-review-20260912`. All five running services are healthy.
+
+The revision uses bundled Manrope throughout, shared type roles, restrained semantic
+colors, clearer Admin copy and a readable compact session-document panel. Core and
+session behavior remain covered by the existing regression suite. Verification:
+679 frontend tests, 7 Playwright visual/interaction scenarios and a production build.
+See `docs/reports/2026-09-12-ui-visual-review-delivery.md` for scope, limits and the
+exact local rollback command. Visual approval is required before adoption on `main`.
+
Gitea #28–#31 follow-up is implemented in this checkout: Workspace's four tabs,
Database list-first entry without the preparation footer, full-height Pi instructions
with installation-host OS selection, and short Admin navigation labels. Core and
-session behavior are retained. These follow-up changes are **not yet rebuilt into
-local Docker**; see `docs/reports/2026-09-12-admin-issues-28-31.md` for test/review results.
-The host CLI must regenerate its Compose projection on the destination installation
-to identify the physical host OS correctly when the backend runs in Docker.
+session behavior are retained. At the owner's request, these changes were rebuilt into
+local Docker on 2026-09-12 at 18:31 UTC. Core/frontend are healthy and the UI at
+`http://127.0.0.1:8080` serves the updated bundle. The host projection now supplies
+`THT_HOST_PLATFORM=darwin`, so Pi selects macOS rather than the container's Linux OS.
+Persistent dependency containers and volumes were unchanged. Rollback images are tagged
+`thothii-core:before-admin-28-31-20260912` and
+`thothii-frontend:before-admin-28-31-20260912`. See
+`docs/reports/2026-09-12-admin-issues-28-31.md` for verification and deployment details.
The latest context-shelf A and five Administration pages are implemented locally.
At the owner's request, local Docker project `thothii-18998cca7b0a` was rebuilt and
diff --git a/deploy/compose.visual-review-rollback.yaml b/deploy/compose.visual-review-rollback.yaml
new file mode 100644
index 00000000..2b25659d
--- /dev/null
+++ b/deploy/compose.visual-review-rollback.yaml
@@ -0,0 +1,4 @@
+# The image is tagged from the running frontend before the visual review is published.
+services:
+ frontend:
+ image: thothii-frontend:before-visual-review-20260912
diff --git a/deploy/compose.visual-review.yaml b/deploy/compose.visual-review.yaml
new file mode 100644
index 00000000..abaa77f7
--- /dev/null
+++ b/deploy/compose.visual-review.yaml
@@ -0,0 +1,8 @@
+# Local-only review override. Apply after the existing local installation profiles.
+# Changes only the frontend image; Core, configuration and volumes remain unchanged.
+services:
+ frontend:
+ image: thothii-frontend:visual-review-20260912
+ build:
+ context: /Users/mp/projects/ThothII-visual-review
+ dockerfile: docker/frontend.Dockerfile
diff --git a/docs/reports/2026-09-12-admin-issues-28-31.md b/docs/reports/2026-09-12-admin-issues-28-31.md
index 36fd1128..80dcfa34 100644
--- a/docs/reports/2026-09-12-admin-issues-28-31.md
+++ b/docs/reports/2026-09-12-admin-issues-28-31.md
@@ -52,7 +52,7 @@ projecting the host platform, and shortening navigation labels.
initially exposed horizontal page overflow at 390 pixels; constrained grid children
and narrow definition lists corrected it. Database QA used an empty synthetic catalog;
the unit suites exercise populated tables, columns, edits and operation guards.
-- Docker and real-stack Playwright acceptance were not run for this follow-up.
+- Docker and real-stack Playwright acceptance were not run during initial implementation.
The preview is synthetic and read-only, not a deployment or provider smoke test.
## Standards
@@ -73,5 +73,24 @@ The independent follow-up review confirmed both findings resolved, with no new r
Review summary: Standards 2 findings resolved, 0 outstanding; Spec 2 findings resolved,
0 outstanding. Both reviews were read-only, relative to the user-approved baseline.
-Docker has not been rebuilt for this follow-up; the read-only QA preview uses the changed source.
+## Local Docker deployment
+
+At the owner's request, core and frontend were rebuilt from this checkout and recreated
+on 2026-09-12 at 18:31 UTC using `/private/tmp/thothii-memory-preview.sh`, with
+`--no-deps --force-recreate --wait`. Both are healthy. Database, Qdrant and embedding
+containers retained their original IDs; no persistent volumes were deleted or recreated.
+
+The normal model projection generator was run on this Mac before recreation; the running
+core now receives `THT_HOST_PLATFORM=darwin`. The authored installation configuration and
+credentials were unchanged. Before the update, images were retained as
+`thothii-core:before-admin-28-31-20260912` and
+`thothii-frontend:before-admin-28-31-20260912`; the prior projection directory was copied to
+`/private/tmp/thoth-admin-28-31-docker.5ebAo8/generated`.
+
+HTTP checks for the real UI (`http://127.0.0.1:8080/`), its `/api/health` proxy, and
+the core `/health` returned 200. Served bundle `/index-Bsz7otBx.js` contains Workspace
+areas and Pi configuration, and no longer contains the preparation footer or persisted
+Database child-screen key. Authenticated end-to-end operator workflows were not rerun.
+
+The Vite preview remains separate from Docker. Remote server deployment was not performed.
No Gitea issue state or remote branch was changed.
diff --git a/docs/reports/2026-09-12-ui-survey-and-graphic-revision-plan.md b/docs/reports/2026-09-12-ui-survey-and-graphic-revision-plan.md
new file mode 100644
index 00000000..a97826fa
--- /dev/null
+++ b/docs/reports/2026-09-12-ui-survey-and-graphic-revision-plan.md
@@ -0,0 +1,191 @@
+# ThothII: survey e piano di revisione grafica
+
+Data: 12 settembre 2026. Stato: **proposta, da approvare; nessuna modifica all'interfaccia**.
+
+## Sintesi e direzione consigliata
+
+L'incoerenza segnalata è confermata. Non dipende soltanto da dettagli sfuggiti nelle singole pagine: il design system attuale prescrive tre registri tipografici, ai quali alcuni componenti aggiungono un secondo stack serif. Titoli, etichette operative, documenti e istruzioni finiscono così per sembrare parti di prodotti diversi.
+
+Propongo una direzione unica: **interfaccia operativa interamente sans-serif, rosso istituzionale come accento, colori aggiuntivi soltanto quando comunicano uno stato, maggiore coerenza senza impoverire le informazioni**. Non serve una nuova impaginazione del Core né una nuova collocazione delle sessioni.
+
+Ho usato **Impeccable**, nel registro product, per orientare la valutazione di gerarchia, tipografia, densità, colore e microcopy. La varietà visiva dovrà venire da spaziatura, pesi e organizzazione, non dall'alternanza di famiglie tipografiche. Le grazie non sono intrinsecamente incompatibili con un prodotto tecnologico, ma qui contrastano con la direzione richiesta e non svolgono una funzione necessaria: le eliminerei dalla UI, compresi i lettori di documenti.
+
+## 1. Metodo, copertura e limiti
+
+Verifica tramite Playwright nel browser dell'app, con screenshot, navigazione e lettura degli stili CSS calcolati. La survey principale riguarda la **versione Docker reale su `http://127.0.0.1:8080/`**, autenticata con l'account autorizzato. Una precedente esplorazione dell'anteprima sintetica non è usata come prova dei dati o del funzionamento del Docker.
+
+| Area | Verifica sulla versione reale |
+| --- | --- |
+| Workspace | Preparation, Specific actions, About, Authentication |
+| Database | Elenco database, navigazione alle tabelle e alle colonne |
+| Memory | Elenco vuoto e apertura del form New card, chiuso senza modifiche |
+| Evidence | Fonti/importazione, elenco, dettaglio di un documento |
+| Pi | Runtime e Host maintenance, scheda macOS |
+| Core | Stato iniziale, compositore e controlli presenti senza avviare una domanda |
+| Sessioni | My sessions, All sessions, archivio e lettura di una sessione archiviata |
+| Navigazione | Drawer responsive, accessi Admin e contesto globale |
+
+Non ho salvato form, lanciato elaborazioni, ripreso sessioni, importato documenti o modificato configurazioni. Il controllo del Core attivo, delle fasi, dei gate e del log è limitato alla lettura del codice: non è stato eseguito un ciclo LLM per una survey grafica.
+
+Il viewport misurato nel pannello browser era **649 × 1091 CSS px**. Questo offre evidenza concreta del comportamento a larghezza ridotta, ma non sostituisce una matrice desktop/mobile. Tema scuro, contrasto numerico, navigazione completa da tastiera, zoom e integrazione effettiva in Omics Portal restano da verificare. Non è una certificazione WCAG né un audit automatizzato completo. Le famiglie riportate sono gli stack CSS calcolati, non una verifica del font effettivamente caricato dal sistema.
+
+## 2. Problemi riscontrati
+
+### Tipografia: quattro stack e gerarchie variabili
+
+| Esempio osservato | Trattamento attuale | Problema |
+| --- | --- | --- |
+| Titoli delle pagine Admin | Fraunces/serif, 30 px | Registro editoriale molto più marcato del resto dell'app |
+| Sources and imports; titolo del form Memory | Altro stack `ui-serif`, 18–20 px | Nemmeno i titoli serif usano tutti la stessa famiglia |
+| Evidence library; Original question; Revised question | Monospace, 11 px | Etichette ordinarie trattate come identificatori tecnici |
+| Working context | Monospace maiuscolo, 10 px | Informazione globale importante resa molto piccola |
+| Guida Pi Host maintenance | Testo 12 px, interlinea 16 px; titoletti serif 12 px | Istruzioni lunghe troppo dense e gerarchia debole |
+| Sessione archiviata | Titolo sessione serif 14 px; titolo nel documento serif 23,2 px | Il contenuto sovrasta il contesto del pannello |
+
+La causa è documentata in `DESIGN.md`, nella regola dei tre registri. Nel codice, `frontend/src/index.css` assegna globalmente il font heading a `h1`–`h6` e ai titoli della prosa; Memory ed Evidence aggiungono classi `font-serif`. Il problema ricompare quindi anche quando un componente non richiede esplicitamente un titolo decorativo.
+
+### Colore: troppi significati impliciti
+
+- In Database il tipo di connessione REST e la data di aggiornamento ricevono accenti blu pur essendo informazioni ordinarie.
+- La guida ordinaria di manutenzione Pi è racchiusa in una cornice ambra, visivamente simile a un avviso. Il colore non distingue un pericolo concreto.
+- Gli stati Ready in Pi usano anche testo verde molto chiaro: è un rischio di leggibilità da misurare, non una violazione numericamente accertata in questa survey.
+- Stato operativo, azione primaria, contenitore informativo e semplice categoria non seguono una grammatica cromatica sufficientemente riconoscibile.
+
+Non eliminerei invece indiscriminatamente verde e ambra: successo, errore, attesa di revisione e avvertimento devono restare distinguibili, sempre anche tramite testo o icona.
+
+### Spazio e linguaggio
+
+| Area | Evidenza | Intervento proposto |
+| --- | --- | --- |
+| Workspace | Identità e descrizioni ripetute fra contesto, selezione e intestazioni; molte gerarchie prima delle azioni | Mantenere le quattro schede, ridurre ripetizioni e uniformare sezioni e azioni |
+| Database | Intestazione, stato, cronologia, Fleet summary, breadcrumb e toolbar precedono i dati; a 649 px il riepilogo occupa più righe | Compattare il riepilogo, dare priorità alla griglia; sostituire il gergo Fleet con un nome corrispondente al suo ambito |
+| Memory | Stato vuoto formulato come assenza di risultati filtrati anche senza carte; ampie aree vuote e paginazione disabilitata | Distinguere libreria vuota da ricerca senza risultati; stesso linguaggio visivo di toolbar e form del resto dell'Admin |
+| Evidence | Percorso tecnico e istruzioni di importazione dominano la parte superiore; ricerca compressa rispetto agli altri filtri | Istruzioni brevi con dettagli espandibili; percorso secondario ma copiabile; filtri che si dispongono su più righe prima di diventare illeggibili |
+| Pi | Guida molto lunga e piccola; spiegazioni dell'architettura mescolate con istruzioni all'operatore | Separare stato, azioni e guida; rendere la guida leggibile e consultabile per attività |
+| Sessioni | Molti registri tipografici; a 649 px il pannello documenti è stretto e tronca il titolo | Coerenza dei titoli e dei documenti; adeguare il pannello alla larghezza disponibile senza cambiare la gestione delle sessioni |
+| Core e navigazione | Branding ripetuto, microetichette e controlli di taglie diverse | Riallineare la gerarchia e i componenti condivisi, conservando struttura e comportamento |
+
+Gli stili comunicativi oscillano fra introduzione promozionale nel Core, manuale tecnico in Pi/Evidence e terminologia da dashboard infrastrutturale in Database. La soluzione è un tono operativo unico, non la rimozione delle informazioni tecniche necessarie.
+
+## 3. Regole del sistema visivo proposto
+
+### Una famiglia UI, cinque ruoli dimensionali
+
+Consiglio di **mantenere Manrope**, già adottato per l'interazione, e usarlo per tutta la UI. Non aggiungerei una nuova famiglia per il solo gusto di cambiare. Pesi ordinari 400, 500 e 600; monospace soltanto per SQL, codice, percorsi e identificatori quando serve riconoscerli o copiarli.
+
+| Ruolo | Dimensione proposta | Uso |
+| --- | --- | --- |
+| Titolo pagina | 24 px / 1,5 rem, peso 600 | Core/Admin, senza effetto copertina |
+| Titolo sezione | 20 px / 1,25 rem, peso 600 | Sezioni principali e pannelli di lettura |
+| Lettura | 16 px / 1 rem, peso 400 | Risposte, documenti, istruzioni articolate; interlinea circa 1,5 |
+| Interazione e dati | 14 px / 0,875 rem, peso 400–600 | Form, tab, pulsanti, griglie; sottosezioni compatte in peso 600 |
+| Metadati secondari | 12 px / 0,75 rem, peso 400–500 | Timestamp, conteggi e indicazioni accessorie |
+
+Sono ruoli, non l'obbligo di rendere ogni titolo di sezione grande: una sottosezione compatta può usare il ruolo da 14 px in semibold. Niente ridimensionamento fluido che faccia oscillare continuamente i caratteri con la larghezza. Prima si riorganizza il layout, poi si valutano eccezioni documentate.
+
+Ulteriori regole:
+
+- Eliminare Fraunces e le classi serif dall'interfaccia e dalla resa dei documenti. Non riscrivere il contenuto dei documenti.
+- Usare etichette sans-serif in sentence case; limitare maiuscole e spaziatura espansa.
+- Nessun testo operativo ordinario sotto 12 px; non far stare più contenuto riducendolo a 8–11 px.
+- Numeri tabulari nelle colonne numeriche; testo libero proporzionale; codice monospace leggibile.
+- Distribuire il font con l'app, evitando che Google Fonts sia necessario alla coerenza della UI in un ambiente intranet. Verificare fallback e caricamento, senza presumere che oggi il font remoto non funzioni.
+
+### Palette: neutri e rosso, con eccezioni semantiche
+
+| Ruolo | Regola |
+| --- | --- |
+| Superfici | Bianco e pochi grigi neutri, bordi leggeri; niente colorazione per ogni sezione |
+| Testo | Grafite per testo principale, grigio leggibile per secondario |
+| Rosso istituzionale | Azione primaria, selezione e focus; tonalità coerente con il tema Omics, da verificare nell'integrazione |
+| Successo | Indicatore verde sobrio con testo sufficientemente scuro; non interi paragrafi verde pallido |
+| Avvertimento/attesa umana | Ambra soltanto quando occorre attenzione, con motivazione esplicita |
+| Errore/distruzione | Trattamento distinto tramite icona, etichetta e conferma dove prevista; non affidarsi al solo rosso condiviso con il brand |
+| Informazioni ordinarie | Neutre: timestamp, protocollo, conteggi, guide e configurazione non sono automaticamente stati colorati |
+
+SQL, grafici e visualizzazioni possono mantenere colori utili alla comprensione dei dati. Questa revisione non impone un monocromo indiscriminato. Gli stati del workflow conserveranno il loro significato; ogni modifica cromatica dovrà avere una mappatura esplicita.
+
+### Componenti e testi condivisi
+
+- Un'unica famiglia di intestazioni Admin, toolbar, tab, campi, pulsanti, badge e messaggi.
+- Scala di spaziatura comune basata su multipli di 4 px, con distinzione chiara fra spazio dentro un gruppo e spazio fra gruppi.
+- Una primaria per il compito locale; azioni secondarie neutre, pericolose riconoscibili senza rendere tutto rosso.
+- Tab allo stesso livello con lo stesso trattamento. Le schede OS di una guida possono essere più compatte, ma non appartenere a un altro sistema grafico.
+- Istruzione essenziale accanto all'azione; procedure e dettagli di implementazione in una sezione di aiuto espandibile.
+- Testi UI in inglese; documenti e dati conservano la propria lingua. I titoli italiani di Evidence e sessioni non sono un errore di uniformità.
+
+Esempi di microcopy da affinare nell'implementazione:
+
+| Attuale | Proposta |
+| --- | --- |
+| Fleet summary | Catalog summary, se confermato l'ambito del riepilogo |
+| No cards match these filters… in una libreria vuota | No memory cards yet. Create a card to add reusable knowledge. |
+| Session models in Pi | Available models, con indicazione dell'effettiva idoneità Core/Admin |
+| Spiegazione che la pagina “never creates a second model default” | Installation default, con breve indicazione di dove modificarlo e dettagli tecnici separati |
+
+Il pulsante che prova il default d'installazione deve continuare a dichiarare **quale modello testa**: non va confuso con il modello selezionato nel contesto globale. Anche la distinzione fra importazione, revisione e consolidamento Evidence deve rimanere esplicita.
+
+## 4. Vincoli funzionali e integrazione
+
+La revisione deve conservare:
+
+1. Core originale: domanda/risposta, otto fasi in alto, gate di revisione, log sul lato sinistro e controlli esistenti.
+2. Sessioni nella navigazione destra con **My sessions / All sessions**, archivio e azioni attuali. Nessuna sezione sostitutiva in fondo alla pagina.
+3. Contesto globale A espandibile in alto: workspace e modello unici per tutta l'app; scelte ricordate indipendentemente e default esistenti.
+4. Blocco delle attività senza contesto valido e del cambio contesto durante un'elaborazione; protezione delle modifiche Admin non salvate.
+5. Cinque pagine Admin, preprocessing in Workspace Preparation e gestione database/tabelle/campi/relazioni in Database.
+6. Unificazione già realizzata della configurazione LLM, senza introdurre selettori o default alternativi.
+7. Prototipi precedenti conservati e recuperabili.
+
+**Omics Portal possiede header rosso e sidebar sinistra.** ThothII non deve duplicarli. Le regole globali attuali su `:root`, `body` e titoli richiedono una verifica di isolamento: se l'integrazione avviene nello stesso DOM, gli stili vanno circoscritti alla radice ThothII; se avviene in iframe, vanno verificati dimensionamento, tema e scrolling. È un rischio di integrazione da verificare, non una sovrapposizione già osservata sul portale.
+
+A larghezze ridotte pannelli e filtri devono adattarsi alla larghezza del contenitore reale, non soltanto della finestra. Nel lettore della sessione il testo non dovrebbe restare confinato in una colonna di circa 195 px come nello screenshot a 649 px: prevedere un pannello più ampio o sovrapposto nella modalità compatta, mantenendo accessi e funzione originali.
+
+## 5. Sequenza di lavoro proposta
+
+### Fase 1: regole e campione rappresentativo
+
+Dopo approvazione, aggiornare `DESIGN.md` eliminando la regola dei tre registri e allineando gli eventuali riferimenti superati ai modelli e alla navigazione. Definire token tipografici, colori semantici e componenti comuni.
+
+Applicare un primo campione a **Workspace e Pi**: insieme verificano form, stato operativo, selezioni, istruzioni lunghe e codice. Mostrare il confronto prima/dopo mantenendo stessi contenuti e viewport. Non servono tre nuovi design alternativi: serve validare un sistema coerente.
+
+### Fase 2: shell e tutte le pagine Admin
+
+Uniformare contesto globale, navigazione, titoli, tab e controlli; estendere il sistema a Database, Memory ed Evidence. Compattare riepiloghi e istruzioni senza eliminare funzionalità. Correggere stati vuoti, larghezze dei filtri e formattazione dei blocchi di codice nella guida Pi.
+
+### Fase 3: Core, documenti e sessioni
+
+Applicare gli stessi token a compositore, fasi, log, widget di revisione, documenti e navigazione sessioni. Nessuna nuova struttura del workflow. Controllare separatamente liste, documento aperto, sessione attiva e pannelli nella modalità compatta.
+
+### Fase 4: verifica e consegna
+
+Eseguire typecheck, test dei componenti interessati e regressione Playwright con dati di test, senza consumare chiamate LLM reali soltanto per verificare gli stili. Includere prove di flusso per navigazione con modifiche non salvate e blocco del contesto durante un'operazione.
+
+Preparare screenshot comparabili e verifiche a 390, 649, 768, 1280 e 1600 px, oltre alla larghezza effettiva assegnata da Omics con sidebar presente. Verificare tema chiaro/scuro, zoom 200%, tastiera, focus, testo lungo, stato vuoto/errore/caricamento e griglie larghe. L'integrazione finale nel server resta una fase distinta, secondo le decisioni già prese.
+
+## 6. Criteri di accettazione
+
+- Una sola famiglia sans per la UI; monospace solo per contenuto tecnico. Nessuna classe serif residua nei componenti operativi o nei lettori.
+- Dimensioni e pesi derivati dai ruoli condivisi; ogni eccezione ha un motivo documentato.
+- Colori dei componenti da token semantici; nessun blu decorativo per date o protocolli e nessuna cornice di warning intorno a una guida ordinaria.
+- Contrasto del testo almeno 4,5:1, salvo le eccezioni previste per testo grande e altri casi specifici; non assumere che ogni semibold sia testo grande. Riferimento: [W3C, Contrast Minimum](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html).
+- Contrasto almeno 3:1 per informazioni visive necessarie a identificare controlli e stati, nei casi applicabili; non è un obbligo per ogni bordo decorativo. Riferimento: [W3C, Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html).
+- Stato e azione distinguibili anche senza colore; focus visibile e controlli utilizzabili da tastiera.
+- Nessuna sovrapposizione o scroll orizzontale dell'intera pagina ai viewport concordati; scroll locale consentito per tabelle e codice quando necessario.
+- Nessuna regressione funzionale di Core, sessioni, Admin, selezione globale o salvataggio; test dei flussi critici invariati o rafforzati.
+- Nessuna modifica del contenuto scientifico, dei default LLM, delle autorizzazioni o delle procedure di manutenzione mascherata da intervento grafico.
+
+## 7. Punti principali del codice interessati in una futura implementazione
+
+- `DESIGN.md`: regole tipografiche e cromatiche.
+- `frontend/index.html`: caricamento delle famiglie di caratteri.
+- `frontend/src/index.css`: token, titoli globali, etichette e prosa.
+- `frontend/src/shell/WorkingContextShelf.css`: contesto globale e microtipografia.
+- `frontend/src/shell/administration/AdministrationPage.css`: intestazioni comuni.
+- `frontend/src/shell/WorkspaceManager.css`: gerarchie e densità Workspace.
+- `frontend/src/shell/database-management/FleetLedgerShell.css`: riepiloghi, toolbar e griglie.
+- Componenti Memory/Evidence: override serif di titoli e form.
+- Componenti Pi: guida, stati, tab OS e microcopy operativo.
+- Componenti Core/sessioni: fasi, lettura documenti, log, navigazione e pannelli responsive.
+
+**Decisione richiesta:** approvare questa direzione visiva e il campione Workspace/Pi prima di estenderla. Questa survey non crea ticket, non aggiorna il design normativo e non ricostruisce Docker.
diff --git a/docs/reports/2026-09-12-ui-visual-review-delivery.md b/docs/reports/2026-09-12-ui-visual-review-delivery.md
new file mode 100644
index 00000000..f5fdc357
--- /dev/null
+++ b/docs/reports/2026-09-12-ui-visual-review-delivery.md
@@ -0,0 +1,109 @@
+# Revisione grafica: consegna su worktree e Docker
+
+Stato: **pubblicata per revisione visiva, non integrata in main**.
+
+## Dove provarla
+
+- Docker locale:
+{error.message}diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx index 67f606aa..68c3ea78 100644 --- a/frontend/src/components/ui/button.tsx +++ b/frontend/src/components/ui/button.tsx @@ -25,8 +25,8 @@ const buttonVariants = cva( default: "h-8 gap-1.5 px-3.5 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5", xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3", - sm: "h-7 gap-1 px-3 text-[0.8rem] has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5", - lg: "h-10 gap-1.5 px-5 text-[0.9rem] has-data-[icon=inline-end]:pr-3.5 has-data-[icon=inline-start]:pl-3.5", + sm: "h-8 gap-1.5 px-3 text-sm has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3.5", + lg: "h-10 gap-1.5 px-5 text-sm has-data-[icon=inline-end]:pr-3.5 has-data-[icon=inline-start]:pl-3.5", icon: "size-8", "icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3", "icon-sm": "size-7", diff --git a/frontend/src/index.css b/frontend/src/index.css index c287d1ff..43923387 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -5,7 +5,7 @@ @tailwind utilities; /* - * GSD theme — mirrors the Omics Portal design system (Manrope + Fraunces, warm + * Product theme — shares the Omics Portal identity (Manrope, warm * off-white surfaces, #cb333b red). Tokens are RAW OKLCH triplets (L C H) so the * Tailwind v3 config can wrap them as `oklch(var(--token) /)` and * opacity utilities (bg-primary/80, …) keep working. Dark tokens follow either a @@ -13,9 +13,14 @@ */ @layer base { :root { - --font-sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Arial, sans-serif; - --font-heading: "Fraunces", "Source Serif Pro", Georgia, "Times New Roman", serif; + --font-sans: "Manrope Variable", "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Arial, sans-serif; + --font-heading: var(--font-sans); --font-mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace; + --text-page: 1.5rem; + --text-section: 1.25rem; + --text-body: 1rem; + --text-control: 0.875rem; + --text-meta: 0.75rem; /* Layered elevation, tinted with the foreground hue so depth reads warm on warm surfaces. Borders mark structure; shadows mark elevation. */ @@ -42,11 +47,11 @@ --destructive: 0.5587 0.1881 23.2; --destructive-foreground: 0.9918 0.0011 17.2; --border: 0.9093 0.0035 354.7; - --input: 0.9093 0.0035 354.7; + --input: 0.64 0.008 354.7; --ring: 0.5587 0.1881 23.2; - --success: 0.7577 0.1581 165.0; - --warning: 0.8523 0.1386 78.9; - --info: 0.7035 0.1128 221.3; + --success: 0.46 0.095 160; + --warning: 0.48 0.09 70; + --info: var(--muted-foreground); /* Current navigation shares Instrument Red's hue, with lower chroma and higher lightness so selection reads as a muted location signal. */ --nav-active: 0.9250 0.0520 23.2; @@ -73,8 +78,8 @@ --card-foreground: 0.9310 0 90; --popover: 0.2350 0 90; --popover-foreground: 0.9310 0 90; - --primary: 0.6023 0.1848 20.3; - --primary-foreground: 0.9310 0 90; + --primary: 0.73 0.15 23.2; + --primary-foreground: 0.2178 0.005 23.2; --primary-hover: 0.6897 0.1779 16.9; --secondary: 0.2972 0 90; --secondary-foreground: 0.9310 0 90; @@ -82,11 +87,13 @@ --muted-foreground: 0.7826 0 90; --accent: 0.3485 0 90; --accent-foreground: 0.9310 0 90; - --destructive: 0.6023 0.1848 20.3; + --destructive: 0.73 0.15 23.2; --destructive-foreground: 0.9310 0 90; --border: 0.3715 0 90; - --input: 0.3715 0 90; + --input: 0.62 0.008 23.2; --ring: 0.6897 0.1779 16.9; + --success: 0.78 0.10 160; + --warning: 0.82 0.10 75; --nav-active: 0.3350 0.0550 20.3; --nav-active-hover: 0.3750 0.0650 20.3; --nav-active-foreground: 0.8900 0.0700 20.3; @@ -141,7 +148,18 @@ font-feature-settings: "ss01", "cv11"; } - h1, h2, h3, h4 { + #root :is(input, textarea)::placeholder { + color: oklch(var(--muted-foreground)); + opacity: 1; + } + + #root :is(button, input, select, textarea, summary):focus-visible { + outline: 2px solid oklch(var(--ring)); + outline-offset: 2px; + } + + #root :where(h1, h2, h3, h4, h5, h6), + [data-slot="dialog-content"] :where(h1, h2, h3, h4, h5, h6) { font-family: var(--font-heading); font-optical-sizing: auto; letter-spacing: -0.015em; @@ -196,22 +214,21 @@ padding: 0 1rem 0.75rem; } - /* Standard micro-label: panel headers, nav sections, meta rows. Set in the - mono register so labels/meta read as a distinct typographic layer from the - sans body prose (mono needs less tracking than the sans did). */ + /* UI labels use the same family as controls; monospace is for technical data. */ .thot-label { - font-family: var(--font-mono); - font-size: 0.6875rem; + font-family: var(--font-sans); + font-size: var(--text-meta); font-weight: 600; - letter-spacing: 0.06em; - text-transform: uppercase; + letter-spacing: normal; + text-transform: none; color: oklch(var(--muted-foreground)); } .thot-prose { color: oklch(var(--foreground)); - font-size: 0.9375rem; - line-height: 1.65; + font-size: var(--text-body); + line-height: 1.6; + overflow-wrap: anywhere; } .thot-prose > :first-child { margin-top: 0; } .thot-prose > :last-child { margin-bottom: 0; } @@ -223,9 +240,10 @@ margin: 1.1em 0 0.5em; letter-spacing: -0.01em; } - .thot-prose h1 { font-size: 1.45rem; } - .thot-prose h2 { font-size: 1.2rem; } - .thot-prose h3 { font-size: 1.02rem; } + .thot-prose h1 { font-size: var(--text-page); } + .thot-prose h2 { font-size: var(--text-section); } + .thot-prose h3 { font-size: var(--text-body); } + .thot-prose :where(p, ul, ol, blockquote) { max-width: 75ch; } .thot-prose ul, .thot-prose ol { margin: 0.6em 0; padding-left: 1.3em; } .thot-prose li { margin: 0.25em 0; } .thot-prose a { color: oklch(var(--primary)); text-decoration: underline; text-underline-offset: 2px; } @@ -247,8 +265,10 @@ } .thot-prose pre code { background: transparent; padding: 0; } .thot-prose blockquote { - border-left: 2px solid oklch(var(--border)); - padding-left: 0.9em; + border: 1px solid oklch(var(--border)); + border-radius: var(--radius); + background: oklch(var(--muted) / 0.4); + padding: 0.75em 1em; color: oklch(var(--muted-foreground)); margin: 0.7em 0; } @@ -266,10 +286,10 @@ .thot-prose td { border-top: 1px solid oklch(var(--border) / 0.6); font-variant-numeric: tabular-nums; } .thot-prose th { background: oklch(var(--muted)); - font-size: 0.72rem; + font-size: var(--text-control); font-weight: 600; - letter-spacing: 0.06em; - text-transform: uppercase; + letter-spacing: normal; + text-transform: none; color: oklch(var(--muted-foreground)); } .thot-activity-prose, @@ -325,7 +345,7 @@ @layer components { .thot-database-grid { --ag-font-family: var(--font-sans); - --ag-font-size: 0.8125rem; + --ag-font-size: var(--text-control); --ag-background-color: oklch(var(--card)); --ag-foreground-color: oklch(var(--foreground)); --ag-header-background-color: oklch(var(--muted) / 0.72); diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 4bdfec2f..7ea4ff0b 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,6 +1,7 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { App } from "./App"; +import "@fontsource-variable/manrope"; import "./index.css"; import "./widgets"; diff --git a/frontend/src/shell/AppShell.administration.test.tsx b/frontend/src/shell/AppShell.administration.test.tsx index 505bdba3..1283627e 100644 --- a/frontend/src/shell/AppShell.administration.test.tsx +++ b/frontend/src/shell/AppShell.administration.test.tsx @@ -125,7 +125,7 @@ test("option A has one collapsible global context and preserves the Core draft a renderShell(); const composer = await screen.findByRole("textbox", { name: /new question/i }); await userEvent.type(composer, "Keep my original Core question"); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); expect(screen.getAllByRole("combobox", { name: "Workspace" })).toHaveLength(1); expect(screen.getAllByRole("combobox", { name: "Model" })).toHaveLength(1); await userEvent.selectOptions(screen.getByRole("combobox", { name: "Workspace" }), "beta"); @@ -159,7 +159,7 @@ test("invalid remembered choices do not silently fall back and gate both Core an test("workspace and model stay locked during Core and unlock after it finishes", async () => { renderShell(); await screen.findByRole("textbox", { name: /new question/i }); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); act(() => useSessionStore.getState().setAgentActive(true)); expect(screen.getByRole("combobox", { name: "Workspace" })).toBeDisabled(); expect(screen.getByRole("combobox", { name: "Model" })).toBeDisabled(); @@ -182,7 +182,7 @@ test("dirty Memory blocks workspace and model changes, including after a failed const page = await screen.findByRole("main", { name: "Memory management" }); await userEvent.click(within(page).getByRole("button", { name: "New card" })); await userEvent.type(within(page).getByLabelText("Title"), "Do not lose this"); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); await userEvent.selectOptions(screen.getByRole("combobox", { name: "Workspace" }), "beta"); await userEvent.selectOptions(screen.getByRole("combobox", { name: "Model" }), "test/other"); expect(workspacePreferences.load()).toMatchObject({ workspaceId: "alpha", model: "test" }); @@ -240,7 +240,7 @@ test("a successful Memory save releases the navigation guard and the context loc await userEvent.click(within(page).getByRole("button", { name: "New card" })); await userEvent.type(within(page).getByLabelText("Title"), "Saved card"); await userEvent.type(within(page).getByLabelText("Scope"), "This workspace"); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); await userEvent.click(within(page).getByRole("button", { name: "Save card" })); expect(screen.getByRole("combobox", { name: "Model" })).toBeDisabled(); await userEvent.click(screen.getByRole("button", { name: "Return to session" })); @@ -257,7 +257,7 @@ test("Admin generation locks the context and Core submission across page navigat renderShell(client); const composer = await screen.findByRole("textbox", { name: /new question/i }); await userEvent.type(composer, "Wait for Admin to finish"); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); await act(async () => { client.setQueryData(["description-generation-runs", 50], [{ id: "r1", status: "running" }]); }); diff --git a/frontend/src/shell/AppShell.auth.test.tsx b/frontend/src/shell/AppShell.auth.test.tsx index cc03cc58..8fd2fc24 100644 --- a/frontend/src/shell/AppShell.auth.test.tsx +++ b/frontend/src/shell/AppShell.auth.test.tsx @@ -56,7 +56,7 @@ describe("authenticated shell permissions", () => { const memory = screen.getByRole("main", { name: "Memory management" }); expect(memory).toBeVisible(); expect(within(memory).queryByRole("combobox", { name: "Workspace" })).not.toBeInTheDocument(); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); expect(screen.getByRole("combobox", { name: "Workspace" })).toHaveValue("default"); }); test("does not use the legacy installation default as a preprocessing workspace", async () => { diff --git a/frontend/src/shell/AppShell.new-session.test.tsx b/frontend/src/shell/AppShell.new-session.test.tsx index d0df2552..ca8f73f6 100644 --- a/frontend/src/shell/AppShell.new-session.test.tsx +++ b/frontend/src/shell/AppShell.new-session.test.tsx @@ -177,7 +177,7 @@ test("model selector shows the three Pi-enabled models and stores the selected p renderShell(); await screen.findByRole("textbox", { name: /new question/i }); - await userEvent.click(screen.getByRole("button", { name: /WORKING CONTEXT/ })); + await userEvent.click(screen.getByRole("button", { name: /Working context/ })); const select = screen.getByRole("combobox", { name: "Model" }); await waitFor(() => { expect(within(select).getAllByRole("option").map((option) => option.textContent)).toEqual([ diff --git a/frontend/src/shell/AppShell.tsx b/frontend/src/shell/AppShell.tsx index 748228b6..cf7965d0 100644 --- a/frontend/src/shell/AppShell.tsx +++ b/frontend/src/shell/AppShell.tsx @@ -847,7 +847,7 @@ export function AppShell({ canLogout }: AppShellProps) { {activeSession?.question && ( @@ -1106,14 +1106,14 @@ export function AppShell({ canLogout }: AppShellProps) { className="flex min-h-0 flex-1 flex-col" > {canReadAllSessions && showingAllSessions && ( - Question
-+
{activeSession.question}
+
Administrator view: all sessions
)} {/* L1 — rail title */}- + Sessions@@ -1286,13 +1286,11 @@ export function AppShell({ canLogout }: AppShellProps) { function EmptyState() { return (- + ThothII -); diff --git a/frontend/src/shell/CentralStatus.tsx b/frontend/src/shell/CentralStatus.tsx index 5879c117..2a138144 100644 --- a/frontend/src/shell/CentralStatus.tsx +++ b/frontend/src/shell/CentralStatus.tsx @@ -52,7 +52,7 @@ export function CentralStatus({ working }: { working: boolean }) {- Build datamarts from your database through a guided, - human-in-the-loop workflow. Type your question in the box below to begin - a session. +
+ Type your question below. Review each step before creating your datamart.
diff --git a/frontend/src/shell/DatabaseManagementPage.test.tsx b/frontend/src/shell/DatabaseManagementPage.test.tsx index 9999af67..9469e247 100644 --- a/frontend/src/shell/DatabaseManagementPage.test.tsx +++ b/frontend/src/shell/DatabaseManagementPage.test.tsx @@ -264,7 +264,7 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi expect(screen.queryByRole("button", { name: "Back to workspace" })).not.toBeInTheDocument(); expect(screen.queryByRole("button", { name: /Add database/i })).not.toBeInTheDocument(); expect(screen.getByRole("columnheader", { name: /Catalog status/ })).toBeVisible(); - const summary = screen.getByRole("region", { name: "Fleet summary" }); + const summary = screen.getByRole("region", { name: "Catalog summary" }); expect(await within(summary).findByText("2,275")).toBeVisible(); expect(within(summary).getByText("75%")).toBeVisible(); const modelSelector = await screen.findByRole("combobox", { name: "Global LLM model" }); diff --git a/frontend/src/shell/DatabaseManagementPage.tsx b/frontend/src/shell/DatabaseManagementPage.tsx index 66fdfcbf..1ff98f1e 100644 --- a/frontend/src/shell/DatabaseManagementPage.tsx +++ b/frontend/src/shell/DatabaseManagementPage.tsx @@ -1080,7 +1080,7 @@ export function DatabaseManagementPage({