northlake-health/src/styles.css
Yashas e294df6eba design: three questions, three sizes
Rebuilt the two screens for a person with ninety seconds, not an analyst.

Every screen now answers, in order and at descending size: what happened
(one sentence, 21px), how much (three numbers you can read across a
table — claims denied, money at stake, still recoverable with its first
deadline), and what she wants approved (the ranked list, with the decision
buttons directly under it). The full analysis, her SQL and the live trace
sit behind disclosures — one click for the reviewer who wants to check,
zero clutter for the manager who does not.

The queue opens on a briefing strip: "1 decision waiting for you —
$1,091,000 recoverable". A manager who reads only that line has the day.
Cards lead with the verdict sentence and the recoverable figure; a waiting
case says "Needs your decision", not "Awaiting Review".

Jargon translated where a business reader meets it: "data reconciled"
became "Numbers checked against Finance"; "97% confident" became "Ava is
97% sure"; the trace steps read "Asked the data" and "Thought about it".
Ava's SHOUTED recommendation headings are sentence-cased.

While Ava is still working, the trace is the page — there is nothing else
to show yet, and watching her query is the demo.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 13:38:09 +05:30

244 lines
8.0 KiB
CSS

@import 'tailwindcss';
/* Northlake Health — Denials Desk. Light and dark.
=====================================================================
HOW THEMING WORKS HERE
`@theme` below defines the LIGHT theme, and light is also the fallback:
every token has a value here, so a document with no `data-theme` renders
correctly rather than unstyled. The dark theme is the
`:root[data-theme='dark']` block further down, which redefines the SAME
token names. Tailwind v4 compiles `bg-panel` to
`background-color: var(--color-panel)`, so overriding the variable swaps the
entire app — including opacity modifiers like `bg-brand/10`, which compile to
a `color-mix()` over the same var.
Consequently: NEVER put a literal colour in a component. A hex in a className
is invisible to the toggle and will be wrong in one of the two themes.
THE ONE RULE THAT CARRIES THIS APP'S MEANING
**Violet is the AI, and nothing else is violet.** Every number, sentence and
panel that Ava produced is tinted with it; everything a person or a rule
produced is not. On a screen whose whole claim is "an agent did this work and
you can check it", the reader has to be able to tell the two apart without
reading a label. Red is reserved for a case that needs a human and for a
reject — so when red appears in the queue it means something.
Every colour used for text is checked at WCAG AA against the surfaces it
actually appears on, in both themes. */
@theme {
/* --- Structural ---------------------------------------------------- */
--color-ink: #0f2233; /* primary text */
--color-muted: #4a6076; /* secondary text */
--color-faint: #5a7089; /* labels, placeholders, dashes */
--color-bg: #f2f7f8; /* page canvas — a cool clinical tint */
--color-panel: #ffffff; /* card face */
--color-panel2: #f1f6f8; /* input fill, row hover */
--color-panel3: #e3eef1; /* pressed / hover on panel2 */
--color-line: #d5e4e8; /* borders */
/* Brand accent — a clinical teal. Used BOTH as a fill and as text, so it
carries a companion for whatever sits on top of it. */
--color-brand: #0e7c86;
--color-brand-fg: #ffffff;
--color-brand-hover: #0b636b;
/* Fixed in both themes: the mark's own colours. */
--color-navy: #0e7c86;
--color-signal: #c2333a; /* needs-a-human and reject */
--color-signal-hover: #9f262c;
/* --- Semantic tones ------------------------------------------------
Six meanings, three roles each: `<tone>` is text, `<tone>-soft` is the chip
wash, `<tone>-edge` is the ring. Every `<tone>` passes AA on its own wash
AND on the page and panel, because these are used both inside a badge and
as bare text (a stat value, a rate). */
--color-idle: #55504a;
--color-idle-soft: #f2f0ed;
--color-idle-edge: #dad4cc;
/* THE most important tone in this app. Amber is Awaiting Review — the pile a
human owns — and it is deliberately the only amber in the pipeline, so it
reads as "needs you" without reading as an error. Findings waiting for a
decision are not a problem; they are the product. */
--color-warn: #8a5a00;
--color-warn-soft: #fff8e8;
--color-warn-edge: #f0c368;
--color-info: #0f5c78;
--color-info-soft: #e7f2f6;
--color-info-edge: #a4cadb;
--color-good: #00713d;
--color-good-soft: #e4f6ec;
--color-good-edge: #93d3b0;
--color-bad: #b31e23;
--color-bad-soft: #fdeced;
--color-bad-edge: #eda9ac;
/* The AI's own colour — see the rule at the top. */
--color-ai: #5b2ca0;
--color-ai-soft: #f5f1fd;
--color-ai-edge: #c3adec;
--color-scrim: rgb(6 28 40 / 0.45);
/* Inter: a screen typeface for dense tabular work, self-hosted through
@fontsource-variable/inter (imported in main.tsx) rather than a CDN — this
build is promoted between environments and dropped behind hospital
proxies, and a font fetched from fonts.googleapis.com is one that
sometimes does not arrive. */
--font-sans:
'Inter Variable', Inter, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
--font-mono:
ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
}
/* Non-Tailwind vars: consumed by the hand-rolled rules at the bottom rather
than by generated utilities, so they live outside `@theme`. */
:root {
/* Tinted with navy rather than black, so the lift reads as part of the
palette. In dark it goes near-black and deeper — a navy shadow on a
navy canvas is invisible, so dark leans on the border instead. */
--lift: 0 1px 2px rgb(6 40 52 / 0.07), 0 1px 1px rgb(6 40 52 / 0.04);
--lift-lg: 0 12px 32px rgb(6 40 52 / 0.16), 0 2px 8px rgb(6 40 52 / 0.08);
--sb-thumb: #c4d8dd;
--sb-thumb-hover: #a6c2c9;
/* Makes the browser render native widgets — date picker, select dropdown,
scrollbar gutter — to match. Without it a dark console opens a blinding
white calendar. */
color-scheme: light;
}
/* =====================================================================
DARK — the navy-led palette. Only tokens are redefined; no utility,
component or layout rule is duplicated.
===================================================================== */
:root[data-theme='dark'] {
--color-ink: #e7f1f5;
--color-muted: #a3c0cc;
--color-faint: #93b2c0;
--color-bg: #07161f;
--color-panel: #10233a;
--color-panel2: #17304a;
--color-panel3: #1f3d59;
--color-line: #22405c;
/* The accent lightens and the text on it darkens — the inverse of light. A
#0E7C86 fill would sink into the canvas, and #0E7C86 text on it is
unreadable. */
--color-brand: #4fc3cd;
--color-brand-fg: #06202a;
--color-brand-hover: #6fd2da;
/* The signal red is unchanged: white on it clears AA either way, and it
still clears 3:1 against the dark canvas as a large component. */
--color-signal-hover: #e8686e;
--color-idle: #d6cdbf;
--color-idle-soft: #2a2724;
--color-idle-edge: #4b453b;
--color-warn: #f7cd7a;
--color-warn-soft: #3a2a06;
--color-warn-edge: #8a681f;
--color-info: #9fd0e2;
--color-info-soft: #0d3a4c;
--color-info-edge: #3f7f99;
--color-good: #5fd694;
--color-good-soft: #052a18;
--color-good-edge: #10683b;
--color-bad: #f4a3a6;
--color-bad-soft: #3c1416;
--color-bad-edge: #8c3a3d;
--color-ai: #c9b3f2;
--color-ai-soft: #221542;
--color-ai-edge: #5a3fa2;
--color-scrim: rgb(2 10 14 / 0.66);
--lift: 0 1px 2px rgb(0 0 0 / 0.4);
--lift-lg: 0 16px 40px rgb(0 0 0 / 0.55), 0 2px 8px rgb(0 0 0 / 0.4);
--sb-thumb: #1e4a5e;
--sb-thumb-hover: #2a6376;
color-scheme: dark;
}
html,
body,
#root {
height: 100%;
}
body {
margin: 0;
background: var(--color-bg);
color: var(--color-ink);
font-family: var(--font-sans);
font-size: 15px;
-webkit-font-smoothing: antialiased;
}
/* Tabular figures everywhere numbers line up in a column — amounts,
ratios, file numbers. Proportional digits make a money table look
ragged, and this app is mostly money. */
.tnum {
font-variant-numeric: tabular-nums;
}
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--sb-thumb);
border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--sb-thumb-hover);
}
@keyframes nl-pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.35;
}
}
.live-dot {
animation: nl-pulse 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.live-dot {
animation: none;
}
}
.lift {
box-shadow: var(--lift);
}
.lift-lg {
box-shadow: var(--lift-lg);
}
/* A SQL statement, as Ava sent it. Monospace, wrapped rather than scrolled —
these are read, not edited, and a horizontal scrollbar inside a timeline row
hides the end of the query, which is usually the interesting part. */
.sql {
font-family: var(--font-mono);
font-size: 11.5px;
line-height: 1.55;
white-space: pre-wrap;
word-break: break-word;
}