/* Header, tabs, key panel, dialog root and toast (POLISH rows 2 and 3). */

.app-header { background: #1a5276; color: white; padding: 16px 24px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.app-header h1 { margin: 0; font-size: 1.2rem; font-weight: 600; }
.badge { background: #e8f4fd; color: #1a5276; border-radius: 12px; padding: 2px 10px; font-size: 0.75rem; font-weight: 600; }
/* Was an inline style; white at 0.85 opacity on #1a5276 keeps >= 4.5:1. */
.header-refresh { margin-left: auto; font-size: 0.8rem; opacity: 0.85; }
.header-who { font-size: 0.8rem; }
.btn-header { background: #e8f4fd; color: #1a5276; padding: 4px 10px; }
.header-buttons { display: inline-flex; flex-wrap: wrap; gap: 8px; }

/* P1.2199 key panel: with no accepted key only the panel shows (no
   "Loading…" sections, no refresh note). */
body.needs-key .container > :not(#key-panel),
body.needs-key .header-refresh { display: none !important; }
.key-panel { background: white; border-radius: 8px; padding: 20px 24px; box-shadow: 0 1px 3px rgba(0,0,0,.1); max-width: 520px; margin: 24px auto; }
.key-intro { margin: 0 0 12px; font-weight: 600; color: #1a5276; }
.key-note { margin: 0 0 12px; color: #1a5276; background: #e8f4fd; border-left: 3px solid #1a5276; padding: 8px 12px; border-radius: 0 4px 4px 0; }
.key-label { display: block; margin: 0 0 6px; font-weight: 600; color: #2c3e50; }
/* P3.2294: body size and the normal text colour (as .key-label), right
   under the intro, so a patient sees it first even at 200% zoom. */
.key-patient { margin: 0 0 12px; font-size: 1rem; color: #2c3e50; }
/* R.158 Q20: the patient-portal link on that line (#key-portal-link). */
.key-portal-link { color: #1a5276; font-weight: 600; text-decoration: underline; overflow-wrap: anywhere; }
.key-portal-link:focus-visible { outline: 2px solid #1a5276; outline-offset: 2px; }
/* R.158 Q4 (a): the physician's escalated-items notice at the top of the
   Inbox panel (#escalated-notice, filled by the render code). */
.escalated-notice { margin: 0 0 14px; color: #7d3c00; background: #fef5e7; border-left: 3px solid #d68910; padding: 8px 12px; border-radius: 0 4px 4px 0; font-weight: 600; }
.key-error { margin: 0 0 12px; color: #922b21; background: #fdecea; border-left: 3px solid #c0392b; padding: 8px 12px; border-radius: 0 4px 4px 0; }
.key-row { display: flex; gap: 8px; align-items: center; }
.key-input { flex: 1; min-width: 0; padding: 8px 10px; border: 1px solid #aab7c4; border-radius: 6px; font-size: 0.95rem; }
/* P3.2305: while "Show key" is on, the whole key in a monospace line under
   the box (a 64-character key does not fit in the box), wrapping anywhere so
   every character shows without scrolling. Kept in sync by api.js; emptied
   and hidden on hide, submit and sign-out. */
.key-mirror { margin: 8px 0 0; padding: 6px 10px; background: #f4f6f8; border: 1px dashed #aab7c4; border-radius: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.9rem; line-height: 1.5; color: #2c3e50; overflow-wrap: anywhere; word-break: break-all; }
.btn-key { background: #1a5276; color: white; }
/* POLISH row 4 (P3.2295): reveal the typed key; the pressed state is shown
   by colour as well as aria-pressed. */
.btn-key-show { background: white; color: #1a5276; border: 1px solid #1a5276; }
.btn-key-show[aria-pressed="true"] { background: #e8f4fd; }
/* P3.2201: a card with a request in flight (dispatch.js lockCard). */
[aria-busy="true"] { cursor: progress; }
.btn[aria-disabled="true"] { opacity: 0.55; pointer-events: none; }

.tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 2px solid #e0e0e0; margin-bottom: 18px; }
.tab-btn { background: none; border: none; padding: 12px 22px; font-size: 0.95rem; font-weight: 600; cursor: pointer; color: #666; border-bottom: 3px solid transparent; margin-bottom: -2px; }
.tab-btn.active { color: #1a5276; border-bottom-color: #1a5276; }
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* P3.2201: the toast stack sits bottom-LEFT and stops well short of the
   right-hand actions column, so it never covers the next card's buttons.
   P3.2216: it holds up to three .toast-item entries, newest nearest the
   edge. Clicks pass through a plain toast; a toast with an action (Undo)
   takes the pointer, so hovering it pauses its timer, and has a close
   button. */
.toast-stack { position: fixed; bottom: 20px; left: 20px; right: auto; max-width: min(460px, calc(100vw - 300px)); pointer-events: none; z-index: 999; display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
.toast-item { pointer-events: none; color: white; padding: 10px 18px; border-radius: 8px; font-size: 0.85rem; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; overflow-wrap: anywhere; background: #2c3e50; box-shadow: 0 2px 6px rgba(0,0,0,.2); }
.toast-item.toast-has-action { pointer-events: auto; padding-right: 8px; }
.toast-text { flex: 1 1 auto; min-width: 0; }
/* P3.2302: an outcome notice (toast.js showOutcomeToast): "Escalated" in
   bold, then " · <item label>". */
.toast-outcome { font-weight: 700; }
.toast-success { background: #1e8449; }
.toast-neutral { background: #4d5d6c; }
.toast-error { background: #c0392b; }
.toast-action { pointer-events: auto; background: transparent; color: white; border: 1px solid rgba(255,255,255,.8); border-radius: 4px; padding: 3px 10px; font-weight: 600; cursor: pointer; }
.toast-close { pointer-events: auto; background: transparent; color: white; border: none; border-radius: 4px; padding: 0 8px; font-size: 1.2rem; line-height: 1.6; cursor: pointer; }
.toast-clear-all { pointer-events: auto; position: absolute; right: 0; bottom: 100%; margin-bottom: 3px; line-height: 1.1; background: #2c3e50; color: white; border: 1px solid rgba(255,255,255,.8); border-radius: 4px; padding: 1px 8px; font-size: 0.75rem; font-weight: 600; cursor: pointer; }
.toast-clear-all:focus-visible { outline: 2px solid white; outline-offset: 2px; }
/* 32px hit area under 1000px without growing the notice (the stack stays short). */
@media (max-width: 999px) { .toast-close { position: relative; } .toast-close::after { content: ''; position: absolute; top: 50%; left: 50%; width: 32px; height: 32px; transform: translate(-50%, -50%); } }
.toast-action:focus-visible, .toast-close:focus-visible { outline: 2px solid white; outline-offset: 2px; }

@media (max-width: 640px) {
  /* POLISH row 3 (P3.2226): a compact phone header (about 110 px or less at
     390x844): no refresh note, a shorter signed-in line, small buttons. */
  .app-header { padding: 8px 12px; gap: 4px 10px; }
  .app-header h1 { font-size: 1rem; }
  .header-refresh, .who-prefix { display: none; }
  .header-who { font-size: 0.75rem; }
  .header-buttons { gap: 6px; margin-left: auto; }
  .btn-header { padding: 3px 8px; font-size: 0.75rem; }
  .tab-btn { padding: 8px 10px; font-size: 0.88rem; }
  /* Phone (P3.2309 row 1, round 7): the stack sits at the bottom, above the
     safe area, in the compact one-line form, so it never covers the header
     (Sign out, Use a different key); the page's bottom padding (base.css) and
     toast.js revealClearOfStack keep rows clear of it. */
  .toast-stack { left: 10px; right: 10px; top: auto; bottom: max(10px, env(safe-area-inset-bottom)); max-width: none; }
  .key-row { flex-direction: column; align-items: stretch; }
  /* Room to scroll the last row clear of the bottom stack (three compact
     notices are about 120 px). */
  body:is(.toasts-1, .toasts-2, .toasts-3) .container { padding-bottom: calc(var(--toast-stack-h, 170px) + 24px); }
}

/* POLISH row 5 (P3.2295): a short screen (e.g. 720x450 at 200% zoom). Two
   Undo notices used to cover about 40% of the height: compact entries, the
   text on one line (the full text stays in the DOM, so a screen reader
   still reads all of it) and the stack capped near 30% of the height with
   its own scroll. Lifetimes are unchanged (P3.2216, toast.js). */
@media (max-height: 520px) {
  /* Round 14 (P3.3122 row 5, P3.2862): never a horizontal scrollbar here; the item and its text may shrink, the label wraps (two lines), the outcome word stays whole. */
  /* Round 15 (P3.2607, P3.3379): the stack no longer scrolls on its own. Below 1000 px
     at most two notices show (one live Undo and one other), so it never needs to; and
     a scroller around the focused Undo button took PageUp/PageDown/End away from the
     page (the keys scrolled the stack first), which looked like a keyboard stall. */
  .toast-stack { max-height: none; overflow: visible; gap: 4px; }
  .toast-item { min-width: 0; overflow-x: clip; } /* the 32 px close hit area (::after) pokes past the item edge by a pixel */
  .toast-text { min-width: 0; }
  /* The stack scrolls here, so Clear all stays in the flow, pinned at the top. */
  .toast-item { flex-wrap: nowrap; padding: 4px 10px; font-size: 0.78rem; gap: 6px; flex-shrink: 0; }
  .toast-item.toast-has-action { padding-right: 4px; }
  .toast-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* P3.2302: in an outcome notice only the item label is cut; the outcome
     word ("Approved", "Escalated", "Handled") always shows in full. The
     label keeps its leading " · " (white-space: pre). */
  .toast-text.toast-split { display: flex; text-overflow: clip; }
  .toast-outcome { flex-shrink: 0; }
  .toast-label { flex: 0 1 auto; min-width: 0; overflow: hidden; }
  /* Round 11 (P3.2877 row 4): the label wraps to two lines (clamp on the inner span), then an ellipsis. */
  .toast-label-in { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; }
  .toast-action { padding: 1px 8px; flex-shrink: 0; }
  .toast-close { font-size: 1rem; line-height: 1.3; padding: 0 6px; flex-shrink: 0; }
}

/* P3.2607 round 7 (W1-D), (a), still the rule below 1000 px: one, two or
   three notices (body.toasts-1/2/3, set by toast.js syncStack) use the
   compact one-line rules of the short screen above, so a single notice takes
   about 36 px and three about 110, not 300. An outcome notice keeps its
   outcome word in full and only the item label is cut (full text in title
   and accessible name, P3.2302); a plain notice (an error, "someone already
   handled this") keeps wrapping so its sentence is never cut. From 1000 px
   (next block) the notice has its own lane and wraps to two lines instead. */
@media (max-width: 999px) {
  /* Round 15 (P3.3379, P3.2607): no Clear all here (toast.js shows one notice at a
     time), and the notice text is not a click target: only Undo and close take
     clicks, so a tap on a row under a notice reaches the row. */
  .toast-clear-all { display: none; }
  .toast-item.toast-has-action { pointer-events: none; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-stack { gap: 4px; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-item { flex-wrap: nowrap; padding: 4px 10px; gap: 6px; flex-shrink: 0; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-item.toast-has-action { padding-right: 4px; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-text.toast-split { display: flex; white-space: nowrap; overflow: hidden; text-overflow: clip; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-outcome { flex-shrink: 0; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-label { flex: 0 1 auto; min-width: 0; overflow: hidden; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-label-in { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-action { padding: 1px 8px; flex-shrink: 0; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-close { font-size: 1rem; line-height: 1.3; padding: 0 6px; flex-shrink: 0; }
}

/* Round 8 (P3.2607, R.191 item 2 (a)): from 1000 px wide the left 400 px are
   a notice lane that is ALWAYS reserved, with 0, 1, 2 or 3 notices showing,
   so the content column (.container) is placed identically and tabs, buttons
   and count boxes never move under the pointer. The stack lives in the lane
   (16 px from the edge, 376 px wide) and covers nothing. Below 1000 px there
   is no room for a lane: compact overlay notices (above) and toast.js
   scrolls what they cover clear; phones keep the bottom stack. */
@media (min-width: 1000px) {
  .toast-stack { left: 16px; width: 376px; max-width: 376px; }
  .container {
    margin-left: max(400px, calc((100vw - 1100px) / 2));
    margin-right: auto;
    max-width: min(1100px, calc(100vw - 400px));
  }
  /* The notice is two lines at most: the outcome and the label run on as one
     text (surname, first name and item title first, the ID last). */
  .toast-stack .toast-item { flex-wrap: nowrap; padding: 6px 10px; gap: 6px; font-size: 0.8rem; flex-shrink: 0; }
  .toast-stack .toast-item.toast-has-action { padding-right: 4px; }
  .toast-stack .toast-text.toast-split { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; white-space: normal; text-overflow: clip; overflow-wrap: anywhere; }
  .toast-stack .toast-label { display: inline; white-space: pre-wrap; overflow: visible; }
  body .toast-stack .toast-label-in { display: inline; -webkit-line-clamp: unset; line-clamp: unset; overflow: visible; }
  .toast-stack .toast-action { padding: 1px 6px; flex-shrink: 0; }
  .toast-stack .toast-close { font-size: 1rem; line-height: 1.3; padding: 0 4px; flex-shrink: 0; }
  .toast-stack { max-height: none; overflow: visible; gap: 4px; }
}

/* Round 9 (P3.2862 row 1): on a phone-width screen (below about 600 px) an
   outcome notice may wrap to two lines instead of one, so the surname and the
   medicine name show before the ellipsis (full text stays in title and
   aria-label). Same two-line rule as the lane from 1000 px; the Undo and the
   close button keep their place, and a notice is at most two lines. */
@media (max-width: 599px) {
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-text.toast-split { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; white-space: normal; overflow: hidden; text-overflow: clip; overflow-wrap: anywhere; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-label { display: inline; white-space: pre-wrap; overflow: visible; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-label-in { display: inline; -webkit-line-clamp: unset; line-clamp: unset; overflow: visible; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-outcome { display: inline; }
  body:is(.toasts-1, .toasts-2, .toasts-3) .container { padding-bottom: calc(var(--toast-stack-h, 170px) + 24px); }
}

/* Round 11 (P3.2607): below 1000 px (no notice lane) reserve bottom space equal
   to the stack's height (toast.js syncStack sets --toast-stack-h), so the last
   row, count box or Done line can always be scrolled clear of the notices. */
@media (max-width: 999px) {
  body:is(.toasts-1, .toasts-2, .toasts-3) .container { padding-bottom: calc(var(--toast-stack-h, 170px) + 24px); }
  /* Round 16 (P3.2607): below 1000 px (phone, 200% zoom) the notices are a bar docked
     along the bottom edge, full width, on a solid strip, instead of floating cards
     over the rows. The page ends above it: the container reserves the bar's height
     (--toast-stack-h, measured by toast.js, strip included) and scroll-padding keeps
     keyboard and focus scrolling out from under it. The strip passes clicks through,
     so a tap at the old notice position still reaches the row; Undo and close take
     clicks. */
  html:has(body:is(.toasts-1, .toasts-2, .toasts-3)) { scroll-padding-bottom: var(--toast-stack-h, 170px); }
  body:is(.toasts-1, .toasts-2, .toasts-3) .toast-stack {
    left: 0; right: 0; bottom: 0; width: auto; max-width: none;
    padding: 6px 10px max(6px, env(safe-area-inset-bottom));
    background: #f5f5f5; border-top: 1px solid #c9d1d8; box-shadow: 0 -2px 6px rgba(0,0,0,.12);
    box-sizing: border-box; pointer-events: none;
  }
}

/* R.195 Q12: the visible Undo countdown ("29 s"), after the Undo button. */
.toast-count { flex-shrink: 0; font-size: 0.7rem; margin-left: -2px; font-variant-numeric: tabular-nums; opacity: .9; white-space: nowrap; }
