/* Imladris — app-specific styling layered on top of skeleton.css (vendored
   from fhir_server — see that file's own header for why the shared skeleton
   carries no brand color of its own). Defines Imladris's own accent palette
   plus everything specific to the account picker and dashboard. Linked
   after skeleton.css — see index.html / dashboard.html.

   Imladris's own chrome (buttons, links, the header wordmark, the "link a
   new institution" panel) uses the same teal as the main portfolio site.
   Each institution brings its own identity color instead — primary / dark /
   tint, stored in the `institutions` table and applied at runtime as the
   --inst / --inst-dark / --inst-tint custom properties on whatever element
   belongs to that institution (see applyColors() in dashboard.js). Those
   colors are deliberately not the page's own accent: their whole purpose is
   telling institutions apart, not matching Imladris's own brand. Nothing in
   this file names a specific institution. */

:root {
  --accent: #0F6E56;
  --accent-dark: #085041;
  --accent-tint: #E1F5EE;

  /* Fallback for anything institution-styled that hasn't had its own colors
     applied — reads as Imladris teal rather than as nothing. */
  --inst: var(--accent);
  --inst-dark: var(--accent-dark);
  --inst-tint: var(--accent-tint);

  /* Identity-match badges on institution cards (see .match-badge). */
  --warn: #7A4E00;
  --warn-tint: #FDF2D8;
  --warn-border: #E2B04A;
  --bad-tint: #FBE8E5;
  --bad-border: #E3A49A;
  --neutral-tint: #F0F0EC;
}

button { font-family: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- institution source tags ----
   Small bracketed label naming which institution a piece of data came
   from, in that institution's own color. */
.tag--inst {
  color: var(--inst-dark);
  border-color: var(--inst);
}

/* ---- link-status tags (account picker rows) ----
   Fill-vs-outline convention: solid fill in the institution's own color =
   linked; outlined + muted (~45% opacity) in the same color = not linked. */
.tag--linked.tag--inst {
  background: var(--inst);
  border-color: var(--inst);
  color: #fff;
}

.tag--unlinked {
  background: transparent;
  opacity: 0.45;
}

.tag--unlinked.tag--inst {
  color: var(--inst);
}

/* ---- account picker ----
   Reuses skeleton.css's .results / .result list wholesale (same pattern as
   a patient search-result row in the other explorers). The tags sit on the
   right edge, like .result__id does in the other explorers. */
.result__meta {
  margin-right: 8px;
}

.result__tags {
  display: flex;
  gap: 6px;
  margin-left: auto;
  flex-shrink: 0;
}

/* Each account is a row wrapper: the sign-in button, plus a reset strip
   when the account has drifted from its demo state. The divider moves from
   the button to the wrapper so the strip sits inside the same row. */
.result-row {
  border-bottom: 1px solid var(--border);
}

.result-row:last-child {
  border-bottom: 0;
}

.result-row .result {
  border-bottom: 0;
}

.result__reset {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 0 14px 10px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-soft);
}

.reset-btn {
  padding: 2px 8px;
  background: transparent;
  border: 1px solid var(--accent);
  border-radius: 3px;
  color: var(--accent-dark);
  font-family: var(--mono);
  font-size: 11.5px;
  cursor: pointer;
}

.reset-btn:hover:not(:disabled) {
  background: var(--accent-tint);
}

.reset-btn:disabled {
  cursor: default;
  opacity: 0.6;
}

@media (max-width: 560px) {
  .result {
    flex-wrap: wrap;
  }
}

/* ==== dashboard ==== */

/* ---- app header ---- */

.app-header {
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}

.app-header__inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.app-header__brand {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.02em;
  color: var(--accent-dark);
  text-decoration: none;
}

.app-header__user {
  display: flex;
  align-items: baseline;
  gap: 14px;
  min-width: 0;
  font-size: 14px;
}

.app-header__name {
  font-weight: 600;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-header__switch {
  flex: none;
  font-size: 13.5px;
  color: var(--accent-dark);
}

/* ---- page body ---- */

.dash {
  max-width: 1100px;
  margin: 0 auto;
  padding: 28px 24px 72px;
}

.dash-section {
  margin-top: 32px;
}

.dash-heading {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
}

.dash .hint {
  margin: 0 0 12px;
}

/* Heading + the active-filter chip beside it. The heading's own bottom
   margin moves to the row so the chip lines up with the heading text. */
.dash-heading-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-bottom: 12px;
}

.dash-heading-row .dash-heading {
  margin: 0;
}

/* "showing: Erebor ×" — names the institution the timeline is filtered to
   and clears the filter when clicked. Institution-colored, like the card
   that set it. */
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px 3px 12px;
  background: var(--inst-tint);
  border: 1px solid var(--inst);
  border-radius: 999px;
  color: var(--inst-dark);
  font-size: 13px;
  cursor: pointer;
}

.filter-chip[hidden] {
  display: none;
}

.filter-chip:hover {
  background: var(--inst);
  color: #fff;
}

.filter-chip__x {
  font-size: 16px;
  line-height: 1;
}

/* ---- patient card ---- */

.patient-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 20px 22px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.patient-card__avatar {
  flex: none;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-tint);
  color: var(--accent-dark);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: 0.02em;
}

.patient-card__name {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.patient-card__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 22px;
  margin: 6px 0 0;
}

.patient-card__fact {
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.patient-card__fact dt {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-soft);
}

.patient-card__fact dd {
  margin: 0;
  font-size: 14.5px;
}

/* ---- upcoming appointments ----
   Between the patient card and the institutions row. Each row is tagged
   and edged in its institution's own color, like timeline rows. */

.upcoming[hidden] {
  display: none;
}

.upcoming-list {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.upcoming-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 16px;
  padding: 11px 16px;
  border-left: 4px solid var(--inst);
}

.upcoming-item + .upcoming-item {
  border-top: 1px dashed var(--border);
}

.upcoming-item__when {
  flex: none;
  display: flex;
  gap: 8px;
  width: 150px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--inst-dark);
  font-weight: 600;
}

.upcoming-item__time {
  color: var(--ink-soft);
  font-weight: 400;
}

.upcoming-item__what {
  flex: 1 1 240px;
  min-width: 0;
  font-size: 14px;
}

.upcoming-item__title {
  font-weight: 600;
}

.upcoming-item__detail {
  margin-top: 1px;
  font-size: 12.5px;
  color: var(--ink-soft);
}

/* ---- institutions row ---- */

.inst-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
}

/* A card is mostly a toggle button (.inst-card__main): pressing it filters
   the timeline to that institution, pressing it again clears the filter.
   Its children are spans (a button may only hold phrasing content), laid
   out as blocks. "Remove link" sits in its own footer below — a separate
   button, since a button can't contain another. */
.inst-card {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-top: 4px solid var(--inst);
  border-radius: 10px;
  color: var(--ink);
}

.inst-card:hover {
  border-color: var(--inst);
}

/* A column flex box, so the content sits at the top (a button otherwise
   centers it vertically) when a neighbouring card is taller. */
.inst-card__main {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  flex: 1 1 auto;
  width: 100%;
  padding: 14px 16px 8px;
  background: transparent;
  border: 0;
  border-radius: 6px 6px 0 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.inst-card__foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 0 10px 8px;
}

/* How the institution's front desk said its registration compared with the
   account: amber = differences, red = mismatch, grey = not checked. The
   label carries the meaning; the colour only reinforces it. A button — it
   opens the explanation. */
.match-badge {
  margin-right: auto;
  margin-left: 6px;
  padding: 2px 8px;
  border: 1px solid;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  cursor: pointer;
}

.match-badge:hover {
  text-decoration: underline;
}

.match-badge--differences {
  background: var(--warn-tint);
  border-color: var(--warn-border);
  color: var(--warn);
}

.match-badge--mismatch {
  background: var(--bad-tint);
  border-color: var(--bad-border);
  color: var(--down);
}

.match-badge--unknown {
  background: var(--neutral-tint);
  border-color: var(--border-strong);
  color: var(--ink-soft);
}

.match-fields {
  margin: 8px 0 12px;
  padding-left: 22px;
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.6;
}

/* Deliberately quiet: withdrawing consent is always available, never
   prominent. The confirmation dialog carries the weight. */
.inst-card__remove {
  padding: 3px 6px;
  background: transparent;
  border: 0;
  border-radius: 4px;
  color: var(--ink-soft);
  font-size: 12.5px;
  cursor: pointer;
}

.inst-card__remove:hover {
  color: var(--down);
  text-decoration: underline;
}

/* Selected = the timeline is filtered to this institution. A ring in the
   institution's own color plus its tint — box-shadow rather than a thicker
   border, so selecting never shifts the layout. */
.inst-card.is-selected {
  background: var(--inst-tint);
  border-color: var(--inst);
  box-shadow: 0 0 0 2px var(--inst);
}

.inst-card__name {
  display: block;
  font-size: 17px;
  font-weight: 700;
  color: var(--inst-dark);
}

.inst-card__stat {
  display: flex;
  align-items: flex-start;
  gap: 7px;
  margin-top: 5px;
  font-size: 13.5px;
  color: var(--ink-soft);
}

.inst-card__dot {
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--inst);
}

.inst-card.is-error .inst-card__dot {
  background: var(--down);
}

/* "Registered as …" — the institution's own Patient record. Muted and
   neutral even when it differs from the account: drift between
   registrations is the normal state of affairs Imladris bridges, not an
   error. */
.inst-card__reg {
  display: block;
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px dashed var(--border);
  font-size: 12.5px;
  color: var(--ink-soft);
}

.inst-card__reg[hidden] {
  display: none;
}

.inst-card__differs {
  display: block;
  margin-top: 1px;
  font-style: italic;
}

.inst-card__error {
  display: block;
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--down);
}

/* Starting up (the institution answered 503): a temporary state, not an
   error, so neutral and in the institution's own colors, never red. The
   dot stays the institution's color but hollow. */
.inst-card.is-starting .inst-card__dot {
  background: transparent;
  box-shadow: inset 0 0 0 2px var(--inst);
}

.inst-card__notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 0 12px 10px;
  padding: 9px 11px;
  border: 1px dashed var(--inst);
  border-radius: 8px;
  background: var(--inst-tint);
}

.inst-card__notice p {
  flex: 1 1 160px;
  margin: 0;
  font-size: 13px;
  color: var(--inst-dark);
}

.inst-card__retry {
  padding: 4px 10px;
  font-size: 12.5px;
}

/* The same notice in the document reader. */
.doc-starting {
  max-width: 420px;
  margin: 24px auto;
  padding: 14px 16px;
  border: 1px dashed var(--inst);
  border-radius: 8px;
  background: var(--inst-tint);
  text-align: center;
}

.doc-starting p {
  margin: 0 0 10px;
  font-size: 14.5px;
  color: var(--inst-dark);
}

/* "+N more" — the row shows the four most recently active institutions;
   this reveals the rest. Same footprint as a card, but dashed and muted
   (neutral border, soft ink, no accent color): it's a placeholder for
   institutions not shown, not an institution, and not Imladris's own teal
   "link a new institution" panel either. */
.inst-more {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 82px;
  padding: 14px 16px;
  background: transparent;
  border: 2px dashed var(--border-strong);
  border-radius: 10px;
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.inst-more:hover {
  background: var(--panel);
  border-color: var(--ink-soft);
  color: var(--ink);
}

/* The one generic panel that opens institution discovery. Same footprint as
   a real card, but dashed teal — Imladris's own color, not any
   institution's — and deliberately names none of them. */
.inst-add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 82px;
  padding: 14px 16px;
  background: transparent;
  border: 2px dashed var(--accent);
  border-radius: 10px;
  color: var(--accent-dark);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.inst-add:hover {
  background: var(--accent-tint);
}

.inst-add__plus {
  font-size: 20px;
  line-height: 1;
}

/* ---- unified timeline ----
   The year drawers and rows themselves come from skeleton.css (.timeline-*,
   .collapsible) — the pattern fhir_server's explorer uses, reused so every
   linked institution's events read as one history. */

.timeline-panel {
  padding: 8px 20px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.timeline-panel:empty {
  display: none;
}

/* "View images" in the document reader. Institution-colored, like the row
   buttons, so it reads as that institution's own images. */
.view-btn {
  padding: 3px 14px;
  background: transparent;
  border: 1px solid var(--inst);
  border-radius: 5px;
  color: var(--inst-dark);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.view-btn:hover {
  background: var(--inst);
  color: #fff;
}

/* ---- timeline rows ----
   One grid for every row: Date | Source | Type | Content | Actions. All
   columns but Content are fixed, and Actions is reserved even when a row
   has no button, so every row lines up whatever it holds. */

.trow {
  --trow-date: 52px;
  display: grid;
  grid-template-columns: var(--trow-date) 100px 104px minmax(0, 1fr) 150px;
  grid-template-areas: "date source type content actions";
  align-items: start;
  column-gap: 14px;
  padding: 9px 4px;
}

.timeline-panel--full-dates .trow {
  --trow-date: 92px;
}

.trow__date {
  grid-area: date;
  padding-top: 3px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Source: the institution's bracket tag, filling its column so every
   source tag is the same width, tinted in that institution's own colors
   (from the institutions table, via --inst*). */
.trow__source {
  grid-area: source;
  min-width: 0;
}

.trow__source .tag {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  white-space: nowrap;
  background: var(--inst-tint);
  border-color: var(--inst);
  color: var(--inst-dark);
}

/* Type: neutral, identical width for every type. */
.trow__type {
  grid-area: type;
}

.type-tag {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 100%;
  box-sizing: border-box;
  padding: 2px 4px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--border);
  border-radius: 2px;
  white-space: nowrap;
}

.kind-icon {
  width: 12px;
  height: 12px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.trow__content {
  grid-area: content;
  min-width: 0;
  max-width: 70ch;
}

/* Title: two lines at most (full text in its tooltip). */
.trow__title {
  font-size: 14px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* Detail: status, class, document type, author — two lines at most too. */
.trow__detail {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-soft);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

.trow__actions {
  grid-area: actions;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* Row actions: one size, one style. Institution-colored, like the source
   tag, so it reads as that institution's own document or images. */
.row-btn {
  width: 68px;
  padding: 3px 0;
  background: transparent;
  border: 1px solid var(--inst);
  border-radius: 5px;
  color: var(--inst-dark);
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
}

.row-btn:hover {
  background: var(--inst);
  color: #fff;
}

/* ---- reading a document or report ---- */

.modal--doc .modal__dialog {
  width: min(760px, 100%);
  height: min(900px, 100%);
}

.doc-actions {
  display: flex;
  justify-content: flex-end;
  margin: -4px 0 12px;
}

/* The rendered letter/report. Its HTML is sanitized server-side to plain
   structural tags (headings, paragraphs, lists, emphasis, rules), so only
   those need styling. */
.doc-body {
  max-width: 68ch;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink);
}

.doc-body > :first-child {
  margin-top: 0;
}

.doc-body h1,
.doc-body h2,
.doc-body h3,
.doc-body h4 {
  margin: 1.3em 0 0.4em;
  line-height: 1.3;
}

.doc-body h1 { font-size: 19px; }
.doc-body h2 { font-size: 16px; }
.doc-body h3,
.doc-body h4 { font-size: 14.5px; }

.doc-body p,
.doc-body ul,
.doc-body ol {
  margin: 0.6em 0;
}

.doc-body ul,
.doc-body ol {
  padding-left: 1.4em;
}

.doc-body li + li {
  margin-top: 0.2em;
}

.doc-body hr {
  margin: 1.1em 0;
  border: 0;
  border-top: 1px solid var(--border);
}

/* ---- buttons (dialogs) ---- */

.btn-primary,
.btn-secondary,
.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 18px;
  border: 1px solid transparent;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

/* Inside an institution's own element, its own color; elsewhere teal. */
.btn-primary {
  background: var(--inst);
  border-color: var(--inst);
  color: #fff;
}

.btn-primary:hover {
  background: var(--inst-dark);
  border-color: var(--inst-dark);
}

.btn-secondary {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--ink);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--bg);
}

.btn-danger {
  background: var(--down);
  border-color: var(--down);
  color: #fff;
}

.btn-danger:hover:not(:disabled) {
  filter: brightness(0.9);
}

.btn-primary:disabled,
.btn-secondary:disabled,
.btn-danger:disabled {
  cursor: default;
  opacity: 0.6;
}

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

/* ---- modal (discovery, linking, dialogs, image viewer) ---- */

body.modal-open {
  overflow: hidden;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(16, 24, 22, 0.55);
}

.modal__dialog {
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 100%;
  background: var(--panel);
  border-radius: 12px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.modal__head {
  flex: none;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--border);
}

.modal__heading {
  flex: 1 1 auto;
  min-width: 0;
}

.modal__title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.3;
}

.modal__sub {
  margin-top: 3px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  font-size: 13px;
  color: var(--ink-soft);
}

.modal__sub[hidden] {
  display: none;
}

.modal__close {
  flex: none;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.modal__close:hover {
  background: var(--bg);
  color: var(--ink);
}

.modal__body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 16px 18px 18px;
  overflow-y: auto;
}

/* discovery */

.inst-search {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--panel);
  font: inherit;
  font-size: 14.5px;
  color: var(--ink);
}

.inst-search:focus {
  outline: 2px solid var(--accent);
  outline-offset: 0;
  border-color: var(--accent);
}

.inst-options {
  margin-top: 6px;
}

.inst-option {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.inst-option:last-child {
  border-bottom: 0;
}

.inst-option__row {
  display: flex;
  align-items: center;
  gap: 16px;
}

.inst-option__main {
  flex: 1 1 auto;
  min-width: 0;
  padding-left: 12px;
  border-left: 4px solid var(--inst);
}

.inst-option__name {
  font-size: 16px;
  font-weight: 700;
  color: var(--inst-dark);
}

.inst-option__desc {
  margin-top: 1px;
  font-size: 13.5px;
  color: var(--ink-soft);
}

.inst-option__btn {
  flex: none;
  padding: 7px 18px;
  background: var(--inst);
  border: 1px solid var(--inst);
  border-radius: 6px;
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.inst-option__btn:hover:not(:disabled) {
  background: var(--inst-dark);
  border-color: var(--inst-dark);
}

.inst-option__btn:disabled {
  cursor: default;
  opacity: 0.55;
}

/* ---- linking: the code screen ----
   Inside the discovery dialog once an institution is chosen; everything in
   it wears that institution's colors (--inst*, set on .link-screen). */

.link-code-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  padding: 18px 20px;
  background: var(--inst-tint);
  border: 1px solid var(--inst);
  border-radius: 10px;
}

.link-code {
  font-family: var(--mono);
  font-size: clamp(30px, 8vw, 40px);
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--inst-dark);
  font-variant-numeric: tabular-nums;
  user-select: all;
}

.link-code:focus {
  outline: none;
}

.link-code:focus-visible {
  outline: 2px solid var(--inst);
  outline-offset: 4px;
}

.link-code-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.link-timer {
  font-size: 13px;
  color: var(--ink-soft);
}

.link-timer__value {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
}

.link-timer.is-low .link-timer__value {
  color: var(--down);
}

.link-hint {
  margin: 14px 0 0;
  font-size: 14.5px;
  font-weight: 600;
}

.link-identity {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px dashed var(--border-strong);
  border-radius: 8px;
}

.link-identity__head {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-soft);
}

.link-identity__facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 16px;
  margin: 8px 0 0;
}

.link-identity__facts > div {
  display: contents;
}

.link-identity__facts dt {
  font-size: 13px;
  color: var(--ink-soft);
}

.link-identity__facts dd {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}

.link-identity__note {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--ink-soft);
}

.link-desk {
  width: 100%;
  margin-top: 16px;
  padding: 11px 18px;
  font-size: 15px;
}

/* Blocked popup / closed desk window, in place of the desk button. */
.link-desk-note {
  margin: 16px 0 0;
  font-size: 13.5px;
  color: var(--ink-soft);
  text-align: center;
}

.link-desk-note + .link-desk {
  margin-top: 8px;
}

.link-desk-note--closed {
  padding: 12px 14px;
  border: 1px dashed var(--inst);
  border-radius: 8px;
  background: var(--inst-tint);
}

.link-desk-note--closed p {
  margin: 0 0 10px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--inst-dark);
}

.link-waiting {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--ink-soft);
}

.link-waiting__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--inst);
  animation: link-pulse 1.4s ease-in-out infinite;
}

@keyframes link-pulse {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .link-waiting__dot { animation: none; }
}

/* success / expired */
.link-done {
  padding: 12px 4px 6px;
  text-align: center;
}

.link-done__mark {
  width: 56px;
  height: 56px;
  margin: 0 auto 12px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--inst);
  color: #fff;
  font-size: 28px;
  font-weight: 700;
}

.link-done__title {
  margin: 0;
  font-size: 19px;
  color: var(--inst-dark);
}

.link-done--expired .link-done__title {
  color: var(--ink);
}

.link-done__text {
  max-width: 42ch;
  margin: 6px auto 18px;
  font-size: 14px;
  color: var(--ink-soft);
}

/* ---- confirmation dialog (unlink) ---- */

.modal--confirm .modal__dialog {
  width: min(440px, 100%);
}

.confirm-text {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.5;
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}

.modal--confirm .error:empty {
  display: none;
}

/* viewer — the dialog is nearly the whole window; the stage inside is
   deliberately dark (see viewer.css). */

.modal--viewer .modal__dialog {
  width: min(1400px, 100%);
  height: min(900px, 100%);
}

.modal--viewer .modal__body {
  display: flex;
  padding: 0;
  overflow: hidden;
  background: #000;
}

/* Nothing behind the viewer moves: no page scroll or zoom from a gesture that
   starts on the header or a toolbar (body overflow: hidden alone doesn't stop
   that on iOS), so the address bar never shows or hides under the image.
   The series list opts back in to vertical scrolling (viewer.css). */
.modal--viewer {
  touch-action: none;
  overscroll-behavior: contain;
}

/* Phones, portrait or landscape: the viewer is the whole screen, the dialog
   header and then the image, sized to the dynamic viewport. */
@media (max-width: 700px), (max-height: 500px) {
  /* .modal too: outranks the phone padding every other modal gets */
  .modal.modal--viewer {
    padding: 0;
    bottom: auto;
    height: 100vh;
    height: 100dvh;
  }

  .modal--viewer .modal__dialog {
    width: 100%;
    height: 100%;
    border-radius: 0;
  }
}

/* Phones in landscape: every pixel of height goes to the image. */
@media (max-height: 500px) and (orientation: landscape) {
  .modal--viewer .modal__head {
    padding: 6px 12px;
  }

  .modal--viewer .modal__title {
    font-size: 15px;
  }

  .modal--viewer .modal__sub {
    display: none;
  }
}

@media (max-width: 700px) {
  .app-header__inner,
  .dash {
    padding-left: 16px;
    padding-right: 16px;
  }

  .patient-card {
    padding: 16px;
  }

  .timeline-panel {
    padding-left: 14px;
    padding-right: 14px;
  }

  .modal {
    padding: 12px;
  }

  /* Reading on a phone: the document takes the whole screen. */
  .modal--doc {
    padding: 0;
  }

  .modal--doc .modal__dialog {
    height: 100%;
    border-radius: 0;
  }

  /* Stacked rows on a phone: date, source and type on one line, the content
     below, the actions under that. */
  .trow {
    grid-template-columns: var(--trow-date) 100px 104px minmax(0, 1fr);
    grid-template-areas:
      "date source type ."
      "content content content content"
      "actions actions actions actions";
    row-gap: 6px;
  }

  .trow__actions {
    justify-content: flex-start;
  }

  .trow__actions:empty {
    display: none;
  }

  .upcoming-item__when {
    width: auto;
  }

  .inst-option__row {
    flex-wrap: wrap;
  }
}
