From 2f99bd5f986fa5b6665d110c023b85c04f20a09b Mon Sep 17 00:00:00 2001 From: Ricardo Mancinas Date: Sat, 15 Aug 2026 12:58:14 -0700 Subject: [PATCH] fix(web): define the layout utilities the screens were already using MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The policy OCR review header read "Para revisarPágina 1700489616· PAMELA DENISE WAGONERLICENCIASANA". `.row`, `.stack`, `.tag`, `.page-sub` and `.state-warn` are used across the app but no rule ever defined them. Without `display: flex` the `gap` those call sites pass does nothing, and JSX drops the newline between sibling elements, so the header's spans concatenated. `.tag` rendered as prose rather than as a chip for the same reason. Defined against the existing design tokens: `.tag` takes `.badge`'s shape, `.state-warn` is the gold sibling of `.state-error`, and `p.page-sub` keeps the block margin while the inline form drops it so a flex row still centres. Also dropped the hand-rolled "· " separator and margin from the OCR header — the flex gap does that now, and the literal dot was left floating in it. Co-Authored-By: Claude Opus 5 --- apps/web/src/app/globals.css | 58 +++++++++++++++++++++ apps/web/src/components/PolicyOcrReview.tsx | 9 ++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index e16a94b..7cac4dc 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -3114,3 +3114,61 @@ button { border-color: var(--brand-500); color: var(--brand-700); } + +/* ============================================================================ + Layout + text utilities the screens already assumed + Several components were written against these names before any rule + defined them, so they rendered as bare inline spans. The visible symptom + was the policy OCR review header running together — + "Para revisarPágina 1700489616· PAMELA DENISE WAGONERLICENCIASANA" — + because JSX drops the newline between sibling elements and the `gap` those + call sites pass does nothing without a flex container. + ========================================================================== */ +.row { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.5rem; +} +.stack { + display: flex; + flex-direction: column; + gap: 1rem; +} +/* The muted line under a page title, and the same voice reused inline. Only + the block form takes a margin — as a flex child it would shift the item + off the row's centre line. */ +.page-sub { + color: var(--muted); + font-size: 0.875rem; +} +p.page-sub { + margin: 0.25rem 0 0; +} +/* A neutral chip. Same shape as `.badge` so the OCR statuses, policy type and + carrier read as the labels they are rather than as running prose. */ +.tag { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.1875rem 0.5625rem; + border-radius: 999px; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.01em; + line-height: 1.4; + white-space: nowrap; + background: var(--paper-2); + color: var(--muted); + border: 1px solid var(--line-strong); +} +/* The warning sibling of `.state-error`, used where a page needs a human to + choose between candidates rather than reporting a failure. */ +.state-warn { + background: var(--servicios-tint); + border: 1px solid rgba(154, 106, 18, 0.25); + color: var(--servicios-ink); + border-radius: var(--radius); + padding: 1rem 1.125rem; + font-size: 0.875rem; +} diff --git a/apps/web/src/components/PolicyOcrReview.tsx b/apps/web/src/components/PolicyOcrReview.tsx index 7573a0e..8015cfd 100644 --- a/apps/web/src/components/PolicyOcrReview.tsx +++ b/apps/web/src/components/PolicyOcrReview.tsx @@ -359,11 +359,12 @@ function DocumentRow({ doc, customerIndex, canReview, onSave, onReject }: Docume
{STATUS_LABEL[doc.status] ?? doc.status} Página {doc.pageNumber} - {doc.extractedPolicyNumber && ( - {doc.extractedPolicyNumber} - )} + {/* No hand-rolled separators or margins here: `.row` is a flex + container and its gap does the spacing. A literal "· " would leave + a dot floating in that gap. */} + {doc.extractedPolicyNumber && {doc.extractedPolicyNumber}} {doc.extractedInsuredName && ( - · {doc.extractedInsuredName} + {doc.extractedInsuredName} )} {/* Read-only: the parser names the type, the confirm step resolves it to a policy_types row. Reassigning it is the policy screen's job,