:root {
  /* 2026-07-16, Essa's "Ocean blue" pick from the nav/color mockup --
     replaces the original navy/teal pair app-wide. Deliberately NOT
     touching OFFICIAL_BLUE (delivery.py, #0A4595) or any *_print.html/PDF
     template that reuses it -- that constant is reserved for a real future
     Ministry of Health letterhead spec (see its own docstring comment),
     completely separate from this cosmetic in-app theme. */
  --navy: #0b4f6c;
  --navy-dark: #083a50;
  --teal: #1c8fae;
  --red: #b3312c;
  --bg: #f5f7fa;
  --card-bg: #ffffff;
  --border: #dfe4ea;
  --text: #1f2a37;
  --muted: #6b7684;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}

.container { max-width: 1080px; margin: 0 auto; padding: 24px; }

.topbar {
  display: flex; justify-content: space-between; align-items: center;
  background: var(--navy); color: white; padding: 12px 24px;
}
.topbar .brand { display: flex; align-items: center; gap: 10px; color: white; font-weight: 600; text-decoration: none; font-size: 18px; }
.brand-logo { height: 32px; width: auto; border-radius: 4px; flex: none; }
.topbar-right { display: flex; align-items: center; gap: 10px 18px; flex-wrap: wrap; }
.topbar-right a { color: #d9e8f5; text-decoration: none; font-size: 14px; }
.topbar-right a:hover { text-decoration: underline; }
/* Wraps My Account / user-chip / Log out so they can be hidden as one unit
   on mobile (see media query below) -- lays out identically to before on
   desktop since it's just a plain flex row matching .topbar-right itself. */
.topbar-account-group { display: flex; align-items: center; gap: 10px 18px; flex-wrap: wrap; }
.user-chip { font-size: 13px; color: #b8cfe3; }
/* Keep the notification buttons compact so they don't dominate the bar
   next to the menu button / account links / user chip. */
.topbar-right .btn { padding: 5px 10px; font-size: 12.5px; }

.topbar-menu-btn {
  background: none; border: none; color: #d9e8f5; cursor: pointer;
  padding: 4px; display: flex; align-items: center;
}
.topbar-menu-btn .dock-icon { width: 22px; height: 22px; }
.topbar-menu-btn:hover { color: white; }

/* 2026-07-16, Essa: "easy back to home access" (answered "Both" when asked
   persistent button vs. shortened paths). The bottom dock's first slot has
   always linked to the dashboard, but only as a small icon+"Dashboard"
   label 78px down the screen -- easy to miss, especially on a wide desktop
   window where the dock shrinks and sits unobtrusively (see .bottom-dock's
   900px+ rule). This is an explicit, labeled "Home" pill right in the top
   bar instead -- deliberately NOT inside .topbar-account-group, so it stays
   visible on mobile too (that group alone is hidden under 640px, see the
   media query below). Kept small/secondary (teal, not a big button) so it
   doesn't compete with the brand mark for attention. */
.topbar-home-pill {
  display: flex; align-items: center; gap: 5px; background: var(--teal); color: white;
  font-size: 12.5px; font-weight: 600; text-decoration: none; padding: 6px 12px; border-radius: 20px;
  flex: none;
}
.topbar-home-pill:hover { background: var(--navy-dark); text-decoration: none; }
.topbar-home-pill .dock-icon { width: 15px; height: 15px; }

h1 { font-size: 24px; margin-bottom: 4px; }
h2 { font-size: 17px; margin: 8px 0; }
.subtitle { color: var(--muted); margin-top: 0; }

.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 12px; }

.card, .card-form, .auth-card, .action-card {
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
  padding: 20px; margin-bottom: 18px;
}

.auth-card { max-width: 420px; margin: 60px auto; }
.login-logos { display: flex; justify-content: center; align-items: center; gap: 24px; margin-bottom: 12px; flex-wrap: wrap; }
.login-logo { max-height: 72px; max-width: 140px; object-fit: contain; }

/* Tababa product-brand lockup (icon + Arabic/Latin wordmark) -- separate
   from .login-logo above, which is sized for the small department/MOH
   institutional badges. This is deliberately bigger since it's the app's
   own primary branding, not a small supporting logo. */
.brand-lockup { display: block; max-width: 320px; width: 100%; height: auto; margin: 0 auto 16px; }

/* Two big "who's logging in" squares on the login page -- Essa's request
   (2026-07-08): "create two squares for log in .. one for physicians and
   beside it or below it or do a big icon to navigate the patient to their
   log in". Deliberately its own bigger size, not a reuse of the small
   84px .nav-tile grid (that's for logged-in dashboard shortcuts) -- this
   is the very first thing anyone sees on the login page, so it needs to
   read as a prominent either/or choice, not a small icon shortcut. */
.login-choices { display: flex; flex-wrap: wrap; justify-content: center; gap: 16px; margin: 18px 0 26px; }
.login-choice {
  flex: 0 0 150px;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px;
  padding: 22px 10px 18px; text-decoration: none; color: var(--text);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.login-choice:hover { box-shadow: 0 4px 14px rgba(11, 79, 108, 0.14); transform: translateY(-2px); }
.login-choice-icon {
  width: 60px; height: 60px; border-radius: 16px; background: #e5edf7; color: var(--navy);
  display: flex; align-items: center; justify-content: center;
}
.login-choice-icon svg { width: 32px; height: 32px; }
.login-choice-label { font-size: 15px; font-weight: 700; text-align: center; }
.login-choice-sub { font-size: 12px; color: var(--muted); text-align: center; }

.stacked-form label, .card-form label {
  display: block; margin-bottom: 14px; font-size: 14px; font-weight: 600; color: var(--text);
}
.stacked-form input, .card-form input, .card-form select, .card-form textarea,
.filter-bar select, .filter-bar input {
  display: block; width: 100%; margin-top: 6px; padding: 9px 10px;
  border: 1px solid var(--border); border-radius: 6px; font-size: 14px; font-family: inherit;
}
.textarea-lg { min-height: 260px; font-size: 15px; line-height: 1.5; }
.card-form fieldset, .stacked-form fieldset { border: none; padding: 0; margin: 0 0 12px; }
.card-form legend, .stacked-form legend { font-weight: 700; font-size: 15px; margin-bottom: 8px; padding: 0; }
.checkbox-group { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.checkbox-item { display: flex !important; align-items: center; gap: 6px; font-weight: 400 !important; margin-bottom: 0 !important; }
.checkbox-item input { width: auto !important; margin-top: 0 !important; }
/* 2026-07-13, Essa: filter checkboxes on the Inventory catalog page should
   be tidier/simpler to view -- same 2 checkboxes, same names/behavior, just
   laid out side by side (wraps on narrow screens) with shorter labels
   instead of each one being a full stacked sentence; the extra explanatory
   detail moved into a hover title= instead of being inline text. */
.checkbox-row { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 4px 0 10px; }

/* PPO (pre-printed order sheet) fill-in form -- one checkbox item per line
   (unlike the wrapped .checkbox-group pill row above) since these labels
   are full clinical order text, not short single-word tags, and several
   need room for an inline blank (a rate/POD/duration) right next to them. */
.ppo-section { border-top: 1px solid var(--border); padding-top: 12px; margin-top: 4px; }
/* 2026-07-09 (Essa: "make sure the check box in the confirmation points are
   in line with the sentences"): align-items was "center", which vertically
   centers the checkbox against the FULL HEIGHT of its label -- invisible for
   a short one-line PPO item, but the long pre-submit confirmation sentences
   (e.g. "All relevant images and reports are attached (or none exist for
   this case)") wrap to 2-3 lines on a phone, and a vertically-centered
   checkbox then floats in the middle of that paragraph instead of sitting
   next to its first line -- exactly what "not in line with the sentence"
   looks like. flex-start fixes the wrapped case and is visually identical
   to center for anything that still fits on one line. */
.ppo-item { display: flex !important; align-items: flex-start; flex-wrap: wrap; gap: 4px 10px; margin-bottom: 10px !important; font-weight: 400 !important; }
.ppo-item > input[type="checkbox"] { margin-top: 3px; } /* nudge to sit next to the text's first line, not its very top edge */
.ppo-blank { width: auto !important; flex: 1 1 160px; margin-top: 0 !important; padding: 6px 8px !important; font-size: 13px; }
.subsection-label {
  font-weight: 700; font-size: 12px; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.04em; margin: 4px 0 10px;
}
/* A titled group nested inside a .card -- e.g. one Room's beds nested inside
   its Ward's card on the Wards & Beds admin page, or one Ward's groups on
   the Bed Board. */
.subsection { margin: 16px 0; padding-top: 14px; border-top: 1px dashed var(--border); }
.subsection h3 { font-size: 15px; margin: 0 0 8px; }
/* A compact select+button form inside a table cell -- e.g. the Bed Board's
   "Move to" action. */
.inline-form { display: flex; gap: 6px; align-items: center; }
.inline-form select { width: auto; margin: 0; padding: 4px 6px; font-size: 13px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 20px; }

/* 2026-07-16, Essa photo (Statistics page): the chart caption "Share of
   total by Referring Hospital..." was visibly overlapping the data table's
   header row above it. Root cause is a CSS Grid default, not a positioning
   bug: a grid item's min-width defaults to "auto" (content-based), not 0 --
   so when "Group by" produces many columns (one per hospital, e.g. 8
   hospitals + bucket + total = 10 columns), the table's natural content
   width can exceed its .grid-2 column's 1fr share, and a grid item is
   allowed to overflow past its own track instead of shrinking to fit. The
   table doesn't wrap onto a new line -- it just paints past its column's
   right edge, straight through the chart column sitting next to it in the
   grid, producing exactly the header/caption overlap in the photo. Only
   .data-table-col's specific "table next to a chart" pairing (currently
   statistics_admissions.html) hits this -- .grid-2 itself is reused
   unchanged by dozens of unrelated 2-column forms elsewhere in the app, so
   the fix is scoped to this one wrapper class rather than to .grid-2
   itself. min-width:0 lets the grid item actually shrink to its track's
   width instead of overflowing it; overflow-x:auto then hands off to a
   horizontal scrollbar on the table itself instead of bleeding into the
   next column. */
.data-table-col { min-width: 0; overflow-x: auto; }

.chart-box { max-width: 260px; margin: 0 auto; }

/* 2026-07-13, Essa: "huge space under Quantity on Hand" -- the horizontal
   bar charts (renderBarChart() in charts.js: Inventory catalog's
   per-item quantity chart, Inventory home's Top Items chart) reused the
   doughnut-chart .chart-box above, which caps width at 260px. Their
   container height is deliberately set per-item-count (see
   inventory_items.html/inventory_home.html inline style) so a long item
   list gets a readable row each -- but squeezed into a 260px-wide box,
   Chart.js's default aspect-ratio containment rendered a much SHORTER
   chart than that tall container actually was, leaving the rest as dead
   space below it. This class removes the width cap for exactly those two
   charts (paired with maintainAspectRatio:false in charts.js, which is the
   other half of the fix -- without both, the container is still either
   too narrow or the canvas still won't fill the height it's given). */
.chart-box-bar { max-width: none; margin: 0; }

/* 2026-07-18: Essa's screenshot of the Inventory catalog showed "Add Stock",
   "Print Label", etc. splitting one-letter-per-line inside the action
   buttons -- same root cause as the .ref-no fix below: overflow-wrap:anywhere
   on .data-table td (further down this file) counts as a break opportunity
   when the browser sizes flex children, so once the 3-segment stock bar
   (added alongside these buttons in .row-actions) left too little width for
   4 buttons side by side, flexbox shrank each <a>/<button> toward zero and
   the button label wrapped a character at a time to fit. white-space:nowrap
   gives every button a fixed min-content width again, so flexbox lets the
   row overflow instead of shrinking text below readable size -- the same
   .card{overflow-x:auto} horizontal scroll already used for wide tables
   picks up the rest, exactly like the .ref-no case. */
.btn {
  display: inline-block; border: none; border-radius: 6px; padding: 10px 18px;
  font-size: 14px; font-weight: 600; cursor: pointer; text-decoration: none; color: white;
  white-space: nowrap;
}
.btn-primary { background: var(--navy); }
.btn-primary:hover { background: var(--navy-dark); }
.btn-secondary { background: #eef1f5; color: var(--text); border: 1px solid var(--border); }
.btn-danger { background: var(--red); }
.btn-small { padding: 6px 12px; font-size: 13px; }
.button-row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }

.multi-attach-list { list-style: none; padding: 0; margin: 8px 0 0; font-size: 13px; }
.multi-attach-list li { padding: 4px 0; display: flex; align-items: center; gap: 8px; }

/* 2026-07-17, ICD-10 autocomplete (see data-icd10-autocomplete in app.js) --
   the field's own label wrapper is the positioning anchor (.icd10-field),
   so the suggestion list floats directly under whichever row's input is
   focused, even after addDiagnosisRow() clones a fresh row. */
.icd10-field { position: relative; }
.icd10-suggestions {
  display: none;
  position: absolute;
  left: 0; right: 0;
  z-index: 40;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
  max-height: 220px;
  overflow-y: auto;
  margin-top: 2px;
}
.icd10-suggestions.open { display: block; }
.icd10-suggestion { padding: 8px 10px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--border); }
.icd10-suggestion:last-child { border-bottom: none; }
.icd10-suggestion:hover { background: var(--bg); }
.icd10-suggestion .code { font-weight: 700; margin-right: 6px; }
.icd10-suggestion .desc { color: var(--muted); }

.auth-footer { text-align: center; font-size: 14px; margin-top: 16px; }
.link-button {
  background: none; border: none; padding: 0; color: var(--navy);
  font-size: 14px; font-weight: 600; text-decoration: underline; cursor: pointer;
}

.flash-stack { margin-bottom: 16px; }
.flash { padding: 10px 14px; border-radius: 6px; margin-bottom: 8px; font-size: 14px; }
.flash-success { background: #e3f5ec; color: #1b6e46; border: 1px solid #b9e6cf; }
.flash-error { background: #fdecec; color: #a3352f; border: 1px solid #f7c9c6; }
/* A heads-up, not a success and not an error -- e.g. the New Consult form's
   same-Civil-ID notice (2026-07-17, item 6). */
.flash-warning { background: #fff6e0; color: #8a6100; border: 1px solid #f2dda0; }
.flash-warning a { color: #8a6100; text-decoration: underline; }
/* 2026-07-21: Reason-for-consult character counter, submit_consult.html --
   turns red once the maxlength=200 cap is reached, so hitting the limit
   reads as "you're at the cap" rather than "typing silently stopped". */
.char-limit-reached { color: var(--red); font-weight: 600; }
/* 2026-07-21: one row per related consult inside #relatedConsultBanner
   (app.js) -- the description on the left, the "Same issue" action button
   on the right, wrapping on narrow (mobile) screens instead of squeezing. */
.related-consult-row {
  display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap;
  gap: 8px; padding: 6px 0; border-top: 1px solid #f2dda0;
}
.related-consult-row:first-of-type { border-top: none; }

/* 2026-07-09 (root cause of a multi-round "my fix isn't reaching Essa's
   phone" bug hunt): an installed "Add to Home Screen" PWA on iOS can resume
   its previous in-memory page/JS indefinitely across app-switches, without
   ever performing a fresh page load -- so a real, already-deployed fix can
   sit completely unseen until the app is force-quit and reopened, or the
   icon is deleted and re-added. app.js now shows this banner the moment a
   NEW service worker takes over (which happens automatically on every
   deploy -- see sw.js's skipWaiting()/clients.claim()), so anyone with the
   app already open gets an obvious, one-tap way to pick up the update
   instead of silently running stale code -- deliberately NOT an automatic
   reload, since that could discard whatever someone's mid-typing into a
   consult form. */
.update-banner {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  flex-wrap: wrap; padding: 12px 16px;
  background: var(--navy); color: #fff; font-size: 14px;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
}
.update-banner button {
  background: var(--teal); color: #fff; border: none; border-radius: 6px;
  padding: 6px 14px; font-size: 14px; font-weight: 600; cursor: pointer;
}

.data-table { width: 100%; border-collapse: collapse; background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
/* vertical-align: top (not the browser default of middle) so every row's
   name/description/buttons start at the same top edge regardless of how
   many lines a long form name wraps to -- with middle-alignment, a 3-4
   line name (e.g. "Post-operative Orders (Interventional Pulmonology)")
   visibly pulls its own row's "Fill Out"/"Download Blank" buttons down to
   float in the middle of that taller row while a short name's buttons sit
   near the top, so neighboring rows read as raggedly misaligned even
   though the underlying table columns themselves are correctly lined up. */
/* 2026-07-16, Essa: Operation Logbook screenshot showed the Category column
   ("VATS Wedge Resection / Segmentectomy") wrapping mid-word ("Segmentecto"
   +"my") even with the min-width floor below in place -- some category
   names are simply too long to fit 100px at 14px type. Essa's own fix:
   "decrease the font size a bit to fit all in inline." 13px (from 14px) is
   a small enough step to stay comfortably readable everywhere this class is
   used app-wide, while buying back enough width per character that a long
   single word is meaningfully more likely to fit its column without
   splitting -- combined with the min-width bump just below. */
.data-table th, .data-table td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--border); font-size: 13px; }
.data-table th { background: #eef1f5; font-weight: 700; color: var(--muted); text-transform: uppercase; font-size: 12px; }
.data-table tbody tr:hover { background: #f5f9fc; cursor: pointer; }
.data-table .row-actions { padding-top: 2px; }

/* 2026-07-09: consult-list attachment marker (see _macros.html
   attachment_marker()) -- a small inline paperclip next to the reference
   number when a consult has one or more attachments on file. */
.attachment-marker { display: inline-flex; vertical-align: middle; color: var(--muted); }
.attachment-icon { width: 14px; height: 14px; }

/* 2026-07-13: Inventory catalog's item-name warning triangle, replacing the
   old separate "Stock Alerts" table (Essa: too much data on one page) --
   #d9364f matches the existing Low Stock / Special Order badge red
   elsewhere on this page, so it reads as the same "pay attention" color. */
.warning-icon { width: 16px; height: 16px; color: #d9364f; vertical-align: -3px; margin-left: 5px; }

/* 2026-07-13: Inventory catalog's Stock Level column -- green/yellow/red
   dot replacing the plain Minimum-quantity number, itself replacing the
   Quantity on Hand chart Essa found too visually heavy. Same red (#d9364f)
   as the warning triangle/Low Stock badge elsewhere on this page; green/
   yellow match the solid tones already used for chart bars/tags
   (CHART_PALETTE/TAG_CHART_COLORS in charts.js) rather than inventing new
   colors.
   2026-07-13, later same day, Essa: "make the stock level like a bar of
   three color (Green-Yellow-Red)" -- single dot became a small 3-segment
   bar instead so the current level reads against the full scale, not just
   in isolation: all 3 segments are always shown (in that left-to-right
   order, matching how Essa described it), the segment matching the item's
   CURRENT stock_status is fully solid with a subtle dark outline, the
   other two are faded so they're still visible as "the other possible
   states" without competing with the one that matters. */
.stock-bar { display: inline-flex; gap: 2px; vertical-align: -3px; }
.stock-bar-seg { width: 14px; height: 11px; border-radius: 3px; opacity: 0.25; }
.stock-bar-seg.active { opacity: 1; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35) inset; }
.stock-bar-green { background: #1b6e46; }
.stock-bar-yellow { background: #e0a72e; }
.stock-bar-red { background: #d9364f; }

/* 2026-07-23, Essa: "in PT4 form (assessment form) make pain options is bar
   with 1-3 green 4-6 orange 7-10 red" -- same visual family as .stock-bar
   above (small colored segments in a row) but this one is a real FORM INPUT
   (single-select 0-10), not a read-only indicator, so every segment is a
   normal radio button's <label>, just styled to look like a colored block
   instead of a native radio dot. Pure CSS :checked + sibling-label
   selector, no JS needed. Distinct orange (#e0742e) from .stock-bar-yellow
   (#e0a72e) deliberately -- Essa said "orange" here, not "yellow", and using
   the exact same shade as the unrelated Inventory stock-level bar would
   blur two different meanings that happen to share this app. */
.pain-scale { display: inline-flex; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
.pain-scale-radio { position: absolute; opacity: 0; width: 0; height: 0; }
.pain-scale-seg {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 5px; opacity: 0.35;
  cursor: pointer; font-weight: 700; font-size: 13px; color: #fff;
  user-select: none; transition: opacity 0.1s, transform 0.1s;
}
.pain-scale-radio:checked + .pain-scale-seg {
  opacity: 1; transform: scale(1.08);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.45) inset;
}
.pain-scale-radio:focus-visible + .pain-scale-seg { outline: 2px solid #2563eb; outline-offset: 2px; }
.pain-scale-green { background: #1b6e46; }
.pain-scale-orange { background: #e0742e; }
.pain-scale-red { background: #d9364f; }

/* 2026-07-16: white-space:nowrap alongside the min-width cell floor above --
   belt-and-suspenders so a short status word like "Completed" never breaks
   mid-word ("COMPLET"/"ED", seen in Essa's photo of the Consult list) even
   under residual column pressure. A badge is a short single-status label by
   design, never long free text, so it's always safe for it to just push its
   own column a little wider (the table-wide scroll already handles that)
   rather than ever wrap. */
.badge { display: inline-block; padding: 3px 9px; border-radius: 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; white-space: nowrap; }
.badge-pending_first, .badge-pending_second, .badge-needs_scheduling, .badge-pending { background: #fff2d9; color: #9a6300; }
.badge-needs_revision, .badge-cancelled, .badge-no_show, .badge-declined { background: #fdecec; color: #a3352f; }
.badge-approved, .badge-scheduled, .badge-accepted { background: #e3f5ec; color: #1b6e46; }
.badge-completed { background: #e5edf7; color: var(--navy); }
.badge-converted_to_referral { background: #ede7f6; color: #5e35b1; }
.urgency-routine { background: #eef1f5; color: var(--muted); }
.urgency-urgent { background: #fff2d9; color: #9a6300; }
.urgency-emergent { background: #fdecec; color: #a3352f; }

/* Clinic Calendar (appointments_calendar.html) -- Sunday-first month grid.
   Clinic days (Sun/Wed, see CLINIC_SCHEDULE_NOTE in appointments.py) get a
   tinted column header so the two active clinic days stand out from the
   five non-clinic days at a glance. */
.calendar-nav { display: flex; align-items: center; justify-content: center; gap: 16px; margin-bottom: 14px; }
.calendar-nav h2 { margin: 0; min-width: 200px; text-align: center; }
.calendar-grid { width: 100%; border-collapse: collapse; table-layout: fixed; }
.calendar-grid th { background: #eef1f5; color: var(--muted); font-size: 11px; text-transform: uppercase; padding: 6px 4px; text-align: center; border: 1px solid var(--border); }
.calendar-grid th.clinic-day { background: #dcecf5; color: var(--navy); }
.calendar-grid td { border: 1px solid var(--border); vertical-align: top; height: 92px; padding: 4px; width: 14.28%; background: var(--card-bg); }
.calendar-grid td.calendar-blank { background: #fafbfc; }
.calendar-grid td.calendar-today { background: #fff8e6; }
.calendar-day-number { font-size: 12px; font-weight: 700; color: var(--muted); margin-bottom: 3px; }
.calendar-today .calendar-day-number { color: var(--navy); }
.calendar-appt-chip {
  display: block; font-size: 11px; padding: 2px 5px; border-radius: 4px; margin-bottom: 2px;
  background: #e3f5ec; color: #1b6e46; text-decoration: none; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis;
}
.calendar-appt-chip.chip-cancelled, .calendar-appt-chip.chip-no_show { background: #fdecec; color: #a3352f; }
.calendar-appt-chip.chip-completed { background: #e5edf7; color: var(--navy); }
.calendar-more-link { font-size: 11px; color: var(--muted); text-decoration: none; }

/* Peri-operative Patients quick-reference tags: Surgery=red, Interventional=blue,
   Post-operative=green, Core biopsy=yellow, Observation=white. */
.tag { display: inline-block; padding: 3px 9px; border-radius: 12px; font-size: 11px; font-weight: 700; }
.tag-red { background: #fdecec; color: #a3352f; }
.tag-blue { background: #e5edf7; color: var(--navy); }
.tag-green { background: #e3f5ec; color: #1b6e46; }
.tag-yellow { background: #fff2d9; color: #9a6300; }
.tag-white { background: #ffffff; color: var(--text); border: 1px solid var(--border); }
/* 2026-07-19: Essa asked for the Physiotherapy role tag specifically to be
   pink -- "make their tag pink" -- alongside the "First LAST, Physiotherapy"
   name style (see User.display_name in models.py). Not part of the
   peri-operative red/blue/green/yellow/white set above; a new addition. */
.tag-pink { background: #fdf2f8; color: #9d174d; }

/* 2026-07-20, Essa (Physiotherapy Assessment Sheet): "make sure also to
   have the right with bar same color and ADULT ASSESSMENT (P.T. 4)" --
   the original MOH form's right-edge vertical sidebar label.
   2026-07-20, next-day revision round, Essa: "follow the same color
   schemes on the right side of the papers [as the attached original]" --
   the first build recolored this to this app's own --navy as a stand-in;
   turns out the actual MOH scan's sidebar is a dusty terracotta/rust, not
   blue at all (sampled directly off Assessment.pdf's own scan, several
   points along the bar: avg RGB(179, 99, 85)). Hardcoded as its own hex
   here rather than a --navy/--red reuse, since nothing else in this app's
   palette is this color -- deliberately scoped to just this one sheet's
   bar, both here and physio_assessment.py's matching PDF constant
   (ASSESSMENT_BAR_COLOR, NOT the shared OFFICIAL_BLUE every other
   clinical PDF in this app uses for its own letterhead bar). */
.assessment-title-bar {
  display: flex; align-items: stretch; justify-content: space-between;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px;
  margin-bottom: 18px; overflow: hidden;
}
.assessment-title-bar-main { padding: 16px 20px; display: flex; align-items: center; font-size: 14px; }
.assessment-title-bar-tab {
  background: #b36355; color: #fff; font-weight: 700; letter-spacing: 0.04em;
  display: flex; align-items: center; justify-content: center; padding: 0 14px;
  writing-mode: vertical-rl; text-orientation: mixed; transform: rotate(180deg);
  font-size: 13px; white-space: nowrap;
}

/* 2026-07-20, next-day revision round, Essa: "follow exactly the same
   alignment and arrangement of choice (more in columns not rows) so it
   will be more easier to scroll" -- the original form packs every
   section's checkboxes into a 3-4 column grid (reads left-to-right, wraps
   to the next row), not one item per line. A NEW class layered on top of
   the existing .ppo-section/.ppo-item (see physiotherapy_assessment_form
   .html's render_items() macro) rather than editing those two directly --
   they're shared with 4 other templates' checkbox forms elsewhere in this
   app, which must stay single-column/unaffected. auto-fill + minmax lets
   the column COUNT itself respond to the card's actual width instead of a
   hardcoded number -- comfortably 3-4 on this app's normal card width,
   collapsing to fewer on a narrower one, and to a single column on mobile
   via the existing collapse media query below. */
.assessment-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 2px 20px;
}
.assessment-grid .ppo-item { margin-bottom: 6px !important; }

/* 2026-07-20 revision round, Essa: "In the demographic data make it more
   organized" -- the Assessment Sheet's Patient & Referral card now groups
   fields under 3 sub-headings (Identity/Contact/Referral) instead of one
   flat list; .grid-3 fits that shorter, denser field count better than
   .grid-2 (2 columns would leave a lot of the card's width empty for a
   3-6 field group). */
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 20px; }

/* 2026-07-22, PET/CT Request's "Patient Profile" section: the real paper
   form is a genuine table, one row per clinical item (Diabetic, Known
   Oncology, Chemotherapy...), each with its own Yes/No + a few conditional
   detail fields. No existing class fit a repeated "checkbox + small cluster
   of detail inputs" block, so this one's scoped to just that -- a light
   border box per row keeps 11 of these visually separated without needing
   an actual HTML <table> (detail fields vary per row: 1-4 sub-inputs). */
.profile-row { border: 1px solid var(--border); border-radius: 8px; padding: 10px 14px; margin-bottom: 10px; }
.profile-row .grid-3, .profile-row .grid-2 { margin-top: 8px; }
.profile-row .checkbox-item { font-weight: 600 !important; }
.assessment-demo-heading {
  font-size: 12px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted);
  margin: 14px 0 4px; font-weight: 700;
}
.assessment-demo-heading:first-of-type { margin-top: 0; }

/* Spreadsheet-like inline editing for the Assessment Sheet's 3 repeatable
   tables (ROM, Special Tests, Treatment Goals) -- a bare <input> per cell
   instead of the usual bordered field, so a 10-column table doesn't turn
   into a wall of boxes. */
.data-table input[type="text"] {
  width: 100%; border: none; padding: 4px; font-size: 13px; background: transparent;
}
.data-table input[type="text"]:focus { background: #fff9e0; outline: 1px solid var(--navy); }

.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0; font-size: 14px; }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
.preserve-whitespace { white-space: pre-wrap; }

.filter-bar { display: flex; gap: 14px; align-items: flex-end; flex-wrap: wrap; background: var(--card-bg); border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-bottom: 18px; }
.filter-bar label { font-size: 13px; font-weight: 600; }

.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 24px; }
.stat-card { background: var(--card-bg); border: 1px solid var(--border); border-radius: 10px; padding: 18px; text-align: center; }
.stat-number { display: block; font-size: 30px; font-weight: 700; color: var(--navy); }

.row-actions { display: flex; gap: 8px; }
.empty-state { color: var(--muted); font-style: italic; }

/* 2026-07-16, Essa sent photos of the DESKTOP app (not just iPhone) still
   showing "Thoraci"/"c"/"Surgery" and "COMPLET"/"ED" splitting mid-word on
   the Consult list. These 3 rules were written 2026-07-14/15 scoped inside
   the max-width:720px media query below on the (wrong) assumption that only
   a phone-width screen has too little room for an 8-column table -- Essa's
   own photo is a laptop-width browser window, well over 720px, proving a
   modest desktop/laptop window runs into the exact same "too many columns,
   not enough width" squeeze as a phone does. Moved out of the media query
   so the scroll-instead-of-squish behavior applies at every width, not just
   below the phone breakpoint -- harmless at genuinely wide desktop windows
   (these rules only ever act as a floor; they do nothing when a table
   already fits comfortably) and fixes the exact narrower-laptop-window case
   from the photos. */
.card { overflow-x: auto; }
.data-table { min-width: 100%; }
/* 2026-07-16: bumped 100px -> 115px alongside the font-size reduction above
   -- same "decrease the font size a bit" fix for the Operation Logbook's
   Category column wrapping mid-word; a slightly wider floor gives a long
   single word (e.g. "Segmentectomy") a better chance of fitting on one
   line before the overflow-wrap safety net further below has to break it
   mid-character. Still just a floor -- inert on any column already wider
   than this via its own content. */
.data-table td, .data-table th { min-width: 115px; }

@media (max-width: 720px) {
  .grid-2, .grid-3, .detail-grid, .stat-grid, .assessment-grid { grid-template-columns: 1fr; }
  /* Compact top bar: brand stays on one line (hospital name is now the
     short "CDH" instead of "Chest Diseases Hospital"), and the account
     controls (My Account/user-chip/Log out) are hidden entirely -- they're
     already one tap away in the bottom dock (direct "Account" slot for
     referring physicians, "My Account"/"Log Out" inside the bottom dock's
     More popup for every other role). That leaves only the menu button and
     (if present) the two notification buttons, which fit as a single
     right-aligned, wrapping row instead of the previous one-item-per-line
     column that pushed the whole page down. */
  .topbar { padding: 10px 16px; gap: 6px 10px; flex-wrap: wrap; }
  .topbar .brand { font-size: 16px; gap: 8px; }
  .brand-logo { height: 26px; }
  .topbar-right { flex: 1 1 auto; justify-content: flex-end; gap: 8px; }
  .topbar-account-group { display: none; }

  /* 2026-07-14/15: the scroll-instead-of-squish table fix (.card overflow,
     .data-table min-width floors) used to live here, scoped to this mobile
     breakpoint only. 2026-07-16: moved above, outside this media query --
     see the comment there. */
}

/* Defensive safety net (all widths, not just the mobile breakpoint above):
   an unusually long unbroken string with no natural break point (a long
   hospital name, email address, or model number) could still overflow its
   table cell/badge on a narrow phone even with the scroll fix above, since
   scrolling only helps when the OVERFLOW is the table's overall width, not
   a single cell's content forcing that width wider than it needs to be.
   overflow-wrap lets such a string break as a last resort while leaving
   normal word-spaced text wrapping exactly as it already did. */
.data-table td, .badge, .tag { overflow-wrap: anywhere; }

/* 2026-07-14: exempt an ID/reference-number specifically from the rule just
   above. A first-visit Consult's reference_number is the bare Civil ID --
   12 straight digits with no space or hyphen anywhere -- so overflow-wrap's
   "break as a last resort" had nowhere reasonable to break AT ALL, and
   ended up breaking after every single digit on a narrow phone (confirmed
   from Essa's own screenshot: a column that should read one 12-digit number
   turned into 12 separate lines, one digit each). white-space:nowrap keeps
   it on one line and lets the table's existing horizontal-scroll fix handle
   the overflow instead, which is far more readable than a per-character
   stack for the one number most likely to get read back over the phone. */
.ref-no { white-space: nowrap; }

/* ---------------------------------------------------------------------
   Home-screen icon tiles (dashboard quick links) + bottom icon dock.
   Added 2026-07-05 per Essa's request for icon-based navigation on the
   logged-in pages, on top of (not replacing) the existing top nav bar.
   --------------------------------------------------------------------- */

.nav-tiles {
  /* flex, not grid: a CSS grid with a fixed column count leaves a partial
     last row left-aligned (e.g. 2 tiles under a row of 4), which is what
     looked asymmetric. A wrapping flex container centers each row
     independently via justify-content, including a short last row, and a
     fixed (non-growing) tile width guarantees every tile is the same size
     in every row instead of a partial row's tiles stretching wider. */
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 12px; margin-bottom: 22px;
}
/* 2026-07-16, Essa: "smaller icons more stream line flow" -- the whole
   admin/on-call dashboard used to be ONE flat wrapping row of up to 17
   same-size tiles (clinical actions and rarely-touched admin config side
   by side with no visual hierarchy). See _nav_tiles.html: that row is now
   split into labeled .nav-group sections (Clinical / Scheduling & Referrals
   / Admin Tools) -- .nav-group-label is the small caption above each
   group's own .nav-tiles row. Referring physicians' 3-tile row (already
   short, already approved separately -- see 2026-07-14 entry) still uses
   .nav-tiles directly with no group wrapper, unchanged. */
.nav-group { margin-bottom: 6px; }
.nav-group-label {
  font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.03em; margin: 0 0 10px; text-align: center;
}
.nav-tile {
  flex: 0 0 68px;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px;
  padding: 10px 4px 8px; text-decoration: none; color: var(--text);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.nav-tile:hover { box-shadow: 0 2px 10px rgba(11, 79, 108, 0.12); transform: translateY(-1px); }
.nav-tile-icon {
  width: 36px; height: 36px; border-radius: 10px; background: #dceaf0; color: var(--navy);
  display: flex; align-items: center; justify-content: center;
}
.nav-tile-icon svg { width: 19px; height: 19px; }
.nav-tile-label { font-size: 11px; font-weight: 600; text-align: center; line-height: 1.25; }
/* Admin's own config tiles (Users/Hospitals/Procedure Categories/Wards &
   Beds/Hidden Items/Diagnostics) are real but low-frequency -- deliberately
   de-emphasized (not hidden) within their own group so the eye lands on
   Clinical/Scheduling first, same "de-prioritize without removing" idea
   Essa already approved for the OR Inventory duplicate-model-number flag. */
.nav-tile.nav-tile-muted { opacity: 0.75; }

/* Fixed bottom dock, capped at a phone-ish width and centered even on wide
   desktop windows, so it always reads as "one mobile-style control," not a
   stretched-out bar. */
.bottom-dock-spacer { height: 78px; } /* keeps page content from sitting under the fixed dock */

.bottom-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; justify-content: center; pointer-events: none;
}
.bottom-dock-inner {
  pointer-events: auto;
  width: 100%; max-width: 480px;
  display: flex; align-items: flex-end; justify-content: space-around;
  background: var(--card-bg); border-top: 1px solid var(--border);
  box-shadow: 0 -2px 12px rgba(11, 79, 108, 0.10);
  padding: 8px 6px calc(8px + env(safe-area-inset-bottom, 0px));
}
.dock-side { display: flex; flex: 1; }
.dock-item {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: none; border: none; text-decoration: none; color: var(--muted);
  font-size: 10.5px; font-weight: 600; padding: 4px 6px; cursor: pointer; flex: 1;
}
.dock-item .dock-icon { width: 22px; height: 22px; }
/* "In-Patient"/"Out-Patient" can word-wrap at the hyphen on a narrow phone
   (their flex:1 share of the row can get squeezed below the label's
   one-line width) while "Dashboard"/"Consults"/"More" never wrap (no
   space/hyphen to break at) -- so a wrapped item used to end up taller
   than its one-line siblings, and since .bottom-dock-inner bottom-anchors
   every item (align-items: flex-end, needed so .dock-fab's -18px offset
   pokes it above the shared bottom edge), the taller wrapped item's icon
   sat higher than the others. Reserving 2 lines' worth of height on every
   label -- whether it actually wraps or not -- keeps every item the same
   total height, so every icon lines up regardless of label length or
   screen width, without forcing labels to stop wrapping (which risks the
   row overflowing on a narrow phone instead). */
.dock-item span { line-height: 1.2; min-height: 2.4em; text-align: center; }
.dock-item:hover, .dock-item.active { color: var(--navy); }

.dock-fab {
  position: relative; top: -18px;
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--navy); color: white; border: 4px solid var(--bg);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 3px 10px rgba(11, 79, 108, 0.35); cursor: pointer; flex: none;
}
.dock-fab svg { width: 24px; height: 24px; }
.dock-fab:hover { background: var(--navy-dark); }

.dock-popup-backdrop {
  position: fixed; inset: 0; background: rgba(15, 23, 35, 0.28); z-index: 39;
}
.dock-popup {
  position: fixed; left: 50%; bottom: 92px; transform: translateX(-50%);
  width: min(320px, calc(100vw - 32px)); z-index: 41;
  background: var(--card-bg); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 8px 30px rgba(11, 79, 108, 0.25); padding: 8px; max-height: 70vh; overflow-y: auto;
}
.dock-popup-header {
  display: flex; justify-content: space-between; align-items: center;
  padding: 8px 10px; font-size: 12px; font-weight: 700; color: var(--muted); text-transform: uppercase;
}
.dock-popup-close { background: none; border: none; color: var(--muted); cursor: pointer; padding: 2px; }
.dock-popup-close svg { width: 16px; height: 16px; }
/* 2026-07-16, Essa: "more stream line flow" -- the top-bar "..." menu and
   the bottom dock's "More" popup both used to be one flat list of up to 13
   links with zero visual grouping. This small caption (see base.html's
   "Clinical records" / "Scheduling & referrals" / "Admin" dividers) breaks
   that wall of links into scannable groups without changing which links
   exist or where they go -- purely a visual/scan-time change. */
.dock-popup-section {
  font-size: 10.5px; font-weight: 700; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.03em; padding: 10px 10px 4px; margin-top: 2px;
}
.dock-popup-section:first-of-type { margin-top: 0; }
.dock-popup a {
  display: flex; align-items: center; gap: 12px; padding: 11px 10px; border-radius: 8px;
  text-decoration: none; color: var(--text); font-size: 14px; font-weight: 600;
}
.dock-popup a:hover { background: #f0f4f8; }
.dock-popup a .dock-icon { width: 20px; height: 20px; color: var(--navy); flex: none; }

/* Top-bar "..." menu popup -- same .dock-popup box/shadow/list styling,
   just anchored under the header instead of above the bottom dock. */
.topbar-popup {
  left: auto; right: 16px; bottom: auto; top: 62px; transform: none;
}

@media (min-width: 900px) {
  /* On genuinely wide desktop windows the top nav already covers everything
     comfortably -- keep the dock available (consistent, predictable) but
     let it sit unobtrusively rather than spanning attention next to a full
     text nav bar. */
  .bottom-dock-inner { max-width: 420px; border-radius: 16px 16px 0 0; border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
}

/* Patient portal bilingual support (2026-07-08) -- scoped to [dir="rtl"],
   which only the portal ever sets (see base.html's <html> tag), so this
   never affects any staff-facing page. Most of the layout (single-column
   cards, block-level form labels, centered auth footer) already mirrors
   correctly for free once dir="rtl" is set -- text-align's initial value is
   direction-aware, and flexbox row layouts (.page-header) flip their own
   start/end automatically per the CSS spec. Only a small, targeted set of
   overrides is actually needed. */
.lang-toggle { text-align: end; margin: 0 0 8px; font-size: 13px; }
.lang-toggle a { color: var(--navy); font-weight: 600; text-decoration: none; }
.lang-toggle a:hover { text-decoration: underline; }
[dir="rtl"] .auth-footer, [dir="rtl"] .empty-state { text-align: center; }
