/* @import url() FONT IMPORTS MUST ALWAYS BE AT THE VERY TOP OF THIS FILE */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');

/* ============================================================
   BioDrive — Shared Stylesheet
   AI-powered pharmaceutical replenishment platform
   Aesthetic: GREEN + WHITE — shares the marketing homepage's palette
   and Inter typeface (Css/landing.css) so the signed-in product feels
   like the same brand as the public site, not a different app.
   - White backgrounds
   - Green variations for borders, buttons, accents
   - Dark grey text for readability
   Layout strategy: Flexbox for page shell, CSS Grid for widgets
   ============================================================ */

/* ----------------------------------------------------------
   1. Design Tokens (CSS Custom Properties)
   Centralised green palette so the whole UI stays consistent.
   ---------------------------------------------------------- */
:root {
  /* Green scale (light -> dark) — matches Css/landing.css's --g-* scale */
  --g-50:  #E8F5E9;   /* tint backgrounds / hover fills */
  --g-100: #C8E6C9;   /* subtle surfaces */
  --g-200: #A5D6A7;   /* borders */
  --g-300: #81C784;   /* secondary accents */
  --g-500: #4CAF50;   /* primary brand green */
  --g-600: #43A047;   /* buttons / strong accents */
  --g-700: #388E3C;   /* button hover / headings */
  --g-900: #1B5E20;   /* deep green for sidebar */

  /* Neutrals */
  --white:    #ffffff;   /* fixed white — text/icons sitting on a solid accent background (buttons, avatar, badges); NEVER redefined per theme */
  --surface:  #ffffff;   /* the actual "card background" role — this is what changes in dark mode */
  --grey-50:  #F6F9F6;   /* app canvas background */
  --grey-200: #DCE7DC;   /* hairline dividers */
  --text-dark:  #333333; /* primary readable text (dark grey) */
  --text-muted: #6b7280; /* secondary text */

  /* Fixed sidebar tones — the sidebar is permanently dark-green (--g-900) in
     both themes, so its own text/overlay colors never need to invert. Pinned
     separately from --g-50/200/300 because those get redefined for dark
     mode's badge/wash backgrounds elsewhere on the page. */
  --sidebar-ink:        #E8F5E9;
  --sidebar-ink-2:      #A5D6A7;
  --sidebar-ink-muted:  #81C784;

  /* Status helpers (kept within green/neutral family) */
  --ok:    var(--g-600);
  --warn:  #b08400;      /* amber, used sparingly for low stock */
  --danger:#a23b3b;      /* muted red, critical only */
  --warn-bg:      #fdf6e3;
  --warn-border:  #ecd9a0;
  --danger-bg:    #fbeaea;
  --danger-border:#e7bcbc;

  /* Geometry */
  --radius: 12px;
  --radius-sm: 8px;
  --radius-lg: 18px;
  --shadow: 0 2px 10px rgba(76, 175, 80, 0.10);
  --shadow-md: 0 8px 24px -6px rgba(27, 94, 32, 0.14), 0 2px 6px rgba(27, 94, 32, 0.06);
  --shadow-lg: 0 20px 48px -12px rgba(15, 23, 21, 0.22);
  --sidebar-width: 260px;
  --sidebar-width-collapsed: 76px;
}

/* ----------------------------------------------------------
   1b. Dark theme — same tokens, redefined. An explicit user choice
   (`data-theme` set by Js/shell.js) always wins over the OS/browser
   preference: both attribute selectors below carry higher specificity
   than the plain `:root`/media-query blocks, regardless of source order.
   `--white`, `--sidebar-ink*` and the `--g-500..900` accent steps are
   deliberately absent here — see the comments above for why they must
   stay identical across both themes.
   ---------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root {
    --g-50:  #17251A;
    --g-100: #1D2E20;
    --g-200: #26402A;
    --g-300: #2E4D33;

    --surface:  #1E2420;
    --grey-50:  #14181A;
    --grey-200: #2C3530;
    --text-dark:  #E7ECE8;
    --text-muted: #9BA7A0;

    --warn:  #E7B54B;
    --danger:#E2685F;
    --warn-bg:      #3A2E12;
    --warn-border:  #5C4820;
    --danger-bg:    #3A1F1F;
    --danger-border:#5C2F2F;

    --shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
    --shadow-md: 0 8px 24px -6px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 20px 48px -12px rgba(0, 0, 0, 0.55);
  }
}
:root[data-theme="dark"] {
  --g-50:  #17251A;
  --g-100: #1D2E20;
  --g-200: #26402A;
  --g-300: #2E4D33;

  --surface:  #1E2420;
  --grey-50:  #14181A;
  --grey-200: #2C3530;
  --text-dark:  #E7ECE8;
  --text-muted: #9BA7A0;

  --warn:  #E7B54B;
  --danger:#E2685F;
  --warn-bg:      #3A2E12;
  --warn-border:  #5C4820;
  --danger-bg:    #3A1F1F;
  --danger-border:#5C2F2F;

  --shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 8px 24px -6px rgba(0, 0, 0, 0.45), 0 2px 6px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 20px 48px -12px rgba(0, 0, 0, 0.55);
}
:root[data-theme="light"] {
  --g-50:  #E8F5E9;
  --g-100: #C8E6C9;
  --g-200: #A5D6A7;
  --g-300: #81C784;

  --surface:  #ffffff;
  --grey-50:  #F6F9F6;
  --grey-200: #DCE7DC;
  --text-dark:  #333333;
  --text-muted: #6b7280;

  --warn:  #b08400;
  --danger:#a23b3b;
  --warn-bg:      #fdf6e3;
  --warn-border:  #ecd9a0;
  --danger-bg:    #fbeaea;
  --danger-border:#e7bcbc;

  --shadow: 0 2px 10px rgba(76, 175, 80, 0.10);
  --shadow-md: 0 8px 24px -6px rgba(27, 94, 32, 0.14), 0 2px 6px rgba(27, 94, 32, 0.06);
  --shadow-lg: 0 20px 48px -12px rgba(15, 23, 21, 0.22);
}

/* ----------------------------------------------------------
   2. Base Reset & Typography
   ---------------------------------------------------------- */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  font-family: 'Inter', system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
  background-color: var(--grey-50);
  color: var(--text-dark);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
  text-decoration: none;
}

/* Inline SVG icons (see the sprite embedded near the top of <body> on every
   page, same technique as the landing page). Recolors with currentColor, so
   dark mode needs no separate icon assets — every container below just sets
   a size; colour always comes from the surrounding text/button colour. */
.icon {
  width: 1em;
  height: 1em;
  display: inline-block;
  vertical-align: -0.125em;
  flex-shrink: 0;
}

/* ----------------------------------------------------------
   3. Page Shell — Flexbox
   Fixed sidebar on the left, scrollable main content on right.
   ---------------------------------------------------------- */
.app {
  display: flex;
  min-height: 100vh;
}

/* ---- Sidebar ---- */
.sidebar {
  position: fixed;          /* fixed left-hand navigation */
  top: 0;
  left: 0;
  width: var(--sidebar-width);
  height: 100vh;
  background-color: var(--g-900);
  color: var(--sidebar-ink);
  display: flex;
  flex-direction: column;
  padding: 24px 0;
  transition: width 0.22s ease;
  z-index: 50;
}

/* Brand / logo block */
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 24px 24px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.sidebar__mobile-close .icon {
  width: 16px;
  height: 16px;
}
.sidebar__mobile-close {
  display: none;
  margin-left: auto;
  width: 30px;
  height: 30px;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--sidebar-ink-2);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.sidebar__mobile-close:hover {
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--sidebar-ink);
}

.brand__mark {
  width: 48px;
  height: auto;
  aspect-ratio: 513 / 238;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.brand__mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.brand__name {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.3px;
}

.brand__sub {
  display: block;
  font-size: 11px;
  font-weight: 400;
  color: var(--sidebar-ink-2);
  letter-spacing: 0.5px;
  text-transform: uppercase;
}

/* Navigation list */
.nav {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 0 14px;
}

.nav__label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--sidebar-ink-muted);
  padding: 14px 12px 6px;
}

.nav__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  color: var(--sidebar-ink);
  font-size: 14.5px;
  transition: background-color 0.15s ease;
}

.nav__item:hover {
  background-color: rgba(255, 255, 255, 0.07);
}

/* Active route highlight uses brand green + a left accent bar (inset so it
   doesn't need the nav list to become position:relative/overflow:visible) */
.nav__item--active {
  background-color: var(--g-600);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--white);
}

.nav__icon {
  display: inline-flex;
  width: 18px;
  align-items: center;
  justify-content: center;
  opacity: 0.9;
  flex-shrink: 0;
}
.nav__icon .icon {
  width: 18px;
  height: 18px;
}

.nav__item-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- Collapsible sidebar rail — toggled via .app.is-sidebar-collapsed,
   see Js/shell.js's initSidebarCollapse(). Icon-only rail; identity avatar
   and reset link stay reachable, everything else fades to icons only. ---- */
.sidebar__collapse {
  padding: 10px 24px 4px;
}
.sidebar__collapse-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-sm);
  color: var(--sidebar-ink-2);
  font-size: 12.5px;
  padding: 8px 12px;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.sidebar__collapse-btn:hover {
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--sidebar-ink);
}
.sidebar__collapse-icon {
  display: inline-flex;
  transition: transform 0.22s ease;
}
.sidebar__collapse-icon .icon {
  width: 16px;
  height: 16px;
}

.app.is-sidebar-collapsed .sidebar {
  width: var(--sidebar-width-collapsed);
}
.app.is-sidebar-collapsed .main {
  margin-left: var(--sidebar-width-collapsed);
}
.app.is-sidebar-collapsed .brand {
  justify-content: center;
  padding: 0 0 24px;
}
.app.is-sidebar-collapsed .brand > div,
.app.is-sidebar-collapsed .nav__label,
.app.is-sidebar-collapsed .nav__item-label,
.app.is-sidebar-collapsed .sidebar__footer > div:not(.avatar),
.app.is-sidebar-collapsed .sidebar__meta,
.app.is-sidebar-collapsed .sidebar__collapse-btn .nav__item-label {
  display: none;
}
.app.is-sidebar-collapsed .nav__item {
  justify-content: center;
  padding: 11px 0;
}
.app.is-sidebar-collapsed .sidebar__footer {
  justify-content: center;
  padding: 16px 0 0;
}
.app.is-sidebar-collapsed .sidebar__collapse-btn {
  justify-content: center;
}
.app.is-sidebar-collapsed .sidebar__collapse-icon {
  transform: rotate(180deg);
}

/* User card pinned to bottom of sidebar */
.sidebar__footer {
  margin-top: auto;
  padding: 16px 24px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  align-items: center;
  gap: 12px;
}

.avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background-color: var(--g-500);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 14px;
  flex-shrink: 0;
}

.avatar--sm {
  width: 28px;
  height: 28px;
  font-size: 11.5px;
}

.sidebar__footer small {
  display: block;
  color: var(--sidebar-ink-muted);
  font-size: 12px;
}

.sidebar__meta {
  padding: 12px 24px 20px;
  font-size: 11px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.4);
}

.sidebar__meta button {
  display: inline;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--sidebar-ink-muted);
  text-decoration: underline;
  cursor: pointer;
}

/* ---- Main content column ---- */
.main {
  flex: 1;
  margin-left: var(--sidebar-width); /* clears the fixed sidebar */
  display: flex;
  flex-direction: column;
  min-width: 0;
  transition: margin-left 0.22s ease;
}

/* Top header bar inside main — sticky + softly translucent so content
   scrolls underneath it, matching the elevated-shell look while staying
   plain CSS (no JS scroll listener needed). */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background-color: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--grey-200);
  padding: 14px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.hamburger-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--text-dark);
  cursor: pointer;
}
.hamburger-btn .icon {
  width: 18px;
  height: 18px;
}
.hamburger-btn:hover {
  background-color: var(--g-50);
}

.topbar__heading {
  min-width: 0;
}

.breadcrumbs {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 3px;
}
.breadcrumbs__sep {
  color: var(--grey-200);
}
.breadcrumbs__current {
  color: var(--g-700);
  font-weight: 600;
}

.topbar h1 {
  font-size: 22px;
  color: var(--text-dark);
}

.topbar p {
  font-size: 13.5px;
  color: var(--text-muted);
}

.topbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* ---- Profile menu (topbar) ---- */
.profile-menu {
  position: relative;
}
.profile-menu__trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px 4px 4px;
  border: 1px solid var(--grey-200);
  border-radius: 999px;
  background-color: var(--surface);
  color: var(--text-dark);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.profile-menu__trigger:hover {
  background-color: var(--g-50);
}
.profile-menu__name {
  font-size: 13px;
  font-weight: 600;
}
.profile-menu__chevron {
  font-size: 9px;
  color: var(--text-muted);
}
.profile-menu__panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 40;
  width: 240px;
  background-color: var(--surface);
  border: 1px solid var(--g-200);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.profile-menu__head {
  padding: 14px;
  border-bottom: 1px solid var(--grey-200);
}
.profile-menu__head strong {
  display: block;
  font-size: 13.5px;
  color: var(--text-dark);
}
.profile-menu__head small {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  color: var(--text-muted);
}
.profile-menu__item {
  display: block;
  padding: 11px 14px;
  font-size: 13px;
  color: var(--text-dark);
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  transition: background-color 0.15s ease;
}
.profile-menu__item:hover {
  background-color: var(--g-50);
}
.profile-menu__item--danger {
  color: var(--danger);
}
.profile-menu__item--danger:hover {
  background-color: var(--danger-bg);
}

.content {
  padding: 28px 32px 48px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

/* ----------------------------------------------------------
   4. Buttons
   ---------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 18px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

/* Primary — solid green */
.btn--primary {
  background-color: var(--g-600);
  color: var(--white);
}
.btn--primary:hover {
  background-color: var(--g-700);
}

/* Outline — green border on white */
.btn--outline {
  background-color: var(--surface);
  color: var(--g-700);
  border-color: var(--g-200);
}
.btn--outline:hover {
  background-color: var(--g-50);
  border-color: var(--g-300);
}

/* Danger — solid red, for reject/delete-flavoured actions */
.btn--danger {
  background-color: var(--danger);
  color: var(--white);
}
.btn--danger:hover {
  filter: brightness(0.9);
}

/* Subtle/ghost button */
.btn--ghost {
  background-color: transparent;
  color: var(--sidebar-ink);
  border-color: rgba(255, 255, 255, 0.2);
}
.btn--ghost:hover {
  background-color: rgba(255, 255, 255, 0.08);
}

.btn--sm {
  padding: 7px 13px;
  font-size: 13px;
}

.btn--block {
  width: 100%;
}

/* ----------------------------------------------------------
   5. Cards / Widgets
   ---------------------------------------------------------- */
.card {
  background-color: var(--surface);
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 22px;
  border-bottom: 1px solid var(--grey-200);
}

.card__title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 700;
  color: var(--g-700);
}

.card__title .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: var(--g-500);
}

.card__sub {
  font-size: 12.5px;
  color: var(--text-muted);
}

.card__body {
  padding: 22px;
  /* Every wide table in the app (Order Queue, Dispatch, Clinic Stock, etc.)
     lives inside a card body — scrolling it here, rather than the whole
     page scrolling sideways, is what keeps narrow/mobile layouts intact. */
  overflow-x: auto;
}

/* Two-column responsive widget row via Grid */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

/* ----------------------------------------------------------
   6. Alerts Banner
   ---------------------------------------------------------- */
.alert-banner {
  display: flex;
  align-items: center;
  gap: 16px;
  background-color: var(--g-50);
  border: 1px solid var(--g-200);
  border-left: 5px solid var(--g-600);
  border-radius: var(--radius);
  padding: 16px 20px;
}

.alert-banner__icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: var(--g-600);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
}

.alert-banner__text strong {
  color: var(--g-700);
}

.alert-banner__text p {
  font-size: 13.5px;
  color: var(--text-muted);
}

.alert-banner__count {
  margin-left: auto;
  background-color: var(--g-600);
  color: var(--white);
  font-size: 12.5px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 999px;
}

/* ----------------------------------------------------------
   7. Patient list
   ---------------------------------------------------------- */
.patient {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--grey-200);
}
.patient:last-child {
  border-bottom: none;
}

.patient__avatar {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background-color: var(--g-100);
  color: var(--g-700);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 15px;
  flex-shrink: 0;
}

.patient__info {
  flex: 1;
  min-width: 0;
}

.patient__name {
  font-weight: 600;
  font-size: 14.5px;
}

.patient__meta {
  font-size: 12.5px;
  color: var(--text-muted);
}

.tag {
  font-size: 11.5px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 999px;
  background-color: var(--g-50);
  color: var(--g-700);
  border: 1px solid var(--g-200);
  white-space: nowrap;
}

/* ----------------------------------------------------------
   8. AI Recommendation rows
   ---------------------------------------------------------- */
.reco {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
}
.reco:last-of-type {
  margin-bottom: 0;
}

.reco__drug {
  flex: 1;
  min-width: 0;
}
.reco__drug strong {
  font-size: 14.5px;
}
.reco__drug span {
  display: block;
  font-size: 12.5px;
  color: var(--text-muted);
}

.reco__qty {
  text-align: center;
  padding: 0 8px;
}
.reco__qty b {
  display: block;
  font-size: 20px;
  color: var(--g-700);
}
.reco__qty small {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* AI confidence meter */
.meter {
  width: 110px;
  flex-shrink: 0;
}
.meter small {
  font-size: 11px;
  color: var(--text-muted);
}
.meter__track {
  height: 7px;
  border-radius: 999px;
  background-color: var(--g-50);
  overflow: hidden;
  margin-top: 4px;
}
.meter__fill {
  height: 100%;
  background-color: var(--g-500);
}

/* ----------------------------------------------------------
   9. Inventory grid (Warehouse)
   ---------------------------------------------------------- */
.inventory-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}

.stock-card {
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  padding: 16px;
  background-color: var(--surface);
}

.stock-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
}

.stock-card__name {
  font-weight: 700;
  font-size: 14.5px;
}
.stock-card__sku {
  font-size: 11.5px;
  color: var(--text-muted);
}

.stock-card__qty {
  font-size: 26px;
  font-weight: 700;
  color: var(--g-700);
}
.stock-card__unit {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* Status pills */
.pill {
  font-size: 11px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.pill--ok {
  background-color: var(--g-50);
  color: var(--g-700);
  border: 1px solid var(--g-200);
}
.pill--low {
  background-color: var(--warn-bg);
  color: var(--warn);
  border: 1px solid var(--warn-border);
}
.pill--critical {
  background-color: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
}
/* Neutral "in progress, nothing needs your attention right now" status —
   distinct from the amber pill--low, which always means "needs a look". */
.pill--info {
  background-color: var(--grey-200);
  color: var(--text-muted);
  border: 1px solid var(--grey-200);
}

/* Stock level bar */
.level {
  margin-top: 12px;
}
.level__track {
  height: 8px;
  border-radius: 999px;
  background-color: var(--grey-200);
  overflow: hidden;
}
.level__fill {
  height: 100%;
  background-color: var(--g-500);
}
.level__fill--low {
  background-color: var(--warn);
}
.level__fill--critical {
  background-color: var(--danger);
}

/* ----------------------------------------------------------
   10. Incoming orders table
   ---------------------------------------------------------- */
.table {
  width: 100%;
  border-collapse: collapse;
}

.table th {
  text-align: left;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text-muted);
  padding: 10px 14px;
  border-bottom: 2px solid var(--grey-200);
}

.table td {
  padding: 14px;
  border-bottom: 1px solid var(--grey-200);
  font-size: 14px;
  vertical-align: middle;
}

.table tr:last-child td {
  border-bottom: none;
}

.table tr:hover td {
  background-color: var(--grey-50);
}

.order-id {
  font-weight: 700;
  color: var(--g-700);
}

.muted {
  color: var(--text-muted);
  font-size: 12.5px;
}

/* ----------------------------------------------------------
   11. KPI stat strip
   ---------------------------------------------------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.stat {
  background-color: var(--surface);
  border: 1px solid var(--grey-200);
  border-radius: var(--radius);
  padding: 18px 20px;
  box-shadow: var(--shadow);
}
.stat__label {
  font-size: 12.5px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.stat__value {
  font-size: 28px;
  font-weight: 700;
  color: var(--g-700);
  margin-top: 4px;
}
.stat__trend {
  font-size: 12.5px;
  color: var(--g-600);
  margin-top: 2px;
}

/* Pages cross-link helper */
.switcher {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--g-700);
  border: 1px solid var(--g-200);
  background-color: var(--surface);
  padding: 8px 14px;
  border-radius: var(--radius-sm);
}
.switcher:hover {
  background-color: var(--g-50);
}

/* ----------------------------------------------------------
   12. Inline-editable table controls
   Used where a table cell needs to be edited in place (e.g. Warehouse
   Inventory thresholds) instead of opening a separate form.
   ---------------------------------------------------------- */
.table-input {
  width: 88px;
  padding: 6px 8px;
  font-size: 13px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  font-family: inherit;
  color: var(--text-dark);
}

.table-input:focus {
  outline: none;
  border-color: var(--g-500);
  box-shadow: 0 0 0 2px var(--g-50);
}

.table__actions {
  display: flex;
  gap: 8px;
}

/* Shown in place of a table/list when there's nothing to display yet
   (e.g. no pending orders) — keeps empty pages from looking broken. */
.empty-state {
  padding: 36px 22px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13.5px;
}
.empty-state--error {
  color: var(--danger);
}
.empty-state--error .btn {
  margin-top: 10px;
}

/* Shown while an async render() is fetching — same footprint as
   .empty-state so a table doesn't jump size when data arrives. */
.loading-indicator {
  padding: 36px 22px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13.5px;
}
.loading-indicator::before {
  content: '';
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 8px;
  vertical-align: -2px;
  border: 2px solid var(--grey-200);
  border-top-color: var(--g-600);
  border-radius: 50%;
  animation: bd-spin 0.7s linear infinite;
}
@keyframes bd-spin {
  to { transform: rotate(360deg); }
}

/* ----------------------------------------------------------
   13. Simple bar chart (GP Reporting — recent delivery volumes)
   Deliberately plain: a handful of real, small numbers reads better as a
   short bar chart than as a fabricated smooth trend line would.
   ---------------------------------------------------------- */
.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  min-height: 170px;
}

.bar-chart__col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.bar-chart__value {
  font-size: 12px;
  font-weight: 700;
  color: var(--g-700);
}

.bar-chart__bar {
  width: 100%;
  max-width: 44px;
  background-color: var(--g-500);
  border-radius: 6px 6px 0 0;
}

.bar-chart__label {
  font-size: 11px;
  color: var(--text-muted);
  text-align: center;
}

/* ----------------------------------------------------------
   14. Responsive — collapse layout on small screens
   ---------------------------------------------------------- */
@media (max-width: 980px) {
  .grid-2 {
    grid-template-columns: 1fr; /* stack widgets */
  }
  .stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* 900px, not 760px: a 768px tablet in portrait was still being given the
   fixed 260px sidebar, leaving ~500px for tables that need far more than
   that. Below 900 the nav becomes a drawer and the content column gets the
   full width; a 1024px tablet in landscape is wide enough to keep both. */
@media (max-width: 900px) {
  /* Sidebar becomes an off-canvas drawer (opened via the hamburger button,
     see Js/shell.js's initMobileNav()) instead of squeezing into a top bar —
     there's simply too much chrome now (grouped nav, identity, collapse
     control) for a horizontal strip to hold at phone widths. */
  .hamburger-btn {
    display: inline-flex;
  }
  .sidebar {
    width: 280px;
    transform: translateX(-100%);
  }
  .sidebar.is-mobile-open {
    transform: translateX(0);
  }
  .sidebar__mobile-close {
    display: inline-flex;
  }
  /* Ignore the desktop icon-rail collapse state on mobile — the drawer is
     either fully open (full width) or fully hidden, never icon-only. */
  .app.is-sidebar-collapsed .sidebar {
    width: 280px;
  }
  .app .main,
  .app.is-sidebar-collapsed .main {
    margin-left: 0;
  }
  .sidebar-backdrop {
    position: fixed;
    inset: 0;
    z-index: 45;
    background-color: rgba(10, 15, 12, 0.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
  }
  .sidebar-backdrop.is-visible {
    opacity: 1;
    pointer-events: auto;
  }
  .topbar {
    padding: 12px 16px;
  }
  .breadcrumbs {
    display: none;
  }
}

@media (max-width: 640px) {
  .profile-menu__name {
    display: none;
  }
  .topbar p {
    display: none;
  }
}

/* ----------------------------------------------------------
   14b. Phone-width corrections for the GP / Warehouse portals
   These two portals are desktop-first by design, but they still have to be
   usable on a phone — a GP checking a request between patients, a warehouse
   supervisor on the floor. Everything below is about that, and none of it
   changes the desktop layout.
   ---------------------------------------------------------- */
@media (max-width: 640px) {
  /* A card header is a title on the left and a subtitle on the right. Below
     ~640px that becomes two cramped columns of wrapped text, so stack them. */
  .card__head {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
  .card__sub {
    text-align: left;
  }

  /* .content, not .main — .main carries no padding of its own, so an
     override there did nothing. This is the gutter between the cards and
     the screen edge on a phone; 32px of desktop padding is far too much of
     a 375px screen to give away. */
  .content {
    padding: 20px 16px 32px;
  }

  .stats {
    grid-template-columns: 1fr;
  }

  /* Tighter table cells so more columns survive before the card starts
     scrolling sideways. */
  .table th,
  .table td {
    padding: 10px;
    font-size: 13px;
  }

  /* A recommendation / patient-request row is drug · qty · actions across.
     At phone width that stacks, so each part gets the full line instead of
     three squeezed columns. */
  .reco {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .reco__qty {
    text-align: left;
  }

  /* Row actions become a full-width stack rather than buttons squeezed
     side by side into unreadable slivers. */
  .table__actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .table__actions .btn {
    width: 100%;
  }
}

/* ----------------------------------------------------------
   14c. Wide tables
   Data tables are the one thing that genuinely cannot reflow — an eight
   column patient list has no honest single-column form. Rather than let the
   browser squash columns until "1968-11-02" wraps onto three lines, each
   table keeps a sensible minimum width and scrolls inside its own card body
   (`.card__body` already sets overflow-x: auto). The scroll is made obvious
   with a fading edge so it doesn't look like the content is simply cut off.
   ---------------------------------------------------------- */
@media (max-width: 900px) {
  .table {
    min-width: 620px;
  }
  /* Momentum scrolling on iOS, and a scrollbar that's actually visible. */
  .card__body {
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
  }
  .card__body::-webkit-scrollbar {
    height: 6px;
  }
  .card__body::-webkit-scrollbar-thumb {
    background-color: var(--grey-200);
    border-radius: 999px;
  }
}

/* ----------------------------------------------------------
   15. Phone-facing portals (Store / Patient)
   Deliberately NOT the sidebar `.app` shell the GP/Warehouse portals use —
   these two roles sign in on a phone and only ever need one simple,
   single-column screen each, so this is closer in spirit to the auth
   shell: one centred column, same green/white tokens, no navigation chrome.
   ---------------------------------------------------------- */
.phone-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: var(--grey-50);
  /* 18px, not 16px: cards sitting closer than this to the screen edge read
     as cramped on a real handset, and the card's own inner padding then
     leaves body text almost touching the bezel. */
  padding: 20px 18px 40px;
}

.phone-header {
  width: 100%;
  max-width: 480px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 12px;
  padding: 4px 2px 20px;
}

.phone-header__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.phone-header__brand img {
  width: 40px;
  height: auto;
  aspect-ratio: 513 / 238;
  object-fit: contain;
  flex-shrink: 0;
}

.phone-header__name {
  font-weight: 700;
  font-size: 15.5px;
  color: var(--g-700);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.phone-header__sub {
  font-size: 12px;
  color: var(--text-muted);
}

.phone-header__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

@media (max-width: 480px) {
  /* Three items (date, theme toggle, log out) crowd a narrow phone width —
     the date is the least essential, so it's the one that drops. */
  .phone-header__actions [data-today] {
    display: none;
  }
}

.phone-main {
  width: 100%;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.phone-footer-note {
  margin-top: 24px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-muted);
  text-align: center;
}

.phone-footer-note button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--g-600);
  text-decoration: underline;
  cursor: pointer;
}

/* A single delivery/order row on the Store portal — info on the left,
   one clear action on the right. Stacks on very narrow screens rather
   than squeezing a button under 40px wide. */
.mobile-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--grey-200);
}
.mobile-row:last-child {
  border-bottom: none;
}

.mobile-row__info {
  min-width: 0;
}

.mobile-row__title {
  font-weight: 700;
  font-size: 14.5px;
  color: var(--text-dark);
}

.mobile-row__meta {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 2px;
}

.mobile-row__action {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}

@media (max-width: 480px) {
  .mobile-row {
    flex-direction: column;
    align-items: stretch;
  }
  .mobile-row__action {
    width: 100%;
  }
}

/* Code-entry row on the Store portal's "Ready for Pickup" list — a short
   PIN input plus a verify button, sized for a thumb on a small screen. */
.code-entry {
  display: flex;
  gap: 8px;
}

.code-entry input {
  width: 100px;
  text-align: center;
  letter-spacing: 2px;
  font-weight: 700;
  font-size: 16px;
}

.field-error {
  font-size: 12px;
  color: var(--danger);
  margin-top: 6px;
  min-height: 15px;
}

.field-success {
  font-size: 13px;
  color: var(--ok);
  margin-top: 6px;
  margin-bottom: 4px;
}

/* The patient portal's big "your code" reveal — this is the one thing a
   patient actually needs to read out loud or show the shopkeeper, so it's
   deliberately the largest, highest-contrast element on the page. */
.pickup-code-block {
  text-align: center;
  padding: 22px 16px 26px;
  background-color: var(--g-50);
  border: 1px solid var(--g-200);
  border-radius: var(--radius);
}

.pickup-code-block__label {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--g-700);
}

.pickup-code-block__code {
  font-size: 44px;
  font-weight: 800;
  letter-spacing: 8px;
  color: var(--g-700);
  margin: 8px 0 4px;
}

.pickup-code-block__hint {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* Generic status banner used on the Patient portal — a calmer, more
   compact cousin of .alert-banner for "here's where things stand" rather
   than "this needs attention now". Tone controls the accent colour only;
   layout is identical to keep the page visually consistent. */
.status-banner {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 16px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--grey-200);
  background-color: var(--surface);
}

.status-banner__icon {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 700;
  color: var(--white);
  background-color: var(--g-500);
}

.status-banner__text strong {
  display: block;
  font-size: 14.5px;
  color: var(--text-dark);
}

.status-banner__text p {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 2px;
}

.status-banner--attention {
  border-color: var(--warn-border);
  background-color: var(--warn-bg);
}
.status-banner--attention .status-banner__icon {
  background-color: var(--warn);
}

.status-banner--ok {
  border-color: var(--g-200);
  background-color: var(--g-50);
}
.status-banner--ok .status-banner__icon {
  background-color: var(--g-600);
}

/* ----------------------------------------------------------
   16. Notification bell + dropdown (Js/notifications.js builds this DOM
   at runtime around the single [data-notif-bell] button every protected
   page already has in its topbar/phone-header actions).
   ---------------------------------------------------------- */
.notif-bell-wrap {
  position: relative;
  display: inline-flex;
}

.notif-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid var(--g-200);
  border-radius: 8px;
  background-color: var(--surface);
  color: var(--g-700);
  cursor: pointer;
}
/* The bell used to be a CSS ::before injecting the literal U+1F514 emoji —
   that renders in each OS's own full-colour emoji font, so it never matched
   the app's line-icon language or its theme. The real glyph now lives in the
   button's own markup as <svg class="icon"><use href="#i-bell">, sized below,
   so it recolors with dark mode instead of staying a fixed yellow/black. */
.notif-bell .icon {
  width: 18px;
  height: 18px;
}
.notif-bell:hover {
  background-color: var(--g-50);
}

.notif-bell__badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background-color: var(--danger);
  color: var(--white);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

.notif-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 40;
  width: 320px;
  max-width: calc(100vw - 32px);
  max-height: 420px;
  overflow-y: auto;
  background-color: var(--surface);
  border: 1px solid var(--g-200);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.notif-dropdown__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--g-200);
  font-size: 13.5px;
  color: var(--text-dark);
}
.notif-dropdown__head button {
  background: none;
  border: none;
  color: var(--g-600);
  font-size: 12.5px;
  cursor: pointer;
  padding: 0;
}
.notif-dropdown__head button:hover {
  text-decoration: underline;
}

.notif-item {
  display: block;
  width: 100%;
  padding: 10px 14px;
  border: none;
  border-bottom: 1px solid var(--g-200);
  background: none;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.notif-item:last-child {
  border-bottom: none;
}
.notif-item:hover {
  background-color: var(--g-50);
}
.notif-item.is-unread {
  background-color: color-mix(in srgb, var(--g-50) 60%, transparent);
}
.notif-item__title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dark);
  display: flex;
  align-items: center;
  gap: 6px;
}
.notif-item.is-unread .notif-item__title::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: var(--g-600);
  flex-shrink: 0;
}
.notif-item__message {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 2px;
}
.notif-item__time {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
}
.notif-dropdown__empty {
  padding: 28px 14px;
  text-align: center;
  color: var(--text-muted);
  font-size: 13px;
}

/* ----------------------------------------------------------
   17. Onboarding guide overlay (Js/onboarding.js builds this DOM at
   runtime — see also Css/forms.css for nothing extra needed, it reuses
   .btn/.field-error etc.)
   ---------------------------------------------------------- */
.onboarding-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background-color: rgba(20, 30, 22, 0.55);
}

.onboarding-modal {
  width: 100%;
  max-width: 440px;
  background-color: var(--surface);
  border-radius: 16px;
  box-shadow: 0 24px 64px var(--shadow);
  padding: 24px;
}

.onboarding-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.onboarding-modal__step {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--g-600);
}
.onboarding-modal__close {
  background: none;
  border: none;
  font-size: 20px;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 2px 6px;
}
.onboarding-modal__close:hover {
  color: var(--text-dark);
}

.onboarding-modal__body h3 {
  font-size: 19px;
  color: var(--text-dark);
  margin-bottom: 8px;
}
.onboarding-modal__body p {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.55;
}

.onboarding-modal__dots {
  display: flex;
  gap: 6px;
  justify-content: center;
  margin: 20px 0;
}
.onboarding-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: var(--g-200);
}
.onboarding-dot.is-active {
  background-color: var(--g-600);
  width: 18px;
  border-radius: 999px;
}

.onboarding-modal__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.onboarding-modal__nav {
  display: flex;
  gap: 8px;
}

/* ----------------------------------------------------------
   18. Reporting page — controls row, richer stat cards, chart
   cards (Chart.js canvases), radial gauge overlay, weekday bars
   (reuses .meter__track/.meter__fill), delivery-log search.
   ---------------------------------------------------------- */
.report-controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}

.control-select {
  padding: 9px 32px 9px 14px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--text-dark);
  font-size: 13px;
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
}
.control-select:focus {
  outline: none;
  border-color: var(--g-500);
  box-shadow: 0 0 0 2px var(--g-50);
}

.report-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.report-stat {
  background-color: var(--surface);
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: 18px 20px;
}

.report-stat__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 14px;
}

.report-stat__icon {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  background-color: var(--g-50);
  color: var(--g-700);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  flex-shrink: 0;
}

.report-stat__trend {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  background-color: var(--g-50);
  color: var(--g-700);
  white-space: nowrap;
}

.report-stat__label {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
}

.report-stat__value {
  font-size: 27px;
  font-weight: 700;
  color: var(--text-dark);
  margin-top: 4px;
}

.report-stat__sub {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 3px;
}

/* Small tinted icon that can sit before a .card__title's text, matching
   the reporting page's chart-card headers (kept in the green family, not a
   different tint per card, per this app's monochrome-brand convention). */
.card__icon .icon {
  width: 16px;
  height: 16px;
}
.card__icon {
  width: 30px;
  height: 30px;
  border-radius: var(--radius-sm);
  background-color: var(--g-50);
  color: var(--g-700);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.chart-wrap {
  position: relative;
  height: 260px;
}
.chart-wrap--sm {
  height: 200px;
}

.gauge-wrap {
  position: relative;
  height: 200px;
}
.gauge-wrap__value {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.gauge-wrap__value strong {
  font-size: 30px;
  font-weight: 700;
  color: var(--text-dark);
  line-height: 1;
}
.gauge-wrap__value span {
  margin-top: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
}

.weekday-bars {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 16px;
}
.weekday-bars__row {
  display: grid;
  grid-template-columns: 40px 1fr 28px;
  align-items: center;
  gap: 10px;
}
.weekday-bars__row .meter__track {
  margin-top: 0;
}
.weekday-bars__label {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
}
.weekday-bars__value {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dark);
  text-align: right;
}

.scroll-list {
  max-height: 320px;
  overflow-y: auto;
}

.table-toolbar {
  padding: 16px 22px 0;
}
.table-toolbar .control-select,
.table-toolbar input[type="search"] {
  width: 100%;
  max-width: 320px;
  padding: 9px 14px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius-sm);
  background-color: var(--surface);
  color: var(--text-dark);
  font-size: 13.5px;
  font-family: inherit;
}
.table-toolbar input[type="search"]:focus {
  outline: none;
  border-color: var(--g-500);
  box-shadow: 0 0 0 2px var(--g-50);
}

@media (max-width: 980px) {
  .report-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* "Download PDF" is window.print() under the hood — this keeps the printed/
   saved-as-PDF output a clean report instead of the full app chrome. */
@media print {
  .sidebar, .topbar, .report-controls, .table-toolbar, .sidebar-backdrop {
    display: none !important;
  }
  .main {
    margin-left: 0 !important;
  }
  .card {
    box-shadow: none;
    border: 1px solid #ccc;
    break-inside: avoid;
  }
}

/* ----------------------------------------------------------
   19. Mobile app shell — Patient / Store / Driver portals
   These three roles sign in on a phone and now have several screens each
   (Home / Order / Track / Profile ...), so they get a real tabbed app shell
   rather than the single scrolling column section 15 gave them. Section 15's
   .phone-* classes are still used for the header and rows; everything here is
   additive, so nothing that already renders changes shape.

   Every colour below is a token from section 1, which is what makes the whole
   shell theme-aware for free — there is no hardcoded hex in this section, and
   dark mode needs no separate rules.
   ---------------------------------------------------------- */

/* Room at the bottom so the fixed tab bar can never cover the last row of
   content (plus the iOS home-indicator inset on a real device). */
.phone-shell--tabbed {
  padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
}

/* ---- Screens: one DOM subtree per tab, one visible at a time ---- */
.screen {
  display: none;
  flex-direction: column;
  gap: 18px;
}
.screen.is-active {
  display: flex;
}

/* ---- Bottom tab bar ---- */
.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  justify-content: center;
  gap: 2px;
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom, 0px));
  background-color: var(--surface);
  border-top: 1px solid var(--grey-200);
  box-shadow: 0 -2px 14px rgba(0, 0, 0, 0.06);
}

.tabbar__item {
  position: relative;
  flex: 1 1 0;
  max-width: 110px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  /* 56px keeps every tab a comfortable thumb target on a small phone. */
  min-height: 56px;
  padding: 6px 4px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font: inherit;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--text-muted);
  cursor: pointer;
  text-align: center;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.tabbar__item:hover {
  background-color: var(--g-50);
}
.tabbar__item.is-active {
  color: var(--g-700);
  background-color: var(--g-50);
}

.tabbar__icon {
  display: inline-flex;
  line-height: 1;
}
.tabbar__icon .icon {
  width: 19px;
  height: 19px;
}

/* Unread count on the Notifications tab. */
.tabbar__badge {
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(6px);
  min-width: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background-color: var(--danger);
  color: var(--white);
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
}

/* ---- Greeting ---- */
.greeting {
  padding: 2px 2px 0;
}
.greeting__hello {
  font-size: 13px;
  color: var(--text-muted);
}
.greeting__name {
  font-size: 22px;
  font-weight: 800;
  line-height: 1.25;
  color: var(--text-dark);
}

/* ---- Status hero: the one "where is my medication" answer ---- */
.status-hero {
  padding: 18px;
  border-radius: var(--radius-lg);
  background: linear-gradient(140deg, var(--g-600), var(--g-900));
  color: var(--white);
  box-shadow: var(--shadow-md);
}
/* Resting state (nothing in flight) deliberately drops the loud gradient so
   an active order is always the most prominent thing on the screen. */
.status-hero--calm {
  background: var(--surface);
  color: var(--text-dark);
  border: 1px solid var(--grey-200);
  box-shadow: none;
}
.status-hero__label {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.85;
}
.status-hero__headline {
  margin-top: 6px;
  font-size: 19px;
  font-weight: 800;
  line-height: 1.3;
}
.status-hero__detail {
  margin-top: 6px;
  font-size: 13px;
  line-height: 1.5;
  opacity: 0.92;
}
.status-hero__meta {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.22);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 12px;
}
.status-hero--calm .status-hero__meta {
  border-top-color: var(--grey-200);
}
.status-hero__meta strong {
  display: block;
  font-size: 13.5px;
  font-weight: 700;
}

/* ---- Quick actions ---- */
.quick-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.quick-action {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 12px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius);
  background-color: var(--surface);
  color: var(--text-dark);
  font: inherit;
  font-size: 13.5px;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.quick-action:hover {
  border-color: var(--g-300);
  box-shadow: var(--shadow);
}
.quick-action:active {
  transform: scale(0.985);
}
.quick-action__icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: 10px;
  background-color: var(--g-50);
  color: var(--g-700);
}
.quick-action__icon .icon {
  width: 18px;
  height: 18px;
}

/* ---- Horizontal progress rail inside the status hero ---- */
.progress-rail {
  display: flex;
  gap: 4px;
  margin-top: 14px;
}
.progress-rail__step {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.28);
}
.progress-rail__step.is-done {
  background-color: var(--white);
}
.status-hero--calm .progress-rail__step {
  background-color: var(--grey-200);
}
.status-hero--calm .progress-rail__step.is-done {
  background-color: var(--g-500);
}
.progress-rail__caption {
  margin-top: 8px;
  font-size: 11.5px;
  opacity: 0.9;
}

/* ---- Vertical timeline (Track Order) ---- */
.timeline {
  display: flex;
  flex-direction: column;
}
.timeline__item {
  position: relative;
  display: flex;
  gap: 14px;
  padding-bottom: 18px;
}
.timeline__item:last-child {
  padding-bottom: 0;
}
/* The connector is drawn from the marker column rather than as a border on
   the row, so the final step simply has nothing below it to connect to. */
.timeline__marker {
  position: relative;
  flex-shrink: 0;
  width: 24px;
  display: flex;
  justify-content: center;
}
.timeline__dot {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--grey-200);
  background-color: var(--surface);
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 700;
}
.timeline__item:not(:last-child) .timeline__marker::after {
  content: "";
  position: absolute;
  top: 24px;
  bottom: -18px;
  width: 2px;
  background-color: var(--grey-200);
}
.timeline__item.is-done .timeline__dot {
  border-color: var(--g-500);
  background-color: var(--g-500);
  color: var(--white);
}
.timeline__item.is-done:not(:last-child) .timeline__marker::after {
  background-color: var(--g-500);
}
.timeline__item.is-current .timeline__dot {
  border-color: var(--g-500);
  background-color: var(--surface);
  color: var(--g-700);
  box-shadow: 0 0 0 4px var(--g-50);
}
.timeline__body {
  min-width: 0;
  padding-top: 1px;
}
.timeline__title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-dark);
}
.timeline__item.is-pending .timeline__title {
  color: var(--text-muted);
  font-weight: 600;
}
.timeline__meta {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 1px;
}

/* ---- Stat tiles (Store / Driver dashboards) ---- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
@media (min-width: 560px) {
  .stat-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.stat-tile {
  padding: 12px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius);
  background-color: var(--surface);
}
.stat-tile__value {
  font-size: 24px;
  font-weight: 800;
  line-height: 1.1;
  color: var(--g-700);
}
.stat-tile--attention .stat-tile__value {
  color: var(--warn);
}
.stat-tile__label {
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-muted);
}

/* ---- Prescription card (Order Medication) ---- */
.rx-card {
  padding: 14px;
  border: 1px solid var(--grey-200);
  border-radius: var(--radius);
  background-color: var(--surface);
}
.rx-card + .rx-card {
  margin-top: 10px;
}
.rx-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.rx-card__name {
  font-size: 15.5px;
  font-weight: 800;
  color: var(--text-dark);
}
.rx-card__facts {
  margin-top: 10px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 12px;
}
.rx-card__fact {
  font-size: 12.5px;
  color: var(--text-muted);
}
.rx-card__fact strong {
  display: block;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-dark);
}
.rx-card__actions {
  margin-top: 12px;
}

/* ---- Bottom sheet (order confirm, scan result, pickup verify) ---- */
.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background-color: rgba(15, 23, 21, 0.45);
}
.sheet {
  width: 100%;
  max-width: 480px;
  max-height: 88vh;
  overflow-y: auto;
  padding: 18px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background-color: var(--surface);
  box-shadow: var(--shadow-lg);
}
@media (min-width: 560px) {
  .sheet-overlay {
    align-items: center;
    padding: 20px;
  }
  .sheet {
    border-radius: var(--radius-lg);
  }
}
.sheet__grip {
  width: 38px;
  height: 4px;
  margin: 0 auto 14px;
  border-radius: 999px;
  background-color: var(--grey-200);
}
.sheet__title {
  font-size: 17px;
  font-weight: 800;
  color: var(--text-dark);
}
.sheet__sub {
  margin-top: 3px;
  font-size: 13px;
  color: var(--text-muted);
}
.sheet__note {
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background-color: var(--warn-bg);
  border: 1px solid var(--warn-border);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dark);
}
.sheet__actions {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* ---- Scanner (driver at the practice, store on arrival) ----
   No camera/barcode library is a dependency of this project, so the viewport
   below is an honest frame around the manual-entry fallback rather than a
   fake camera preview: it is where a scanner feed mounts, and it says so.
   Js/scanner.js swaps in a live <video> only when getUserMedia AND a
   BarcodeDetector are both actually available in the browser. */
.scanner {
  position: relative;
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: 16px;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--grey-200);
  background-color: var(--grey-50);
  text-align: center;
}
.scanner__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.scanner__frame {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 68%;
  aspect-ratio: 1;
  border: 2px dashed var(--g-300);
  border-radius: var(--radius);
  pointer-events: none;
}
.scanner__hint {
  position: relative;
  max-width: 260px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
.scanner__hint strong {
  display: block;
  margin-bottom: 4px;
  font-size: 13.5px;
  color: var(--text-dark);
}
.scanner-manual {
  margin-top: 12px;
}
.scanner-manual input {
  text-align: center;
  letter-spacing: 1.5px;
  font-weight: 700;
  font-size: 16px;
  text-transform: uppercase;
}

/* ---- Map (driver route / patient tracking) ----
   Provider-agnostic on purpose: no map SDK is bundled, so this renders the
   route endpoints and the last REPORTED driver coordinate. With nothing
   reported it says exactly that instead of drawing a pin somewhere
   plausible. */
.map-frame {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--grey-200);
  /* A neutral grid, not an imitation of any real map tile. */
  background-color: var(--grey-50);
  background-image:
    linear-gradient(var(--grey-200) 1px, transparent 1px),
    linear-gradient(90deg, var(--grey-200) 1px, transparent 1px);
  background-size: 34px 34px;
}
.map-frame__route {
  position: absolute;
  inset: 0;
}
.map-pin {
  position: absolute;
  transform: translate(-50%, -100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dark);
  white-space: nowrap;
}
.map-pin__dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 3px solid var(--surface);
  background-color: var(--g-600);
  box-shadow: var(--shadow);
}
.map-pin--origin .map-pin__dot {
  background-color: var(--text-muted);
}
.map-pin--driver .map-pin__dot {
  background-color: var(--warn);
}
.map-frame__empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  text-align: center;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
.map-legend {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-size: 11.5px;
  color: var(--text-muted);
}
.map-legend__key {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.map-legend__swatch {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background-color: var(--g-600);
}
.map-legend__swatch--origin { background-color: var(--text-muted); }
.map-legend__swatch--driver { background-color: var(--warn); }

/* ---- Stacked actions (the driver card shows one legal action at a time) ---- */
.action-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}
.action-stack .btn {
  width: 100%;
  /* Held one-handed, often in a vehicle — bigger than the desktop default. */
  padding: 13px 16px;
  font-size: 14.5px;
}

/* ---- Chips (driver status, delivery id, package code) ---- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--grey-200);
  background-color: var(--grey-50);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-muted);
}
.chip--ok {
  border-color: var(--g-200);
  background-color: var(--g-50);
  color: var(--g-700);
}
.chip--warn {
  border-color: var(--warn-border);
  background-color: var(--warn-bg);
  color: var(--warn);
}
.chip--mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  letter-spacing: 0.04em;
}

/* ---- Label/value rows shared by scan results, sheets and profile screens ---- */
.detail-list {
  border-top: 1px solid var(--grey-200);
  margin: 14px 0 0;
}
.detail-list__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--grey-200);
  font-size: 13.5px;
}
.detail-list__label {
  color: var(--text-muted);
  flex-shrink: 0;
}
.detail-list__value {
  margin: 0;
  font-weight: 700;
  color: var(--text-dark);
  text-align: right;
  min-width: 0;
  word-break: break-word;
}

/* ---- Section heading inside a screen ---- */
.screen-title {
  font-size: 18px;
  font-weight: 800;
  color: var(--text-dark);
  padding: 2px 2px 0;
}
.screen-title__sub {
  margin-top: 2px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-muted);
}

/* ---- In-screen notification list (distinct from the bell dropdown) ---- */
.notif-row {
  display: flex;
  gap: 10px;
  padding: 12px 0;
  border-bottom: 1px solid var(--grey-200);
}
.notif-row:last-child {
  border-bottom: none;
}
.notif-row__dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background-color: var(--grey-200);
}
.notif-row.is-unread .notif-row__dot {
  background-color: var(--g-500);
}
.notif-row__title {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-dark);
}
.notif-row.is-unread .notif-row__title {
  color: var(--g-700);
}
.notif-row__message {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
.notif-row__time {
  margin-top: 2px;
  font-size: 11px;
  color: var(--text-muted);
}

/* ----------------------------------------------------------
   20. Responsive scaling for the phone portals (Patient / Store / Driver)
   These three are mobile-first and stay that way — but "mobile-first" is not
   "mobile-only". Pinned at a 480px column they left most of a tablet or
   laptop screen empty, so the reading column grows in steps and the denser
   grids gain columns as the space appears. The layout never becomes a
   desktop dashboard; it stays a single, centred app column, which is how
   these portals are meant to be read.
   ---------------------------------------------------------- */

/* Small tablet / large phone landscape. */
@media (min-width: 600px) {
  .phone-header,
  .phone-main {
    max-width: 560px;
  }
  /* 4 quick actions in one row instead of a 2×2 block. */
  .quick-actions {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  .quick-action {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  /* The tab bar stops being an edge-to-edge strip and becomes a floating
     pill over the content, matching the width of the column it belongs to. */
  .tabbar {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: min(560px, calc(100% - 32px));
    margin-bottom: 14px;
    border: 1px solid var(--grey-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
  }
  .phone-shell--tabbed {
    padding-bottom: calc(104px + env(safe-area-inset-bottom, 0px));
  }
}

/* Tablet portrait and up. */
@media (min-width: 900px) {
  .phone-shell {
    padding-top: 28px;
  }
  .phone-header,
  .phone-main {
    max-width: 680px;
  }
  .tabbar {
    width: min(680px, calc(100% - 32px));
  }
  /* With real width available, the medication/order cards can show their
     four facts on one line instead of a 2×2 grid. */
  .rx-card__facts {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
  /* Sheets stop being bottom-sheets and become centred dialogs (the
     ≥560px rule in section 19 already starts this) with a little more room. */
  .sheet {
    max-width: 520px;
  }
}

/* Desktop. The column stops growing — beyond this a single app column just
   becomes a long line of text that's tiring to read. */
@media (min-width: 1200px) {
  .phone-header,
  .phone-main {
    max-width: 720px;
  }
  .tabbar {
    width: min(720px, calc(100% - 32px));
  }
}

/* ----------------------------------------------------------
   21. Very narrow phones (≤360px)
   The 320px class of device (older Androids, iPhone SE in some modes) is
   still in real use in the markets this app targets, so it gets explicit
   attention rather than being left to overflow.
   ---------------------------------------------------------- */
@media (max-width: 360px) {
  .phone-shell {
    /* Still a real gutter at 320px — the card padding tightens instead
       (below), which buys back more width than squeezing the page edge and
       doesn't make the layout look like it's falling off the screen. */
    padding: 14px 14px 32px;
  }
  .card__body {
    padding: 16px;
  }
  .phone-header {
    padding-bottom: 14px;
  }
  /* Six tabs at 320px need every pixel — drop the horizontal padding and
     let the labels shrink rather than letting the bar overflow. */
  .tabbar {
    gap: 0;
    padding-left: 2px;
    padding-right: 2px;
  }
  .tabbar__item {
    font-size: 10px;
    padding: 6px 2px;
  }
  .tabbar__icon {
    font-size: 15px;
  }
  .quick-actions {
    grid-template-columns: 1fr;
  }
  .status-hero {
    padding: 15px;
  }
  .status-hero__headline {
    font-size: 17px;
  }
  .greeting__name {
    font-size: 19px;
  }
  /* Label/value rows stack so a long value isn't crushed into a 60px column. */
  .detail-list__row,
  .sheet__row {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }
  .detail-list__value,
  .sheet__row dd {
    text-align: left;
  }
  .stat-grid {
    gap: 8px;
  }
  .stat-tile__value {
    font-size: 21px;
  }
}

/* ----------------------------------------------------------
   22. Touch input
   Anything driven by a finger rather than a cursor gets a larger target and
   loses hover-only affordances. Scoped to coarse pointers so the desktop
   density the GP/Warehouse portals rely on is untouched.
   ---------------------------------------------------------- */
@media (pointer: coarse) {
  .btn {
    min-height: 42px;
  }
  .btn--sm {
    min-height: 36px;
  }
  /* 16px is the threshold below which iOS Safari zooms the page on focus —
     which then leaves the layout scrolled sideways. */
  input,
  select,
  textarea {
    font-size: 16px;
  }
  .notif-bell {
    min-width: 42px;
    min-height: 42px;
  }
  /* Hover states are meaningless on touch and can stick after a tap. */
  .quick-action:hover,
  .tabbar__item:hover {
    background-color: inherit;
  }
  .tabbar__item.is-active:hover {
    background-color: var(--g-50);
  }
}

/* Respect a user's reduced-motion preference across the whole app. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ----------------------------------------------------------
   23. Reporting page, narrow screens
   These live at the end of the file deliberately: the base .report-* rules
   are defined in section 18, well after section 14, so an override placed
   with the other responsive rules would lose the cascade at equal
   specificity. Same-specificity overrides have to come after what they
   override.
   ---------------------------------------------------------- */
@media (max-width: 640px) {
  /* The trend badge is `white-space: nowrap` so a figure like "5,000" can't
     break mid-number. At 320px the full label ("5,000 this week") was wide
     enough on its own to push the whole page sideways, so let the badge wrap
     between words — the number itself still can't split. */
  .report-stat__trend {
    white-space: normal;
    text-align: right;
  }
  .report-stat__head {
    flex-wrap: wrap;
    gap: 6px;
  }
}

@media (max-width: 560px) {
  .report-stats {
    grid-template-columns: 1fr;
  }
  /* Chart legends and the adherence list crowd badly under ~560px. */
  .report-controls {
    flex-direction: column;
    align-items: stretch;
  }
  .report-controls .btn,
  .report-controls select {
    width: 100%;
  }
}

/* ----------------------------------------------------------
   24. Live-connection indicator
   Js/live.js keeps one Server-Sent Events stream open per tab and puts a
   class on <body> when that stream is unhealthy. Nothing is rendered while
   it IS healthy — a permanent "connected" badge is noise. But a clinical
   screen quietly showing data that stopped updating is worse than one that
   admits it, so degraded states announce themselves.
   ---------------------------------------------------------- */
body.is-live-reconnecting::after,
body.is-live-polling::after {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 200;
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  box-shadow: var(--shadow-md);
  pointer-events: none;
}

body.is-live-reconnecting::after {
  content: "Reconnecting…";
  background-color: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn);
}

/* Polling still updates the page, just less promptly — worth saying, but
   quietly, since nothing is actually broken for the user. */
body.is-live-polling::after {
  content: "Live updates unavailable — refreshing periodically";
  background-color: var(--surface);
  border: 1px solid var(--grey-200);
  color: var(--text-muted);
  max-width: calc(100vw - 32px);
}

/* The phone portals have a fixed tab bar sitting exactly where this badge
   would land, so lift it clear. :has() is how a parent can react to the
   presence of that tab bar; where it isn't supported the badge simply keeps
   its default position and overlaps the bar slightly, which is a cosmetic
   fallback rather than a broken one. */
body:has(.phone-shell--tabbed).is-live-reconnecting::after,
body:has(.phone-shell--tabbed).is-live-polling::after {
  bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}

/* ----------------------------------------------------------
   25. System administrator portal
   The admin portal reuses the GP/Warehouse `.app` shell wholesale; these are
   the few things it needs on top. It is deliberately the densest surface in
   the product — an overseer is reading, comparing and exporting, not filling
   in forms on a phone.
   ---------------------------------------------------------- */

/* The role badge in the topbar. Red-tinted rather than green on purpose: it
   should be obvious at a glance that this session can read every tenant's
   data, so nobody leaves one open on a shared screen by accident. */
.tag--admin {
  background-color: var(--danger-bg);
  border-color: var(--danger-border);
  color: var(--danger);
  font-weight: 700;
}

/* A stat tile's value can carry a tone when the number itself is the point
   (a negative margin, a healthy contribution). */
.stat__value--ok { color: var(--g-700); }
.stat__value--critical { color: var(--danger); }

.stat__note {
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--text-muted);
}

/* Report and pager button rows. */
.report-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.report-controls-card .form-grid-3 {
  margin-bottom: 14px;
}

/* Inline code — ids, table names, actions, session prefixes. These are read
   character by character, so they get a monospace face and a tinted ground
   to separate them from prose. */
.content code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  padding: 1px 6px;
  border-radius: 5px;
  background-color: var(--g-50);
  color: var(--g-700);
  white-space: nowrap;
}

/* The admin tables carry more columns than any other screen in the app, so
   they get a slightly tighter rhythm before section 14c's scroll kicks in. */
.content .table th,
.content .table td {
  padding: 11px 12px;
}

/* An opened patient record is inserted after the patient list; give it a
   clear edge so it reads as a distinct, deliberate act rather than more list. */
#patient-record:not(:empty) {
  margin-top: 4px;
}
#patient-record .card {
  border-color: var(--g-300);
  box-shadow: var(--shadow-md);
}

/* Printing a report should produce the report, not the application. The base
   print rules in section 20 already drop the sidebar and topbar; these drop
   the controls that only make sense on screen. */
@media print {
  .report-controls,
  .report-controls-card,
  .sidebar__meta,
  .tag--admin {
    display: none !important;
  }
  .content {
    padding: 0 !important;
    gap: 12px !important;
  }
  /* Let a long report table print in full instead of scrolling in a box. */
  .card__body {
    overflow: visible !important;
  }
  .content .table {
    min-width: 0 !important;
    font-size: 10.5px;
  }
  .content .table th,
  .content .table td {
    padding: 5px 6px;
  }
  .content code {
    background: none;
    color: inherit;
  }
}
