
:root {
  /* Brand, from the logo. */
  --brand: #5C9A85;
  --brand-deep: #3F7563;
  --brand-tint: #EDF5F1;
  --brand-ink: #1E1E1E;

  /* Neutrals. */
  --bg: #F7F8FA;
  --surface: #FFFFFF;
  --surface-2: #FBFCFD;
  /* A shade you can actually see against a white card. --surface-2 is a
     half-step used for hover states; this one is for shading a whole region,
     like a weekend column on the calendar. */
  --surface-3: #F1F4F7;
  --line: #E7EAEF;
  --line-strong: #D3D9E0;
  --ink: #16191D;
  --ink-2: #4A5361;
  --ink-3: #7A8494;

  /* Track states. Not a traffic light: a stage nobody has started and a stage
     someone has halted are different situations, and one colour axis pushes a
     reader to treat amber as "nearly fine". */
  --clear: #1B7A57;
  --clear-bg: #E4F3EC;
  --waiting: #8A6100;
  --waiting-bg: #FDF4DE;
  --blocked: #B02436;
  --blocked-bg: #FCEAEC;
  --idle: #6B7280;
  --idle-bg: #EFF1F4;

  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06);
  --shadow-lg: 0 4px 6px -1px rgba(16, 24, 40, 0.06), 0 12px 24px -4px rgba(16, 24, 40, 0.08);
  --sidebar-w: 232px;
}

* { box-sizing: border-box; }

/*
 * The hidden attribute must win over any display this stylesheet sets.
 *
 * The browser hides [hidden] with a UA rule of display:none, and a UA rule is
 * beaten by any author rule that sets display — so styling a class as a flex
 * or grid container silently makes hidden stop working on it. The element goes
 * invisible-ish and keeps its box.
 *
 * That is exactly what happened to the staff picker: .code-chosen is a flex
 * row, so the hidden chosen-name element still took 32px, the field it sits in
 * was two rows tall inside a one-row flex row, and the due date and Add task
 * button sat below the name box instead of beside it. It was reported as the
 * buttons being funky, which is what a layout bug looks like from outside.
 *
 * !important because that is the only thing that beats an id or an inline
 * style, and hidden means hidden.
 */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand-deep); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

/* ---------------------------------------------------------------- shell --- */

.shell { display: flex; min-height: 100vh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  padding: 18px 12px;
  gap: 22px;
  position: sticky;
  top: 0;
  height: 100vh;
}

/* Padded to 8px so the mark's left edge lines up with the section headings
   below it — REQUESTS, PRE-ADMISSION — which carry the same 8px inside
   .nav-group h6. Measured rather than eyeballed: at 10px it sat two pixels
   right of them, which is the sort of misalignment that reads as sloppy
   without being obvious enough to name. */
.brand { display: flex; align-items: center; padding: 2px 8px; }
.brand img { height: 34px; width: auto; display: block; }

.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group h6 {
  margin: 0 0 6px 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-weight: 500;
  font-size: 13.5px;
}
.nav-item:hover { background: var(--surface-2); text-decoration: none; color: var(--ink); }
.nav-item.active { background: var(--brand-tint); color: var(--brand-deep); font-weight: 600; }
.nav-item .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--line-strong); flex: 0 0 7px;
}
.nav-item.active .dot { background: var(--brand); }
.nav-item .soon {
  margin-left: auto; font-size: 10px; font-weight: 600; letter-spacing: 0.04em;
  color: var(--ink-3); background: var(--idle-bg);
  padding: 1px 6px; border-radius: 20px; text-transform: uppercase;
}

.sidebar-foot { margin-top: auto; display: flex; flex-direction: column; gap: 10px; }

.who {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 10px; border-radius: var(--radius-sm); background: var(--surface-2);
  border: 1px solid var(--line);
}
.who .name { font-weight: 600; font-size: 13px; line-height: 1.25; }
.who .role { font-size: 11.5px; color: var(--ink-3); line-height: 1.3; }

.avatar {
  width: 28px; height: 28px; flex: 0 0 28px;
  border-radius: 50%;
  background: var(--brand); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
}
.avatar.sm { width: 22px; height: 22px; flex-basis: 22px; font-size: 9.5px; }

button.link {
  background: none; border: none; padding: 8px 10px; text-align: left;
  color: var(--ink-3); font: inherit; font-size: 13px; cursor: pointer;
  border-radius: var(--radius-sm);
}
button.link:hover { background: var(--surface-2); color: var(--ink); }

/*
 * The navigation, collapsed to a rail.
 *
 * A preference kept in a cookie and applied server-side, so the class is on the
 * shell when the page arrives — no flash of the wide sidebar, and no script.
 *
 * Collapsed keeps the dots and hides the words: the dots carry the active
 * state, so the current position is still legible at 56px. Section headings go
 * entirely rather than truncating, because a clipped "PRE-ADMISSI" reads as a
 * rendering fault.
 */
.shell.nav-collapsed { --sidebar-w: 56px; }
.nav-collapsed .sidebar { padding-left: 8px; padding-right: 8px; }
.nav-collapsed .nav-group h6,
.nav-collapsed .nav-item > span:not(.dot),
.nav-collapsed .nav-item .soon,
.nav-collapsed .who span:not(.avatar),
.nav-collapsed .sidebar-foot form[action="/auth/logout"] { display: none; }
.nav-collapsed .nav-item { justify-content: center; padding-left: 0; padding-right: 0; }
.nav-collapsed .who { justify-content: center; padding-left: 0; padding-right: 0; }
/*
 * Collapsed, the mark gives way to the control.
 *
 * The wordmark is far wider than a 56px rail, and clipping it to show only the
 * icon leaves no room for the arrow beside it — two things fighting for forty
 * pixels. The arrow is the one that has a job here, so it takes the row and the
 * mark stands down until the rail opens again.
 */
.nav-collapsed .brand { justify-content: center; padding-left: 0; padding-right: 0; }
.nav-collapsed .brand img { display: none; }
.nav-collapsed .nav-toggle-form { margin-left: 0; }

/*
 * The collapse control, beside the mark.
 *
 * A quiet square with no border until it is hovered: it sits next to the
 * product's own logo, and a button competing with the mark for attention would
 * be the loudest thing on a screen whose job is to show clinical status.
 */
.nav-toggle-form { margin: 0; margin-left: auto; }
.nav-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  background: none; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--ink-3); font: inherit; font-size: 17px; line-height: 1;
  cursor: pointer;
}
.nav-toggle:hover { background: var(--surface-2); border-color: var(--line); color: var(--ink); }

/* ----------------------------------------------------------------- main --- */

.content { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 26px; border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.topbar .crumb { font-size: 12px; color: var(--ink-3); }
.topbar h1 { margin: 2px 0 0; font-size: 19px; font-weight: 650; letter-spacing: -0.01em; }
.topbar .spacer { margin-left: auto; }

.page { padding: 22px 26px 40px; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 16px;
}
.card > header {
  padding: 13px 16px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px;
}
.card > header h2 { margin: 0; font-size: 14px; font-weight: 650; }
.card > header .spacer { margin-left: auto; }
.card .body { padding: 16px; }
.card .body.tight { padding: 0; }

.grid { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr); gap: 16px; align-items: start; }
@media (max-width: 1080px) { .grid { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- views --- */

/*
 * The one control on the worklist.
 *
 * A segmented row rather than underlined tabs: it reads as a single switch
 * with one position selected, which is what it is, and it survives wrapping
 * on a narrow screen without the selected item losing its underline.
 */
.viewbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-bottom: 10px;
}

nav.views {
  display: inline-flex; flex-wrap: wrap; gap: 3px;
  padding: 3px;
  background: #EDEFF3;
  border-radius: 9px;
}
nav.views a {
  padding: 6px 12px;
  font-size: 12.5px; font-weight: 550; letter-spacing: -0.005em;
  color: var(--ink-2);
  border-radius: 6px;
  white-space: nowrap;
}
nav.views a:hover { color: var(--ink); text-decoration: none; background: rgba(255,255,255,0.6); }
nav.views a.on {
  background: var(--surface); color: var(--brand-deep); font-weight: 650;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.10);
}

.viewbar .density { margin-left: auto; }

.view-hint { margin: 0 0 14px; font-size: 12.5px; color: var(--ink-3); }

/* The lookup field on the patient index is a different question from the
   demographic ones beside it, and wants room for a reference. */
.filters .field.wide input { min-width: 230px; }

/* A list that was cut says so, above the numbers it qualifies. */
.truncated {
  margin: 0 0 14px;
  padding: 10px 13px;
  font-size: 12.5px; line-height: 1.5;
  color: var(--ink-2);
  background: #FFF8E6;
  border: 1px solid #F2DFA8;
  border-radius: 8px;
}
.truncated strong { color: var(--ink); font-weight: 650; }

/* The answer to a miss, on the screen the miss lands on. */
.find-miss {
  margin: 0 0 14px;
  padding: 9px 12px;
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--surface-2, #F4F6F9);
  border: 1px solid var(--line);
  border-radius: 8px;
}

/* A lookup in the shell, deliberately quiet. It is not patient search and
   must not read as a place to browse. */
.topbar .find-case {
  display: flex; align-items: center; gap: 6px;
  margin-right: 10px;
}
.topbar .find-case input {
  width: 232px;
  padding: 7px 10px;
  font-size: 12.5px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 7px;
}
.topbar .find-case input:focus {
  outline: none;
  border-color: var(--brand-deep);
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

@media (max-width: 860px) {
  .topbar .find-case input { width: 150px; }
}

/* Moving between days. The day itself is the largest thing in the strip
   because it is the thing being read; the steps either side are controls, and
   controls that shout compete with the answer. */
.daynav {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 0 0 10px;
}
.daynav .step {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 6px 11px;
  font-size: 12.5px; font-weight: 550;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 7px;
  white-space: nowrap;
}
.daynav .step:hover { color: var(--ink); text-decoration: none; border-color: var(--ink-3); }
.daynav .day {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 0 6px;
  font-size: 14.5px;
}
.daynav .day strong { font-weight: 650; letter-spacing: -0.01em; }
.daynav .is-today {
  font-size: 11px; font-weight: 650; text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--brand-deep);
}
.daynav .back-to-today { margin-left: 4px; font-size: 12.5px; color: var(--ink-3); }
.daynav .back-to-today:hover { color: var(--brand-deep); }

/* Not a tab. It narrows whatever view is showing, so it sits under the hint
   with the rest of the sentence rather than among the views as a peer. */
.panel-filter {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: -6px 0 14px;
}
.panel-filter .chip {
  padding: 5px 11px;
  font-size: 12.5px; font-weight: 550;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  white-space: nowrap;
}
.panel-filter .chip:hover { color: var(--ink); text-decoration: none; border-color: var(--ink-3); }
.panel-filter .chip.on {
  color: var(--brand-deep); font-weight: 650;
  border-color: var(--brand-deep);
  background: rgba(37, 99, 235, 0.06);
}
.panel-filter .sub { font-size: 12.5px; color: var(--ink-3); }

@media (max-width: 640px) {
  .daynav .step .label { display: none; }
  .daynav .day { font-size: 13.5px; }
}

/* A quieter summary strip. Four hero cards for four small numbers is a lot of
   furniture for a glance. */
.stats { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.stat { padding: 10px 13px; }
.stat .n { font-size: 20px; }
.stat .k { font-size: 11px; }

/* --------------------------------------------------------------- stats --- */

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px; }
.stat {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 15px; box-shadow: var(--shadow);
}
.stat .n { font-size: 24px; font-weight: 680; letter-spacing: -0.02em; line-height: 1.1; }
.stat .k { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; }
.stat.alert .n { color: var(--blocked); }
.stat.good .n { color: var(--clear); }

/* ------------------------------------------------------- attention cards --- */
/*
 * The premise the first design got wrong is that every case deserves equal
 * space. A scheduler is not reading the list, they are hunting the problems in
 * it — so cases with something outstanding get room to breathe and state their
 * problem in a full sentence, while cases on track collapse to one quiet line.
 * Airy where it earns the space, dense where it does not.
 */

.section-head {
  display: flex; align-items: baseline; gap: 9px;
  margin: 4px 2px 11px;
}
.section-head h3 { margin: 0; font-size: 14px; font-weight: 650; letter-spacing: -0.01em; }
.section-head .count {
  font-size: 11px; font-weight: 650; color: var(--ink-3);
  background: var(--idle-bg); border-radius: 20px; padding: 1px 8px;
}
.section-head .spacer { margin-left: auto; }
.section-head .hint { font-size: 12px; color: var(--ink-3); }

.attention { display: grid; gap: 12px; margin-bottom: 26px; }

.case-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--blocked);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.case-card:hover { box-shadow: var(--shadow-lg); }

/*
 * The whole card opens the case, not just the case number.
 *
 * Done with a stretched link rather than a click handler: the case reference is
 * still a real anchor, so it keeps its keyboard focus, its middle-click, its
 * right-click "open in new tab" and its status-bar preview — all of which a
 * div with an onclick throws away, and none of which this product can spare,
 * since opening two cases side by side is ordinary work here. It also needs no
 * JavaScript, which the content security policy forbids inline anyway.
 *
 * The overlay covers the card, so anything else interactive inside it has to be
 * lifted back above — see .case-card .btn below.
 */
.case-card { position: relative; }
.case-card .head .case-ref::after {
  content: ''; position: absolute; inset: 0; border-radius: var(--radius);
}
.case-card .btn, .case-card .problem { position: relative; z-index: 1; }
/* The problem text is selectable prose; the overlay would swallow a drag. */
.case-card .problem { cursor: text; }

/*
 * The same trick for a table row.
 *
 * The row is the containing block and the cells are explicitly static, so the
 * stretched anchor sizes itself to the whole row rather than to its own cell.
 */
tr.row-link { position: relative; }
tr.row-link td { position: static; }
/* The anchor that stretches. A dedicated class rather than .case-ref, which is
   also a plain text style used on cells that are not links. */
tr.row-link a.row-target::after {
  content: ''; position: absolute; inset: 0;
}
tr.row-link:hover { background: var(--surface-2); }
/* Anything else clickable in the row has to sit above the overlay. */
tr.row-link a:not(.row-target), tr.row-link button { position: relative; z-index: 1; }

.case-card .card-main { padding: 13px 16px; }

.case-card .head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.case-card .head .case-ref { font-size: 15px; }
.case-card .proc { margin: 7px 0 0; font-size: 14px; color: var(--ink); }
.case-card .meta { margin-top: 3px; font-size: 12px; color: var(--ink-3); }

/* Stays visible collapsed. It is the reason this section exists. */
.case-card .problem {
  margin-top: 10px; padding: 9px 12px;
  background: var(--blocked-bg); border-radius: var(--radius-sm);
  color: #8A1B2A; font-size: 13px; line-height: 1.5;
}
.case-card .problem .more { color: var(--ink-3); font-size: 12px; display: block; margin-top: 3px; }

/*
 * Beside the case, not beneath it.
 *
 * Three versions of this. The first gave the schedule and the track bar a
 * labelled side panel and put a separate surgeon line on the left, which made
 * the card about twice the height of the sentence it exists to deliver. The
 * second stacked everything into one column, which was shorter but wasted the
 * whole right-hand side of a wide screen and still grew downward.
 *
 * This one spends the width instead: the case, its procedure and its problem
 * on the left, everything about where and with whom on the right. Card height
 * is now the taller of the two columns rather than the sum, and in a stack of
 * blocked cases height is the entire cost.
 */
.case-card { display: grid; grid-template-columns: minmax(0, 1fr) 264px; }
.case-card .card-main { min-width: 0; }

.card-detail {
  display: flex; flex-direction: column; gap: 10px;
  padding: 13px 16px;
  border-left: 1px solid var(--line);
  min-width: 0;
}
.card-detail .meta { margin-top: 0; line-height: 1.55; }
.card-detail .btn { align-self: flex-start; }

/* Below this the two columns have nothing to gain from each other. */
@media (max-width: 900px) {
  .case-card { grid-template-columns: 1fr; }
  .card-detail { border-left: none; border-top: 1px solid var(--line); }
}

/* The custom range, revealed only on its own tab. */
/*
 * Held time and unplaced bookings, above the day board.
 *
 * Not drawn across the grid: a block that grants time without a theatre does
 * not occupy every room, and spanning it would say that it does.
 */
.cal-unplaced { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
/* Assigning a theatre for the day. Compact, because it sits inside a cell. */
/* "Take this case" sits under the sentence it answers, not beside it. */
.take-case { display: block; margin-top: 8px; }

.cal-assign { display: flex; gap: 6px; margin-top: 5px; align-items: center; }
.cal-assign-label {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; color: var(--ink-3); font-weight: 550;
}
.cal-assign select.compact { min-width: 0; flex: 1 1 auto; }
.cal-unplaced-item .cal-assign { margin-top: 0; }
.cal-unplaced-item {
  display: inline-flex; gap: 8px; align-items: baseline;
  padding: 5px 9px; font-size: 12px;
  border: 1px solid var(--line-strong); border-left-width: 3px;
  border-radius: var(--radius-sm); background: var(--surface-3);
}
/* The week's row for the same thing. */
tr.cal-week-unassigned th.cal-week-room { font-style: italic; }
tr.cal-week-unassigned td { background: var(--surface-3); }

/* ---- The reference shelf --------------------------------------------- */
.resource-search { min-width: 340px; }
ul.hits > li { padding: 9px 0; border-bottom: 1px solid var(--line); }
ul.hits > li:last-child { border-bottom: none; }
ul.hits a { display: inline-flex; gap: 8px; align-items: baseline; }
.hit-page {
  font-size: 11px; font-weight: 700; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--brand-deep);
}
.hit-title { font-size: 12px; color: var(--ink-3); }
/*
 * The snippet is context, not the instruction — so it is set quieter than the
 * link above it, and the marked terms are the only thing that stands out.
 * Anything that reads like guidance here gets acted on without the page being
 * opened, which is the one outcome this screen must not produce.
 */
.hit-snippet {
  margin: 3px 0 0; font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.hit-snippet mark { background: var(--brand-tint); color: var(--ink); padding: 0 2px; }

/*
 * The excerpt keeps the page's own layout, and the monospace is not decoration.
 *
 * The extraction is pdftotext -layout: a four-column table is held apart by
 * runs of spaces, and a proportional font closes those runs up until one drug's
 * hold instruction sits against another's. So the block is preformatted, in a
 * fixed pitch, and scrolls sideways rather than wrapping — a wrapped line of a
 * table is a line that has changed row.
 *
 * Quieter than the link above it. Anything here that reads like guidance gets
 * acted on without the page being opened, which is the one outcome this screen
 * must not produce.
 *
 * **No vertical scroll, deliberately.** It had a max-height, and a page of this
 * protocol is longer than that — so the block clipped and the rest sat behind
 * an inner scrollbar. On a screen whose entire history is content going missing
 * where it mattered, a reader who does not notice a scrollbar is a reader who
 * has been shown a fragment again. The card grows instead and the page scrolls
 * the way pages do. Sideways still scrolls, because a table row is genuinely
 * wider than the column and wrapping it would move a line into another row.
 */
.hit-excerpt {
  margin: 4px 0 0;
  padding: 8px 10px;
  background: var(--surface-2);
  border-left: 2px solid var(--line-strong);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-2);
  white-space: pre;
  overflow-x: auto;
}
.hit-excerpt mark { background: var(--brand-tint); color: var(--ink); padding: 0 1px; }
/*
 * Sits directly under the page, because it is a caveat about that page.
 *
 * A summary rather than a sentence when there is a next page to offer: the
 * table row this document is built from does not stop at a page boundary, and
 * the interval a reader is looking for is routinely on the page after the one
 * that names the drug. Folded, because it is usually not needed and is a whole
 * page when it is.
 */
.hit-continues { margin: 4px 0 0; font-size: 11.5px; }
details.hit-continues > summary {
  cursor: pointer;
  color: var(--brand-deep);
  font-weight: 600;
  padding: 3px 0;
}
ul.docs > li { padding: 10px 0; border-bottom: 1px solid var(--line); }
ul.docs > li:last-child { border-bottom: none; }

/* A hint under a field must not decide the field's width. */
.field > .sub { max-width: 30ch; }

form.range {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end;
  padding: 12px 14px; margin-bottom: 14px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}

/* --------------------------------------------------------------- table --- */

table { width: 100%; border-collapse: separate; border-spacing: 0; }

/*
 * One column grid for every worklist section.
 *
 * Each table would otherwise size itself to its own rows — so "Scheduled" sits
 * in a different place under "Needs attention" than under "Closed", and a
 * reader scanning down a column has to find it again in each section. Fixed
 * widths cost some elasticity and buy a page that reads as one table.
 *
 * Scoped to the worklist class rather than applied to every table: the patient
 * index has different columns and no reason to share this rhythm.
 */
/*
 * Every column is sized, and the table has a floor it cannot shrink below.
 *
 * The first version fixed five of the six and let Procedure take whatever was
 * left. That is fine on a wide monitor and collapses on anything narrower: the
 * five fixed widths already came to 646px, so on a laptop the Procedure column
 * was handed the remainder — sometimes a few pixels — and "Laparoscopic
 * appendectomy" rendered one letter per line while the headings overlapped
 * each other. A residual column in a fixed layout has no floor, and the page
 * gave no sign anything was wrong until it was unreadable.
 *
 * So: an explicit width for all six, and a min-width equal to their sum. The
 * table now keeps its proportions and scrolls inside its own card rather than
 * compressing a column out of existence.
 */
table.worklist { table-layout: fixed; min-width: 1300px; }
table.worklist th:nth-child(1), table.worklist td:nth-child(1) { width: 108px; }
table.worklist th:nth-child(2), table.worklist td:nth-child(2) { width: 190px; }
table.worklist th:nth-child(3), table.worklist td:nth-child(3) { width: 230px; }
table.worklist th:nth-child(4), table.worklist td:nth-child(4) { width: 160px; }
table.worklist th:nth-child(5), table.worklist td:nth-child(5) { width: 190px; }
table.worklist th:nth-child(6), table.worklist td:nth-child(6) { width: 148px; }
table.worklist th:nth-child(7), table.worklist td:nth-child(7) { width: 260px; }

/*
 * Break between words, not inside them.
 *
 * This was overflow-wrap: anywhere — a last resort for unbreakable strings
 * like a uuid, and entirely wrong for prose. "Laparoscopic appendectomy"
 * rendered as "Laparoscopic appendectom / y", splitting a word across lines
 * while a perfectly good space sat one character earlier. break-word breaks
 * mid-word only when a single word genuinely cannot fit, which is the
 * behaviour that was wanted all along.
 */
table.worklist td { overflow-wrap: break-word; }
thead th {
  text-align: left; padding: 9px 14px;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--ink-3); background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}
thead th:first-child { border-top-left-radius: var(--radius); }
thead th:last-child { border-top-right-radius: var(--radius); }
tbody td { padding: 12px 14px; border-bottom: 1px solid var(--line); vertical-align: top; }

/* Compact is the default for the on-track table: those rows are being scanned
   for a name, not read. Comfortable is one click away for a quieter day. */
table.compact tbody td { padding: 7px 14px; font-size: 13px; }
table.compact tbody td .sub { display: none; }
table.compact .trackbar .seg { height: 5px; }

.density { display: flex; gap: 2px; }
.density a {
  font-size: 11.5px; font-weight: 600; padding: 3px 9px;
  border: 1px solid var(--line-strong); color: var(--ink-3); background: var(--surface);
}
.density a:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.density a:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; border-left: none; }
.density a:hover { text-decoration: none; color: var(--ink); }
.density a.on { background: var(--brand-tint); color: var(--brand-deep); border-color: var(--brand); }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }

.case-ref { font-weight: 650; font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.person { display: flex; align-items: center; gap: 8px; }
.person .name { font-weight: 550; }
.sub { color: var(--ink-3); font-size: 12px; }
.nowrap { white-space: nowrap; }

/* --------------------------------------------------- track progress bar --- */
/*
 * Seven segments, one per track, each coloured by its own state.
 *
 * This replaces the single percentage the brief asked for, and does the job
 * the percentage was reaching for without its flaw: you can see at a glance
 * how much of the case is settled AND which specific stage is the problem.
 * A number cannot carry the second half, and the second half is the one that
 * tells somebody what to do next.
 */
/* The bar and its legend share one column rhythm, so a label always sits
   under the segment it names. */
.trackbar { display: flex; gap: 3px; align-items: center; }
.seg {
  height: 6px; flex: 1 1 0; min-width: 10px; border-radius: 3px;
  background: var(--line-strong);
}
.seg.clear { background: var(--clear); }
.seg.waiting { background: #E8B93B; }
.seg.blocked { background: var(--blocked); }
.seg.idle { background: var(--line-strong); }
.tracklegend { display: flex; gap: 3px; margin-top: 7px; }
.legend-cell {
  flex: 1 1 0; min-width: 0;
  display: flex; justify-content: center;
}
.legend-cell .pill {
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis;
}

.pill {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 20px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.01em; white-space: nowrap;
}
.pill.clear { color: var(--clear); background: var(--clear-bg); }
.pill.waiting { color: var(--waiting); background: var(--waiting-bg); }
.pill.blocked { color: var(--blocked); background: var(--blocked-bg); }
.pill.idle { color: var(--idle); background: var(--idle-bg); }
.pill.brand { color: var(--brand-deep); background: var(--brand-tint); }

.status-line { font-size: 13px; }
.status-line.blocked { color: var(--blocked); font-weight: 550; }
.status-line.ok { color: var(--clear); }
.status-line.done { color: var(--ink-3); }

/* --------------------------------------------------------------- forms --- */

/*
 * Fields line up on the top of their boxes, not the bottom.
 *
 * It was flex-end, which lines the *boxes* up — so a field carrying a hint
 * under its input is taller, and lining its bottom edge up with the others
 * pushes its input above them. The scheduling form's Finish box sat a line
 * higher than Start and Date the moment it gained a hint, which is what "the
 * finish is out of line" was.
 *
 * flex-start lines them up on the label instead. Every label in these forms
 * is one line, so the inputs land level and anything below one hangs off the
 * bottom where it belongs.
 */
form.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; }
form.filters .spacer { margin-left: auto; }
/*
 * The miss message, level with the box it is about.
 *
 * form.filters aligns to flex-start, which puts a bare span beside a labelled
 * input at the top of the label rather than beside the field — the same
 * mismatch the rule further down fixes for the submit button. It gets the
 * button's treatment for the same reason, plus the line-height that stops it
 * sitting a pixel high against a bordered input.
 */
form.filters > .sub { align-self: flex-end; padding-bottom: 8px; line-height: 1.4; }
.find-case { margin-bottom: 14px; }
label.field { display: flex; flex-direction: column; gap: 4px; font-size: 11.5px; color: var(--ink-3); font-weight: 550; }
/*
 * textarea belongs here and was missing, which is why every multi-line box on
 * the site rendered in the browser's monospace default — the placeholder read
 * as code rather than as a hint.
 */
input, select, textarea {
  font: inherit; font-size: 13px; padding: 7px 9px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); min-width: 150px;
}

/*
 * A checkbox is not a text field, and the rule above thought it was.
 *
 * A 150px floor is right for something somebody types into and wrong for a
 * 22px box -- and min-width beats width, so the 22px asked for by
 * .pt-check input lost silently. Every tick box in this product has been
 * rendering 150 pixels wide, shoving whatever sits beside it about a hundred
 * and thirty pixels to the right.
 *
 * Most visible on the confirm screen after a photograph, where the medicine's
 * name floated into the middle of the card away from its own checkbox -- on
 * the one screen whose whole job is making a person look at a name and decide
 * whether it is theirs. Reported from a handset, 2026-09-15.
 *
 * Nothing wanted the inherited value: a checkbox and a radio are sized by
 * their own rules or by the browser, never by a text field's floor.
 */
input[type='checkbox'],
input[type='radio'] {
  min-width: 0;
}
input:hover, select:hover, textarea:hover { border-color: var(--ink-3); }

/*
 * Placeholder text has one job on the request form and it is unusual: it shows
 * the value the hospital already holds, inside the box where a new one would be
 * typed, so a change is a comparison rather than a guess.
 *
 * It therefore has to be legible — a whisper-grey hint is useless for reading a
 * postcode off — while staying clearly not-a-value, or somebody will believe
 * the field is filled in. Italic does that work without relying on contrast
 * alone, which is also the accessible choice.
 */
input::placeholder, textarea::placeholder { color: var(--ink-3); font-style: italic; }

.btn {
  font: inherit; font-size: 13px; font-weight: 600;
  padding: 8px 15px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--brand); background: var(--brand); color: #fff;
}
/*
 * A link styled as a button is a button-shaped target, not a word.
 *
 * .btn set no display, so an <a> carrying it stayed display:inline — the
 * padding painted, and the hit area was the glyph plus whatever the inline box
 * happened to give it. On a wide label nobody notices. On the calendar's ‹ and
 * › it means the only reliable place to press is the arrow itself, which is
 * how it was reported.
 *
 * inline-flex on the anchor alone: <button> already lays out as a box, and
 * changing the shared rule would have touched every screen to fix two arrows.
 */
a.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}
a.btn:hover { text-decoration: none; }
/*
 * A button sitting beside a field rather than under a label.
 *
 * .field is a column — label text above, input below — so a button that is a
 * sibling of one stretches over both and stands a whole label taller than the
 * box it belongs to. It lines up with the input instead, and takes the input's
 * vertical padding so the two are the same height rather than nearly.
 */
/*
 * form.filters needs it too, and did not have it.
 *
 * It sets align-items: flex-start, so a Search button beside a labelled box sat
 * level with the *label* and floated a whole line above the input it submits.
 * The rule above was written for exactly this and only ever named one of the
 * two rows it applies to.
 */
.field-row > .btn,
form.filters > .btn { align-self: flex-end; padding-top: 7px; padding-bottom: 7px; }
.btn:hover { background: var(--brand-deep); border-color: var(--brand-deep); }
.btn.ghost { background: var(--surface); color: var(--ink-2); border-color: var(--line-strong); }
.btn.ghost:hover { background: var(--surface-2); color: var(--ink); }

/* --------------------------------------------------------------- lists --- */

/*
 * The protocol link beside a drug name.
 *
 * Quiet, and set apart from the name rather than wrapped around it: the drug is
 * a fact on the record and the link is a way out to somebody else's document.
 * Making the name itself clickable would blur those, and this screen keeps that
 * line everywhere else.
 */
/*
 * The health system's instruction, under the drug it belongs to.
 *
 * Shown, not folded. Every failure this material has had came from hiding part
 * of it, and a collapsed panel is one more way for the half that matters to be
 * the half nobody opened.
 *
 * pre-wrap rather than pre: the branches are a bulleted list with real line
 * breaks, and those carry the meaning — but the lines are prose and should wrap
 * to the card rather than scroll sideways the way a table does.
 */
.med-guidance { margin: 4px 0 2px; padding-left: 8px; border-left: 2px solid var(--line-strong); }
.med-guidance-head { font-weight: 600; }
.med-guidance-body {
  margin: 2px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  white-space: pre-wrap;
}
/*
 * A guidance hit on the resources screen.
 *
 * The same block as on a case, because it is the same material and a reader
 * should not have to recognise two presentations of one instruction.
 */
.guidance-hits > li { padding: 10px 0; border-bottom: 1px solid var(--line); }
.guidance-hits > li:last-child { border-bottom: none; }
.guidance-head { margin-bottom: 2px; }

/* An unlisted drug is a fact, not an absence. */
.med-guidance-none { margin: 4px 0 2px; font-style: italic; }

.med-protocol {
  margin-left: 8px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--brand-deep);
  white-space: nowrap;
}

ul.plain { list-style: none; margin: 0; padding: 0; }
ul.plain > li { padding: 11px 0; border-bottom: 1px solid var(--line); }
ul.plain > li:first-child { padding-top: 0; }
ul.plain > li:last-child { border-bottom: none; padding-bottom: 0; }

dl.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 9px 16px; margin: 0; }
dl.facts dt { color: var(--ink-3); font-size: 12px; font-weight: 550; }
dl.facts dd { margin: 0; font-size: 13px; }

/*
 * Two label/value pairs per row where there is room.
 *
 * A short facts list reads fine in one column; a longer one becomes a tall
 * ladder of six words per line with the right half of the card empty. Opt-in
 * rather than applied to every list, because the case dashboard's facts carry
 * long values — a procedure description, a cancellation reason — that need
 * the full width.
 */
@media (min-width: 720px) {
  dl.facts.two-up {
    grid-template-columns:
      max-content minmax(0, 1fr) max-content minmax(0, 1fr);
    column-gap: 22px;
  }
  /* A value that needs the whole row says so. */
  dl.facts.two-up dd.wide { grid-column: 2 / -1; }
}

/*
  The paper-trail panel: tasks, comments and the timeline behind three tabs.

  Links rather than script, so the open tab is bookmarkable, survives a form
  post and works with scripting off. The strip sits on the card it controls
  rather than floating above it, so it reads as one object.
*/
.panel { display: flex; flex-direction: column; }
/*
  The panel does not grow without bound, and that is a scrolling fix as much as
  a layout one.

  A case with twenty tasks made the panel most of the document. Returning to it
  after a write then scrolled as far as the page could go and stopped — which
  reads as being thrown to the bottom, because it is. Bounding the list keeps
  the page a predictable height, keeps the tabs and the box you type in on
  screen together, and means the anchor lands where it says it will.

  The list scrolls inside the panel; nothing is hidden, and the count in the tab
  says how much there is.
*/
.panel-scroll { max-height: 46vh; overflow-y: auto; overscroll-behavior: contain; }
/* Not jammed against the top of the window when a write returns here. */
#panel { scroll-margin-top: 16px; }
.panel-tabs {
  display: flex; gap: 2px;
  border-bottom: 1px solid var(--line);
  margin-bottom: -1px;
}
.panel-tab {
  display: flex; align-items: center; gap: 6px;
  padding: 9px 13px;
  font-size: 12.5px; font-weight: 600;
  color: var(--ink-3); text-decoration: none;
  border: 1px solid transparent; border-bottom: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.panel-tab:hover { color: var(--ink); background: var(--surface-2); }
/* The active tab joins the card below it — no line between them. */
.panel-tab.active {
  color: var(--ink);
  background: var(--surface);
  border-color: var(--line);
  border-bottom: 1px solid var(--surface);
}
.panel-count {
  min-width: 17px; padding: 0 5px;
  border-radius: 9px;
  background: var(--surface-2); color: var(--ink-3);
  font-size: 11px; font-weight: 700; text-align: center;
}
.panel-tab.active .panel-count { background: var(--brand-deep); color: #fff; }
/* The card under the strip loses its top rounding so the two meet flush. */
.panel > .card { border-top-left-radius: 0; border-top-right-radius: 0; }

/*
  Tasks: what somebody owes on this case.

  Open ones first and plainly, resolved ones dimmed but present — "we already
  asked for that on Tuesday and PAT answered" is most of the value of having
  written it down, so they are kept rather than hidden.
*/
.tasks li { display: block; padding: 11px 0; border-bottom: none; }
.tasks li + li { border-top: 1px solid var(--line); }
.tasks .what { font-size: 14px; line-height: 1.45; overflow-wrap: anywhere; }
.tasks .owner { font-size: 12px; color: var(--muted); margin-top: 3px; }
.tasks .owner strong { color: var(--ink); font-weight: 600; }
/* Done, not gone. Legible at a glance as finished without being unreadable. */
.tasks li.done .what { color: var(--muted); }
.tasks .done-note { font-size: 12px; color: var(--muted); margin-top: 3px; }
/* Same collapsed-control shape as the timeline's "earlier" toggle. */
details.close-task > summary {
  cursor: pointer; list-style: none;
  margin-top: 6px;
  font-size: 12.5px; font-weight: 600; color: var(--brand-deep);
}
details.close-task > summary::-webkit-details-marker { display: none; }
details.close-task > summary::marker { content: ''; }
details.close-task > summary:hover { text-decoration: underline; }
details.close-task[open] > summary { margin-bottom: 6px; }

/*
  The count beside "My tasks" in the navigation.

  This is the entire notification mechanism this product has: nothing here
  delivers anything to anybody who is not already looking at a screen. A number
  is the smallest honest version of being told, so it has to be legible at a
  glance without shouting on every page.
*/
.nav-count {
  margin-left: auto;
  min-width: 18px; padding: 1px 6px;
  border-radius: 9px;
  background: var(--brand-deep); color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1.5;
  text-align: center;
}
.nav-collapsed .nav-count { display: none; }

.tasks-compose { margin-top: 14px; }
.tasks-compose textarea { width: 100%; min-height: 56px; resize: vertical; }
.tasks-compose .row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }

/*
  The conversation on a case.

  Oldest first, so it reads downwards like the exchange it is — the opposite of
  the timeline directly above it, which answers "what happened most recently".
  Two lists in one column ordered differently would be confusing if they looked
  alike, so this one does not: attribution on its own line above the words, no
  rule between entries, and the words given room to be read rather than scanned.
*/
.comments li { display: block; padding: 12px 0; border-bottom: none; }
.comments li + li { border-top: 1px solid var(--line); }
/*
 * byline, not who.
 *
 * .who is the sidebar's signed-in user chip — background, border, padding —
 * and a comment attribution written as .who silently inherited all of it. The
 * result was a boxed name above plain text, so the eye went to the timestamp
 * before the sentence. Third collision in this stylesheet from having no
 * naming convention; see the note in STATUS.
 *
 * Below the message, not above it, for the same reason every messaging
 * application does it: the thing said is the content and the attribution is the
 * footnote.
 */
.comments .byline { font-size: 11.5px; color: var(--muted); margin-top: 4px; }
.comments .byline strong { color: var(--ink-2); font-weight: 600; }
.comments .said {
  font-size: 14px;
  line-height: 1.5;
  /* A pasted list or a note with line breaks keeps them, and a long unbroken
     string wraps instead of widening the column past the page. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* The box sits under the conversation, where the next thing to say goes. */
.comments-compose { margin-top: 14px; }
.comments-compose textarea { width: 100%; min-height: 68px; resize: vertical; }

.timeline li { display: block; }
.timeline .when {
  display: block; color: var(--ink-3); font-size: 11px;
  letter-spacing: 0.01em; margin-bottom: 2px;
}
.timeline .what { font-size: 13px; line-height: 1.45; }

details.earlier > summary {
  cursor: pointer; list-style: none;
  padding: 9px 0 0; margin-top: 4px;
  border-top: 1px solid var(--line);
  font-size: 12.5px; font-weight: 600; color: var(--brand-deep);
}
details.earlier > summary::-webkit-details-marker { display: none; }
details.earlier > summary::marker { content: ''; }
details.earlier > summary:hover { text-decoration: underline; }
details.earlier[open] > summary { margin-bottom: 8px; }

.layer { padding: 12px 0; border-bottom: 1px solid var(--line); }
.layer:last-child { border-bottom: none; }
.layer:first-child { padding-top: 0; }
.layer h4 {
  margin: 0 0 7px; font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-3);
}
.critical { color: var(--blocked); font-weight: 650; }

.note {
  color: var(--ink-3); font-size: 12px; line-height: 1.5;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 11px; margin: 0 0 14px;
}
.note strong { color: var(--ink-2); }

.chosen {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 14px; margin-bottom: 6px;
  background: var(--brand-tint); border: 1px solid var(--brand);
  border-radius: var(--radius-sm);
}
.chosen p { margin: 0; }
/*
 * The confirm button goes to the far end of the band, not next to the name.
 *
 * Sitting immediately after the name it read as part of the name — a green
 * slab abutting the text it confirms, with the rest of a wide band empty
 * beside it. Pushed right, the band reads as what it is: here is the person on
 * the left, here is the decision on the right.
 */
.chosen > form, .chosen > p { margin-left: auto; }
.topbar .btn + .btn { margin-left: 8px; }
/*
 * A button that posts, sitting level with the links beside it.
 *
 * The topbar's actions are anchors carrying .btn, except where the action is a
 * POST — following a case — and that one has to be a button inside a form. The
 * form is then what the topbar's flex lays out, and the user-agent stylesheet
 * gives a form margin-block-end: 1em, which is 14px here.
 *
 * align-items: center centres an item's *margin box*, so a bottom margin and no
 * top margin lifts the border box by half of it. Measured in the browser: the
 * two anchors at top 23, "Add to my list" at 16, and the form reporting
 * margin: 0px 0px 14px. Seven pixels, which is exactly what was reported.
 *
 * The form's own box needs nothing else — its height already matches the
 * button's. An earlier version of this rule made it a flex container to remove
 * a line box that is not there, which fixed nothing and looked like it might.
 */
.topbar form { margin: 0; }

.card.danger { border-color: #E9B8BE; }
.card.danger > header { background: var(--blocked-bg); border-bottom-color: #E9B8BE; }
.card.danger > header h2 { color: #8A1B2A; }
.btn.danger { background: var(--blocked); border-color: var(--blocked); }
.btn.danger:hover { background: #8A1B2A; border-color: #8A1B2A; }
/*
 * A quiet destructive control, for the ones that are the rare correction rather
 * than the point of the screen — deleting a room typed by mistake, taking a
 * piece of equipment out of the catalogue. A solid red button beside Save reads
 * as the main action, which these are not.
 */
.btn.danger-ghost {
  background: var(--surface);
  color: var(--blocked);
  border-color: var(--line-strong);
}
.btn.danger-ghost:hover { background: var(--blocked-bg); border-color: var(--blocked); }
.inline-form { margin-top: 8px; }
.interpreter { margin-top: 4px; }
/* The nearby-procedure signal (access-control.md §4). Its explanation is the
   substance — the pill alone reads as a label rather than an instruction — so
   the two are kept together and given room, not tucked under a name. */
.nearby { margin-top: 4px; }
.nearby .sub { margin-top: 4px; max-width: 44ch; }

/* The correction form: rows of fields that wrap, rather than a rigid grid. */
form.stack { display: flex; flex-direction: column; gap: 14px; }
form.stack h4 { margin: 6px 0 0; }
.field-row { display: flex; flex-wrap: wrap; gap: 12px; }
.field-row .field { flex: 1 1 190px; }
.field-row .field.wide { flex: 2 1 320px; }
/* A field that must not stretch to fill a row it shares with nothing — a
   five-digit code in a full-width box invites a sentence. */
.field-row .field.narrow { flex: 0 1 240px; }
/*
 * A field sized to what is in it rather than to a column.
 *
 * Height and weight are one thought and were sitting a column apart, because
 * narrow still reserves 240px whether the control needs it or not. These hug
 * their tray, so the two land beside each other.
 */
.field-row .field.tight { flex: 0 0 auto; }
label.field.checkbox {
  flex-direction: row; align-items: center; gap: 7px;
  align-self: flex-end; padding-bottom: 8px; font-size: 13px; color: var(--ink-2);
}
.allergies { display: flex; flex-wrap: wrap; gap: 5px; }
/* Sits inside a definition list, so it must not introduce a row of its own. */
/*
 * Value, toggle and form all on one line.
 *
 * The first version put the value on one row, a disclosure beneath it, and the
 * form beneath that — three rows of a definition list for a single short fact,
 * and two of them empty most of the time. Open, the input simply replaces the
 * toggle in place.
 */
/* The details box is the flex line: summary and form are its items, so the
   editor opens beside the toggle rather than under it. */
details.encounter { display: inline-flex; align-items: baseline; gap: 10px; }
details.encounter > summary {
  display: inline-flex; align-items: baseline; gap: 10px;
  cursor: pointer; list-style: none;
}
details.encounter > summary::-webkit-details-marker { display: none; }
details.encounter > summary .toggle {
  text-decoration: underline; font-size: 12px; color: var(--brand-deep);
}
/* One label at a time. The summary stays put when open, so the disclosure can
   be closed again — hiding it outright left no way back. */
details.encounter > summary .when-open { display: none; }
details.encounter[open] > summary .when-open { display: inline; }
details.encounter[open] > summary .when-closed { display: none; }
/* While editing, the input already shows the value — repeating it beside the
   field pushed the editor onto a second line for no gain. */
details.encounter[open] > summary .case-ref,
details.encounter[open] > summary .sub:not(.toggle) { display: none; }
/*
 * Save first, then Cancel.
 *
 * The toggle is the summary, so it has to come first in the markup — that is
 * how a disclosure works. Reordering it visually while open puts the primary
 * action where a reader expects it and leaves the escape to its right. Only
 * the painting order changes; the summary keeps its place in the tab order,
 * which for two adjacent controls is a fair trade.
 */
details.encounter[open] > summary { order: 2; }
form.encounter-form { display: inline-flex; gap: 6px; align-items: center; }
form.encounter-form input { width: 190px; }

/* A labelled field and its button on one line, rather than stacked. */
form.row-form { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
form.row-form .field { flex: 1 1 300px; }
form.row-form .btn { flex: 0 0 auto; }

/*
 * A card whose header is its disclosure.
 *
 * Named "outstanding", not "attention": the worklist already owns .attention
 * for its grid of blocked-case cards, and reusing that name here silently
 * applied display:grid and a 26px bottom margin to this element — which showed
 * up as a band of dead space under the collapsed header that no rule of mine
 * explained.
 *
 * Styled to match a plain card header exactly, so collapsing is available
 * without the section announcing that it is collapsible — the tally on the
 * right is the thing worth noticing, not the triangle.
 */
details.outstanding > summary {
  padding: 13px 16px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 8px;
  cursor: pointer; list-style: none;
}
details.outstanding > summary::-webkit-details-marker { display: none; }
details.outstanding > summary:hover { background: var(--surface-2); }
details.outstanding > summary h2 { margin: 0; font-size: 14px; font-weight: 650; }
details.outstanding > summary .spacer { margin-left: auto; }
/* Points right when closed, down when open. Rotating one glyph rather than
   swapping two keeps the header from shifting by a pixel as it turns. */
details.outstanding > summary .chev {
  color: var(--ink-3); font-size: 17px; line-height: 1; font-weight: 600;
  width: 10px; text-align: center;
  transition: transform 120ms ease; display: inline-block;
}
details.outstanding[open] > summary .chev { transform: rotate(90deg); }
/* Closed, the header is the whole card, so it keeps the card's own corners. */
details.outstanding:not([open]) > summary {
  border-bottom: none; border-radius: var(--radius);
}

.empty { color: var(--ink-3); padding: 44px 20px; text-align: center; font-size: 13px; }
.empty .big { display: block; font-size: 15px; color: var(--ink-2); font-weight: 550; margin-bottom: 4px; }

.soon-page { max-width: 620px; }
/*
 * The three pages that render without the application shell — sign in, no
 * access, choose a health system — sit in the top-left corner otherwise,
 * because .page is written for a screen that has a sidebar beside it and these
 * have nothing. On a front door that reads as unfinished.
 */
.standalone { min-height: 82vh; display: flex; align-items: center; justify-content: center; }
.soon-page h2 { font-size: 17px; margin: 0 0 10px; }
.soon-page p { color: var(--ink-2); line-height: 1.65; }

/* ----------------------------------------------------------- compliance --- */

/* A broken hash chain is the one thing on any screen here that is an assertion
   rather than a question, so it is the one thing allowed to look like an
   alarm. Everything else on these pages is deliberately quiet. */
.note.bad {
  background: var(--blocked-bg); border-color: #E9B8BE; color: #8A1B2A;
}
.note.bad strong { color: #8A1B2A; }

.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; color: var(--ink-2);
}
pre.mono {
  margin: 6px 0 0; padding: 8px 10px; white-space: pre-wrap; overflow-wrap: anywhere;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); max-height: 260px; overflow-y: auto;
}
details summary { cursor: pointer; }
details summary::marker { color: var(--ink-3); }

/*
 * Deliberately NOT table-layout: fixed, unlike the worklist.
 *
 * The worklist fixes its columns so that several tables on one page line up as
 * though they were one. There is only ever one table here, so that argument
 * does not apply — and fixed widths actively hurt: the first attempt gave the
 * timestamp 170px, a few pixels short at this font, so every row read
 * "20:36 UTCDana Whitfield" with the time overflowing into the next column.
 * Long action names had the same problem from the other end, breaking
 * mid-word.
 *
 * Letting the browser size the columns fixes both, since it measures the
 * actual text rather than trusting a number somebody guessed.
 */
table.audit td { vertical-align: top; }
/* The one column that must never wrap or overflow — it is scanned downward. */
table.audit td:nth-child(1), table.audit th:nth-child(1) { white-space: nowrap; }
/* Action names wrap at their own separators rather than mid-word. */
table.audit td:nth-child(3) { overflow-wrap: break-word; }
/* Metadata is the elastic column: it takes whatever room is left. */
table.audit th:nth-child(5), table.audit td:nth-child(5) {
  width: 100%; overflow-wrap: anywhere;
}

/*
 * The audit table is the widest thing in the product — five columns, one of
 * them arbitrary JSON — and on a laptop it does not fit. Letting it push the
 * page sideways moves the sidebar and the headings off-screen too, so the
 * whole layout drifts while somebody is reading a row. Scrolling it inside its
 * own card keeps everything else still.
 */
.table-scroll { overflow-x: auto; }

.scope-summary {
  display: block; max-width: 26ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/*
 * One patient's encounters. Sized for its own content rather than borrowing
 * the worklist's grid, which was chosen for a Patient column this page does
 * not have and a Status column it does not want.
 */
table.encounters { table-layout: fixed; min-width: 1080px; }
table.encounters td { overflow-wrap: break-word; }
table.encounters th:nth-child(1), table.encounters td:nth-child(1) { width: 110px; }
table.encounters th:nth-child(2), table.encounters td:nth-child(2) { width: 140px; }
table.encounters th:nth-child(3), table.encounters td:nth-child(3) { width: 200px; }
table.encounters th:nth-child(4), table.encounters td:nth-child(4) { width: 240px; }
table.encounters th:nth-child(5), table.encounters td:nth-child(5) { width: 160px; }
table.encounters th:nth-child(6), table.encounters td:nth-child(6) { width: 160px; }
table.encounters th:nth-child(7), table.encounters td:nth-child(7) { width: 150px; }

.pager { display: flex; align-items: center; }
.pager .spacer { margin-left: auto; }

/* ------------------------------------------------------- patient intake ---
 *
 * The one surface here that is not used by staff at a desk. Everything in this
 * block is scoped under "pt-" and nothing above it is reused, deliberately:
 * the application's 14px type, 6px radii and dense tables are right for
 * somebody who lives in the product and wrong for somebody who will see it
 * once, on a phone, holding it in one hand.
 *
 * The prefix is also the answer to the collision this stylesheet has already
 * had twice — ".attention" belonging to the worklist and being reused
 * elsewhere. Nothing here can be picked up by an unrelated screen.
 */

.pt-body {
  background: var(--bg);
  /* 17px, because the questionnaire is read rather than scanned, and a good
     proportion of these patients are long-sighted. */
  font-size: 17px;
  line-height: 1.55;
}

.pt-page {
  max-width: 34rem;
  margin: 0 auto;
  padding: 16px 16px 48px;
}

.pt-masthead {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 4px 18px;
  color: var(--ink-2);
  font-size: 17px;
}
.pt-masthead img { width: 42px; height: 42px; }

.pt-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 22px 20px 26px;
}

.pt-card h1 {
  margin: 0 0 12px;
  font-size: 24px;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.pt-card h2 {
  margin: 22px 0 8px;
  font-size: 17px;
  color: var(--ink-2);
}

.pt-lead { margin: 0 0 14px; color: var(--ink-2); }

.pt-help {
  margin: 6px 0 0;
  font-size: 15px;
  color: var(--ink-3);
}

.pt-error,
.pt-notice {
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: 10px;
  font-size: 16px;
}
.pt-error { background: var(--blocked-bg); color: var(--blocked); }
.pt-notice { background: var(--brand-tint); color: var(--brand-deep); }

.pt-field {
  display: block;
  margin: 18px 0 6px;
  font-weight: 600;
}

.pt-input {
  display: block;
  width: 100%;
  padding: 14px 12px;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
}
.pt-input-number { max-width: 10rem; }

/* Full width and tall enough to be a thumb target rather than a mouse one. */
.pt-btn {
  display: block;
  width: 100%;
  margin-top: 22px;
  padding: 16px 18px;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: var(--brand-deep);
  border: 1px solid var(--brand-deep);
  border-radius: 10px;
  cursor: pointer;
}
.pt-btn:hover { background: var(--brand); border-color: var(--brand); }
.pt-btn-quiet {
  color: var(--ink-2);
  background: var(--surface);
  border-color: var(--line-strong);
}
.pt-btn-quiet:hover { background: var(--surface-2); border-color: var(--line-strong); }

.pt-back {
  display: inline-block;
  margin-top: 18px;
  font-size: 16px;
}

/* --- one question --- */

.pt-q {
  margin: 0;
  padding: 20px 0 18px;
  border: 0;
  border-top: 1px solid var(--line);
}
.pt-q:first-of-type { border-top: 0; padding-top: 8px; }

.pt-prompt {
  display: block;
  padding: 0;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.35;
}

/*
 * Yes and No, drawn identically.
 *
 * The radios themselves are taken out of the layout rather than hidden with
 * "display: none", which would take them out of the accessibility tree and off
 * the keyboard with it. Neither is preselected anywhere in the markup: a
 * default here is an answer nobody gave.
 */
.pt-choice {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 14px;
}
.pt-choice input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.pt-choice label {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 54px;
  padding: 10px;
  font-size: 17px;
  font-weight: 600;
  color: var(--ink-2);
  background: var(--surface);
  border: 1.5px solid var(--line-strong);
  border-radius: 10px;
  cursor: pointer;
}
.pt-choice label:hover { border-color: var(--brand); }
.pt-choice input:checked + label {
  color: #fff;
  background: var(--brand-deep);
  border-color: var(--brand-deep);
}
.pt-choice input:focus-visible + label {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.pt-blank-note { margin-top: 20px; }

/* --- progress --- */

.pt-progress { margin-bottom: 18px; }
.pt-progress-bar {
  height: 6px;
  background: var(--line);
  border-radius: 3px;
  overflow: hidden;
}
.pt-progress-fill {
  display: block;
  height: 100%;
  background: var(--brand);
}
/* Tenths, because the CSP rules out an inline width and a <progress> cannot be
   styled the same way in every browser. */
.pt-fill-0 { width: 0; }
.pt-fill-1 { width: 10%; }
.pt-fill-2 { width: 20%; }
.pt-fill-3 { width: 30%; }
.pt-fill-4 { width: 40%; }
.pt-fill-5 { width: 50%; }
.pt-fill-6 { width: 60%; }
.pt-fill-7 { width: 70%; }
.pt-fill-8 { width: 80%; }
.pt-fill-9 { width: 90%; }
.pt-fill-10 { width: 100%; }
.pt-progress-text {
  margin: 8px 0 0;
  font-size: 14px;
  color: var(--ink-3);
}

/* --- review --- */

.pt-unanswered {
  margin: 18px 0;
  padding: 16px 18px;
  background: var(--waiting-bg);
  border-radius: 10px;
}
.pt-unanswered h2 { margin-top: 0; color: var(--waiting); }
.pt-unanswered ul { margin: 10px 0 0; padding-left: 20px; }
.pt-unanswered li { margin-bottom: 6px; }

.pt-summary dl { margin: 0; }
.pt-summary-row {
  display: flex;
  gap: 12px;
  align-items: baseline;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.pt-summary-row dt { flex: 1 1 auto; font-size: 16px; color: var(--ink-2); }
.pt-summary-row dd {
  flex: 0 0 auto;
  margin: 0;
  font-weight: 600;
  white-space: nowrap;
}
/* A blank is a state, not a failure — muted and italic rather than red. */
.pt-summary-row dd.pt-blank {
  font-weight: 400;
  font-style: italic;
  color: var(--ink-3);
}

.pt-footer {
  margin-top: 22px;
  padding: 0 4px;
  color: var(--ink-3);
  font-size: 14px;
}

/* --- the medication list --- */

.pt-meds { margin: 18px 0 0; padding: 0; list-style: none; }
.pt-meds > li {
  padding: 14px 0;
  border-top: 1px solid var(--line);
}

.pt-med-name {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  font-size: 17px;
  font-weight: 600;
}
/*
 * A medication the index did not recognise, said as a state rather than an
 * error. "Something for blood pressure" is a real answer from a real patient
 * and belongs on the list; red text next to it would teach them to delete it.
 */
.pt-med-unmatched {
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-3);
}

.pt-med-detail {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.pt-input-inline {
  flex: 1 1 8rem;
  min-width: 0;
  padding: 10px;
  font-size: 16px;
}
.pt-btn-inline {
  width: auto;
  margin-top: 0;
  padding: 10px 16px;
  font-size: 16px;
}

/* A destructive action that reads as a link: present, and not competing with
   the button the patient is meant to press next. */
.pt-link-btn {
  margin-top: 10px;
  padding: 6px 0;
  font: inherit;
  font-size: 15px;
  color: var(--ink-2);
  background: none;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
}
.pt-link-btn:hover { color: var(--blocked); }

.pt-matches {
  margin-top: 18px;
  padding: 16px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.pt-matches h2 { margin-top: 0; }
.pt-matches ul { margin: 0; padding: 0; list-style: none; }

/* Full-width rows, because this is a list tapped with a thumb. */
/*
 * A search result has to look like something you press.
 *
 * It was the search box, pixel for pixel: same width, same 14px 12px padding,
 * same surface, same 1px line-strong border, same 10px radius. The only things
 * telling a result apart from the field above it were a hover colour and
 * cursor: pointer — and a phone has neither. A patient reported not knowing the
 * results were tappable, which on that stylesheet was the correct reading.
 *
 * So it now carries the brand, weight, and a chevron. Nothing here depends on
 * hover, because the device this page was written for cannot do it.
 */
.pt-match {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  margin-bottom: 8px;
  padding: 15px 14px;
  font: inherit;
  font-size: 17px;
  font-weight: 600;
  text-align: left;
  color: var(--brand-deep);
  background: var(--brand-tint);
  border: 1.5px solid var(--brand);
  border-radius: 10px;
  cursor: pointer;
}
/* Drawn rather than typed, so it cannot be mistaken for part of the name. */
.pt-match::after {
  content: '';
  flex: none;
  width: 9px; height: 9px;
  margin-right: 3px;
  border-right: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  transform: rotate(-45deg);
}
.pt-match:active { background: var(--brand); color: #fff; }
.pt-match:active::after { border-color: #fff; }

/*
 * What just happened, when the page otherwise looks unchanged.
 *
 * Both cases it serves are ones where the list is identical afterwards: a dose
 * saved onto a row that already showed it, and a duplicate refused. Silence
 * there reads as a button that did not work.
 */
.pt-notice {
  margin: 0 0 14px;
  padding: 11px 13px;
  font-size: 15px;
  color: var(--brand-deep);
  background: var(--brand-tint);
  border: 1px solid var(--brand);
  border-radius: 10px;
}

/*
 * A medicine is one line until somebody asks to change it.
 *
 * It used to be an open pair of inputs plus a sentence underneath repeating
 * what they held: the same information twice, and four times the height. A
 * patient listing eleven medicines scrolled past eleven forms they were not
 * filling in. Reported on a handset.
 *
 * The dose and the control sit on one row, the control pushed to the end so
 * the reading order is what it says before how to change it.
 */
/*
 * What the medicine says about itself, directly under its name.
 *
 * It used to sit two lines lower with a control in between, so six medicines
 * read as eighteen unrelated lines. Name and dose are one sentence — "Warfarin,
 * 5 mg, once daily, by mouth" is how a person says it aloud — and the controls
 * belong at the bottom with each other rather than wedged into the middle.
 * Reported on a handset.
 */
.pt-med-line {
  margin: 2px 0 0;
  font-size: 15px;
  color: var(--ink-3);
}
.pt-med-line-detail { min-width: 0; }

/* Change and Remove together: both are things you can do to this row. */
.pt-med-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 8px 0 0;
}
.pt-med-actions form { margin: 0; }

/* The search box and its button on one line, so the page has exactly one
   full-width primary button and it is the one that moves forward. */
/*
 * The photograph control, and the tick beside each thing read off a label.
 *
 * A checkbox on a phone is a 13px target unless it is told otherwise, and this
 * one is the human confirmation the whole OCR path rests on — somebody
 * mis-tapping it either adds a medicine they do not take or misses one they
 * do. So the label is the target, the box is enlarged, and there is room
 * around it.
 */
.pt-photo { margin: 22px 0 0; }
.pt-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 6px 0;
  cursor: pointer;
}
.pt-check input[type='checkbox'] {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin: 1px 0 0;
  accent-color: var(--brand);
}

.pt-search-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.pt-search-row .pt-input { flex: 1 1 auto; min-width: 0; }
.pt-search-row .pt-btn-inline { flex: 0 0 auto; align-self: stretch; }

/*
 * Date of birth, as three fields rather than one.
 *
 * Month, day and year in that order and labelled, because a native date input
 * lays its segments out by the browser's locale and says nothing about which
 * order it chose. Year is given twice the width so four digits fit without
 * scrolling inside the box — the failure this whole control exists to prevent
 * is somebody entering a two-digit year and being told it does not match.
 */
.pt-dob {
  display: grid;
  grid-template-columns: 1fr 1fr 1.5fr;
  gap: 10px;
  align-items: end;
}
/*
 * Grid children default to min-width:auto, and a text input carries an
 * intrinsic width of about twenty characters — so without this the three
 * columns refuse to shrink and the year runs off the side of the card.
 */
.pt-dob > div { min-width: 0; }
.pt-dob-label {
  display: block;
  margin-bottom: 4px;
  font-size: 14px;
  color: var(--ink-3);
}
.pt-dob .pt-input {
  width: 100%;
  /* The div may shrink and the input must shrink with it, or it overflows its
     own cell and the three boxes overlap. */
  min-width: 0;
  padding-left: 6px;
  padding-right: 6px;
  text-align: center;
  /* Tabular figures so 11 and 19 do not sit at different widths in the box. */
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* One clinician-recorded item on the case dashboard. */
.clin-item { padding: 10px 0; border-top: 1px solid var(--line); }
.clin-item:first-child { border-top: 0; padding-top: 0; }
.clin-item .name { font-weight: 600; }
.clin-item .inline-form { margin-top: 8px; }
.clin-item input[type="text"] {
  padding: 7px 9px;
  font: inherit;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
}

/* Agree and disagree, side by side and the same size. A control that makes
   accepting easier than refusing is a thumb on the scale of a clinical answer. */
.proposal-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.proposal-actions .inline-form { margin: 0; }

/* How long a request has waited, standing where its scheduled date would.
   Quieter than a date, because it is context for triage rather than a
   commitment somebody has made. */
.waiting-since { color: var(--ink-3); font-style: italic; }

/*
 * Several boxes that are one measurement.
 *
 * Feet and inches are not two facts a reader should have to assemble — they are
 * one height, and three separate full-width fields down a form read as three
 * unrelated questions. The tray holds them together: the boxes sit inside it
 * with their units beside them, and the border belongs to the group rather than
 * to each box.
 */
.compound {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  /* The field around it is a stretching column, which pulled the tray to the
     full width of the label and left the units marooned at the far edge. It
     should be as wide as what is in it and no wider. */
  width: fit-content;
  align-self: flex-start;
}
/* The boxes lose their own chrome — the tray is the control now. */
.compound input {
  border: 0;
  background: none;
  padding: 3px 2px;
  /* Every input on the form has a 150px floor so fields line up in a row. A
     two-digit box is the one place that is wrong, and the floor beats a width
     rather than losing to it — which left the tray 360px wide with its units
     marooned at the far edge. */
  min-width: 0;
  width: 2.6ch;
  text-align: center;
  font-variant-numeric: tabular-nums;
  border-radius: 3px;
}
/* Wide enough for three digits of pounds without looking like a text field. */
.compound input[maxlength="3"] { width: 3.6ch; }
.compound input:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.compound .unit { font-size: 12px; color: var(--ink-3); }
.compound .unit + input { margin-left: 4px; }

/*
 * What has been picked, as a list (0042).
 *
 * A row is a code, its descriptor, and a way to remove it. Nothing here is a
 * text box: both halves are the library's, and a field somebody can edit is a
 * field whose contents can stop matching the code beside them. The side is the
 * one control, because it is the one fact that is not the library's.
 */
/*
 * Air above each lookup. Two of them sit in one card with a list of picked rows
 * between, and without this the second label crowds the box above it and reads
 * as part of it rather than as the start of something new.
 */
.code-picker { margin-top: 20px; }
.card .body > .code-picker:first-child { margin-top: 0; }

.picked { margin: 8px 0 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.picked-row {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px; border-bottom: 1px solid var(--line);
}
.picked-row:last-child { border-bottom: 0; }
.picked-what { display: flex; align-items: baseline; gap: 10px; flex: 1 1 auto; min-width: 0; }
.picked-side { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.picked-side select { width: auto; }
.picked-row .btn { flex: 0 0 auto; }
.btn.quiet {
  background: none; border: 1px solid var(--line-strong); color: var(--ink-2);
}
.btn.quiet:hover { background: var(--surface-2); color: var(--ink); }
/* Stacked procedures on a detail screen. */
.stacked { margin-top: 6px; }

/* The code picker on the request form — a search box with its button beside it
   and the results as a tappable list. Used twice: CPT and ICD-10. Named for
   what it is rather than for the first thing that used it, because it now
   drives two libraries and a class called cpt- driving ICD-10 is the kind of
   drift this codebase spends its comments avoiding. */
.code-search-row { display: flex; gap: 8px; align-items: stretch; }
.code-search-row input { flex: 1 1 auto; min-width: 0; }
.code-search-row .btn { flex: 0 0 auto; }

/*
 * The results list, whether the type-ahead built it or the server rendered it.
 * Capped and scrollable: fifteen procedures is a list, not a page, and a
 * dropdown that pushes the rest of a long form down the screen is worse than
 * one that scrolls inside itself.
 */
.code-results {
  margin: 6px 0 14px;
  max-height: 17rem;
  overflow-y: auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow);
}

/*
 * Anchoring the results to the box that produced them.
 *
 * Capping the height was not enough: the list still sat in the flow, so every
 * field under it — the procedure description, the side, the code — moved down
 * the screen the moment anybody typed, and moved back when they picked. The
 * section the office is reading should not reflow because a lookup answered.
 *
 * **Only when the type-ahead is running**, which is what --live marks. The
 * script sets it, the same way it hides the Search button, and the no-script
 * path never gets it: a panel floating over the fields with nothing able to
 * dismiss it would cover them permanently, and the server-rendered list is
 * dismissed by the next submit. In the flow it is honest there and an overlay
 * here, for the same reason each way.
 */
.code-lookup { position: relative; }
.code-lookup--live .code-results {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin: 6px 0 0;
  box-shadow: var(--shadow-lg);
}
.code-results li { border-top: 1px solid var(--line); }
.code-results li:first-child { border-top: 0; }
.code-none { padding: 10px 12px; color: var(--ink-3); font-size: 13px; }

/* Full-width rows: the whole row is the target, not just the code. */
.code-option {
  display: flex;
  gap: 10px;
  align-items: baseline;
  width: 100%;
  /* The code was sitting against the list's own border on the left. */
  padding: 9px 14px;
  font: inherit;
  text-align: left;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
}
.code-option:hover,
.code-option.active { background: var(--brand-tint); }
.code-option-code {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--brand-deep);
}
/*
 * The trailing note on a row: credentials, on the staff picker.
 *
 * Muted and pushed to the end rather than set beside the name, because it
 * disambiguates two people with the same surname and is noise the rest of the
 * time. Nothing in the code libraries uses it.
 */
.code-option-note {
  margin-left: auto;
  flex: 0 0 auto;
  color: var(--ink-3);
  font-size: 13px;
}

/*
 * The staff picker: a search that sets a field, on the tasks panel.
 *
 * Narrower than the code pickers by circumstance rather than by rule — it sits
 * in a row beside the due date inside a panel, where they have a whole form
 * width to themselves.
 */
/*
 * Flexible, not fixed.
 *
 * A min-width floor here was the first attempt and it pushed the Add task
 * button onto its own line on a narrow case column: the name field would not
 * shrink, so the row ran out of space and wrapped. The field absorbs slack when
 * there is room and gives it back when there is not, which is what the select
 * it replaced did by being content-sized.
 */
.staff-picker { display: block; min-width: 0; }
.tasks-compose .row > .field { flex: 1 1 150px; min-width: 0; }
.tasks-compose .row > .btn { flex: 0 0 auto; }
.staff-picker .code-results { max-height: 220px; overflow-y: auto; }

/*
 * Who the task is addressed to, once somebody is chosen.
 *
 * **One line, the same height as the box it replaces**, which is the whole
 * point. This started as a second line under the search and made the field two
 * rows tall inside a flex row whose other fields are one — so the due date and
 * the button fell out of alignment beside it, which is how it was reported.
 *
 * Sized against the input rather than the text: matching padding and border
 * width so that swapping one for the other does not move anything around it.
 */
.code-chosen {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: space-between;
  /*
   * The same box metrics as an input, so swapping one for the other does not
   * move anything: 13px text, 7px/9px padding, a 1px border and the shared
   * radius. Picking somebody nudged the field 4px taller before this matched,
   * which is small and is exactly the sort of jump that reads as the layout
   * being unstable.
   */
  font-size: 13px;
  padding: 7px 9px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--brand-tint);
}
.code-chosen-name {
  color: var(--ink);
  font-size: 13px;
  font-weight: 550;
  /* A long name shortens rather than widening the field it sits in. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/*
 * A quiet link rather than a button, because it undoes a choice rather than
 * doing anything — and a second solid control beside "Add task" reads as a
 * second way to submit.
 */
.code-chosen-clear {
  flex: 0 0 auto;
  padding: 0;
  font: inherit;
  font-size: 12px;
  color: var(--ink-3);
  background: none;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
}
.code-chosen-clear:hover { color: var(--ink); }

/*
 * The panel, for when somebody hits Enter on a half-typed term.
 *
 * The overlay above is right for the common case: type three letters, the
 * answer is the first row, pick it. Enter means something different — it is
 * what a person does when they have typed what they know and want to read
 * what came back. Fifteen descriptors at dropdown density is a cramped scroll
 * inside a 17rem window; the same fifteen with room to breathe is a list you
 * read once.
 *
 * A native dialog rather than a hand-built overlay, because showModal() brings
 * the backdrop, the focus trap, the Escape key and the inert background with
 * it, and every one of those hand-rolled is a way to strand somebody inside a
 * box they cannot leave. It is created by the script, so it does not exist at
 * all on the no-script path — where Enter never reaches this anyway.
 */
.code-panel {
  width: min(640px, calc(100vw - 32px));
  max-height: min(70vh, 560px);
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  background: var(--surface);
  color: var(--ink);
  overflow: hidden;
}
.code-panel[open] { display: flex; flex-direction: column; }
.code-panel::backdrop { background: rgba(16, 24, 40, 0.38); }

.code-panel-head {
  display: flex; align-items: baseline; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line);
}
.code-panel-head h2 { margin: 0; font-size: 14px; font-weight: 650; }
.code-panel-head .code-panel-term { font-size: 12.5px; color: var(--ink-3); min-width: 0; overflow-wrap: anywhere; }
.code-panel-close {
  margin-left: auto; flex: 0 0 auto;
  background: none; border: 0; padding: 4px 8px;
  font: inherit; font-size: 13px; color: var(--ink-3);
  border-radius: var(--radius-sm); cursor: pointer;
}
.code-panel-close:hover { background: var(--surface-2); color: var(--ink); }

/* The list fills the panel and scrolls inside it: the chrome above and below
   must stay put, or the close button leaves with the scroll. */
.code-panel-list {
  flex: 1 1 auto;
  margin: 0;
  max-height: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
/* Room to read, which is the entire reason this is not the dropdown. */
.code-panel-list .code-option { padding: 13px 16px; }
.code-panel-list .code-none { padding: 14px 16px; }

.code-panel-foot {
  flex: 0 0 auto;
  padding: 9px 16px; border-top: 1px solid var(--line);
  font-size: 12px; color: var(--ink-3);
}

/* What was chosen, said out loud — the code lands in a field further up, and a
   list disappearing is not evidence that anything was recorded. */

/* A code the library does not hold. Said plainly, not in red: it is allowed —
   a code the library has not caught up with must still be enterable — but it
   leaves the procedure crosswalk with nothing to match, and that is worth
   seeing while somebody is still looking at the field. */
.sub.warn { color: var(--waiting); }
/* How long there is, on an attention card. Quiet until it is not. */
.countdown { margin: 6px 0 0; font-size: 12px; color: var(--ink-3); }
.countdown.warn { color: var(--waiting); font-weight: 600; }

/*
 * Merging two patient records.
 *
 * Each candidate offers both directions, so the row has to hold a pair of
 * buttons without them reading as one control with an accident in it. They sit
 * at the end, apart from the name.
 */
.merge-current { margin: 14px 0; }
.merge-results { margin-top: 14px; }
.merge-results li { border-top: 1px solid var(--line); padding: 10px 0; }
.merge-results li:first-child { border-top: 0; }
.merge-candidate {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}
.merge-actions { display: flex; gap: 8px; flex: 0 0 auto; }

/*
 * Administering the rooms at a site.
 *
 * A room that is not active is dimmed rather than hidden: the person on this
 * screen is the one who has to be able to put it back, so it has to stay
 * readable while clearly not being in the running.
 */
/*
 * A room is one line of controls, not a stack of forms.
 *
 * This was three forms with three buttons — status, equipment, delete — which
 * made every room about four inches tall for six controls holding almost no
 * data. Status, reason, the equipment checks and Save now sit on one wrapping
 * row, and everything on it is denser.
 */
.rooms li { border-top: 1px solid var(--line); padding: 10px 0; }
.rooms li:first-child { border-top: 0; }
.room-inactive { opacity: 0.72; }
.room-head { display: flex; gap: 8px; align-items: baseline; }
.room-equipment { margin: 2px 0 6px; }

.room-controls {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.room-controls select.compact { flex: 0 0 auto; }
/* The reason takes the slack, since it is the only free text on the row. */
.room-controls input[name='reason'] { flex: 1 1 180px; min-width: 0; }

/*
 * A grant is one line and, before it starts, one folded editor.
 *
 * The same shape a room takes, for the same reason: a facility screen is a
 * list somebody scans for the one row they came to change, not a stack of
 * forms. An ended grant stays on the list, dimmed — a list that hid them would
 * have no answer to "why did this group's Tuesday stop".
 */
.blocks li { border-top: 1px solid var(--line); padding: 10px 0; }
.blocks li:first-child { border-top: 0; }
.block-ended { opacity: 0.6; }
.block-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.block-dates { margin: 2px 0 6px; }

.block-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  flex-wrap: wrap;
}
/* The last-day box is a date and never needs the width a field gets by default. */
.block-form .field.narrow { max-width: 170px; }

.block-add summary, .block-edit summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--brand-deep);
  padding: 6px 0;
}
.block-edit { margin-top: 4px; }

/* The upload form, folded away until somebody wants it. Same shape as the
   block-time editors: a facility screen is a list somebody scans, not a stack
   of forms. */
.waiting > li { padding: 12px 0; border-bottom: 1px solid var(--line); }
.waiting > li:last-child { border-bottom: none; }
.waiting-head { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.waiting-form { display: flex; gap: 8px; align-items: flex-end; flex-wrap: wrap; margin-top: 6px; }
.waiting-form .field { flex: 1 1 260px; }

.doc-upload { margin-top: 12px; }
.doc-upload summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--brand-deep);
  padding: 6px 0;
}
.doc-upload input[type='file'] { font-size: 12px; padding: 6px 0; }

.room-equipment-picks { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.room-equipment-item {
  display: flex;
  gap: 5px;
  align-items: center;
  font-size: 12.5px;
  color: var(--ink-2);
  white-space: nowrap;
}
.room-equipment-item input[type='checkbox'] { min-width: 0; margin: 0; }

.room-delete { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
.room-add { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 12px; }
.room-add input[type='text'] { flex: 1 1 200px; min-width: 0; }
.room-add input.order { flex: 0 0 64px; min-width: 0; width: 64px; }

/*
 * Denser controls, for screens where the values are short and the count is
 * high. Not a global change: the case and request forms are read carefully once
 * and earn their size.
 */
.compact { font-size: 12.5px; padding: 4px 7px; min-width: 0; }
select.compact { padding-right: 22px; }
.btn.compact { padding: 4px 10px; font-size: 12.5px; }

/* The catalogue: a name, what it is, and the way out. */
.catalogue li {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--line);
  padding: 10px 0;
}
.catalogue li:first-child { border-top: 0; }

/*
 * Block time. A released block is the one worth spotting on the page — it is
 * time somebody else can have — so it is tinted rather than merely labelled.
 */
.blocks li { border-top: 1px solid var(--line); padding: 10px 0; }
.blocks li:first-child { border-top: 0; }
.block-released { background: var(--brand-tint); }
.block-head { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }

/*
 * The schedule grid: hours down the side, days across, blocks spanning the
 * hours they cover.
 *
 * CSS grid and no script. A block sits at grid-row start / end, which is the
 * same arithmetic a dragging calendar does — done by the browser instead of by
 * a layout engine somebody has to write and keep correct across timezones.
 *
 * It scrolls sideways rather than compressing. A fortnight of columns squeezed
 * to fit is unreadable, and a schedule nobody can read is worse than one they
 * have to scroll.
 */
/*
 * A whole day is twenty-four rows tall, so the grid scrolls in both directions
 * inside its own box rather than making the page two screens long.
 *
 * The height is the window's, not a number. It was a flat 560px, which on a
 * tall screen cut the day off at two in the afternoon and left a third of the
 * page empty underneath — the box was short while the room to draw it was
 * there. 300px is what sits above the grid on this page, measured off the
 * rendered layout rather than guessed: 277px of shell, controls and heading,
 * plus the page's own bottom padding.
 *
 * A max rather than a height, so it still shrinks to its content — a week with
 * one block in it does not need to be a window tall — and a min so a short
 * window keeps a usable grid and scrolls the page instead.
 */
.cal-scroll { max-height: calc(100vh - 340px); min-height: 280px; overflow: auto; }
.cal { display: grid; min-width: 100%; position: relative; }
.cal-corner { grid-column: 1; grid-row: 1; border-bottom: 1px solid var(--line); }
.cal-day {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  border-bottom: 1px solid var(--line);
  border-left: 1px solid var(--line);
}
.cal-hour {
  font-size: 11px;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  /* Sat against the line it names, not centred in the band below it. */
  transform: translateY(-6px);
  text-align: right;
  padding-right: 8px;
}
.cal-slot { border-top: 1px solid var(--line); border-left: 1px solid var(--line); }

/*
 * The block itself, drawn over the slots it covers.
 *
 * z-index because it shares its cells with the empty slots underneath, which
 * are what give the grid its ruled lines.
 */
.cal-block {
  position: relative;
  z-index: 1;
  margin: 1px 3px;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  overflow: hidden;
  font-size: 12px;
}
.cal-block details { height: 100%; }
.cal-block summary {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 7px;
  cursor: pointer;
  list-style: none;
}
.cal-block summary::-webkit-details-marker { display: none; }
.cal-block details[open] summary { border-bottom: 1px solid var(--line); }
.cal-block details > *:not(summary) { padding: 6px 7px; }
.cal-when { color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cal-who { color: var(--ink-2); }
.cal-status { color: var(--ink-3); text-transform: lowercase; }

/* Status reads off the left edge, so a glance down a day tells you what is
   ordinary and what is going spare. */
.cal-allocated { border-left: 3px solid var(--brand-deep); }

/*
 * The day board.
 *
 * A block becomes a *band* rather than a card: on a day the column already
 * says which room it is, and what matters is the cases drawn on top of it. So
 * it drops behind them, loses its fill, and keeps only its coloured edge and
 * its actions.
 */
.cal-band { z-index: 0; background: var(--surface-3); opacity: 0.85; }
.cal-band summary { padding: 3px 6px; }

/*
 * A booked case (access-control.md §8).
 *
 * Sits above the band and inside a lane. What it says to a reader who cannot
 * open it is "Booked", a window and a group — no patient, no procedure, no case
 * reference. The number is withheld in SQL, not here.
 */
/*
 * A month: seven columns of squares, one per day, each a link into the day.
 *
 * No hour grid, so none of the row machinery above applies. Nothing in a
 * square is placed or sized with an inline style -- the CSP forbids it, and
 * this calendar rendered one stacked column the last time something tried.
 * Widths snap to tenths and colours are palette classes instead.
 */
.cal-month-wrap { display: flex; flex-direction: column; gap: 10px; }

.cal-month-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px;
  font-size: 12px; color: var(--ink-2);
}
.cal-month-key { display: inline-flex; align-items: center; gap: 6px; }
.cal-month-swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  background: var(--mc);
}
.cal-month-keyline {
  display: inline-block; width: 30px; height: 4px; border-radius: 2px;
  background: #2C6E57;
}

.cal-month {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.cal-month-head {
  padding: 7px 8px;
  background: var(--surface-2, #F4F6F9);
  font-size: 11.5px; font-weight: 650; letter-spacing: 0.02em;
  color: var(--ink-3); text-transform: uppercase;
}
.cal-month-day {
  position: relative;
  display: flex; flex-direction: column; gap: 5px;
  min-height: 104px;
  padding: 7px 8px 14px;
  background: var(--surface);
  color: var(--ink);
}
.cal-month-day:hover { background: rgba(37, 99, 235, 0.05); text-decoration: none; }
.cal-month-day.cal-weekend { background: var(--surface-2, #F7F8FA); }
.cal-month-day.cal-month-outside { color: var(--ink-3); opacity: 0.5; }
.cal-month-day.cal-today { box-shadow: inset 0 0 0 2px var(--brand-deep); }

/* Row one: the date, and the one thing a scheduler is hunting for. */
.cal-month-top { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.cal-month-date {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 13px; font-weight: 650;
}
.cal-month-today {
  font-size: 10px; font-weight: 650; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--brand-deep);
}
/* Red, and nowhere else on the square is red except an over-full day. */
.cal-month-flag {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 7px 1px 6px;
  font-size: 11px; font-weight: 700; line-height: 1.5;
  color: #fff; background: #C8372D; border-radius: 999px;
  white-space: nowrap;
}

.cal-month-count { font-size: 12px; color: var(--ink-2); }
.cal-month-count b { color: var(--ink); font-weight: 650; }

/* One bar per group holding the day. The legend says which colour is whom. */
.cal-month-groups { display: flex; gap: 3px; }
.cal-month-bar {
  flex: 1 1 0; height: 6px; min-width: 10px;
  border-radius: 3px;
  background: var(--mc);
}
/* Released: the same colour, hatched, so it still says whose time it was. */
.cal-month-bar.cal-month-released {
  background: repeating-linear-gradient(45deg, var(--mc) 0 3px, transparent 3px 6px);
  box-shadow: inset 0 0 0 1px var(--mc);
}
.cal-month-bar.cal-lit { outline: 2px solid var(--ink); outline-offset: 1px; }

/* Bookable time: the most actionable fact on the screen, so the only green. */
.cal-month-open {
  align-self: flex-start;
  padding: 1px 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
  color: #1F7A4D; background: #E3F4EA;
  border-radius: 4px;
}

/* Along the bottom edge: booked hours against the block time held. */
.cal-month-load {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 4px; background: #EEF0F3;
}
.cal-month-load i { display: block; height: 100%; background: #2C6E57; }
.cal-month-load.cal-month-hot i { background: #C8372D; }
.cal-load-0 i { width: 0; }
.cal-load-1 i { width: 10%; }
.cal-load-2 i { width: 20%; }
.cal-load-3 i { width: 30%; }
.cal-load-4 i { width: 40%; }
.cal-load-5 i { width: 50%; }
.cal-load-6 i { width: 60%; }
.cal-load-7 i { width: 70%; }
.cal-load-8 i { width: 80%; }
.cal-load-9 i { width: 90%; }
.cal-load-10 i { width: 100%; }

/*
 * Eight group colours, chosen to stay apart from each other and from the
 * flag's red and the OPEN tag's green, so no bar can be mistaken for either.
 */
.cal-g0 { --mc: #2F6FDB; }
.cal-g1 { --mc: #C2792B; }
.cal-g2 { --mc: #7A5AC7; }
.cal-g3 { --mc: #178A9C; }
.cal-g4 { --mc: #B8488F; }
.cal-g5 { --mc: #5E7388; }
.cal-g6 { --mc: #A38A1F; }
.cal-g7 { --mc: #3E4FA8; }

@media (max-width: 760px) {
  .cal-month-day { min-height: 64px; padding: 5px 5px 9px; }
  /* A phone keeps the shapes and drops the words; the day board has them. */
  .cal-month-count, .cal-month-open { display: none; }
  .cal-month-head { padding: 5px; font-size: 10px; }
  .cal-month-flag { padding: 0 5px; font-size: 10px; }
}

.cal-case {
  position: relative;
  z-index: 2;
  border-radius: 5px;
  border: 1px solid var(--brand-deep);
  border-left: 3px solid var(--brand-deep);
  background: var(--brand-tint);
  overflow: hidden;
  font-size: 11px;
  box-sizing: border-box;
}
.cal-case a,
.cal-case > span {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 4px 6px;
  color: var(--ink);
}
.cal-case a:hover { text-decoration: none; background: var(--surface); }
/*
 * A bar sharing its column with others.
 *
 * Smaller, tighter, and clipped rather than wrapped: four theatres working at
 * ten o'clock is four bars in one day column, and a wrapped label in a quarter
 * of a column is a stack of broken words. The whole label is on the title
 * attribute, which is where a hover finds it.
 */
.cal-case.cal-tight { font-size: 10.5px; }
.cal-case.cal-tight a,
.cal-case.cal-tight > span { padding: 3px 4px; gap: 0; }
.cal-case strong,
.cal-case .cal-when,
.cal-case .cal-room,
.cal-case .cal-who {
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/*
 * Theatre tabs, and the surgeon filter beside them.
 *
 * Tabs because a dozen theatres with surgeons rotating through them is
 * unreadable as one grid: the first answers "what is happening this week", the
 * rest answer "what is happening in this room".
 */
.cal-tabs-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.cal-tabs { display: inline-flex; gap: 2px; flex-wrap: wrap; }
.cal-tabs a {
  padding: 6px 12px; font-size: 12.5px; font-weight: 600;
  color: var(--ink-2); border: 1px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.cal-tabs a:hover { background: var(--surface-2); text-decoration: none; }
.cal-tabs a.on {
  color: var(--brand-deep); background: var(--brand-tint);
  border-color: var(--line);
}
.cal-surgeon { display: inline-flex; gap: 6px; margin-left: auto; }

/*
 * The anaesthetist's own list.
 *
 * Sits with the surgeon filter at the right-hand end rather than beside the
 * tabs: the tabs say what the board is of, and these two say whose. When both
 * are drawn the pair travels together, so cal-mine takes the auto margin and
 * hands it off — otherwise a reader with only one of them would find their
 * control on the opposite side of the strip from where a colleague has it.
 *
 * Lit the way every other on state on this screen is lit.
 */
/*
 * Take this list, in a day board's column heading.
 *
 * The heading is a room name and now a verb, so the button is quiet and sits
 * under the name rather than beside it — a column is narrow, and a control on
 * the same line pushes the name it belongs to out of the way.
 */
/* Stacked, like the week's heading: the room is what the column is, and the
   control is a second line under it rather than a competitor beside it. */
.cal-room-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  width: 100%;
}
.cal-take { display: block; }
.cal-take .btn { font-size: 11px; padding: 2px 7px; font-weight: 600; }

/* The rota picker on the anaesthesia card. */
.inline-form.rota { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }

.cal-mine { margin-left: auto; }
.cal-mine + .cal-surgeon { margin-left: 0; }
.cal-mine.on {
  background: var(--brand-tint); color: var(--brand-deep);
  border-color: var(--brand);
}

/* The theatre, on a case box, when the columns are days and cannot say it. */
.cal-room { color: var(--ink-2); font-weight: 600; }

/*
 * Block time belonging to the surgeon who is filtered for.
 *
 * The pair that answers "where is she this week, and where could she be": her
 * cases isolated, and her group's sessions lit under them. Loud on purpose — it
 * answers a question somebody just asked, rather than sitting in the background.
 */
.cal-block.cal-lit,
.cal-unplaced-item.cal-lit {
  background: var(--brand-tint); opacity: 1;
  border-color: var(--brand-deep); border-left-width: 4px;
}

/*
 * The week: rooms down, days across.
 *
 * A table rather than a grid, and that is the point. Overlap is impossible by
 * construction — a room on a day is one cell — where the hour grid it replaced
 * needed lane arithmetic to avoid drawing two blocks on top of each other, and
 * did not have it.
 */
table.cal-week { width: 100%; border-collapse: collapse; }
table.cal-week th,
table.cal-week td {
  border: 1px solid var(--line);
  padding: 7px 9px;
  vertical-align: top;
  text-align: left;
  min-width: 148px;
}
table.cal-week thead th { padding: 0; background: var(--surface); }
/*
 * The heading is a link and a two-line one — weekday over date.
 *
 * .cal-day .cal-open only reaches the day grid, so in the table the two spans
 * sat inline and rendered "MON08/31/2026" as one word.
 */
table.cal-week thead th .cal-open {
  display: flex; flex-direction: column; gap: 1px;
  padding: 7px 9px; color: inherit;
}
table.cal-week thead th .cal-open:hover { background: var(--brand-tint); text-decoration: none; }
table.cal-week thead th.cal-week-room { padding: 7px 9px; }
/* The room column stays put while the week scrolls sideways. */
th.cal-week-room {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface);
  font-size: 12px; font-weight: 600; color: var(--ink-2);
  min-width: 96px; white-space: nowrap;
}
table.cal-week td.cal-weekend, table.cal-week th.cal-weekend { background: var(--surface-3); }

/* One block in a cell: its hours, whose it is, and its state if not the usual. */
.cal-wk-block {
  display: flex; flex-direction: column; gap: 1px;
  border-left: 3px solid var(--brand-deep);
  padding: 2px 0 2px 7px; margin-bottom: 5px;
  font-size: 12px;
}
.cal-wk-block.cal-release-requested, .cal-wk-block.cal-released {
  border-left-color: var(--waiting);
}
.cal-wk-block.cal-claimed { border-left-color: var(--clear); }

/*
 * What is booked in that room that day — the half the week never showed.
 *
 * One line per operation rather than a count. "1 booked" was true and useless:
 * somebody looking for a case they knew existed could not find it and reported
 * the schedule as not matching the worklist.
 */
.cal-wk-booked { display: block; font-size: 12px; color: var(--ink); }
.cal-wk-booked:hover { text-decoration: none; background: var(--brand-tint); }
.cal-wk-item { display: flex; gap: 6px; padding: 1px 0; align-items: baseline; }
.cal-wk-at { font-variant-numeric: tabular-nums; color: var(--ink-3); flex: 0 0 auto; }
.cal-wk-what { font-weight: 600; color: var(--brand-deep); min-width: 0; }
/* One line, clipped. A group name is three words and a cell is 148px; letting
   it wrap took the whole row's height with it. */
.cal-wk-what .sub {
  display: block; font-weight: 400;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* How full a day is, on the week's column heading. */
.cal-count { font-size: 10px; font-weight: 500; line-height: 1.1; color: var(--brand-deep); }

/*
 * The column heading of a week is a link to that day.
 *
 * The whole heading, not the count inside it: an empty day is exactly the one
 * somebody wants to open and fill, and it has no count to click.
 */
.cal-day .cal-open {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  width: 100%;
  padding: 3px 2px;
  line-height: 1.15;
  color: inherit;
  border-radius: var(--radius-sm);
}
.cal-day .cal-open:hover { background: var(--brand-tint); text-decoration: none; }
.cal-dow { font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase; }

/* Today's column, on a week. */
.cal-day.cal-today { color: var(--brand-deep); }
.cal-day.cal-today .cal-dow { font-weight: 700; }

/*
 * The heading row: what this screen is of, and which unit it is in.
 *
 * The date used to be small grey text at the right-hand end of the controls,
 * which is where a detail goes. On a day board it is the subject.
 */
.cal-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.cal-title { display: flex; flex-direction: column; gap: 2px; }
.cal-title h2 { margin: 0; font-size: 20px; line-height: 1.2; }
.cal-head .cal-modes { margin-left: auto; }

/* The controls row: paging, then site and date. */
.cal-controls { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.cal-controls form { margin: 0; }
.cal-nav, .cal-modes { display: inline-flex; gap: 4px; }
/*
 * The paging arrows get a real target rather than a glyph's worth.
 *
 * 36×32 is comfortably past the ~24px that stops being a reliable press with a
 * trackpad, and it is the control on this screen that gets used most — a week
 * at a time to reach anything more than a fortnight out.
 */
.cal-nav .btn { min-width: 36px; min-height: 32px; }
.cal-nav .cal-step { font-size: 17px; line-height: 1; padding-bottom: 3px; }
.cal-pick { display: inline-flex; gap: 6px; align-items: center; margin-left: auto; }

/*
 * The hour labels and the column headings have to survive that scroll, or a
 * bar in the afternoon is a rectangle with no idea what time or room it is in.
 */
.cal-day { position: sticky; top: 0; z-index: 3; background: var(--surface); }
.cal-corner { position: sticky; top: 0; left: 0; z-index: 4; background: var(--surface); }
.cal-hour { position: sticky; left: 0; z-index: 3; background: var(--surface); }
.cal-hour-top { transform: none; }
/*
 * Saturday and Sunday: present, and visibly not a working day.
 *
 * --ink-3 rather than --ink-2, which is the whole point — the first draft of
 * this reached for a --muted that does not exist in this palette, so the
 * declaration fell back to the inherited --ink and rendered the weekend
 * *darker* than the weekdays. Exactly backwards, and invisible in a diff:
 * an undefined custom property is not an error, it is an empty value.
 *
 * --surface-3 on the slots for the same reason: --surface-2 is #FBFCFD against
 * a #FFF card, which is a difference you can measure and not one you can see.
 */
.cal-day.cal-weekend { color: var(--ink-3); font-weight: 500; }
.cal-slot.cal-weekend { background: var(--surface-3); }
.cal-release-requested { border-left: 3px solid var(--waiting); background: var(--surface-2); }
.cal-released { border-left: 3px solid var(--waiting); background: var(--brand-tint); }
.cal-claimed { border-left: 3px solid var(--clear); background: var(--surface-2); }
.cal-block form { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.cal-block form input[type='text'] { flex: 1 1 120px; min-width: 0; }

/*
 * Acting as somebody else. Deliberately not in the product's own palette — this
 * is a state you should notice you are in from across a room, and it is the
 * only banner here that is allowed to shout.
 */
.acting-as {
  display: flex;
  gap: 10px;
  align-items: baseline;
  flex-wrap: wrap;
  padding: 8px 20px;
  background: #4B2E83;
  color: #fff;
  font-size: 12.5px;
}
.acting-as strong { color: #fff; }
.acting-as .link { color: #fff; text-decoration: underline; }
/*
 * The demo switcher, in a sidebar that is narrower than its two controls.
 *
 * It was a flex row, so the select and the button competed for a rail about
 * 200px wide and the button wrapped onto its own line half off the edge.
 * Stacked instead: the select takes the full width and the button sits under
 * it. A control that is only present on a demo deployment does not deserve a
 * fight with the layout.
 *
 * min-width: 0 on the select because a select's default minimum is its
 * longest option, and "Dr. Margit Halvorsen · anesthesia director" is wider
 * than the sidebar.
 */
.switcher { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.switcher .field { min-width: 0; font-size: 10.5px; }
.switcher select { width: 100%; min-width: 0; }
.switcher .btn { width: 100%; }

/*
 * The staff screens on a phone.
 *
 * The sidebar was a fixed column 220 pixels wide at every size, so on a 375px
 * handset it took more than half the screen and crushed every page into a
 * strip down the right — the schedule, the worklist, a case. The patient pages
 * were built for a phone from the start; these never were, and it showed the
 * first time anybody looked (2026-09-17).
 *
 * **Below 760px the sidebar becomes a strip across the top that scrolls
 * sideways.** Every destination stays one tap away, the page underneath gets
 * the full width, and it needs no script: a menu that opens and closes would
 * need JavaScript on a surface that has deliberately none, and the CSP would
 * ignore an inline handler without a word.
 *
 * Section headings go, because a strip has no room for "PRE-ADMISSION" and the
 * items read fine without it. The collapse control goes too — collapsing is a
 * desktop rail, and on a phone the strip is already as small as it gets. And a
 * rail somebody collapsed on their desk must not follow them onto the phone as
 * a row of dots, so the collapsed rules are undone here.
 *
 * Last in the file on purpose: rules after this one would otherwise win.
 */
@media (max-width: 760px) {
  .shell { flex-direction: column; }

  .sidebar,
  .shell.nav-collapsed .sidebar {
    width: auto; flex: none; height: auto;
    position: sticky; top: 0; z-index: 20;
    flex-direction: row; align-items: center;
    gap: 4px;
    padding: 6px 10px;
    border-right: 0; border-bottom: 1px solid var(--line);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .sidebar::-webkit-scrollbar { display: none; }

  .brand, .nav-collapsed .brand { flex: none; padding: 0 6px 0 2px; justify-content: flex-start; }
  .brand img, .nav-collapsed .brand img { display: block; height: 24px; }
  .nav-toggle-form { display: none; }

  .nav-group { flex: none; flex-direction: row; gap: 2px; }
  .nav-group h6 { display: none; }

  .nav-item,
  .nav-collapsed .nav-item {
    flex: none;
    padding: 7px 10px;
    justify-content: flex-start;
    white-space: nowrap;
    font-size: 13px;
  }
  .nav-collapsed .nav-item > span:not(.dot),
  .nav-collapsed .nav-item .soon { display: inline; }
  .nav-item .dot { display: none; }
  .nav-item .soon { margin-left: 6px; }

  /* Who is signed in, reduced to their initials; signing out stays reachable. */
  .sidebar-foot { margin-top: 0; flex: none; flex-direction: row; align-items: center; gap: 4px; }
  .who, .nav-collapsed .who { padding: 0; background: none; border: 0; }
  .who span:not(.avatar), .nav-collapsed .who span:not(.avatar) { display: none; }
  .sidebar-foot form[action="/auth/logout"],
  .nav-collapsed .sidebar-foot form[action="/auth/logout"] { display: block; }
  .sidebar-foot button.link { padding: 7px 8px; white-space: nowrap; }
  .switcher { display: none; }

  /* The page underneath, which now has the whole width to itself. */
  .topbar { flex-wrap: wrap; gap: 8px 10px; padding: 12px 14px; }
  .topbar h1 { font-size: 17px; }
  .topbar .find-case { order: 3; flex: 1 1 100%; margin-right: 0; }
  .topbar .find-case input { flex: 1 1 auto; width: auto; min-width: 0; }
  .page { padding: 14px 12px 32px; }

  /*
   * The schedule's site and date pickers, which were one row that never
   * wrapped: a hospital's full name in a select, a date box and a button,
   * pushed the page ninety pixels past the edge of a phone and made the whole
   * screen scroll sideways. Measured, not guessed — the page was 464px wide in
   * a 375px viewport. They wrap now, the select taking a line of its own.
   */
  .cal-pick { flex-wrap: wrap; margin-left: 0; width: 100%; }
  .cal-pick select { flex: 1 1 100%; min-width: 0; }
  .cal-pick input { flex: 1 1 auto; min-width: 0; }

  /*
   * The OPEN tag is hidden in a phone's squares for room, so its entry in the
   * key goes too — a legend explaining a mark that is not on the screen reads
   * as the mark being missing.
   */
  .cal-month-key:has(.cal-month-open) { display: none; }
}

.cal-d1 { grid-template-columns: 56px repeat(1, minmax(150px, 1fr)); }
.cal-d2 { grid-template-columns: 56px repeat(2, minmax(150px, 1fr)); }
.cal-d3 { grid-template-columns: 56px repeat(3, minmax(150px, 1fr)); }
.cal-d4 { grid-template-columns: 56px repeat(4, minmax(150px, 1fr)); }
.cal-d5 { grid-template-columns: 56px repeat(5, minmax(150px, 1fr)); }
.cal-d6 { grid-template-columns: 56px repeat(6, minmax(150px, 1fr)); }
.cal-d7 { grid-template-columns: 56px repeat(7, minmax(150px, 1fr)); }
.cal-d8 { grid-template-columns: 56px repeat(8, minmax(150px, 1fr)); }
.cal-d9 { grid-template-columns: 56px repeat(9, minmax(150px, 1fr)); }
.cal-d10 { grid-template-columns: 56px repeat(10, minmax(150px, 1fr)); }
.cal-d11 { grid-template-columns: 56px repeat(11, minmax(150px, 1fr)); }
.cal-d12 { grid-template-columns: 56px repeat(12, minmax(150px, 1fr)); }
.cal-d13 { grid-template-columns: 56px repeat(13, minmax(150px, 1fr)); }
.cal-d14 { grid-template-columns: 56px repeat(14, minmax(150px, 1fr)); }
.cal-d15 { grid-template-columns: 56px repeat(15, minmax(150px, 1fr)); }
.cal-d16 { grid-template-columns: 56px repeat(16, minmax(150px, 1fr)); }
.cal-d17 { grid-template-columns: 56px repeat(17, minmax(150px, 1fr)); }
.cal-d18 { grid-template-columns: 56px repeat(18, minmax(150px, 1fr)); }
.cal-d19 { grid-template-columns: 56px repeat(19, minmax(150px, 1fr)); }
.cal-d20 { grid-template-columns: 56px repeat(20, minmax(150px, 1fr)); }
.cal-d21 { grid-template-columns: 56px repeat(21, minmax(150px, 1fr)); }
.cal-d22 { grid-template-columns: 56px repeat(22, minmax(150px, 1fr)); }
.cal-d23 { grid-template-columns: 56px repeat(23, minmax(150px, 1fr)); }
.cal-d24 { grid-template-columns: 56px repeat(24, minmax(150px, 1fr)); }
.cal-d25 { grid-template-columns: 56px repeat(25, minmax(150px, 1fr)); }
.cal-d26 { grid-template-columns: 56px repeat(26, minmax(150px, 1fr)); }
.cal-d27 { grid-template-columns: 56px repeat(27, minmax(150px, 1fr)); }
.cal-d28 { grid-template-columns: 56px repeat(28, minmax(150px, 1fr)); }
.cal-d29 { grid-template-columns: 56px repeat(29, minmax(150px, 1fr)); }
.cal-d30 { grid-template-columns: 56px repeat(30, minmax(150px, 1fr)); }
.cal-d31 { grid-template-columns: 56px repeat(31, minmax(150px, 1fr)); }
.cal-h1 { grid-template-rows: 50px repeat(1, 34px); }
.cal-h2 { grid-template-rows: 50px repeat(2, 34px); }
.cal-h3 { grid-template-rows: 50px repeat(3, 34px); }
.cal-h4 { grid-template-rows: 50px repeat(4, 34px); }
.cal-h5 { grid-template-rows: 50px repeat(5, 34px); }
.cal-h6 { grid-template-rows: 50px repeat(6, 34px); }
.cal-h7 { grid-template-rows: 50px repeat(7, 34px); }
.cal-h8 { grid-template-rows: 50px repeat(8, 34px); }
.cal-h9 { grid-template-rows: 50px repeat(9, 34px); }
.cal-h10 { grid-template-rows: 50px repeat(10, 34px); }
.cal-h11 { grid-template-rows: 50px repeat(11, 34px); }
.cal-h12 { grid-template-rows: 50px repeat(12, 34px); }
.cal-h13 { grid-template-rows: 50px repeat(13, 34px); }
.cal-h14 { grid-template-rows: 50px repeat(14, 34px); }
.cal-h15 { grid-template-rows: 50px repeat(15, 34px); }
.cal-h16 { grid-template-rows: 50px repeat(16, 34px); }
.cal-h17 { grid-template-rows: 50px repeat(17, 34px); }
.cal-h18 { grid-template-rows: 50px repeat(18, 34px); }
.cal-h19 { grid-template-rows: 50px repeat(19, 34px); }
.cal-h20 { grid-template-rows: 50px repeat(20, 34px); }
.cal-h21 { grid-template-rows: 50px repeat(21, 34px); }
.cal-h22 { grid-template-rows: 50px repeat(22, 34px); }
.cal-h23 { grid-template-rows: 50px repeat(23, 34px); }
.cal-h24 { grid-template-rows: 50px repeat(24, 34px); }
.cal-h25 { grid-template-rows: 50px repeat(25, 34px); }
.cal-h26 { grid-template-rows: 50px repeat(26, 34px); }
.cal-c1 { grid-column: 1; }
.cal-c2 { grid-column: 2; }
.cal-c3 { grid-column: 3; }
.cal-c4 { grid-column: 4; }
.cal-c5 { grid-column: 5; }
.cal-c6 { grid-column: 6; }
.cal-c7 { grid-column: 7; }
.cal-c8 { grid-column: 8; }
.cal-c9 { grid-column: 9; }
.cal-c10 { grid-column: 10; }
.cal-c11 { grid-column: 11; }
.cal-c12 { grid-column: 12; }
.cal-c13 { grid-column: 13; }
.cal-c14 { grid-column: 14; }
.cal-c15 { grid-column: 15; }
.cal-c16 { grid-column: 16; }
.cal-c17 { grid-column: 17; }
.cal-c18 { grid-column: 18; }
.cal-c19 { grid-column: 19; }
.cal-c20 { grid-column: 20; }
.cal-c21 { grid-column: 21; }
.cal-c22 { grid-column: 22; }
.cal-c23 { grid-column: 23; }
.cal-c24 { grid-column: 24; }
.cal-c25 { grid-column: 25; }
.cal-c26 { grid-column: 26; }
.cal-c27 { grid-column: 27; }
.cal-c28 { grid-column: 28; }
.cal-c29 { grid-column: 29; }
.cal-c30 { grid-column: 30; }
.cal-c31 { grid-column: 31; }
.cal-c32 { grid-column: 32; }
.cal-rs1 { grid-row-start: 1; }
.cal-re1 { grid-row-end: 1; }
.cal-rs2 { grid-row-start: 2; }
.cal-re2 { grid-row-end: 2; }
.cal-rs3 { grid-row-start: 3; }
.cal-re3 { grid-row-end: 3; }
.cal-rs4 { grid-row-start: 4; }
.cal-re4 { grid-row-end: 4; }
.cal-rs5 { grid-row-start: 5; }
.cal-re5 { grid-row-end: 5; }
.cal-rs6 { grid-row-start: 6; }
.cal-re6 { grid-row-end: 6; }
.cal-rs7 { grid-row-start: 7; }
.cal-re7 { grid-row-end: 7; }
.cal-rs8 { grid-row-start: 8; }
.cal-re8 { grid-row-end: 8; }
.cal-rs9 { grid-row-start: 9; }
.cal-re9 { grid-row-end: 9; }
.cal-rs10 { grid-row-start: 10; }
.cal-re10 { grid-row-end: 10; }
.cal-rs11 { grid-row-start: 11; }
.cal-re11 { grid-row-end: 11; }
.cal-rs12 { grid-row-start: 12; }
.cal-re12 { grid-row-end: 12; }
.cal-rs13 { grid-row-start: 13; }
.cal-re13 { grid-row-end: 13; }
.cal-rs14 { grid-row-start: 14; }
.cal-re14 { grid-row-end: 14; }
.cal-rs15 { grid-row-start: 15; }
.cal-re15 { grid-row-end: 15; }
.cal-rs16 { grid-row-start: 16; }
.cal-re16 { grid-row-end: 16; }
.cal-rs17 { grid-row-start: 17; }
.cal-re17 { grid-row-end: 17; }
.cal-rs18 { grid-row-start: 18; }
.cal-re18 { grid-row-end: 18; }
.cal-rs19 { grid-row-start: 19; }
.cal-re19 { grid-row-end: 19; }
.cal-rs20 { grid-row-start: 20; }
.cal-re20 { grid-row-end: 20; }
.cal-rs21 { grid-row-start: 21; }
.cal-re21 { grid-row-end: 21; }
.cal-rs22 { grid-row-start: 22; }
.cal-re22 { grid-row-end: 22; }
.cal-rs23 { grid-row-start: 23; }
.cal-re23 { grid-row-end: 23; }
.cal-rs24 { grid-row-start: 24; }
.cal-re24 { grid-row-end: 24; }
.cal-rs25 { grid-row-start: 25; }
.cal-re25 { grid-row-end: 25; }
.cal-rs26 { grid-row-start: 26; }
.cal-re26 { grid-row-end: 26; }
.cal-rs27 { grid-row-start: 27; }
.cal-re27 { grid-row-end: 27; }
.cal-t0 { margin-top: 0px; }
.cal-b0 { margin-bottom: 0px; }
.cal-t15 { margin-top: 8.5px; }
.cal-b15 { margin-bottom: 8.5px; }
.cal-t30 { margin-top: 17px; }
.cal-b30 { margin-bottom: 17px; }
.cal-t45 { margin-top: 25.5px; }
.cal-b45 { margin-bottom: 25.5px; }
.cal-lane-1-of-1 { margin-left: 0.0000%; width: 100.0000%; }
.cal-lane-1-of-2 { margin-left: 0.0000%; width: 50.0000%; }
.cal-lane-2-of-2 { margin-left: 50.0000%; width: 50.0000%; }
.cal-lane-1-of-3 { margin-left: 0.0000%; width: 33.3333%; }
.cal-lane-2-of-3 { margin-left: 33.3333%; width: 33.3333%; }
.cal-lane-3-of-3 { margin-left: 66.6667%; width: 33.3333%; }
.cal-lane-1-of-4 { margin-left: 0.0000%; width: 25.0000%; }
.cal-lane-2-of-4 { margin-left: 25.0000%; width: 25.0000%; }
.cal-lane-3-of-4 { margin-left: 50.0000%; width: 25.0000%; }
.cal-lane-4-of-4 { margin-left: 75.0000%; width: 25.0000%; }
