/* MOYO Registry — served from this origin, no CDN.
   Clinics on this deployment run older tablets and intermittent connectivity,
   so this is one small stylesheet with no external fonts or assets. */

:root {
  --brand: #8a1538;
  --brand-dark: #6b1029;
  /* Pale maroon wash, for row hovers and secondary button states. */
  --brand-tint: #fbeef2;
  --brand-edge: #e6c3ce;
  --ink: #1c2530;
  --ink-muted: #5b6876;
  --line: #e2dcde;
  --surface: #ffffff;
  --canvas: #f7f4f5;
  --ok: #2f9e8f;
  --warn: #d98324;
  --danger: #c0392b;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(45, 20, 28, 0.08), 0 4px 14px rgba(45, 20, 28, 0.05);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--canvas);
}

a { color: var(--brand); }
h1, h2, h3 { line-height: 1.25; margin: 0 0 0.5rem; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.05rem; }

/* ---------- Layout ---------- */

/* Sidebar shell. .app-main carries min-width:0 so a wide table scrolls inside
   its own container instead of stretching the flex row and pushing the
   sidebar off screen. */

.app-shell { display: flex; min-height: 100vh; align-items: stretch; }

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

.sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--brand-dark);
  color: #fff;
  display: flex;
  flex-direction: column;
  padding: 1.25rem 0 0;
  /* Sticky and viewport-tall, so Sign out and the account details stay
     reachable instead of sitting at the foot of a long dashboard. Scrolls
     internally if the nav ever outgrows the screen. */
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  overflow-y: auto;
}

.sidebar .brand {
  display: block;
  padding: 0 1.25rem 1.25rem;
  font-weight: 700;
  font-size: 1.2rem;
  line-height: 1.1;
  letter-spacing: 0.04em;
  color: #fff;
  text-decoration: none;
}
.sidebar .brand-sub {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: rgba(255, 255, 255, 0.62);
  margin-top: 0.15rem;
}

.sidebar-nav { display: flex; flex-direction: column; flex: 1; }

.nav-heading {
  padding: 1rem 1.25rem 0.35rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.5);
}

.sidebar-nav a {
  display: block;
  padding: 0.55rem 1.25rem;
  color: rgba(255, 255, 255, 0.82);
  text-decoration: none;
  font-size: 0.94rem;
  border-left: 3px solid transparent;
}
.sidebar-nav a:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.sidebar-nav a.active {
  background: rgba(255, 255, 255, 0.14);
  border-left-color: #fff;
  color: #fff;
  font-weight: 600;
}

.sidebar-account {
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  padding: 0.9rem 1.25rem 1.1rem;
  font-size: 0.82rem;
}
.account-name { font-weight: 600; color: #fff; }
.account-meta { color: rgba(255, 255, 255, 0.62); margin-bottom: 0.6rem; }
.account-actions { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.account-actions form { margin: 0; }
.account-actions a,
.account-actions button {
  font: inherit;
  font-size: 0.8rem;
  padding: 0.3rem 0.6rem;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: transparent;
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}
.account-actions a:hover,
.account-actions button:hover {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
}

main { width: 100%; max-width: 1140px; margin: 0 auto; padding: 1.5rem; flex: 1; }

/* ---------- Small screens: the sidebar becomes a drawer ---------- */

/* Focusable but invisible: keyboard users tab to it and press Space, and the
   focus ring is drawn on the label instead. */
.nav-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.mobile-bar { display: none; }
.nav-scrim { display: none; }

/* The breakpoint sits above 1024 deliberately: an iPad in landscape is
   exactly that, and the patient list and audit trail are eight-column tables
   that need the full width more than they need a pinned sidebar. */
@media (max-width: 1080px) {
  .app-shell { display: block; }

  .mobile-bar {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--brand-dark);
    color: #fff;
    padding: 0.6rem 1rem;
  }
  .mobile-brand {
    color: #fff;
    text-decoration: none;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.06em;
  }

  .nav-toggle-button {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.7rem;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 6px;
    color: #fff;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    user-select: none;
  }
  .nav-toggle-button:hover { background: rgba(255, 255, 255, 0.12); }

  /* Three bars drawn in CSS: no icon font, no image request. */
  .nav-toggle-button .bars,
  .nav-toggle-button .bars::before,
  .nav-toggle-button .bars::after {
    display: block;
    width: 16px;
    height: 2px;
    background: #fff;
    border-radius: 2px;
  }
  .nav-toggle-button .bars { position: relative; }
  .nav-toggle-button .bars::before,
  .nav-toggle-button .bars::after { content: ''; position: absolute; left: 0; }
  .nav-toggle-button .bars::before { top: -5px; }
  .nav-toggle-button .bars::after { top: 5px; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 260px;
    max-width: 82vw;
    height: 100vh;
    z-index: 40;
    align-self: auto;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    box-shadow: 0 0 24px rgba(0, 0, 0, 0.35);
  }
  .nav-toggle:checked ~ .app-shell .sidebar { transform: translateX(0); }

  .nav-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 35;
    background: rgba(20, 8, 12, 0.5);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .nav-toggle:checked ~ .app-shell .nav-scrim { opacity: 1; pointer-events: auto; }

  /* Draw the focus ring on the label, since the checkbox itself is invisible. */
  .nav-toggle:focus-visible ~ .app-shell .nav-toggle-button {
    outline: 2px solid #fff;
    outline-offset: 2px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sidebar, .nav-scrim { transition: none; }
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.page-head p { margin: 0; color: var(--ink-muted); }

/* ---------- Cards and grids ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.25rem;
  margin-bottom: 1.25rem;
}
.card > h2, .card > h3 { margin-top: 0; }

.grid { display: grid; gap: 1.25rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 1.25rem; }
.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
}
.stat .stat-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-muted); }
.stat .stat-value { font-size: 1.75rem; font-weight: 700; }
.stat .stat-note { font-size: 0.8rem; color: var(--ink-muted); }

/* ---------- Tables ---------- */

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
th, td { text-align: left; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-muted); background: #faf7f8; }
tbody tr:hover { background: var(--brand-tint); }
td.numeric, th.numeric { text-align: right; font-variant-numeric: tabular-nums; }

.duplicate-warning {
  border-left: 4px solid var(--warn);
  background: #fffaf3;
}
.duplicate-warning h2 { color: #8a4f11; }

.plain-list { margin: 0; padding-left: 1.1rem; }
.plain-list li { margin-bottom: 0.5rem; }

.empty-state { color: var(--ink-muted); font-style: italic; padding: 1rem 0; }

/* ---------- Badges and alerts ---------- */

.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: #f0ebed;
  color: var(--ink-muted);
}
.badge-low, .badge-ok, .badge-sent, .badge-active { background: #e3f4f1; color: #1f6f64; }
.badge-medium, .badge-queued { background: #fdf0e2; color: #8a4f11; }
.badge-high, .badge-danger, .badge-failed { background: #fbe9e7; color: #8f2c21; }

.alert-list { list-style: none; margin: 0; padding: 0; }
.alert-list li {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--line);
}
.alert-list li:last-child { border-bottom: none; }
.alert-count { font-size: 1.25rem; font-weight: 700; min-width: 2.5rem; }
.alert-high .alert-count { color: var(--danger); }
.alert-medium .alert-count { color: var(--warn); }
.alert-low .alert-count { color: var(--ink-muted); }
.alert-detail { display: block; font-size: 0.82rem; color: var(--ink-muted); }

.flash { padding: 0.75rem 1rem; border-radius: var(--radius); margin-bottom: 1rem; border: 1px solid; }
.flash-success { background: #e8f6f3; border-color: #a9ddd3; color: #1f6f64; }
.flash-error { background: #fdecea; border-color: #f2bcb5; color: #8f2c21; }
.flash-info, .flash-message { background: var(--brand-tint); border-color: var(--brand-edge); color: var(--brand-dark); }

/* ---------- Charts ---------- */

.chart svg { width: 100%; max-width: 220px; height: auto; }
.chart-donut { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }
.donut-total { font-size: 26px; font-weight: 700; fill: var(--ink); }
.donut-caption { font-size: 10px; fill: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.08em; }

.chart-legend { list-style: none; margin: 0; padding: 0; font-size: 0.9rem; }
.chart-legend li { display: flex; align-items: center; gap: 0.5rem; padding: 0.2rem 0; }
.swatch { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
.legend-label { flex: 1; }
.legend-value { font-weight: 600; font-variant-numeric: tabular-nums; }

.chart-bars { list-style: none; margin: 0; padding: 0; }
.bar-row { display: grid; grid-template-columns: 8.5rem 1fr 3rem; align-items: center; gap: 0.75rem; padding: 0.25rem 0; font-size: 0.88rem; }
.bar-label { color: var(--ink-muted); }
.bar-track { background: #f0ebed; border-radius: 999px; height: 0.7rem; overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: 999px; }
.bar-value { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }

/* Vertical bars for a time series. */
.chart-columns {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: flex-end;
  gap: 0.4rem;
  height: 190px;
  overflow-x: auto;
}
.column { display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  flex: 1; min-width: 2.6rem; height: 100%; }
.column-value { font-size: 0.72rem; font-weight: 600; color: var(--ink-muted); margin-bottom: 0.2rem; }
.column-bar { display: block; width: 100%; max-width: 2.2rem; border-radius: 4px 4px 0 0; }
.column-label { font-size: 0.7rem; color: var(--ink-muted); margin-top: 0.35rem; white-space: nowrap; }

/* Cascade: each step as a share of the first. */
.chart-funnel { list-style: none; margin: 0; padding: 0; }
.funnel-step { margin-bottom: 0.9rem; }
.funnel-label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 0.25rem; }
.funnel-track { display: block; position: relative; background: #f0ebed; border-radius: 6px;
  height: 1.7rem; overflow: hidden; }
.funnel-fill { display: block; height: 100%; background: var(--brand); border-radius: 6px; }
.funnel-count { position: absolute; left: 0.6rem; top: 0; line-height: 1.7rem;
  font-size: 0.82rem; font-weight: 600; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.35); }
.funnel-detail { display: block; font-size: 0.78rem; color: var(--ink-muted); margin-top: 0.2rem; }

.chart-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-muted);
  font-style: italic;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}

/* ---------- Forms ---------- */

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; }
.field { display: flex; flex-direction: column; gap: 0.3rem; }
.field.field-wide { grid-column: 1 / -1; }
.field label { font-size: 0.85rem; font-weight: 600; color: var(--ink-muted); }
.field input, .field select, .field textarea {
  font: inherit;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid rgba(138, 21, 56, 0.35);
  border-color: var(--brand);
}
.field textarea { min-height: 90px; resize: vertical; }
.field .hint { font-size: 0.78rem; color: var(--ink-muted); }
.field .field-error { font-size: 0.8rem; color: var(--danger); }
.field-checkbox { flex-direction: row; align-items: center; gap: 0.5rem; }
.field-checkbox input { width: auto; }
.field-checkbox label { font-weight: 500; color: var(--ink); }

.form-actions { margin-top: 1.25rem; display: flex; gap: 0.75rem; align-items: center; }

/* WTForms renders SubmitField as <input type="submit">, so it has to be
   styled alongside real buttons. */
button, .button, input[type="submit"] {
  font: inherit;
  font-weight: 600;
  padding: 0.6rem 1.2rem;
  border-radius: 8px;
  border: 1px solid transparent;
  background: var(--brand);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
button:hover, .button:hover, input[type="submit"]:hover { background: var(--brand-dark); }
.button-secondary, .link-button {
  background: transparent;
  color: var(--brand);
  border-color: var(--line);
}
.button-secondary:hover, .link-button:hover { background: var(--brand-tint); color: var(--brand-dark); }

/* Per-row action buttons. Each is its own POST form, so they need to sit
   side by side rather than stack. */
.row-actions { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.row-actions form { margin: 0; display: flex; gap: 0.35rem; align-items: center; }
.row-actions button { padding: 0.3rem 0.6rem; font-size: 0.8rem; }
.inline-link-form select { font: inherit; font-size: 0.8rem; padding: 0.25rem; max-width: 14rem;
  border: 1px solid var(--line); border-radius: 6px; }

/* A generated password, shown once and never again. */
code.secret {
  display: inline-block;
  font-family: ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.2rem 0.5rem;
  user-select: all;
}

.scan-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 4px solid var(--brand);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.85rem 1rem;
  margin-bottom: 1.25rem;
}
.scan-bar label { font-size: 0.85rem; font-weight: 600; color: var(--ink-muted); }
.scan-bar input {
  font: inherit;
  flex: 1;
  min-width: 12rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
}
.scan-bar input:focus { outline: 2px solid rgba(138, 21, 56, 0.35); border-color: var(--brand); }

.search-bar { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
.search-bar input { flex: 1; max-width: 380px; }
.search-bar select { font: inherit; padding: 0.5rem 0.7rem; border: 1px solid var(--line); border-radius: 8px; background: #fff; }

/* ---------- Sign in ---------- */

.auth-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 1.5rem; }
.auth-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 2rem; width: 100%; max-width: 380px; }
.auth-card h1 { color: var(--brand); margin-bottom: 0.25rem; }
.auth-card .subtitle { color: var(--ink-muted); font-size: 0.9rem; margin: 0 0 1.5rem; }
.auth-card button, .auth-card input[type="submit"] { width: 100%; margin-top: 0.5rem; }

/* ---------- Pagination ---------- */

.pagination { display: flex; gap: 0.5rem; align-items: center; margin-top: 1rem; font-size: 0.9rem; }
.pagination .current { color: var(--ink-muted); }

/* ---------- Misc ---------- */

.definition-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.85rem; margin: 0; }
.definition-list div { display: flex; flex-direction: column; }
.definition-list dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-muted); }
.definition-list dd { margin: 0; font-weight: 600; }

.error-page { text-align: center; padding: 4rem 1.5rem; }
.error-page .code { font-size: 4rem; font-weight: 700; color: var(--brand); line-height: 1; }

.site-footer { text-align: center; color: var(--ink-muted); font-size: 0.8rem; padding: 1.5rem; }

/* ---------- Merging duplicate records ---------- */

/* Two records side by side. Below 900px they stack, because on a phone a
   two-column comparison of clinical detail is unreadable and this decision
   should never be made from a screen too small to read both sides. */
.merge-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-bottom: 1.5rem; }
@media (max-width: 900px) { .merge-compare { grid-template-columns: 1fr; } }

.merge-side { border: 1px solid var(--line); border-radius: var(--radius); padding: 1rem 1.1rem; }
.merge-side-keep { border-color: var(--brand-edge); background: var(--brand-tint); }
.merge-side h3 { margin: 0.15rem 0 0.75rem; }
.merge-role { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; color: var(--ink-muted); }
.merge-side-keep .merge-role { color: var(--brand); }

.merge-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 0.7rem; margin: 0 0 1rem; }
.merge-facts div { display: flex; flex-direction: column; }
.merge-facts dt { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-muted); }
.merge-facts dd { margin: 0; font-weight: 600; font-size: 0.9rem; }

.merge-history h4 { margin: 0.75rem 0 0.35rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-muted); }
.merge-history ul { margin: 0; padding-left: 1.1rem; font-size: 0.87rem; }
.merge-history li { margin-bottom: 0.2rem; }
.merge-history .empty-state { padding: 0; font-size: 0.87rem; }

/* The merge itself, and withdrawal: destructive enough to be worth its own
   colour rather than sharing the ordinary submit button. */
.button-danger, button.button-danger {
  background: var(--danger); color: #fff; border: 1px solid var(--danger);
}
.button-danger:hover, button.button-danger:hover { background: #a3301f; border-color: #a3301f; }

/* Shown on a patient record that lost a merge, and on one with an open
   duplicate suggestion. */
.merge-notice { border-left: 4px solid var(--brand); background: var(--brand-tint); padding: 0.85rem 1rem; border-radius: var(--radius); margin-bottom: 1.25rem; font-size: 0.9rem; }
.merge-notice strong { color: var(--brand-dark); }

/* ---------- Preview deployment banner ---------- */

/* A preview is on the public internet and looks identical to the real thing.
   This is the only thing distinguishing them, so it is deliberately loud,
   full width, and cannot be dismissed. The stripes read as "not finished"
   at a glance, before anyone has read a word of it. */
.preview-banner {
  background: repeating-linear-gradient(
    135deg, #fdf0e2, #fdf0e2 12px, #fae4cd 12px, #fae4cd 24px);
  border-bottom: 2px solid var(--warn);
  color: #7a3f06;
  padding: 0.85rem 1.5rem;
  font-size: 0.9rem;
  line-height: 1.5;
}
.preview-banner strong { color: #5c2f04; }

/* Inside the sign-in card, where it is a block in a narrow column rather
   than a full-width bar across the top of the app. */
.preview-banner-inline {
  border: 1px solid var(--warn); border-radius: var(--radius);
  margin-bottom: 1.25rem; font-size: 0.85rem; padding: 0.75rem 0.9rem;
}

@media print {
  /* A printed page from a preview must still say so: a screenshot or a
     printout is exactly how one gets mistaken for the real registry. */
  .preview-banner { background: none; border-bottom: 2px solid #000; }
}
@media print {
  .sidebar, .mobile-bar, .nav-scrim, .site-footer,
  .form-actions, .search-bar, .pagination { display: none; }
  .app-shell { display: block; }
  body { background: #fff; }
  .card { box-shadow: none; break-inside: avoid; }
}
