Proposal Demo workspace

Component sheet

Every token and component Orchestrator uses, in every state it needs. The base is the shared Medical library (assets/orc-ui/, vendored without changes); the Orchestrator layer (assets/orc/) adds chat blocks with the orc- prefix and the shared login-* sign-in pattern. Chat specimens sit inside an .orc-shell and sign-in specimens inside a .login-page (without the viewport frame), so they show the product focus ring, field border and unavailable look as in the app. All data on this page is synthetic.

<link rel="stylesheet" href="assets/orc-ui/components.css">  <!-- baseline: tokens, base, components layers -->
<link rel="stylesheet" href="assets/orc/tokens.css">        <!-- product tokens (var() aliases, no new hues) -->
<link rel="stylesheet" href="assets/orc/app.css">           <!-- every page: shell, chat blocks, utilities -->
<link rel="stylesheet" href="assets/orc/login.css">         <!-- sign-in screen only -->

Foundations · assets/orc-ui/tokens.css + assets/orc/tokens.css

Tokens

Colours come only from the baseline. Orchestrator adds layout, type, motion and z-index tokens (the baseline has none) and names its surfaces through --orc-* aliases such as --orc-message-user-bg: var(--color-surface-selected). Contrast is WCAG 2.x, computed against the background named in the note.

Colour — baseline variables Orchestrator uses

--color-page-bg

#f4f7fa

Shell and rail background

--color-surface

#ffffff

Header, thread, cards, composer

--color-surface-muted

#f3f5f8

Chip, suggestion and unavailable button background

--color-surface-selected

#eff6ff

User message bubble

--color-text-primary

#172033

Text, titles · 16.27:1 on surface

--color-text-secondary

#506486

Meta, hints, references, placeholders · 5.99:1 surface, 5.57:1 page

--color-text-tertiary

#7e8ea9

3.32:1 — field border and touch grip only, never text

--color-text-placeholder

#92a4c3

2.52:1 — baseline gap, replaced in the product scope

--color-border

#d7dfea

Dividers, rail edge, composer hairline · decorative

--color-border-strong

#c8ced8

Unavailable button border · 1.58:1 as the baseline input border

--color-primary-50

#eff6ff

Info notice, hovers, assistant tile

--color-primary-100

#dbeafe

User bubble border, avatar

--color-primary-200

#bfdbfe

Suggestion hover, pending bubble, resizer hover line

--color-primary-500

#3b82f6

Typing dots · 3.68:1 non-text

--color-primary-600

#2563eb

Primary button, selected bar, resizer drag line · 5.17:1

--color-primary-700

#1d4ed8

Brand tile, focus ring, assistant mark · 6.70:1

--color-primary-800

#1e40af

Info notice text · 8.01:1 on primary-50

--color-danger-50

#fef2f2

Error notice, delete confirm

--color-danger-100

#fee2e2

Error notice and confirm border

--color-danger-500

#ef4444

Failed bubble, invalid field · 3.76:1

--color-danger-600

#dc2626

Destructive button, field error · 4.83:1

--color-danger-700

#b91c1c

Failed turn, counter over limit · 6.47:1

--color-warning-50

#fff9eb

Demo chip, warning notice

--color-warning-300

#f9cf6c

Demo chip and notice border

--color-warning-700

#894c06

Demo chip text, counter near limit · 6.45:1

Colour — product roles for focus, fields and states

--orc-field-border

= text-tertiary · #7e8ea9

Composer and sign-in field edge · 3.32:1

--orc-field-placeholder

= text-secondary · #506486

Placeholder in the product scope · 5.99:1

--orc-disabled-bg

= surface-muted · #f3f5f8

Unavailable filled button and suggestion

--orc-disabled-border

= border-strong · #c8ced8

Its edge

--orc-disabled-fg

= text-secondary · #506486

Its text, ghost included · 5.48:1 on muted

--orc-assistant-tile-bg

= primary-50 · #eff6ff

Assistant and typing tile

--orc-assistant-tile-fg

= primary-700 · #1d4ed8

Mark on that tile · 6.16:1

--orc-reference-fg

= text-secondary · #506486

“Reference: <id>” in chat and sign-in

--orc-resizer-hover

= primary-200 · #bfdbfe

Resizer line on hover · a hint only

--orc-resizer-active

= primary-600 · #2563eb

Resizer line while dragged or focused · 4.81:1

--orc-resizer-grip

= text-secondary · #506486

Three-dot grip on hover · 5.57:1

--orc-resizer-grip-touch

= text-tertiary · #7e8ea9

Pill grip on touch · 3.09:1

--orc-composer-divider

= border · #d7dfea

Composer hairline while the thread is not at its end

--orc-brand-tile-* is for the header and sign-in logos only; answer and typing tiles use the quiet --orc-assistant-tile-*.

Contrast of every text pair in use

WhereForegroundBackgroundRatio
Messages, titles, conversation titles--color-text-primarysurface · page-bg · surface-selected16.27 · 15.13 · 14.95
Time, meta, hints, references, typing text, rail footer, disclaimer, login notes, placeholders--color-text-secondarysurface · page-bg · surface-muted · surface-selected5.99 · 5.57 · 5.48 · 5.50
Unavailable buttons and suggestions--orc-disabled-fgsurface-muted5.48
Ghost buttons (Change email, Resend code)--color-primary-600surface · primary-50 (hover)5.17 · 4.75
Module label, suggestion hover, assistant tile mark, filter chip--color-primary-700surface · primary-506.70 · 6.16
Avatar initials--color-primary-700primary-1005.49
Info notice title · message (82% mix)--color-primary-800primary-508.01 · 5.23
Error notice title · message (82% mix), delete confirm--color-danger-700danger-505.91 · 4.51
Warning notice title, Demo chip--color-warning-700warning-506.45
Warning notice message (82% mix) — Orchestrator puts warning copy in the title instead--color-warning-700 82%warning-504.35
Field error, composer over-limit error--color-danger-600surface4.83
Failed turn line, counter over limit--color-danger-700surface6.47
Counter near limit--color-warning-700surface6.77
Primary button · brand tile · destructive button--color-whiteprimary-600 · primary-700 · danger-6005.17 · 6.70 · 4.83
Toast title · message--color-white · 78% whitetext-primary16.27 · 10.32
Non-text: selected bar, field focus border--color-primary-600surface5.17
Non-text: failed bubble border · typing dots--color-danger-500 · --color-primary-500surface3.76 · 3.68
Non-text: product focus ring (after a surface gap)--orc-focus-ringsurface · page-bg · surface-muted6.70 · 6.23 · 6.14
Non-text: composer and sign-in field border--orc-field-bordersurface3.32
Non-text: resizer line while dragged or focused · touch grip--orc-resizer-active · --orc-resizer-grip-touchpage-bg4.81 · 3.09
Non-text baseline gaps, outside the product scope onlyinput border · focus ring halosurface1.58 · 1.29

Type scale — --orc-text-*

brand
1.375rem · 750 · 1
headline
1.5rem · 700 · 1.25 (1.375rem below 40rem)

What could make your working day easier?

title
1rem · 700 · 1.3

Chats

message
0.9375rem · 400 · 1.65

Check dose settings against the local reference levels before the protocol is approved.

body
0.875rem · 400 · 1.5

Ask about worklists, reporting, scheduling or anything else in your clinical workflow.

label
0.8125rem · 600 · 1.3

One-time code

meta
0.75rem · 400 · 1.45 — the floor for meaningful text

Deleted when you sign out

eyebrow
0.75rem · 700 · 0.04em · uppercase

Clinical assistant

Spacing — --space-N = N × 0.25rem

--space-10.25rem
--space-20.5rem
--space-30.75rem
--space-41rem
--space-51.25rem
--space-61.5rem
--space-82rem
--space-102.5rem
--space-123rem

Radii, shadows, focus

--radius-sm
0.375rem · rows, chips
--radius-md
0.5rem · tiles, notices
--radius-lg
0.75rem · cards, bubbles, composer
--shadow-sm
header, selected row
--shadow-md
login card, drawer
--orc-focus-ring
every control in the product scope
--orc-focus-ring-inset
thread scroller, rail rows

Layout, motion and layers

Layout tokenValue
--orc-header-height5.25rem (mirrors .app-header; 4.5rem below 40rem)
--orc-rail-width20rem default (two columns from 64rem); set inline on the shell when resized
--orc-rail-width-min · --orc-rail-width-max16rem · 32rem; the conversation keeps at least 40rem
--orc-drawer-width22.5rem (below 64rem; full width below 40rem)
--orc-thread-measure46rem reading width of the thread
--orc-composer-max= thread measure
--orc-composer-max-lines12 lines before the field scrolls
--orc-bubble-max36rem (and at most 88% of the thread)
--orc-gutter1.5rem; 1rem below 40rem
--orc-login-width27rem sign-in panel
--orc-touch-target2.75rem under any-pointer: coarse and in shells at or below 40rem
Motion / layer tokenValue
--orc-duration-instant80ms
--orc-duration-fast120ms — hovers, rows
--orc-duration-intent150ms — delay before the resizer shows its line and grip
--orc-duration-base200ms — fields, login step, rail collapse
--orc-duration-slow240ms — drawer
--orc-duration-loop1200ms — typing, skeleton
--orc-ease-out · --orc-ease-standard · --orc-ease-emphasizedease-out · ease · cubic-bezier(0.2, 0, 0, 1)
--orc-z-raised · header · backdrop · drawer · toast1 · 50 · 60 · 70 · 80
Under prefers-reduced-motion: reduce every transition and animation in assets/orc/ is off; the typing dots are hidden, skeletons stop pulsing and the rail collapses at once.

assets/orc-ui/icons.svg + assets/orc/icons.svg

.icon sprites

Same drawing spec as the baseline: 24 × 24 viewBox, stroke only, .icon sets stroke-width 1.8, round caps and joins and currentColor. The Orchestrator sprite adds only what the baseline lacks; message and sparkle appear on this sheet only. refresh, plus, close, lock, check (copied), alert, error, chevron-right and chevron-down (“New answer”) come from the baseline.

Orchestrator sprite · assets/orc/icons.svg

orc-mark
send
copy
message
trash
log-out
panel-left
wifi-off
shield
clock
info
sparkle

Baseline sprite used by Orchestrator · assets/orc-ui/icons.svg

plus
close
refresh
lock
check
alert
error
chevron-right
chevron-down

Medical baseline · assets/orc-ui (unchanged)

Baseline components Orchestrator uses

Used as they are. Orchestrator composes them and tunes them only through their own custom properties (--button-height, --input-font-size, and in its scope --focus-ring, --input-border and --input-placeholder); unavailable buttons take the product look. Focus states are simulated on this static page.

.app-header with the Orchestrator brand, Demo chip, user and Sign out

Orchestrator Clinical assistant
Demo workspace

.button variants

.button states

Busy = .button__spinner + aria-busy="true" + aria-disabled="true"; it keeps the baseline fade and the label changes to the busy copy. Unavailable (without aria-busy) takes the product look: see Focus and unavailable.

.chip and .avatar

Demo workspace Proposal
User initials · quiet assistant tile, 1.5rem (.orc-message__avatar)

.form-field + .input

.inline-notice info · warning · error · compact

Your session ended. Sign in again to continue.

You're offline. Messages won't send until your connection is back.

You've reached 20 chats. Delete one to start another.

Warning copy goes in __title: the baseline __message mixes the colour to 82% and drops warning text to 4.35:1.

.toast

Signed out

The toast lives in .toast-region (fixed, bottom end) after sign-out. The baseline .empty-state is not used: its dashed border reads as a drop zone.

Orchestrator layer · assets/orc/app.css

.orc-shell

The signed-in screen: baseline .app-header, then the chat list (rail) beside the conversation. The shell fills the viewport (100dvh); only the list and the thread scroll. The shell is a size container, so its breakpoints follow its own width: from 64rem two columns, with a resizer (__resizer) on the rail's edge and “Hide chats” in the rail header; below 64rem the rail becomes a drawer opened by the header “Chats” button, with a backdrop; at or below 40rem the drawer is full width and header actions become icon-only. The frames below set --orc-shell-height: 100% to embed it.

Two columns (≥ 64rem) · rail at a stored width of 24rem, resizer on its edge · .orc-shell, __resizer

Orchestrator Clinical assistant
Demo workspace

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

CT protocol checklist

You

Draft a CT protocol review checklist

Orchestrator

Here is a short checklist you can adapt for a CT protocol review:

  1. Confirm the clinical question and the body region on the request.
  2. Check that the protocol name matches the department's current version.
  3. Review contrast use, timing and documented contraindications.
  4. Compare dose settings with the local reference levels.
  5. Record who approved the protocol and when it is due for review.
You

Add a step for checking the scanner model.

Orchestrator

Add it as step 3: “Confirm that the scanner model and software version match the protocol.” The later steps move down by one.

Synthetic demo only — do not send real PHI.

The rail is clamp(16rem, var(--orc-rail-width), min(32rem, 100cqi − 40rem)) wide; the thread keeps its 46rem measure. Hover, focus or tab to the rail's edge to see the resizer; dragging needs the prototype's script. Tab order: rail, resizer, thread, composer.

Two columns, list hidden · .orc-shell--rail-collapsed

Orchestrator Clinical assistant
Demo workspace

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

CT protocol checklist

You

Add a step for checking the scanner model.

Orchestrator

Add it as step 3: “Confirm that the scanner model and software version match the protocol.” The later steps move down by one.

Synthetic demo only — do not send real PHI.

The rail column closes to 0; the rail is inert and hidden, and so is the resizer. “Chats” (aria-expanded="false") appears in the header and expands the rail in place to its last width; the title strip names the open chat. “Hide chats”, Enter on the resizer, or a drag 4rem past the narrowest width collapse it; focus moves to “Chats”, and back to the selected row on expand. Below 64rem the modifier has no effect.

Resizer states (simulated, drawn with the resizer tokens) · rail on the left, conversation on the right

Rest — only the rail's 1px border; dashed: the 1rem hit zone (sheet only)
Hover, after --orc-duration-intent — 2px --orc-resizer-hover, three-dot grip, col-resize
Drag — 2px --orc-resizer-active; .orc-shell--resizing on the shell
Focus — the drag line plus --orc-focus-ring around the grip
Touch — 1.5rem zone (0.5rem over the rail, 1rem over the conversation), pill grip 0.25 × 2.5rem always visible

role="separator", aria-orientation="vertical", aria-controls the rail, “Resize chat list”, values in CSS px: “Chat list width: 320 px, default”, “…, narrowest” at 16rem, “…, widest” at the maximum. ←/→ 1rem, Shift 4rem, Home/End narrowest/widest, Enter collapses; a click without movement switches Default 20rem ↔ Wide 28rem; Esc during a drag restores the width. Forced colours: CanvasText at rest, Highlight on hover, focus and drag.

Below 64rem, drawer closed · new empty chat (48rem frame)

Orchestrator Clinical assistant
Demo workspace

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

Untitled chat

What could make your working day easier?

Ask about worklists, reports, protocols or handovers. Use synthetic examples only.

This is a demo. Live clinical systems are not connected.

Synthetic demo only — do not send real PHI.

Below 64rem, drawer open · .orc-shell--drawer-open

Orchestrator Clinical assistant
Demo workspace

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

CT protocol checklist

You

Draft a CT protocol review checklist

Synthetic demo only — do not send real PHI.

Open drawer: role="dialog", aria-modal="true", focus moves to the close button and is kept inside; Escape, the backdrop and “Close chats” close it and return focus to “Chats”. Closed, it is visibility: hidden, so nothing inside can take focus. Below 64rem there is no resizer and no “Hide chats”.

Below 40rem, drawer open (full width, 24.375rem frame)

Demo workspace

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

CT protocol checklist

The phone layout of the closed shell (header shows only icon, Demo chip and icon actions) depends on the baseline header's viewport media query, so it is shown in screens.html at 390 px, and here when this page itself is narrower than 40rem.

Orchestrator layer · assets/orc/app.css

.orc-rail

The chat list: header (title, “Deleted when you sign out”, then “Hide chats” from 64rem or “Close chats” in the drawer), “New chat”, a persistent notice slot (__notice), the scrolling list and the shared-computer hint. Up to 20 chats; at the limit “New chat” is disabled and the warning notice explains why. With no chats the list slot holds one meta line (__empty), not a card.

Loading · .orc-skeleton in the list slot

Chats

Deleted when you sign out

Loading chats…

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

Empty (first run) · .orc-rail__empty

Chats

Deleted when you sign out

No chats yet. Chats you start appear here.

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

A plain meta line in secondary text: no border, icon or card. The composer is ready; the first message starts a chat.

Limit reached (20 chats) · notice slot filled

Chats

Deleted when you sign out

You've reached 20 chats. Delete one to start another.

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

Narrowest width (16rem) · long titles

Chats

Deleted when you sign out

On a shared computer? Sign out when you're done.

Demo workspace

Synthetic demo only — do not send real PHI.

Title, time and delete must not overlap at 16rem; the full title is in each row's title.

Orchestrator layer · assets/orc/app.css

.orc-conversation

One row: __select (title in one line with ellipsis, the full title in its title, update time in tabular-nums) and an icon __delete. On fine pointers delete rests at 0.6 opacity in unselected rows and is full on hover, on focus within the row and in the selected row; always full on touch. Selected uses the .worklist-row language: surface, 0.25rem inset bar in primary-600 and --shadow-sm, plus aria-current="true". The row button takes the inset ring, because the list clips. Delete asks inline before it acts.

Default · hover · selected · focus

Second row hover and fourth row focus (inset ring) are simulated. The first row shows the resting delete at 0.6 on fine pointers.

Untitled · long title · delete focused · disabled

Disabled (--disabled + disabled) while a reply is in flight: one of the two fades kept on purpose; the selected row keeps full opacity and its disabled delete control fades to 0.5.

Confirm delete · --confirm · deleting · --deleting

  • Worklist triage ideas

    Delete this chat? This can't be undone.

  • Scheduling contrast slots

    Delete this chat? This can't be undone.

Focus goes to “Cancel” when the confirm opens; after deletion it moves to the next row or to “New chat”. While deleting, “Delete” is busy (fade and spinner) and “Cancel” takes the unavailable look.

Orchestrator layer · assets/orc/app.css

.orc-skeleton

Loading placeholders that replace false empty states. role="status" with an .orc-sr-only text; the shapes are aria-hidden. They pulse gently and stop under reduced motion.

List · .orc-skeleton (default list variant)

Loading chats…

Messages · .orc-skeleton--thread

Loading messages…

Reduced motion (simulated): static shapes

Loading messages…

Orchestrator layer · assets/orc/app.css

.orc-thread

The conversation column: __notices (persistent status and alert slots above the scroll area, kept mounted when empty), __scroll (the only scrolling part) and __content, centred at --orc-thread-measure, which holds the __log (role="log", aria-live="polite", additions only), the __extra slot for the welcome or loading shapes, the typing status and the failed-turn and copy status slots. __jump floats above the composer while the reader is away from the end. Notices are baseline .inline-notices; errors fill the alert slot, info and warning fill the status slot; raw error codes are never shown.

Chat busy in another tab (warning)

This chat is still answering in another tab. Try again in a moment.

Server error, no Retry (error) with reference

Offline (warning)

You're offline. Messages won't send until your connection is back.

Chat no longer available (info) with action

This chat is no longer available. It may have been deleted in another tab.

An answer arrived while reading earlier · __jump “New answer”, .orc-composer--divided

Shift handover notes

You

List what to check before a shift handover

Orchestrator

A useful handover covers what is open, what is urgent and what the next person must not miss.

Start with studies still waiting for a report, then anything flagged as urgent, then follow-ups that were promised to a referrer. Close with equipment or scheduling issues the next shift should know about.

You

Turn that into a short checklist.

Orchestrator
  1. Studies still waiting for a report
  2. Urgent flags and who owns them
  3. Follow-ups promised to referrers
  4. Equipment or scheduling issues

Synthetic demo only — do not send real PHI.

The thread did not move when the answer arrived; the button scrolls to the end, pins the thread, hides itself and puts focus in the composer. It follows the scroll area in the DOM, so Tab reaches it before the composer. The hairline shows while the thread is not at its end.

Reading more than a screen above the end · __jump “Jump to latest”

CT protocol checklist

You

Draft a CT protocol review checklist

Orchestrator

Here is a short checklist you can adapt for a CT protocol review:

  1. Confirm the clinical question and the body region on the request.
  2. Check that the protocol name matches the department's current version.
  3. Review contrast use, timing and documented contraindications.
  4. Compare dose settings with the local reference levels.
  5. Record who approved the protocol and when it is due for review.
You

Add a step for checking the scanner model.

Synthetic demo only — do not send real PHI.

Same element and behaviour, with no unseen answer. Hidden (hidden) whenever the reader is at the end. Not a live region: the log announces answers itself.

Thread with a notice in the slot and the loading shapes in __extra

CT protocol checklist

You're offline. Messages won't send until your connection is back.

Loading messages…

Orchestrator layer · assets/orc/app.css

.orc-message

The user's turn is a compact bubble on the end side (--color-surface-selected, border --color-primary-100, small tail corner) with an .orc-sr-only “You”. The assistant's answer is unboxed reading text under a quiet 1.5rem tile (--orc-assistant-tile-*) and the name “Orchestrator”; its turn id is data-turn-id, never visible text, and __actions holds “Copy answer” and “Copy reference”. Turns are --space-8 apart, a question and its answer --space-4, the name and the text --space-1. The user's text is plain text that keeps line breaks (white-space: pre-wrap) and wraps long strings; the answer's body is .orc-md, rendered from its Markdown.

You

List what to check before a shift handover

Orchestrator

A useful handover covers what is open, what is urgent and what the next person must not miss.

Start with studies still waiting for a report, then anything flagged as urgent, then follow-ups that were promised to a referrer. Close with equipment or scheduling issues the next shift should know about.

You

Turn that into a short checklist.

Orchestrator
  1. Studies still waiting for a report
  2. Urgent flags and who owns them
  3. Follow-ups promised to referrers
  4. Equipment or scheduling issues

Used 2 tools

You

Can you read this protocol link? https://example.org/protocols/ct/abdomen-pelvis-portal-venous-phase-synthetic-example-v12

Sending…

Default — user and assistant, with time (__meta / __time). Tool use under an answer is one whole phrase: “Used 1 tool”, “Used {n} tools”.

__actions — visible on the newest answer; on earlier answers they appear on hover and when focus is inside the article (hover the first answer). Always visible on touch.

--pending — optimistic turn: dashed bubble edge and “Sending…” instead of the time; long strings wrap.

Failed, can be retried · --failed, __error-meta

You

Turn the review steps into a one-page summary.

Orchestrator didn't answer this message.

Reference: 3c9e1b2f

Aligned to the bubble's end and no wider than it. The text stays in the bubble and the composer stays empty: “Retry” is the one way to send it again, with the same client turn id. The persistent alert outside the log says once, without the id: “Orchestrator didn't answer. Press Retry to send it again.”

Failed while offline · “Retry” unavailable, __retry-note

You

Turn the review steps into a one-page summary.

Orchestrator didn't answer this message.

Reference: 3c9e1b2f Available when you're back online

“Retry” keeps its name and stays in the Tab order (aria-disabled="true", described by the note); its handler ignores click and Enter. When the connection returns it becomes available and the note goes.

Refused, cannot be retried · no “Retry”

You

Turn the review steps into a one-page summary.

The message couldn't be sent. Check it and try again.

Reference: 8e5b0c34

An invalid request or a turn id conflict: the sentence comes from the error mapping, there is no “Retry”, and the text returns to the composer unless a new draft was typed meanwhile.

Copied (simulated) · __copy shows check for 2 seconds

Orchestrator

Close with equipment or scheduling issues the next shift should know about.

The persistent status outside the log says “Copied” (“Reference copied” for the reference). Without the Clipboard API the answer text is selected and the status says “Press Ctrl+C to copy”. Focus stays on the button.

At or below 40rem: touch sizes · a 24.375rem .orc-shell container

Orchestrator

Close with equipment or scheduling issues the next shift should know about.

You

Turn the review steps into a one-page summary.

Orchestrator didn't answer this message.

Reference: 3c9e1b2f

Synthetic demo only — do not send real PHI.

On touch (any-pointer: coarse, or a shell at or below 40rem): answer actions always visible and 2.75rem, “Retry” and “Copy reference” 2.75rem, the failed line wraps with “Retry” first to move, no assistant indent, and “Send” icon-only 2.75rem with its accessible name kept. The key hint is omitted.

Orchestrator layer · assets/orc/app.css

.orc-md

The answer's Markdown, rendered as DOM nodes inside .orc-message__body: paragraphs with line breaks, headings h3–h5 no larger than the title size, strong and em, inline code, fenced code with a language caption, lists with one nested level, quotes, GFM tables, rules and http(s) links with an arrow and “(opens in a new tab)” in their name. Blocks are --space-2 apart; code and tables sit on --color-surface-muted with hairline borders and scroll inside their own focusable container. Source refs such as [S1] stay text. User messages stay plain text. The markup below is the renderer's output for the prototype state chat-answer-markdown.

You

Compare the two contrast protocols in a table.

Orchestrator

Contrast protocols compared

Both synthetic protocols cover the abdomen and pelvis. They differ in contrast timing and in who checks the dose. [S1]

CheckProtocol AProtocol B
Contrast phasePortal venous, 70 sSplit bolus
Dose checkBefore each scanWeekly audit
OwnerRadiographerRadiologist
Before switching
  1. Confirm the clinical question with the referrer.
  2. Check the scanner:
    • model and software version
    • available reconstructions
  3. Record who approved the change.

Local policy sets the review interval; treat this as a starting point. [S2]

The protocol record keeps the review date in next_review:

yaml

protocol: CT abdomen-pelvis (synthetic)
version: 12
contrast_phase: portal_venous
notes: "Check the scanner model and software version before switching protocols"
next_review: 2027-04

Reference levels: the department summary and https://example.org/guidelines.


Dose trend chart (synthetic) opens as a link; the image is not loaded.

Used 2 tools

Unsafe or cut-off input stays text

Orchestrator

Raw HTML shows as typed: <img src=x onerror=alert(1)> and <b>bold</b>.

Other schemes stay text: [open](javascript:alert(1)), [file](data:text/html,hi), [host](//example.org).

A cut-off answer keeps its markers: **an unclosed bold and `an unclosed code span

No img, script or javascript: link is created: raw HTML and links with any scheme other than http: or https: show as the characters the answer contains. Unclosed ** and backticks stay as typed; an unclosed fence runs to the end of the answer.

At or below 40rem · a 24.375rem .orc-shell container

No answer indent. The table and the code block keep whole words and scroll sideways inside their own containers (Tab to them, then use the arrow keys); long links and text wrap, so the page never scrolls horizontally.

Orchestrator layer · assets/orc/app.css

.orc-typing

Shown after the log, in the place where the answer will appear, while a turn is in flight: the quiet tile, three decorative dots and the sentence, always visible as secondary meta text. A persistent role="status". From 10 seconds __elapsed adds “· 0:12” (tabular-nums, updated every second, aria-hidden); at 15 seconds the sentence changes once to “Still preparing a response…”. No stages or percentages. Under reduced motion and forced colours the dots are hidden.

Up to 10 seconds

Orchestrator is preparing a response…

From 10 seconds · __elapsed

Orchestrator is preparing a response…

From 15 seconds · the status changes once

Still preparing a response…

Reduced motion (simulated)

Orchestrator is preparing a response…

In the thread · where the answer will appear

You

Add a step for checking the scanner model.

Orchestrator is preparing a response…

Only the sentence is announced; the elapsed time stays silent. Keep the container mounted after the log (not inside it) and change only the text at 15 seconds.

Orchestrator layer · assets/orc/app.css

.orc-welcome

The empty conversation, a product block of its own (no .empty-state, border, card or icon): the question as a one-line title, the explanation (__text), three example requests as full-width chip buttons (__suggestion; each sends its text, creating a chat first when none is selected) and the demo note. It follows the thread measure from the messages' edge; on tall windows it sits at the bottom above the composer, and when it overflows it starts at the top.

Default

What could make your working day easier?

Ask about worklists, reports, protocols or handovers. Use synthetic examples only.

This is a demo. Live clinical systems are not connected.

Suggestion states: default · hover · focus (simulated)

Suggestions disabled at the 20-chat limit, no chat selected

You've reached 20 chats. Delete one to start another.

Unavailable look (muted surface, strong border, secondary text), no hover tint; the limit sentence beside them is linked by aria-describedby.

Orchestrator layer · assets/orc/app.css

.orc-composer

Pinned under the thread at the same measure. The field is baseline .input.input--textarea (+ __field, __control) and holds “Send” (__send) in its bottom end corner: the send icon and “Send” (__send-label), 2.25rem, above 40rem on fine pointers; icon-only 2.75rem on touch. The field grows with the text from 2 to 12 lines (field-sizing: content; scripts set the height where it is unsupported). Under it one service line (__footer): the hint, note or error at the start, the counter from 7,500 bytes at the end; the hint shows only while the field has focus. The disclaimer is always the last line. “Send” is button--secondary with native disabled for an empty draft; for any other reason it is aria-disabled="true" and points at the reason.

Ready, empty · Send disabled

Synthetic demo only — do not send real PHI.

Typing, focused (simulated) · Send primary, hint shown

Synthetic demo only — do not send real PHI.

Sending · field cleared, Send busy

Synthetic demo only — do not send real PHI.

Near the limit · __count--warning

Synthetic demo only — do not send real PHI.

The numbers are aria-hidden; the field is described by “Message size: 7,940 of 8,000”. Crossing 7,500 is announced once through the status slot.

Over the limit · __error, __count--error, Send aria-disabled

Synthetic demo only — do not send real PHI.

The error replaces the hint; n is how many characters must go from the end to fit 8,000 bytes (“Remove 1 character to send.” for one).

No chat selected · __note, sending starts a chat

Synthetic demo only — do not send real PHI.

Creating the chat · text kept, Send busy

Synthetic demo only — do not send real PHI.

A second Send or Enter creates nothing. If creating fails, the text stays here and the thread shows the failure with a reference.

No chat selected at the 20-chat limit · unavailable, explained by the note

Synthetic demo only — do not send real PHI.

Offline · draft kept, Send described by the offline notice

You're offline. Messages won't send until your connection is back.

Synthetic demo only — do not send real PHI.

Draft restored after a refused turn (no Retry)

Synthetic demo only — do not send real PHI.

Only refusals without “Retry” return the text. After a failure that offers “Retry” the composer stays empty.

Loading · field and Send disabled

Synthetic demo only — do not send real PHI.

Orchestrator layer · assets/orc/app.css

.orc-disclaimer

The synthetic-data line under the composer and on the sign-in screen. Never hidden at any width or height; 0.75rem semibold in --color-text-secondary with a shield icon in --color-warning-700.

Synthetic demo only — do not send real PHI.

Orchestrator layer · assets/orc/app.css

.orc-reference and .orc-sr-only

.orc-reference shows a request id after a system failure: a line of its own under a notice sentence, or beside “Copy reference” in a failed turn. It is secondary text (--orc-reference-fg) in chat and sign-in alike, never the error's colour, and wraps anywhere instead of widening its block; __id uses the UI font with tabular numbers and selects with one click. .orc-sr-only hides text visually and keeps it for screen readers (“You”, field labels, loading text, the copy and size statuses).

We couldn't send the code. Try again in a moment.

Reference: 7f3a9c21

A long id wraps anywhere:

Reference: 3c9e1b2f-6a7d-4e21-9b0c-5d8f2a41e7c3

Hidden label here → “Message Orchestrator” (present for screen readers only).

Product scope · .orc-shell and .login-page

Focus, fields and unavailable buttons

Inside .orc-shell and .login-page the product sets the baseline's own custom properties, so the vendored files stay unchanged: --focus-ring, --input-focus-shadow and --input-invalid-shadow are --orc-focus-ring (a 0.125rem surface gap, then a 0.125rem --color-primary-700 ring, 6.70:1); in .orc-composer and .login-form the field edge is --orc-field-border (3.32:1) and the placeholder --orc-field-placeholder. Where an outer ring would be clipped (the thread scroller, rail rows) the inset ring is used. Focus is simulated here; Tab through the page to see the real ring.

Focus ring (simulated) · on the surface and on the page background

6.70:1 on the surface, 6.23:1 on the page background, 6.14:1 on muted surfaces. Elements not built on .button (rows, suggestions, the resizer) set the same box-shadow themselves, with a transparent outline that forced colours repaint.

Fields: rest · focused · invalid · invalid and focused (simulated)

The field edge reaches 3:1 at rest; the placeholder is secondary text. A focused invalid field keeps its danger border and gains the blue ring, so it differs from an unfocused one.

Unavailable buttons · filled, ghost, focused · busy keeps the fade

You're offline. Messages won't send until your connection is back.

:disabled or [aria-disabled="true"] without aria-busy: full opacity, cursor: not-allowed, no hover; filled variants take --orc-disabled-bg, --orc-disabled-border and --orc-disabled-fg (5.48:1) without a shadow, ghost stays transparent with --orc-disabled-fg. A focused one keeps its ring (second row, simulated). Busy buttons keep the baseline fade beside their spinner.

Where each applies

CaseMarkup
Send, empty draftbutton--secondary, native disabled
Send at the chat limit, over the length limit, offlinearia-disabled="true" + aria-describedby → note, error or offline notice
Retry offlinearia-disabled="true" + aria-describedby → “Available when you're back online”
Sending, creating a chat, “Sending code…”, “Checking code…”aria-busy="true" + aria-disabled="true" + spinner (fade kept)
“Send code”, “Sign in”Never disabled for empty input; checked on press
Locked rows during a turn, resting deleteFades kept on purpose: 0.55 (delete 0.5) and 0.6

Shared Medical pattern · assets/orc/login.css

login-* — sign in with a one-time code

The RIS/HIS sign-in, with the same form structure: 27rem panel, brand tile, .card--elevated, 2.75rem fields. The page content is anchored to the top, so the brand and the card stay put between the steps. The code step has one sent line with the email (.login-code-sent) and “Change email” under it, one code field (inputmode="numeric", autocomplete="one-time-code", no icon) with six fixed digit slots centred in a 3.25rem box: 1.5rem monospace digits, letter-spacing: .5em, and placeholder zeros (.login-otp__slots, hidden from assistive tech) that each typed digit replaces in place, and right under the field the resend row: the spam note and a fixed-size slot (.login-resend__slot) with the countdown as text, then “Resend code”. Input errors stay at the field without a reference; system failures are a notice between the field and the main button, with a reference. “Send code” and “Sign in” are never disabled for empty input; only their busy states are. Orchestrator adds the session-ended notice, the footnote and the fixed demo strip above the scrollable form. Below 40rem the panel takes the full width and fields use 1rem text. The prototype keeps status slots mounted and updates their contents; static specimens illustrate their populated state.

Full screen · email step after sign-out (toast) · .login-page

Full screen · code step, sent · the brand and card top stay where they were