/* Saath — consumer-health htmx shell stylesheet (S13 shell, redesigned S18).
   Served as /app.css from Workers Static Assets and shared by every surface:
   the dynamic worker-rendered shell (base.html + saath-web fragments), the
   static SaaS shells (apps/saath-provider|patient|admin), and the hospital
   demo. Kept framework-free (no build step beyond build-app.sh copy).

   DESIGN TOKENS — single source of truth for the product's look. Reference
   these instead of hardcoding colors/radii/shadows in future work.
---------------------------------------------------------------------------- */
:root {
  color-scheme: light;

  /* Brand + semantic color */
  --accent: #0b7285; /* calm teal-indigo — primary action */
  --accent-strong: #0a5c6b; /* hover / active */
  --accent-soft: #e0f2f4; /* tinted chip, banner, active-tab bg */
  --ink: #17202b; /* near-black body text */
  --ink-2: #374151; /* secondary text */
  --muted: #64748b; /* hint / captions */
  --surface: #ffffff; /* card + header bg */
  --bg: #f4f7fa; /* page background */
  --line: #e2e8f0; /* card/input borders */
  --ok: #15803d;
  --ok-soft: #dcfce7;
  --warn: #b45309;
  --warn-soft: #fef3c7;
  --err: #b91c1c;
  --err-soft: #fee2e2;

  /* Shape + elevation */
  --radius: 0.875rem;
  --radius-sm: 0.5rem;
  --shadow-xs: 0 1px 2px rgb(15 23 42 / 0.05);
  --shadow-sm: 0 1px 2px rgb(15 23 42 / 0.06), 0 1px 3px rgb(15 23 42 / 0.06);
  --shadow-md: 0 2px 4px rgb(15 23 42 / 0.06), 0 8px 24px rgb(15 23 42 / 0.05);
  --focus: 0 0 0 3px rgb(11 114 133 / 0.28);

  /* Rhythm + layout */
  --space: 1.5rem;
  --nav-h: 3.75rem;
  --content-max: 62rem;

  /* Type scale */
  --fs-h1: clamp(1.4rem, 2.5vw + 0.5rem, 1.75rem);
  --fs-h2: 1.15rem;
  --fs-h3: 1rem;
  --fs-body: 1rem;
  --fs-sm: 0.875rem;
  --fs-xs: 0.8rem;
  --font: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

/* Base
---------------------------------------------------------------------------- */
* {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  font-size: var(--fs-body);
  line-height: 1.5;
}
h1,
h2,
h3,
h4 {
  line-height: 1.25;
  margin: 0 0 0.5rem;
  color: var(--ink);
  font-weight: 650;
  letter-spacing: -0.01em;
}
h1 {
  font-size: var(--fs-h1);
}
h2 {
  font-size: var(--fs-h2);
}
h3 {
  font-size: var(--fs-h3);
}
p {
  margin: 0 0 0.75rem;
}
a {
  color: var(--accent);
  text-decoration: none;
}
a:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}
code {
  font-size: 0.9em;
  background: var(--accent-soft);
  color: var(--accent-strong);
  padding: 0.1rem 0.35rem;
  border-radius: 0.375rem;
}

/* Header / app bar
---------------------------------------------------------------------------- */
header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgb(255 255 255 / 0.92);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--line);
  padding: 0 var(--space);
  min-height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  box-shadow: 0 1px 0 rgb(15 23 42 / 0.03);
}
header h1 {
  font-size: 1.2rem;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
header h1::before {
  content: '';
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
header .hint {
  font-size: var(--fs-sm);
  margin: 0;
}

/* Layout
---------------------------------------------------------------------------- */
main {
  max-width: var(--content-max);
  margin: 2rem auto;
  padding: 0 1.25rem;
  display: grid;
  gap: var(--space);
}
main > section,
main > div {
  min-width: 0;
}

/* Card
---------------------------------------------------------------------------- */
main section {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  box-shadow: var(--shadow-sm);
}
/* Hub slots are htmx mount points: the wrapper is a transparent container
   and the mounted fragment card carries the chrome. Before a fragment mounts,
   the slot holds a span.hint — treat that as an inviting "choose a tab" cue
   (a soft, dashed placeholder) rather than a broken empty card. */
main section[id^='patient-'] {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
}
main section[id^='patient-'] > span.hint {
  margin: 0;
  text-align: center;
  display: block;
  color: var(--muted);
  font-size: var(--fs-sm);
  background: var(--surface);
  border: 1px dashed #cbd5e1;
  border-radius: var(--radius);
  padding: 1.5rem;
}
main section[id^='patient-'] > section {
  animation: mountIn 0.18s ease;
}
@keyframes mountIn {
  from {
    opacity: 0;
    transform: translateY(3px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Buttons
---------------------------------------------------------------------------- */
.btn,
button {
  --btn-bg: var(--accent);
  --btn-fg: #ffffff;
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.9rem;
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition:
    background 0.12s ease,
    box-shadow 0.12s ease,
    transform 0.04s ease;
  text-decoration: none;
}
.btn:hover,
button:hover {
  background: var(--accent-strong);
  color: #ffffff;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
}
.btn:active,
button:active {
  transform: translateY(1px);
}
.btn:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
a:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
button[type='submit'] {
  background: var(--accent);
  color: #fff;
}

/* Ghost/soft variant used for secondary + logout */
.btn.logout {
  --btn-bg: transparent;
  --btn-fg: var(--ink-2);
  border-color: var(--line);
  box-shadow: none;
}
.btn.logout:hover {
  --btn-bg: #fef2f2;
  --btn-fg: var(--err);
  border-color: #fecaca;
  box-shadow: none;
}

/* Hint / muted text
---------------------------------------------------------------------------- */
.hint {
  color: var(--muted);
  font-size: var(--fs-sm);
}

/* Tab cue (U2): the pre-mount placeholder inside a hub tab slot. Mirrors the
   patient-hub slot cue (a soft dashed placeholder) so an un-mounted tab reads
   as an invitation rather than a broken empty card. */
.tab-cue {
  display: block;
  margin: 0;
  text-align: center;
  color: var(--muted);
  font-size: var(--fs-sm);
  background: var(--surface);
  border: 1px dashed #cbd5e1;
  border-radius: var(--radius);
  padding: 1.5rem;
}

/* Skeleton loaders (U2): pulsing content blocks shown while an htmx region is
   in flight, in place of raw "Loading…" text. Static (non-animated) under
   prefers-reduced-motion. */
.skeleton {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.skeleton-block {
  display: block;
  height: 0.85rem;
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--line) 25%, #eef2f6 37%, var(--line) 63%);
  background-size: 400% 100%;
  animation: skeletonPulse 1.3s ease-in-out infinite;
}
.skeleton-block:last-child {
  width: 62%;
}
.skeleton-block.skeleton-title {
  height: 1.15rem;
  width: 42%;
}
@keyframes skeletonPulse {
  from {
    background-position: 100% 50%;
  }
  to {
    background-position: 0 50%;
  }
}

/* Developer debug bar (U2): collapsed disclosure holding stack metadata that
   used to leak into the product header. Deliberately de-emphasised — muted,
   small, and out of the primary visual flow. */
.dev-bar {
  max-width: var(--content-max);
  margin: 1.5rem auto 2rem;
  padding: 0 1.25rem;
  font-size: var(--fs-xs);
  color: var(--muted);
}
.dev-bar > summary {
  cursor: pointer;
  display: inline-block;
  padding: 0.25rem 0.6rem;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: var(--fs-xs);
  list-style: none;
}
.dev-bar > summary::-webkit-details-marker {
  display: none;
}
details.dev-bar[open] > summary {
  margin-bottom: 0.5rem;
}
.dev-bar .hint {
  margin: 0;
  font-size: var(--fs-xs);
}

/* Overview cards (U3): the provider hub's at-a-glance metrics, rendered ABOVE the
   tab body. Each card is an <a> that links OUT to the tab that owns the detail
   (the review's "overview, then drill in" shape) rather than duplicating the
   fragment inline. The value is precomputed in the view model and is a neutral
   em-dash when the metric is absent, so the emphasis here is on legibility of
   that value, not on any state colouring — an absent metric must NOT look like a
   warning or an error. */
.provider-overview {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0.75rem;
  margin: 1rem 0 0.25rem;
}
.overview-card {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.85rem 1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  text-decoration: none;
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease,
    transform 0.12s ease;
}
.overview-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-sm);
}
.overview-card:focus-visible {
  box-shadow: var(--focus);
  outline: none;
}
.overview-label {
  font-size: var(--fs-xs);
  font-weight: 550;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.overview-value {
  font-size: var(--fs-h2);
  font-weight: 650;
  line-height: 1.2;
  color: var(--ink);
}

/* Dev banner (U4): staging-only sign-in affordance. Visually distinct but not
   alarming; never rendered in production. */
.dev-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  max-width: var(--content-max);
  margin: 1rem auto 0;
  padding: 0.6rem 1.25rem;
  font-size: var(--fs-sm);
  color: var(--accent-strong);
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
}
.dev-banner > .hint {
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-block {
    animation: none;
    background: var(--line);
  }
  main section[id^='patient-'] > section {
    animation: none;
  }
}

/* Forms
---------------------------------------------------------------------------- */
label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-2);
  margin: 0.25rem 0 0.35rem;
}
input[type='text'],
input[type='email'],
input[type='number'],
input[type='password'],
input[type='tel'],
textarea,
select {
  width: 100%;
  padding: 0.55rem 0.7rem;
  font: inherit;
  font-size: var(--fs-body);
  color: var(--ink);
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
  transition:
    border-color 0.12s ease,
    box-shadow 0.12s ease;
}
input::placeholder,
textarea::placeholder {
  color: #94a3b8;
}
input:hover,
textarea:hover,
select:hover {
  border-color: #94a3b8;
}
input:focus,
textarea:focus,
select:focus {
  border-color: var(--accent);
  box-shadow: var(--focus);
}
textarea {
  resize: vertical;
  min-height: 4.5rem;
}
form {
  display: grid;
  gap: 0.25rem;
}
form button {
  justify-self: start;
  margin-top: 0.75rem;
}

/* =========================================================================
   PATIENT HUB
   ========================================================================= */

/* Welcome card + pillar nav */
.patient-home-fragment {
  border-top: 3px solid var(--accent);
}
.patient-home-fragment > p {
  color: var(--ink-2);
}

.patient-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.25rem;
}
.patient-nav a {
  display: inline-flex;
  align-items: center;
  padding: 0.45rem 0.85rem;
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--ink-2);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
  transition:
    background 0.12s ease,
    border-color 0.12s ease,
    color 0.12s ease;
}
.patient-nav a:hover {
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-color: transparent;
}
.patient-nav a:focus-visible {
  box-shadow: var(--focus);
}

/* Shared role-hub nav (provider admin shell + admin portal): the same pill
   treatment as the patient hub's pillar nav, but on the full-width hub
   surfaces. Links mount each fragment region on demand (S18.5 prefetch). */
.hub-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.5rem 0 0.25rem;
}
.hub-nav a {
  display: inline-flex;
  align-items: center;
  padding: 0.45rem 0.85rem;
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--ink-2);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
  transition:
    background 0.12s ease,
    border-color 0.12s ease,
    color 0.12s ease;
}
.hub-nav a:hover {
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-color: transparent;
}
.hub-nav a:focus-visible {
  box-shadow: var(--focus);
}

/* =========================================================================
   PATIENT HOME AS SIDEBAR / DRAWER
   =========================================================================
   The patient-home card is a persistent left sidebar on wide screens and a
   slide-in overlay drawer (behind a scrim) on narrow screens. Pure UI chrome:
   htmx owns every content mount; the tiny toggle script on the patient
   dashboard page only flips `body.patient-hub-open`, which the rules here
   react to. The inner patient-home fragment keeps its content; the drawer
   chrome lives on the #patient-home wrapper. */

/* Brand cluster in the sticky header (toggle + title). */
.hub-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
/* Hamburger — visible only while the overlay drawer is active (narrow). */
.hub-toggle {
  display: none;
  cursor: pointer;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  width: 2.4rem;
  height: 2.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-2);
  transition:
    background 0.12s ease,
    border-color 0.12s ease;
}
.hub-toggle:hover {
  background: var(--accent-soft);
  border-color: transparent;
}
.hub-toggle:focus-visible {
  box-shadow: var(--focus);
  outline: none;
}
.hub-toggle-bar {
  display: block;
  width: 1.05rem;
  height: 2px;
  border-radius: 999px;
  background: currentColor;
}

/* Scrim behind the overlay drawer — inert until the drawer is open. */
.hub-scrim {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 90;
  border: 0;
  cursor: pointer;
  background: rgb(15 23 42 / 0.38);
  opacity: 0;
  transition: opacity 0.2s ease;
}
body.patient-hub-open .hub-scrim {
  display: block;
  opacity: 1;
}

/* Wide: the hub becomes a persistent sidebar column + content column. */
main.patient-hub {
  grid-template-columns: 15.5rem minmax(0, 1fr);
  align-items: start;
}
main.patient-hub > :not(#patient-home) {
  grid-column: 2;
}
main.patient-hub > #patient-home {
  grid-row: 1 / -1;
  grid-column: 1;
  position: sticky;
  top: calc(var(--nav-h) + 1.25rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 1.25rem 1.15rem;
  box-shadow: var(--shadow-sm);
}
/* The mounted fragment is pure content — drop the nested card chrome. */
main.patient-hub > #patient-home .patient-home-fragment {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
}
main.patient-hub > #patient-home .patient-home-fragment > p {
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
/* Nav reads as a vertical sidebar menu inside the drawer. */
main.patient-hub > #patient-home .patient-nav {
  flex-direction: column;
  align-items: stretch;
  gap: 0.375rem;
  margin-top: 0.25rem;
}
main.patient-hub > #patient-home .patient-nav a {
  width: 100%;
  justify-content: flex-start;
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.85rem;
}

/* Advisory ("Things to know") — soft info surface */
.hub-advisory {
  background:
    linear-gradient(180deg, rgb(224 242 244 / 0.55), rgb(224 242 244 / 0.25)), var(--surface);
  border-color: #bcd7da;
}
.pack-advisory-region .hint {
  margin: 0;
  font-size: var(--fs-sm);
}
.advisory-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}
.advisory-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
}
.advisory-card h3 {
  margin: 0 0 0.25rem;
  color: var(--accent-strong);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.advisory-card p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* =========================================================================
   CAPTURE ("Add a health record")
   ========================================================================= */
.phr-capture-form h2 {
  margin-bottom: 0.25rem;
}
.phr-capture-form form {
  margin-top: 0.75rem;
}

/* S19-01 photo-OCR affordance, generalized by S20 to any health document:
   camera (image) + filesystem (image/PDF/text) buttons wired to the lazy OCR
   bridge. Progressive enhancement — hidden preview + status line are driven
   by the fragment's inline script; if JS/OCR is unavailable these stay inert
   and manual entry still works. */
.phr-capture-photo {
  margin-top: 0.75rem;
}
.phr-capture-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.phr-photo-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px dashed var(--line-strong, var(--line));
  background: var(--surface-2, #fff);
  color: var(--ink);
  padding: 0.55rem 0.85rem;
  border-radius: 10px;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}
.phr-photo-btn:hover {
  background: var(--bg-pressed, #f2f4f7);
}
.phr-photo-btn[hidden] {
  display: none;
}
/* Document badge shown for PDF/text selections (a printable pill with the
   file name + size) instead of a broken <img> preview. */
.phr-doc-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.6rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--ink-2);
  font-size: var(--fs-sm);
  font-weight: 550;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.phr-doc-badge[hidden] {
  display: none;
}
.phr-photo-preview {
  display: block;
  max-width: 100%;
  max-height: 9rem;
  margin-top: 0.6rem;
  border-radius: 10px;
  border: 1px solid var(--line);
  object-fit: contain;
}
.phr-photo-status {
  min-height: 1.2em;
  margin-top: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* =========================================================================
   TIMELINE
   ========================================================================= */
.phr-timeline-fragment {
  border-top: 3px solid var(--ok);
}
.phr-timeline-fragment > p:first-of-type {
  color: var(--muted);
}
.phr-timeline {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: grid;
}
.phr-timeline .phr-entry {
  position: relative;
  display: grid;
  gap: 0.15rem;
  padding: 0.6rem 0 0.6rem 1.25rem;
  border-bottom: 1px dashed var(--line);
}
.phr-timeline .phr-entry:last-child {
  border-bottom: 0;
}
.phr-timeline .phr-entry::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.85rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 999px;
  background: var(--ok);
  box-shadow: 0 0 0 3px var(--ok-soft);
}
.phr-at,
.phr-type {
  display: inline-block;
  font-size: var(--fs-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.phr-summary {
  color: var(--ink);
  font-weight: 500;
}
.phr-notice {
  display: block;
  font-size: var(--fs-sm);
  color: var(--warn);
  background: var(--warn-soft);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.55rem;
  margin-top: 0.25rem;
}
.phr-timeline-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1rem;
}
.phr-timeline-actions .btn {
  --btn-bg: var(--surface);
  --btn-fg: var(--accent-strong);
  border-color: var(--accent);
  box-shadow: none;
}
.phr-timeline-actions .btn:hover {
  --btn-bg: var(--accent-soft);
  border-color: var(--accent-strong);
  box-shadow: none;
}

/* =========================================================================
   HEALTH ("Your Health" dashboard)
   ========================================================================= */
.phr-dashboard-fragment {
  border-top: 3px solid var(--accent);
}
.phr-banner {
  background: var(--ok-soft);
  color: var(--ok);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.9rem;
  font-weight: 600;
  margin-bottom: 0.75rem;
}
.phr-record-count {
  color: var(--ink-2);
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-weight: 600;
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  font-size: var(--fs-sm);
}
.phr-recent h3,
.phr-advisories h3 {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin: 1.25rem 0 0.5rem;
}
.phr-recent ul,
.phr-advisories ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.phr-recent li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.6rem;
  padding: 0.5rem 0;
  border-bottom: 1px dashed var(--line);
}
.phr-recent li:last-child {
  border-bottom: 0;
}
.phr-advisories details {
  margin: 0.25rem 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  padding: 0.5rem 0.75rem;
}
.phr-advisories summary {
  font-weight: 600;
  cursor: pointer;
  color: var(--ink);
}
.phr-advisories details li {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  padding: 0.2rem 0;
  list-style: disc;
  margin-left: 1.1rem;
}

/* =========================================================================
   REMINDERS
   ========================================================================= */
.patient-reminders-ledger {
  border-top: 3px solid var(--warn);
}
.patient-reminders-ledger .hint {
  margin-bottom: 0.75rem;
}
.phr-reminder-ledger {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}
.phr-reminder-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.6rem;
  padding: 0.6rem 0;
  border-bottom: 1px dashed var(--line);
}
.phr-reminder-row:first-child {
  padding-top: 0;
}
.phr-reminder-row:last-child {
  border-bottom: 0;
}
.phr-reminder-medication {
  font-weight: 600;
  color: var(--ink);
}
.phr-reminder-dosage {
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.phr-reminder-cadence {
  margin-left: auto;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--warn);
  background: var(--warn-soft);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
}
.phr-reminder-fire-btn {
  --btn-bg: var(--warn);
}
.phr-reminder-fire-btn:hover {
  --btn-bg: #92400e;
}
/* Fire result */
.phr-reminder-fire {
  margin-top: 1rem;
  background: var(--accent-soft);
  border: 1px solid #bcd7da;
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
}
.phr-reminder-headline {
  font-weight: 600;
  color: var(--accent-strong);
  margin: 0;
}
.phr-reminder-list {
  margin: 0.5rem 0 0;
  padding-left: 1.2rem;
}
.phr-reminder-list li {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.phr-reminder-state {
  color: var(--ok);
  font-weight: 600;
}

/* Reminder set form */
.patient-reminder-form form {
  margin-top: 0.5rem;
}

/* =========================================================================
   FEEDBACK
   ========================================================================= */
.phr-feedback-invite {
  border-top: 3px solid #7c3aed;
}
.phr-feedback-banner {
  color: var(--ink-2);
}
.phr-feedback-metrics {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}
.phr-feedback-metrics h3 {
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.phr-feedback-metrics ul {
  margin: 0.5rem 0 0;
  padding-left: 1.1rem;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.phr-feedback-metrics li {
  margin-bottom: 0.35rem;
}

/* =========================================================================
   EXPLORE (health feed, platform-packs)
   ========================================================================= */
.pack-feed-fragment {
  border-top: 3px solid #0891b2;
}
.feed-cards {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}
.feed-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1rem;
  background: var(--surface);
  box-shadow: var(--shadow-xs);
}
.feed-kind {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  margin-bottom: 0.4rem;
}
.feed-card h3 {
  margin: 0 0 0.25rem;
  font-size: var(--fs-h3);
}
.feed-card p {
  margin: 0 0 0.5rem;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.feed-card .btn {
  --btn-bg: var(--accent);
  padding: 0.3rem 0.75rem;
  font-size: var(--fs-xs);
}

/* =========================================================================
   SEARCH (catalog)
   ========================================================================= */
.patient-search-fragment {
  border-top: 3px solid #0ea5e9;
}
.catalog-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
}
.catalog-item {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.6rem 0;
  border-bottom: 1px dashed var(--line);
}
.catalog-item:last-child {
  border-bottom: 0;
}
.catalog-name {
  font-weight: 600;
}
.catalog-specialty {
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* =========================================================================
   APPOINTMENTS
   ========================================================================= */
.patient-appointments-fragment {
  border-top: 3px solid #8b5cf6;
}

/* =========================================================================
   PROVIDER / ONBOARDING
   ========================================================================= */
.onboarding {
  border-top: 3px solid #0ea5e9;
}
.onboarding .onboarding-step strong {
  color: var(--accent-strong);
}

/* =========================================================================
   LOGIN
   ========================================================================= */
#login-form {
  margin-top: 0.25rem;
}
#login-result {
  margin-bottom: 0;
}
.otp-result p {
  background: var(--ok-soft);
  color: var(--ok);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.9rem;
  font-size: var(--fs-sm);
}

/* =========================================================================
   RESPONSIVE
   ========================================================================= */
@media (max-width: 640px) {
  main {
    margin: 1.25rem auto 3rem;
    padding: 0 0.9rem;
    gap: 1rem;
  }
  main section {
    padding: 1rem 1.1rem;
  }
  header {
    padding: 0 0.9rem;
    min-height: var(--nav-h);
  }
  header h1 {
    font-size: 1.05rem;
  }
  .patient-nav a {
    font-size: var(--fs-xs);
    padding: 0.4rem 0.7rem;
  }
  .phr-reminder-cadence {
    margin-left: 0;
  }
}

/* Overlay drawer on narrow viewports: not enough horizontal space for the
   persistent sidebar, so the patient-home card slides in from the left edge
   over the content, behind a dimming scrim, toggled via the hamburger. */
@media (max-width: 48rem) {
  main.patient-hub {
    grid-template-columns: 1fr;
  }
  main.patient-hub > :not(#patient-home) {
    grid-column: auto;
  }
  .hub-toggle {
    display: flex;
  }

  main.patient-hub > #patient-home {
    grid-row: auto;
    grid-column: auto;
    position: fixed;
    top: var(--nav-h);
    left: 0;
    bottom: 0;
    width: min(84vw, 17.5rem);
    z-index: 100;
    margin: 0;
    border-radius: 0;
    border-top: 0;
    border-bottom: 0;
    padding: 1.25rem 1.15rem;
    transform: translateX(-102%);
    opacity: 0;
    visibility: hidden;
    transition:
      transform 0.22s ease,
      opacity 0.22s ease,
      visibility 0.22s ease;
    overflow-y: auto;
  }
  body.patient-hub-open main.patient-hub > #patient-home {
    transform: translateX(0);
    opacity: 1;
    visibility: visible;
    box-shadow: var(--shadow-md);
  }
  main.patient-hub > #patient-home .patient-nav a {
    padding: 0.5rem 0.7rem;
  }
}
/* =========================================================================
   PATIENT CARD SEARCH (S26-02, ADR-028)
   Deterministic card-search surface on /app/patient/search. Presented with
   the existing token system; purely additive so first-paint layout is
   unchanged. No JS here — one .card-search CSS (below) drives a tiny scanline
   that flashes only while htmx swaps the results region.
   ========================================================================= */

.card-search-row {
  display: flex;
  align-items: center;
  gap: var(--space);
}
.card-search-input {
  flex: 1 1 auto;
  min-width: 0;
  /* S38 (owner direction): "make the text box bigger and more like a llm chat start box."

     The hero copy that used to sit above this input is GONE, so the input is now the page's visual
     entry point and carries the weight a prompt field does: tall, generously padded, strongly
     rounded, with a soft resting border and an accent focus ring.

     Sized in rem/em rather than a fixed pixel height, so it grows with the user's font preference
     instead of fighting it. `.card-search-row` is `align-items: center`, so the Search button stays
     centred against the taller field with no further change. */
  width: 100%;
  padding: 1.05rem 1.3rem;
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 1.4rem;
  box-shadow: 0 1px 2px rgb(15 23 42 / 0.04);
  transition:
    border-color 120ms ease,
    box-shadow 120ms ease;
}
.card-search-input::placeholder {
  color: var(--muted);
}
.card-search-input:focus,
.card-search-input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgb(11 114 133 / 0.14);
}

/* S38 (owner direction): "Move the search box to the bottom of the screen so that we can later
   continue the conversation."

   Both Discover surfaces (Everyone and Mine) render their composer as the LAST element, so
   `position: sticky; bottom: 0` holds it against the viewport bottom while the results above scroll
   past it. An element with further content after it would instead be pushed UP by that content, which
   is why the ordering in the templates is load-bearing rather than cosmetic.

   STICKY, not `fixed`: a fixed bar leaves the flow, so the last card would sit underneath it and
   would need a bottom padding that has to be kept in sync with the bar's height. Sticky stays in
   flow, so the content ends above it with nothing to measure.

   The tinted background and backdrop blur are REQUIRED, not decorative — without them the results
   show through the bar as they scroll under it. The tint matches the page background so the bar
   reads as part of the page rather than a floating panel. `env(safe-area-inset-bottom)` keeps the
   input clear of the home indicator on phones, where a bottom-pinned control is most likely to
   collide with it. */
.discover-dock {
  position: sticky;
  bottom: 0;
  z-index: 10;
  margin: 1rem 0 0;
  padding: 0.85rem 1rem calc(0.85rem + env(safe-area-inset-bottom));
  background: rgb(244 247 250 / 0.92); /* --bg, near-opaque so results do not bleed through */
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--line);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
/* S38: the sticky container now wraps the BAR **and** the corpus SELECTORS, rather than the bar
   alone. That is what keeps the two visible together — only the dock is sticky, so selectors left in
   the feed would scroll away while the bar stayed pinned. It also makes "below the search bar" a
   structural fact (document order inside the dock) rather than a coincidence of two sticky offsets. */
.discover-dock .card-search-row {
  gap: 0.6rem;
}
.search-indicator {
  flex: 0 0 auto;
  color: var(--muted);
  font-size: var(--fs-sm);
  visibility: hidden;
}
.search-indicator.htmx-request {
  visibility: visible;
}

/* Filter chips — labelled toggles produced server-side from the catalog's
   seen categories/tags (no hard-coded taxonomy drift). */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
}
/* S38 (owner direction): "They should be below the search bar easier to the thumb."

   The selectors render BELOW the bar inside `.discover-dock`, so the thumb reaches the filter row
   without first crossing the input. The base rule's TOP margin belongs to the old position (between
   the header and the results); down here the gap sits ABOVE, separating the row from the bar. */
.filter-chips--dock {
  margin: 0.5rem 0 0;
}
.filter-chips[role='group'] {
  align-items: center;
}
.filter-chips .filter-chips-label {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  margin-right: 0.15rem;
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  font-size: var(--fs-sm);
  font-weight: 550;
  line-height: 1;
  color: var(--ink-2);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
  cursor: pointer;
  transition:
    background 0.12s ease,
    border-color 0.12s ease,
    color 0.12s ease;
}
.filter-chip:hover {
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-color: transparent;
}
.filter-chip:focus-visible {
  box-shadow: var(--focus);
  outline: none;
}
.filter-chip.is-active {
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-color: var(--accent);
}
.filter-chip[aria-pressed='true'] {
  color: #fff;
  background: var(--accent);
  border-color: transparent;
}
.filter-chip .remove {
  font-weight: 700;
}

/* S26-03 (ADR-028): discover scope row — Everyone (public) vs Mine (private). */
.discover-scope {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 1rem;
}
.discover-scope-tab,
.discover-scope-tab:any-link {
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.85rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1;
  color: var(--ink-2);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  text-decoration: none;
  cursor: pointer;
}
.discover-scope-tab:hover {
  color: var(--accent-strong);
  border-color: var(--accent);
}
.discover-scope-tab.is-active {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
}
/* S38: the scope tabs in the HEADER (owner direction: "move the Everyone and Mine tabs to the top
   bar instead of patient marketplace").

   The base rule carries `margin: 0 0 1rem`, which exists for its old IN-CONTENT position (above the
   results, below the input). Inside the sticky header that bottom margin would push the tab row off
   the header's centre line, so the top-bar variant resets it. The pills keep their shape, so the row
   reads as a segmented control next to the wordmark rather than as a second toolbar. */
.discover-scope--top {
  margin: 0;
  gap: 0.25rem;
  flex-wrap: nowrap;
}
.discover-scope--top .discover-scope-tab {
  padding: 0.3rem 0.7rem;
  white-space: nowrap;
}

/* S26-03 Mine (private records) discover body. */
.patient-mine-fragment {
  display: block;
}
.patient-mine-fragment .mine-privacy-note {
  margin: 0 0 0.75rem;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.patient-mine-fragment .mine-body {
  display: block;
}

/* S27-01 Mine-scoped search (owner-only). Reuses the .card-search shell; only
   the summary/spacing chrome is new. Separated from the Everyone/public bar so
   searching on the Mine tab never reaches public catalog/advisory content. */
.patient-mine-fragment .mine-search {
  margin: 0 0 0.75rem; /* card-search form wrapper inside Mine */
}
.mine-search-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.75rem;
  margin: 0.75rem 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.mine-search-clear {
  margin-left: auto;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent-strong);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.mine-no-match {
  margin: 1rem 0 0;
  padding: 0.8rem 1rem;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

/* S27-03 (DP-27-1 safe direction): Mine may ALSO reach public guidance. While a
   Mine search is active (?q= non-empty) the worker resolves the same public
   Everyone result set (providers + advisory) and renders it as an additive,
   clearly-labelled block BELOW the owner-record .mine-body. Owner records never
   appear here and public cards never enter the record body above. */
.mine-public {
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.mine-public-title {
  margin: 0 0 0.35rem;
  font-size: var(--fs-h3);
  color: var(--ink);
}
.mine-public-note {
  margin: 0 0 0.4rem;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.mine-public .result-card-list {
  margin-top: 0.9rem;
}
.mine-public .result-card {
  background: var(--surface);
}

/* Ranked result cards. */
.result-card-list {
  display: grid;
  gap: 0.75rem;
  margin: 0.9rem 0 0;
  padding: 0;
  list-style: none;
}
.result-card {
  display: block;
  padding: 0.9rem calc(var(--space) * 1.1);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}
.result-card .card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.35rem 0.75rem;
}
.result-card .card-title {
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: 680;
  color: var(--ink);
}
.result-card .card-specialty {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.5rem;
  font-size: var(--fs-xs);
  font-weight: 550;
  color: var(--accent-strong);
  background: var(--accent-soft);
  border-radius: 999px;
  white-space: nowrap;
}
.result-card .card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  margin: 0.5rem 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.result-card .card-price {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
}
.result-card .card-rating {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.result-card .card-summary {
  margin: 0.5rem 0 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
}
.result-card .card-why {
  margin: 0.55rem 0 0;
  padding: 0.45rem 0.6rem;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  background: var(--surface-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.result-card .card-why .why-label {
  font-weight: 620;
  color: var(--accent-strong);
}
.result-card .card-cta {
  display: inline-flex;
  align-items: center;
  margin: 0.65rem 0 0;
  padding: 0.5rem 0.95rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: #fff;
  background: var(--accent);
  border-radius: 0.375rem;
  text-decoration: none;
  transition: background 0.12s ease;
}
.result-card .card-cta:hover {
  background: var(--accent-strong);
}
.result-card .card-cta:focus-visible {
  outline: none;
  box-shadow: var(--focus);
}
.result-card[data-score] {
  position: relative;
}
.result-card[data-score]::after {
  content: attr(data-score);
  position: absolute;
  top: 0.6rem;
  right: 0.65rem;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* S26-05 Discover polish (ADR-028): header subline + guided empty/landing states. */
/* S38: `.discover-sub` is REMOVED as dead CSS, together with the hero copy it styled.

   Owner direction: "Remove the copy - Everything in one search / Search verified doctors, clinics,
   and trusted health guidance — all in one place." The paragraph it styled no longer renders, so
   the rule has no element to match. Kept as a note rather than left in place because a selector for
   a deleted element is the kind of thing that later reads as "this is still used". */
.discover-empty {
  margin: 1.1rem 0 0;
  padding: 1.25rem 1.35rem;
  background: var(--surface);
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}
.discover-empty-title {
  margin: 0 0 0.3rem;
  font-size: var(--fs-h3);
  font-weight: 680;
  color: var(--ink);
}
.discover-empty-copy {
  margin: 0 0 0.8rem;
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 44rem;
}
.suggest-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* =========================================================================
   S28-01 — Immersive Discover home (patient shell). Mirrored additive block:
   patient == admin carry this byte-identical; the worker-origin provider shell
   carries the same new classes. Discover is the immersive patient home and no
   card region renders outside the two tabs.
   ========================================================================= */

/* Primary content: the immersive Discover two-tab surface fills the content
   column and lays out spaciously. */
main.patient-hub > #patient-search.hub-discover {
  display: block;
  min-height: calc(100vh - var(--nav-h) - 3rem);
  padding: 0.25rem 0 1.5rem;
}
main.patient-hub > #patient-search.hub-discover .patient-everyone-fragment,
main.patient-hub > #patient-search.hub-discover .patient-mine-fragment {
  width: 100%;
  max-width: 60rem;
}

/* Real-action regions (capture/reminders/feedback/appointments) are hidden until
   a user opens a form — they are not competing card stacks on the immersive home. */
main.patient-hub > .patient-action-region:empty {
  display: none;
}
main.patient-hub > .patient-action-region:not(:empty) {
  padding-bottom: 1.5rem;
}

/* Rail section labels + reserved non-card slot. */
.patient-nav-label {
  display: block;
  margin: 0.9rem 0 0.3rem;
  padding: 0 0.2rem;
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.patient-nav-label:first-child {
  margin-top: 0.4rem;
}
.patient-nav-placeholder {
  display: block;
  padding: 0.55rem 0.85rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* Mine browse overview (S28-01): owner cards folded together under Mine. */
.mine-overview {
  display: block;
}
.mine-overview > * + * {
  margin-top: 1.4rem;
}

/* ---- S36 D52: per-lane result tabs + panes ------------------------------------------------
 *
 * The tab row sits above the single swappable results region; each tab is an ordinary link
 * (hx-get with a full href), so this works with JS disabled.
 *
 * Panes are all rendered server-side and all but the active one carry `hidden`, so switching
 * tabs is a plain navigation and needs no client state. `[hidden]` is set explicitly rather
 * than relying on the default, because a flex/grid parent can override `display: none`. */
.list-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0 0 0.75rem;
  border-bottom: 1px solid var(--border, #e5e7eb);
}
.list-tab {
  padding: 0.4rem 0.75rem;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: 0.5rem 0.5rem 0 0;
  font-size: 0.875rem;
  text-decoration: none;
  color: inherit;
  opacity: 0.7;
}
.list-tab:hover {
  opacity: 1;
}
.list-tab.is-active {
  border-color: var(--border, #e5e7eb);
  background: var(--surface, #fff);
  font-weight: 600;
  opacity: 1;
}
.lane-pane[hidden] {
  display: none;
}

/* ---- S36 D52: per-source card facts -------------------------------------------------------
 *
 * The corpora share only `id`, so each card renders whatever its own source knows
 * (`generic_name`, `brand_name`, `therapeutic_class`, `also_called`, …) as a labelled list. The
 * labels come from the data, so this styling must work for any label/value pair rather than for a
 * fixed set of columns.
 *
 * Two columns with `auto` on the label so the values line up down the card without a hardcoded
 * width — the labels differ per corpus (`generic_name` vs `therapeutic_class`), so any fixed
 * width would either clip the long ones or leave a gap after the short ones. */
.card-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.6rem;
  margin: 0.4rem 0 0;
  font-size: 0.8rem;
}
.card-fact-label {
  color: var(--muted, #6b7280);
  /* The labels are machine-ish keys; make that legible rather than pretending they are prose. */
  font-variant: small-caps;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.card-fact-value {
  margin: 0;
  overflow-wrap: anywhere;
}
