/**
 * PalMed Custom Theme for OpenMRS O3
 *
 * Color Palette:
 *   Brand #1 (Primary):  #821b3b  — navbar, selected items
 *   Brand #2 (Dark):     #5c1329  — hover states, darker accents
 *   Brand #3 (Accent):   #a8264e  — buttons, active indicators
 *   Warm White:           #FAF8F7  — page backgrounds (replaces cold #f4f4f4)
 *   Surface:              #FFFFFF  — card/section backgrounds
 *   Border:               #E8E4E2  — softer borders
 *   Text Primary:         #2D2A2A  — headings
 *   Text Secondary:       #6B6565  — body text
 *   Text Muted:           #9A9494  — labels, hints
 *
 * Note: Brand colors (navbar, buttons, tabs) are also configured via
 * palmed-config.json -> @openmrs/esm-styleguide Brand color #1/#2/#3.
 */

/* =============================================================================
   1. TYPOGRAPHY — Inter + Noto Sans Arabic
   ============================================================================= */
/* 'Inter' has zero Arabic glyph coverage. Before this fix, Arabic text
   silently fell through the rest of this stack to whichever generic
   sans-serif the OS/browser happened to substitute -- confirmed live
   (computed styles + screenshot) that this was never a deliberate choice,
   just an accidental fallback; different OSes/browsers ship different
   default Arabic-capable fonts, so this was never guaranteed to render
   consistently across real users' devices even though it happened to look
   acceptable in this session's own test environment. 'Noto Sans Arabic' is
   loaded (see deploy-branding.sh) specifically as an Arabic companion to
   Inter, not a replacement -- per-character font-family fallback resolves
   Latin/digit glyphs via Inter (first in the stack, full coverage) and
   Arabic-script glyphs via Noto Sans Arabic (Inter simply has no glyphs
   there to "win" with) automatically, with no [dir="rtl"]-scoped override
   needed. Chosen over a more stylized Arabic-native font (Cairo, Tajawal)
   for the same reason 'Inter' itself was chosen -- broad, reliable,
   professional-register Unicode coverage over a distinctive but narrower
   typographic identity, appropriate for a clinical record system. */
body,
.cds--body,
.cds--content,
.omrs-main-content,
.cds--text-input,
.cds--text-area,
.cds--dropdown,
.cds--btn,
.cds--side-nav__link-text,
.cds--header__name,
.cds--modal-content,
.cds--data-table th,
.cds--data-table td {
  font-family: 'Inter', 'Noto Sans Arabic', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* Smoother font rendering */
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* =============================================================================
   2. WARM BACKGROUND COLORS
   Replace Carbon's cold #f4f4f4 with warm #FAF8F7
   ============================================================================= */
body {
  background-color: #FAF8F7 !important;
}

/* Main content area */
.omrs-main-content,
[class*="dashboard-container__dashboardContainer"],
[class*="dashboardView"] {
  background-color: #FAF8F7 !important;
}

/* Carbon's default backgrounds */
.cds--content {
  background-color: #FAF8F7 !important;
}

/* Data table backgrounds */
.cds--data-table-container {
  background-color: #FFFFFF !important;
}

/* =============================================================================
   3. CSS CUSTOM PROPERTIES
   ============================================================================= */
:root {
  /* PalMed color tokens */
  --palmed-bg: #FAF8F7;
  --palmed-surface: #FFFFFF;
  --palmed-border: #E8E4E2;
  --palmed-text-primary: #241B1E;
  --palmed-text-secondary: #5F5559;
  --palmed-text-muted: #A79DA0;

  /* The brand wash, and the hairline that makes it read on a light ground. Both are
     the public site's own values (`--brand-wash` and the 26%-of-`--brand-lift` border
     its .alert/.chip use); section 19 independently arrived at the same #F8EDF1 for
     Carbon's selected-surface tokens, which is what makes this a palette entry rather
     than one rule's magic number. A wash this close to paper needs the border: on the
     patient banner's own ground it sits at 1.09:1. */
  --palmed-brand-wash: #F8EDF1;
  --palmed-brand-wash-border: rgba(168, 38, 78, 0.26);

  /* Display typeface, used by section 20. Inter leads so Latin headings are unchanged;
     Noto Kufi Arabic has only the arabic subset, so it wins exactly the glyphs Inter has
     none of. Noto Sans Arabic stays last as the fallback if Kufi has not loaded yet. */
  --palmed-font-display: 'Inter', 'Noto Kufi Arabic', 'Noto Sans Arabic',
    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* Warm shadow, not neutral black. Every surface here sits on a warm paper (#FAF8F7),
     and a pure-black shadow on a warm ground reads as grey dirt rather than depth. */
  --palmed-shadow-sm: 0 1px 2px rgba(36, 27, 30, 0.06);
  --palmed-shadow-md: 0 4px 12px rgba(36, 27, 30, 0.10);

  /* Override OpenMRS interaction colors */
  --omrs-color-interaction: #821b3b;
  --omrs-color-interaction-minus-two: #5c1329;
  --omrs-color-interaction-plus-two: #a8264e;
}

/* =============================================================================
   4. SIDEBAR / LEFT NAV STYLING
   ============================================================================= */
/* Sidebar background: white instead of gray */
.cds--side-nav,
.cds--side-nav--expanded,
[class*="left-nav-module__leftNav"] {
  background-color: var(--palmed-surface) !important;
}

/* Sidebar border: softer */
[class*="left-nav-module__leftNav"] {
  border-right: 1px solid var(--palmed-border) !important;
}

/* Nav links: better spacing; square corners in every state (rest, hover, active) */
.cds--side-nav__link {
  border-radius: 0 !important;
  margin: 0.125rem 0.5rem !important;
  padding: 0 0.75rem !important;
  transition: background-color 0.15s ease, color 0.15s ease !important;
}

.cds--side-nav__link:hover {
  background-color: #FAF8F7 !important;
}

/* Active nav link: brand-colored background tint + left indicator */
.cds--side-nav__link.active-left-nav-link {
  background-color: rgba(130, 27, 59, 0.08) !important;
  border-left: 0.25rem solid var(--brand-01, #821b3b) !important;
  border-radius: 0 !important;
}

.cds--side-nav__link.active-left-nav-link .cds--side-nav__link-text {
  color: #821b3b !important;
  font-weight: 600 !important;
}

/* Nav link text styling */
.cds--side-nav__link-text {
  color: var(--palmed-text-secondary) !important;
  font-size: 0.875rem !important;
  font-weight: 500 !important;
}

.cds--side-nav__link:hover .cds--side-nav__link-text {
  color: var(--palmed-text-primary) !important;
}

/* =============================================================================
   5. LOGIN PAGE
   ============================================================================= */
[class*="container"][class*="login"] {
  background: linear-gradient(135deg, #FAF8F7 0%, #f8dfe7 50%, #f2bece 100%) !important;
}

/* =============================================================================
   6. HIDE "Built with OpenMRS" footer on login page
   ============================================================================= */
[class*="poweredByTile"] {
  display: none !important;
}

/* =============================================================================
   7. CUSTOM SCROLLBAR
   ============================================================================= */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  background: #faf6f7;
}

::-webkit-scrollbar-thumb {
  background: #e47d9d;
  border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
  background: #a8264e;
}

/* =============================================================================
   8. SELECTION HIGHLIGHT
   ============================================================================= */
::selection {
  background-color: #f2bece;
  color: #5c1329;
}

/* =============================================================================
   9. FOCUS RING
   ============================================================================= */
*:focus-visible {
  outline-color: #a8264e !important;
}


/* =============================================================================
   RTL (Right-to-Left) Layout Overrides
   =============================================================================
   These overrides fix layout issues when the UI language is set to Arabic (or
   any RTL language). The pre-built O3 module bundles use physical CSS properties
   (margin-left, border-right, etc.) that don't automatically flip in RTL mode.
   We override them here with direction-aware values under html[dir="rtl"].
   ============================================================================= */

/* ---------------------------------------------
   1. CRITICAL: Main Content Area Margin
   --------------------------------------------- */
html[dir="rtl"] .omrs-main-content {
  margin-left: unset !important;
  margin-right: 0 !important;
  transition: margin-right 0.5s ease !important;
}

html[dir="rtl"] .omrs-breakpoint-gt-tablet .omrs-main-content {
  margin-left: unset !important;
}

/* ---------------------------------------------
   1b. CRITICAL: Dashboard Container Width
   --------------------------------------------- */
html[dir="rtl"] [class*="dashboard-container__dashboardContainer"] {
  width: auto !important;
  flex: 1 1 0% !important;
  min-width: 0 !important;
}

/* ---------------------------------------------
   2. Left Nav Border (RTL)
   --------------------------------------------- */
html[dir="rtl"] [class*="left-nav-module__leftNav"] {
  border-right: none !important;
  border-left: 1px solid var(--palmed-border) !important;
}

html[dir="rtl"] .active-left-nav-link {
  border-left: unset !important;
  border-right: 0.25rem solid var(--brand-01) !important;
}

/* ---------------------------------------------
   3. Workspace Panel
   ---------------------------------------------
   The original rule here (targeting a [class*="workspace-module__..."]
   substring) is dead -- a later esm-app-shell bundle switched this
   component to fully-hashed CSS-module class names with no readable
   prefix at all (confirmed live: zero elements on the page match any
   class containing the word "workspace"), so the selector has silently
   matched nothing for some time.

   The real, currently-live bug this masked: the v2 workspace panel is
   positioned with plain physical `right: 0; left: -Npx` (docking flush
   against the right edge, sliding in from further left) -- correct only
   for LTR. `<body>`'s own CSS Grid (`grid-template-areas: "leftNav
   appRoots workspace"`) correctly mirrors under RTL per spec, moving the
   #omrs-workspaces-container grid cell itself to the visual LEFT edge of
   the viewport (confirmed live: leftNav's own anchor moves to the right,
   matching this app's existing intentional RTL nav mirroring) -- but the
   panel's own left/right docking values never got a matching RTL flip,
   so it renders 420px past the LEFT edge into negative x-coordinates:
   fully present in the DOM with real content, completely invisible.
   Every Arabic-locale user opening any v2 workspace (Dispense, Pause,
   Close, lab orders, clinical notes, etc.) hit this.

   Fixed with a stable ID-based structural selector (#omrs-workspaces-
   container is a permanent index.html anchor, not a build artifact) that
   flips the panel to dock flush against its now-mirrored LEFT edge
   instead, matching where its grid cell actually sits under RTL.
   --------------------------------------------- */
html[dir="rtl"] #omrs-workspaces-container > div {
  right: auto !important;
  left: 0 !important;
}

html[dir="rtl"] [class*="action-menu-module__container"] {
  right: unset !important;
  left: 0 !important;
  border-left: none !important;
  border-right: 1px solid #a8a8a8 !important;
}

/* ---------------------------------------------
   4. Service Queues Module
   --------------------------------------------- */
html[dir="rtl"] [class*="patient-queue-header__header"] {
  border-left: unset !important;
  border-right: 0 !important;
  padding-right: unset !important;
  padding-left: 0.5rem !important;
}

html[dir="rtl"] [class*="patient-queue-header__dropdown"] .cds--dropdown--inline .cds--list-box__menu {
  left: unset !important;
  right: -4rem !important;
}

html[dir="rtl"] [class*="patient-queue-header__date-and-location"] {
  margin-left: unset !important;
  margin-right: 1rem !important;
}

html[dir="rtl"] [class*="queue-status__statusContainer"] svg {
  margin-right: unset !important;
  margin-left: 0.5rem !important;
}

html[dir="rtl"] [class*="queueTableByStatusNavMenu"] .active-left-nav-link {
  padding-left: unset !important;
  padding-right: 1.75rem !important;
}

html[dir="rtl"] [class*="metrics-card__link"] svg {
  margin-left: unset !important;
  margin-right: 0.5rem !important;
}

html[dir="rtl"] [class*="backButton"] button svg {
  margin-right: unset !important;
  margin-left: 0.5rem !important;
}

html[dir="rtl"] [class*="triage-note__unit"],
html[dir="rtl"] [class*="triage-note__vitalValues"],
html[dir="rtl"] [class*="triage-note__danger-icon"],
html[dir="rtl"] [class*="triage-note__iconWrapper"] {
  margin-left: unset !important;
  margin-right: 0.25rem !important;
}

html[dir="rtl"] [class*="triage-note__grid"] {
  padding-left: unset !important;
  padding-right: 0 !important;
}

html[dir="rtl"] [class*="past-visit-summary__selectedTab"] > button,
html[dir="rtl"] [class*="past-visit-summary__tab"][aria-selected="true"] {
  border-left: none !important;
  border-right: 3px solid var(--brand-03) !important;
  margin-left: unset !important;
  margin-right: 0 !important;
}

html[dir="rtl"] [class*="past-visit-summary__tab"][aria-selected="false"] {
  border-left: none !important;
  border-right: 0.125rem solid #e0e0e0 !important;
  margin-left: unset !important;
  margin-right: 0 !important;
}

html[dir="rtl"] [class*="queue-linelist-base-table__subTitle"] {
  margin-left: unset !important;
  margin-right: 0.75rem !important;
}

/* ---------------------------------------------
   5. Appointments Module
   --------------------------------------------- */
html[dir="rtl"] [class*="appointments-header__header"] {
  border-left: unset !important;
  border-right: 0 !important;
  padding-right: unset !important;
  padding-left: 0.5rem !important;
}

html[dir="rtl"] [class*="metrics-header__metricsContent"] {
  margin-left: unset !important;
  margin-right: auto !important;
}

html[dir="rtl"] [class*="calendar-header__titleContainer"],
html[dir="rtl"] [class*="calendar-header__titleContent"],
html[dir="rtl"] [class*="patient-appointments-header__titleContent"] {
  margin-left: unset !important;
  margin-right: 1rem !important;
}

html[dir="rtl"] [class*="calendar-header__backButton"] svg,
html[dir="rtl"] [class*="patient-appointments-header__backButton"] svg {
  margin-right: unset !important;
  margin-left: 0.5rem !important;
}

html[dir="rtl"] [class*="appointments-table__headerContainer"] svg {
  margin-left: unset !important;
  margin-right: 0.5rem !important;
}

html[dir="rtl"] [class*="monthly-workload__monthly-cell"] {
  border-left: none !important;
  border-right: 1px solid #e0e0e0 !important;
}

html[dir="rtl"] [class*="workload__tileContainer"]:first-child {
  border-left-width: unset !important;
  border-right-width: 1px !important;
}

html[dir="rtl"] [class*="monthly-workload__serviceArea"] {
  text-align: right !important;
}

/* ---------------------------------------------
   6. Laboratory Module
   --------------------------------------------- */
html[dir="rtl"] [class*="overlay__desktopOverlay"] {
  right: unset !important;
  left: 0 !important;
  border-left: none !important;
  border-right: 1px solid #a8a8a8 !important;
}

html[dir="rtl"] [class*="overlay__desktopOverlay"]::after {
  border-left: none !important;
  border-right: 1px solid #a8a8a8 !important;
}

html[dir="rtl"] [class*="orders-data-table__toolbarItem"] {
  margin-left: unset !important;
  margin-right: 1rem !important;
}

html[dir="rtl"] [class*="orders-data-table__toolbarItem"] p {
  padding-right: unset !important;
  padding-left: 0.5rem !important;
}

html[dir="rtl"] [class*="lab-summary-tile__link"] svg {
  margin-left: unset !important;
  margin-right: 0.5rem !important;
}

/* ---------------------------------------------
   7. Shared Components (all modules)
   --------------------------------------------- */
html[dir="rtl"] [class*="datepicker-module__inputWrapper"],
html[dir="rtl"] [class*="date-range-picker-module__inputWrapper"],
html[dir="rtl"] [class*="date-range-picker-module__dateInputWrapper"],
html[dir="rtl"] [class*="date-range-picker-module__inputsWrapper"] {
  margin-left: unset !important;
  margin-right: 1rem !important;
}

html[dir="rtl"] [class*="error-state-module__desktopHeading"],
html[dir="rtl"] [class*="error-state-module__tabletHeading"],
html[dir="rtl"] [class*="empty-state__desktopHeading"],
html[dir="rtl"] [class*="empty-state__tabletHeading"],
html[dir="rtl"] [class*="appointments-table__desktopHeading"],
html[dir="rtl"] [class*="appointments-table__tabletHeading"] {
  text-align: right !important;
}

html[dir="rtl"] [class*="app-menu-panel__launchIcon"] {
  margin-left: unset !important;
  margin-right: 0.5rem !important;
}

/* ---------------------------------------------
   8. Table row-action "..." (kebab) overflow menus
   --------------------------------------------- */
/* Every data table's per-row action menu (Vitals, Biometrics, Conditions,
   Allergies, Programs, Medications, etc.) is a Carbon <OverflowMenu flipped>
   from esm-patient-common-lib, sharing the aria-label pattern
   "Edit or delete <thing>". Carbon computes RTL "flip" positioning in JS by
   anchoring the menu's *right* edge to the trigger's right edge:
   left = triggerRight - menuWidth (page-absolute pixels, recalculated fresh
   on every open). On a full-width single table, the Actions column ends up
   at the visual left edge (RTL mirrors the table), leaving no room to open
   further left, so the menu renders partly off-screen (observed:
   left: -62px on the Vitals table).

   FIRST ATTEMPT (reverted): overrode `left` to a fixed absolute value
   (`left: 0.5rem !important`). This "worked" on single-table pages by
   coincidence — the Actions column happens to sit near the page's own
   left edge there — but broke completely on the Patient Summary page,
   where multiple tables sit side-by-side in a grid (e.g. Conditions in
   the *right* column, Active medications in the *left*). An absolute
   override drags every menu to the same fixed page position regardless
   of which column its trigger is actually in — confirmed live: Carbon's
   own computed `left` for the Conditions table's menu was `551.5px`
   (correctly near its right-column trigger), but the absolute override
   forced it to `8px`, all the way across the page into the *left*
   column's content.

   ACTUAL FIX: `transform: translateX()` is *additive* on top of Carbon's
   own computed `left`/`right` (left untouched here, unlike the first
   attempt), so it correctly re-anchors relative to each trigger's real
   position regardless of which column/table it's in. Carbon's flip
   formula is `left = triggerRight - menuWidth`; shifting right by
   exactly `menuWidth` (200px = 12.5rem, this menu's fixed Carby "sm"
   size) turns that into `left = triggerRight` — i.e. flips the menu to
   open forward from the trigger's own right edge instead of backward
   past it, which stays on-screen no matter where the trigger sits.
   Verified on both the single-table Vitals page and the multi-column
   Patient Summary page.

   THE SELECTOR USED TO BE KEYED ON `[aria-label^="Edit or delete"]`, AND
   THAT WAS SELF-DEFEATING. It is an ENGLISH LITERAL, but this rule only
   ever applies in Arabic -- so every component that correctly translates
   its aria-label stopped matching in exactly the language the rule exists
   for. Measured on Patient Summary at 360px in an Arabic session: the
   Vitals menus render `aria-label="تعديل أو حذف العلامات الحيوية"` and
   Medications renders "قائمة الإجراءات", so neither matched, while
   Conditions matched only because it hardcodes `aria-label="Edit or
   delete condition"` in English rather than passing it through t(). The
   one component that forgot to translate was the one component the fix
   reached, which is why Conditions was reported as behaving correctly
   and every other section was not.

   Menus that miss this rule do not merely stay off-screen: the runtime
   safety net (palmed-rtl-popover-fix.js) then clamps them to the viewport
   edge, which reproduces the absolute-`left` behaviour described above as
   the reverted FIRST ATTEMPT. Measured at 1280px: the Medications trigger
   sits at 110..150 while its menu was pinned to 8..208, i.e. dragged out
   of its own column. With this rule matching, the menu lands at
   `triggerRight..triggerRight+width` and the safety net computes a zero
   shift, so it no longer intervenes at all.

   Scoped now to `.cds--overflow-menu--flip` with no label test. In this
   codebase `flipped` is passed only by row-action kebab menus -- ten of
   them (allergies, attachments, clinical-views, conditions, encounters,
   medications, orders, procedures, programs, vitals) -- so the class is a
   precise stand-in for "table row action" and reaches all of them in any
   language. The patient banner does not use OverflowMenu at all, so it
   cannot be caught by this.

   `translateX(100%)` rather than a hardcoded 12.5rem: the shift has to be
   exactly the menu's own width for `left = triggerRight - width` to
   become `left = triggerRight`, and a percentage in a transform resolves
   against the element's own border box. 100% is that width by definition,
   so this stays correct if a menu is ever wider than Carbon's 200px "sm"
   default -- which Arabic labels can easily cause. */
html[dir="rtl"] ul.cds--overflow-menu-options.cds--overflow-menu--flip {
  transform: translateX(100%) !important;
}

/* ---------------------------------------------
   9. Table row-action "..." (kebab) HOVER TOOLTIP
       fixed at the source, no rule needed here
   --------------------------------------------- */
/* This used to carry `transform: translateX(6.5rem) !important` plus a
   `pointer-events: none`, and both are gone. Do not reinstate either.

   Same cause as #9b: upstream hardcoded `align="left"` on these OverflowMenu
   triggers, Carbon treats that as a PHYSICAL side and ships `[dir='rtl']` rules
   that deliberately un-mirror it, and so in Arabic the "Options" label opened
   leftward into the table's own `overflow: auto` scroll container and was
   clipped away. The 6.5rem shift restored visibility and nothing else: one fixed
   offset for labels of different widths, landing each on top of its own trigger
   by a different amount, which is why `pointer-events: none` was needed to stop
   the label swallowing the click meant for the button underneath. Overriding
   `transform` also discarded the `-50%` that centres the label on its trigger.

   Every one of those call sites now passes a mirrored `align` instead
   (`useActionMenuAlignment`, in esm-patient-common-lib and duplicated into the
   two patient-management apps and palmed-esm-visits-app), so Carbon places the
   label itself — correct side, correct offset, correct caret, never over the
   button. `pointer-events: none` is still applied at runtime by
   palmed-rtl-popover-fix.js to any popover it inspects, so the click-swallowing
   protection is not lost with this rule.

   Rule #8 above is a DIFFERENT bug and stays: that is the open dropdown menu,
   positioned by Carbon's own JS flip, not this hover label. */

/* ---------------------------------------------
   9b. Left action rail (Order basket / Visit note / Clinical forms)
       HOVER TOOLTIP — fixed at the source, no rule needed here
   --------------------------------------------- */
/* This used to carry a `transform: translateX(8rem) !important` to drag the rail's
   hover labels back on screen in RTL. That is gone, and must not come back.

   The cause was upstream hardcoding `align="left"` on these triggers. Carbon treats
   that as a PHYSICAL side and even ships `[dir='rtl']` rules that deliberately
   un-mirror it, so in Arabic — where the rail moves to the left edge — the label
   opened off the left of the viewport. The 8rem shift made it visible again but
   could not make it right: a fixed nudge lands every label at the same x whatever
   its width, so all three sat on top of their own icons, and because the override
   replaced Carbon's whole transform it also dropped the `-50%` that centres the
   label on its trigger, leaving each one hanging half a label-height too low.

   `ActionMenuButton`/`ActionMenuButton2` now pass `align="right"` under RTL
   (see use-document-direction.ts), which is the mirror of what LTR already does and
   hands Carbon back full control of placement, caret included. Nothing to override.

   Rule #9 above is NOT the same case and stays: those are data-table row action
   menus, a different Carbon component in a scrollable container, not this rail. */

/* ---------------------------------------------
   9c. Laboratory app (esm-laboratory-app): content stops well short
       of the (right, in RTL) nav, leaving a large empty gap
   --------------------------------------------- */
/* Different bug class from #8/#9/#9b above — this one is a plain
   layout-width bug, not a popover/tooltip positioning bug.

   Rule #1b earlier in this file already fixes the *outer* dashboard
   container (`[class*="dashboard-container__dashboardContainer"]`) to
   correctly narrow itself to the space actually available next to the
   nav. But the laboratory app's own tab-content wrapper — a completely
   unstyled `<section>` with no class or id at all — carries its *own*,
   separate `margin-right: 256px` (reserving space for the 256px-wide
   nav a second time, nested one level inside a container that already
   accounts for it), squeezing the visible content down to 1088px
   inside an already-correctly-sized 1344px container. Net effect: a
   ~256px dead gap between the content and the nav.

   No class/id to select on directly, so this uses `:has()` with an
   explicit direct-child combinator (`> `) to identify it structurally:
   "the `<section>` whose direct child is the laboratory tabs wrapper".
   The direct-child combinator is required, not optional — without it,
   `:has()` also matches the *outer* dashboard-container `<section>`
   (the tabs wrapper is a descendant of that one too, just not a direct
   child), and zeroing that one's margin as well made the content
   overlap the nav entirely instead of stopping short of it. Verified
   after the fix: content's right edge and the nav's left edge both
   land at the same x-coordinate, and no horizontal scrollbar appears
   (`document.documentElement.scrollWidth === window.innerWidth`). */
html[dir="rtl"] section:has(> [class*="laboratory-tabs__tabs"]) {
  margin-right: 0 !important;
  width: auto !important;
}

/* ---------------------------------------------
   9d. Patient Lists app (esm-patient-list-management-app): same
       double-reserved-nav-width gap as #9c, plus a flex-basis wrinkle
   --------------------------------------------- */
/* Same root cause and same fix shape as Gotcha 143 (#9c above) — this
   app's own dashboard `<section>`
   (`[class*="lists-dashboard__dashboard___"]`, e.g.
   `-esm-patient-list-management__lists-dashboard__dashboard___O17Hh`,
   distinct from the *sibling* `...dashboardContainer___` class on its
   MAIN ancestor, which is already correctly handled by rule #1b) also
   carries its own redundant `margin-right: 256px`.

   Unlike #9c's plain unstyled `<section>`, this one's class name IS
   readable (webpack's CSS-module hash embeds the original name), so no
   `:has()` structural workaround was needed here — a direct
   `[class*=]` attribute selector on the stable name prefix works. The
   `___` (three underscores, right before the hash suffix) in the
   selector is load-bearing: without it, `[class*="lists-dashboard__dashboard"]`
   also matches the sibling `...dashboardContainer___` class (which
   starts with the same "dashboard" prefix) — harmless in practice here
   since that element's margin is already 0, but imprecise and easy to
   have go wrong if that ancestor's styling ever changes.

   Removing the margin alone was NOT sufficient here (unlike #9c) — the
   element still didn't widen to fill the freed space, just shifted
   right while staying at its shrink-to-fit content width. Its parent
   is a flex container and this element had `flex-grow: 0`, so `width:
   auto` alone has no effect in a flex item that isn't allowed to grow.
   Needed `flex: 1 1 0%` as well to actually let it expand and claim the
   available space. Verified: content's right edge lands exactly at the
   nav's left edge, no horizontal scrollbar, consistent across all 4
   tabs (Starred / System lists / My lists / All lists). */
html[dir="rtl"] [class*="lists-dashboard__dashboard___"] {
  margin-right: 0 !important;
  width: auto !important;
  flex: 1 1 0% !important;
}

/* ---------------------------------------------
   9e. Patient Lists app: same visible nav gap as #9d, but on the LIST
       DETAIL page (viewing one list's patients) instead of the browse
       page, and via a genuinely different mechanism
   --------------------------------------------- */
/* Confirmed live by walking `document.styleSheets` for every rule whose
   selector actually matches this element (not guessing from the SCSS
   source, which declares no margin on `.cohortHeader` at all — see
   `list-details.scss`). The real culprit is a core OpenMRS/esm-styleguide
   global RTL rule, NOT a PalMed or app-specific one:

     html[dir="rtl"] .omrs-breakpoint-gt-tablet main > section {
       margin-right: var(--omrs-sidenav-width); (= 16rem = 256px)
       margin-left: unset;
     }

   This rule is meant to reserve nav space for the app's real top-level
   content section (an actual `<main> > <section>` pair right under
   `.omrs-main-content`). It's unscoped beyond that plain tag-combinator
   shape, so it also matches ANY unrelated `<main> > <section>` pair
   anywhere in the DOM — and `list-details.component.tsx` happens to
   render exactly that shape internally: `<section className={cohortHeader}>`
   is a direct child of its own `<main className={container}>` wrapper,
   several levels deep inside the real page structure, not the top-level
   target this rule was written for. Net effect: the same "nav width
   reserved twice" gap as #9c/#9d, but the second reservation comes from
   a generic selector collision rather than a duplicated dashboard-container
   class.

   Fixed narrowly, scoped only to this one class, so the legitimate
   top-level `main > section` rule is untouched everywhere else. No
   `width`/`flex` override needed here (unlike #9d) — `.cohortHeader`'s
   parent (`.container`) is a `flex-direction: column` container with the
   default `align-items: stretch`, so a plain flex child already fills
   the available cross-axis width once its own margin stops shrinking it.
   Verified after the fix: content's right edge lands exactly at the
   nav's left edge, top/bottom/left margins unaffected (they were already
   0 from a more specific override elsewhere), no horizontal scrollbar. */
html[dir="rtl"] [class*="list-details__cohortHeader___"] {
  margin-right: 0 !important;
}

/* =============================================================================
   10. MOBILE NAVBAR RESPONSIVENESS
   Upstream O3 navbar doesn't collapse — items overflow on narrow screens.
   We progressively hide / shrink elements to fit.
   ============================================================================= */

/* Nothing in this section hides a navbar control by ROLE, and nothing here should start to.
   Pharmacist and Lab Technician do not get the patient-search and add-patient icons, but that is
   decided in `esm-primary-navigation-app`'s `minimal-navbar.ts`, which filters them out of
   `top-nav-actions-slot` so they are never mounted at all. A `display: none` rule would leave both
   in the DOM and, for patient search specifically, would take the full-screen search overlay down
   with it -- see the standing warning in the ≤320px block below. The rules here are about width,
   for everyone; that one is about who the user is. */

/* --- Tablet: ≤ 480px — hide location text, keep icon only --- */
@media (max-width: 480px) {
  /* Shrink logo */
  .cds--header [class*="logo__logo"] {
    max-width: 80px !important;
    height: auto !important;
  }

  /* Hide location name text, keep the location icon button */
  [class*="currentLocationText"] {
    display: none !important;
  }

  /* Tighten header action button padding */
  .cds--header .cds--header__action {
    padding: 0 0.5rem !important;
    width: auto !important;
    min-width: 2.5rem !important;
  }

  /* "Add patient" is NOT hidden here, and must not be hidden again.
     It used to be, on the stated grounds that it was "accessible via the app
     menu" -- but the app menu was gated to System Developer only on 2026-08-29,
     so for the doctors and registration clerks who actually register patients
     that fallback no longer exists and the icon was the only route left. There
     is no space argument for hiding it either: measured with it shown,
     `document.scrollWidth` still equals the viewport at 390px, 360px AND 320px,
     the header's own scrollWidth does not grow, and the logo does not move. */
}

/* --- Small phone: ≤ 360px — further compact --- */
@media (max-width: 360px) {
  /* Smaller logo */
  .cds--header [class*="logo__logo"] {
    max-width: 64px !important;
  }

  /* Hide the divider between logo and location */
  .cds--header [class*="divider"] {
    display: none !important;
  }

  /* Tighter action buttons */
  .cds--header .cds--header__action {
    padding: 0 0.375rem !important;
    min-width: 2rem !important;
  }

  /* Hide implementer tools button if visible */
  [data-extension-id="implementer-tools-button"] {
    display: none !important;
  }
}

/* --- Very narrow: ≤ 320px — minimal navbar --- */
@media (max-width: 320px) {
  /* Even smaller logo */
  .cds--header [class*="logo__logo"] {
    max-width: 52px !important;
  }

  /*
   * DO NOT hide `[data-extension-id="patient-search-icon"]` here. A rule that did so lived at
   * this spot, justified as "accessible via app menu or page search". Both halves of that were
   * false by the time it was read:
   *
   *  - the App Menu was gated to System Developer on 2026-08-29, so for a doctor, nurse or
   *    clerk there is no menu to reach search through;
   *  - `PatientSearchOverlay` is rendered INSIDE `.patientSearchIconWrapper`, so hiding this
   *    extension also hid the full-screen search UI on /search itself -- destroying the "page
   *    search" fallback the comment named. At <=320px the page fell back to the desktop
   *    two-column layout, laid out 1032px wide and centred, which put every row's Actions and
   *    Start visit buttons off-screen with no way to scroll to them, and left no search input
   *    at all.
   *
   * The space it was meant to reclaim is not needed: with the icon shown, the header still fits
   * exactly at 320px (icon at 184..218) and at 302px (166..200) -- measured, header scrollWidth
   * == clientWidth in both. Same shape as Gotcha 472, which un-hid the add-patient icon here for
   * the same reason.
   */

  /* Compact hamburger */
  .cds--header [class*="headerMenuButton"] {
    padding: 0 0.375rem !important;
    width: auto !important;
    min-width: 2rem !important;
  }
}

/* =============================================================================
   11. DISPENSING WORKSPACE — MOBILE RESPONSIVENESS
   Upstream dispense/pause/close workspace forms use fixed-width flex layouts
   that overflow on narrow screens. Override to stack vertically.
   ============================================================================= */

/* --- Always: prevent overflow from upstream fixed widths --- */
[class*="medicationDispenseReviewContainer"] {
  max-width: 100% !important;
  width: 100% !important;
  box-sizing: border-box !important;
  overflow: hidden !important;
}

/* Stack vertical container: clip children that overflow */
[class*="medicationDispenseReviewContainer"] .cds--stack-vertical {
  max-width: 100% !important;
  overflow: hidden !important;
}

[class*="medicationTile"] {
  max-width: 100% !important;
  min-width: 0 !important;
  flex-wrap: wrap !important;
}

/* --- Tablet & phone: ≤ 672px — stack dispensing form fields vertically --- */
@media (max-width: 672px) {
  /* Main dispense details: stack fields vertically, respect parent width */
  [class*="dispenseDetailsContainer"] {
    flex-direction: column !important;
    max-width: 100% !important;
    width: auto !important;
    min-width: 0 !important;
    box-sizing: border-box !important;
    gap: 0.75rem !important;
  }

  /* Force the review container to not exceed parent */
  [class*="medicationDispenseReviewContainer"],
  [class*="medicationDispenseReviewContainer"] > * {
    max-width: 100% !important;
    min-width: 0 !important;
  }

  /* Form group: stack vertically */
  [class*="forms__formGroup"] {
    flex-direction: column !important;
  }

  /* Medication tile: stack drug name and info icon */
  [class*="medicationTile"] {
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 0.5rem !important;
    padding: 0.5rem !important;
  }

  /* Quantity summary: full width */
  [class*="quantitySummary"] {
    max-width: 100% !important;
  }

  /* Number inputs / combo boxes: full width */
  [class*="medicationDispenseReviewContainer"] .cds--number,
  [class*="medicationDispenseReviewContainer"] .cds--combo-box,
  [class*="medicationDispenseReviewContainer"] .cds--text-input,
  [class*="medicationDispenseReviewContainer"] .cds--date-picker,
  [class*="medicationDispenseReviewContainer"] .cds--text-area {
    max-width: 100% !important;
    width: 100% !important;
  }

  /* Form items: full width, allow shrinking */
  [class*="medicationDispenseReviewContainer"] .cds--form-item {
    width: 100% !important;
    min-width: 0 !important;
  }

  /* Dispense details: override intrinsic sizing */
  [class*="dispenseDetailsContainer"] .cds--form-item,
  [class*="dispenseDetailsContainer"] .cds--number,
  [class*="dispenseDetailsContainer"] .cds--combo-box,
  [class*="dispenseDetailsContainer"] .cds--list-box__wrapper {
    min-width: 0 !important;
    max-width: 100% !important;
  }
}

/* =============================================================================
   12. HOME PAGE: Fix flex overflow on mobile
   The upstream homePageWrapper is flex-row. Its child (dashboardContainerTablet)
   has flex: 1 1 auto but min-width: auto causes content to overflow the parent.
   ============================================================================= */
[class*="homePageWrapper"] > * {
  min-width: 0 !important;
}

[class*="dashboardContainerTablet"] {
  overflow: hidden;
}

/* =============================================================================
   13. PATIENT CHART: Modern warm design overhaul
   Targets upstream patient-chart, patient-banner, vitals, medications widgets.
   Uses attribute selectors to match hashed CSS module class names.
   ============================================================================= */

/* --- Patient Banner --- */
[class*="patient-banner__container"] {
  background: linear-gradient(135deg, #faf8f5 0%, #f5f0ec 100%) !important;
  border-bottom: 2px solid #e8e0da !important;
  padding: 1rem 1.25rem !important;
}

/* Patient name in the patient chart's page header. The styleguide component that renders
   it is a CSS module with content-hashed class names, so this counts DOM depth from the
   chart banner's own (readable) class instead. Scoped to esm-patient-banner deliberately:
   esm-patient-search-app renders the same component one level deeper, behind its own
   patientInfoAndClinic wrapper, and scales those rows itself via compact-patient-info. */
[class*="esm-patient-banner__patient-banner__patientBanner"] > div > div > div > span {
  font-weight: 400 !important;
  font-size: 1.0625rem !important;
  color: #4a4545 !important;
  letter-spacing: normal !important;
}

[class*="patient-banner__container"] [class*="patientInfo"] {
  gap: 0.25rem !important;
}

[class*="patient-banner__container"] [class*="demographics"] {
  color: #5a5353 !important;
  font-size: 0.875rem !important;
}

/* Active Visit tag */
[class*="patient-banner__container"] .cds--tag--green,
[class*="patient-banner__container"] .cds--tag--blue {
  font-weight: 500 !important;
  font-size: 0.75rem !important;
  border-radius: 1rem !important;
  letter-spacing: 0.02em !important;
}

/* Identifier chips: PalMed ID and ID Card.

   ONE RULE FOR BOTH, deliberately. They are rendered by two different components --
   the primary identifier is a Carbon Tag, every other identifier is a Carbon
   FormLabel -- and they were styled by two rules that had already drifted apart:
   the Tag inherited the row's 1rem text while the label was pinned to 0.75rem, so
   the PalMed ID sat noticeably larger than the ID Card beside it. They are two
   readings of the same kind of fact and should look like a set, so one declaration
   block now sets the size for both and they cannot diverge again.

   THE COLOUR IS THE PUBLIC SITE'S OWN TAG RECIPE, not a new invention:
   landing-page/assets/styles.css declares `.tag-brand { background: var(--brand-wash);
   color: var(--brand) }`, which in its light palette is exactly these two values.
   What was here before was #3A8D99 -- a teal, hardcoded, from the OpenMRS palette
   this project retired on 2026-09-03. Being written as a literal is why the token
   remap in section 19 never reached it. Contrast is 8.5:1, comfortably past AA.

   Matched on Carbon's own class names rather than the components' CSS-module ones,
   which the app shell minifies to opaque base64 (`WvJbhTqh9ZSXAOeO7O+qjw==`) that no
   stylesheet can select -- see the dead selectors documented in gotcha 425. Verified
   live that the ID Card is the only .cds--label in this banner, with contact details
   both collapsed and expanded.

   The hairline border is not decoration. This banner's own ground is a warm
   #faf8f5 gradient, and the wash sits at 1.09:1 against it -- so on its own the
   pill shape simply does not read, which is the site's own problem with a wash chip
   on a light ground and the site's own answer to it. Both values are named in
   section 3 rather than spelled here; see the note there for where they come from. */
[class*="patient-banner__container"] .cds--tag--gray,
[class*="patient-banner__container"] .cds--label {
  background-color: var(--palmed-brand-wash, #f8edf1) !important;
  color: var(--brand-01, #821b3b) !important;
  border: 1px solid var(--palmed-brand-wash-border, rgba(168, 38, 78, 0.26)) !important;
  padding: 0.125rem 0.5rem !important;
  border-radius: 1rem !important;
  font-size: 0.75rem !important;
  font-weight: 600 !important;
  min-height: 0 !important;
  line-height: 1.35 !important;
  /* An identifier is a single token and breaking it across two lines never helps
     anyone read it. Without this the ID Card became a two-line pill at 320px --
     its label and its value are separate flex children, and a nowrap flex line
     shrinks them past their content width rather than moving one down. The widest
     chip here is ~142px against 288px of usable width, and the row it sits in
     wraps, so a chip that refuses to break still cannot push the page sideways. */
  white-space: nowrap !important;
  /* ...but that last sentence only holds while the identifier TYPE NAME is short, and that name
     is deployment-configured. Staging calls it "OpenMRS Identification Number", which makes the
     chip 310px against 288px of usable width; it runs to x=410 in a 390px viewport and is clipped
     with no scroll to reach it. `max-width: 100%` + `text-overflow: ellipsis` was tried here and
     measured to change nothing -- the chip still drew 310px -- so it was removed rather than left
     looking like a fix. PalMed's own "PalMed ID" / "ID Card" are nowhere near the limit, and only
     the identifier TEXT is affected: every control in the row stays on screen. Recorded in
     CLAUDE_KNOWN_ISSUES.md with what was ruled out. */
}

/* Load-bearing, not belt-and-braces: Carbon sets a colour on the label span itself
   (`.cds--tag__label { color: var(--cds-tag-color-gray, #161616) }`), so colouring
   only the Tag above it leaves the text painted Carbon's near-black regardless. */
[class*="patient-banner__container"] .cds--tag--gray .cds--tag__label {
  color: inherit !important;
  font-size: inherit !important;
}

/* Vitals & biometrics header in banner — lighter */
[class*="vitals-header__heading"] {
  font-weight: 400 !important;
  color: #4a4545 !important;
}

/* Patient avatar in banner */
[class*="patient-banner__container"] [class*="patientAvatar"],
[class*="patient-banner__container"] [class*="avatar"] {
  box-shadow: 0 2px 8px rgba(130, 27, 59, 0.15) !important;
}

/* --- Visit Action Bar --- */
[class*="visitActionBar"] {
  background: #faf8f5 !important;
  border-top: 1px solid #e8e0da !important;
  border-bottom: 1px solid #e8e0da !important;
  padding: 0.5rem 1rem !important;
}

[class*="visitActionBar"] .cds--btn--danger {
  font-weight: 600 !important;
}

/* --- Chart Side Navigation (right sidebar) --- */
.cds--side-nav__link {
  font-size: 0.875rem !important;
  font-weight: 400 !important;
  color: #5f5559 !important;
  transition: color 0.15s ease, background 0.15s ease !important;
}

.cds--side-nav__link:hover {
  color: #241b1e !important;
  background: rgba(139, 30, 63, 0.05) !important;
}

.cds--side-nav__link.active-left-nav-link {
  color: #8b1e3f !important;
  font-weight: 500 !important;
  background: rgba(139, 30, 63, 0.1) !important;
  border-inline-start: none !important;
}

/* --- Widget Cards (tiles) --- */
.cds--tile[class*="tile"] {
  background: #ffffff !important;
  border: none !important;
  box-shadow: var(--palmed-shadow-sm) !important;
  transition: box-shadow 0.2s ease !important;
  overflow: hidden !important;
}

.cds--tile[class*="tile"]:hover {
  box-shadow: var(--palmed-shadow-md) !important;
}

/* Service Queues metric tiles: restore the same light border the Appointments metric cards
   have. Both apps' source declares `border: 1px solid $ui-03` on an identically-named
   metrics-card__tileContainer class, but Service Queues renders a real Carbon <Tile>, which
   the generic widget-card rule above strips (`border: none !important`), while Appointments'
   plain <article> escapes that rule and keeps its border -- per direct user request the two
   should match. Same specificity as the stripping rule; later in the file, so it wins. */
.cds--tile[class*="metrics-card__tileContainer"] {
  border: 1px solid #e0e0e0 !important;
}

[class*="widgetCard"] {
  background: #ffffff !important;
  border: none !important;
  box-shadow: var(--palmed-shadow-sm) !important;
  overflow: hidden !important;
}

/* --- Section Headers (h4 in widget cards) --- */
[class*="desktopHeading"] h4,
[class*="desktopHeader"] h4,
[class*="cardHeader"] h4,
[class*="tabletHeader"] h4 {
  font-weight: 500 !important;
  font-size: 0.9375rem !important;
  color: #3d3838 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  display: flex !important;
  align-items: center !important;
  gap: 0.5rem !important;
}

/* Vertical accent bar before section headers */
[class*="desktopHeading"] h4::before,
[class*="desktopHeader"] h4::before {
  content: '' !important;
  display: inline-block !important;
  width: 3px !important;
  height: 1.125rem !important;
  background: #8b1e3f !important;
  border-radius: 2px !important;
  flex-shrink: 0 !important;
}

/* Remove old underline accent */
[class*="desktopHeading"] h4::after,
[class*="desktopHeader"] h4::after {
  content: none !important;
}

/* --- Empty States --- */
[class*="empty-state__tile"],
[class*="emptyState"] {
  border: none !important;
  background: #ffffff !important;
}

[class*="empty-state"] [class*="content"] {
  color: #7a7272 !important;
}

/* --- Data Tables (medications, etc.) --- */
.cds--data-table {
  overflow: hidden !important;
}

.cds--data-table thead {
  background: #faf8f5 !important;
}

.cds--data-table th {
  font-weight: 500 !important;
  font-size: 0.8125rem !important;
  color: #5f5559 !important;
  text-transform: none !important;
  letter-spacing: normal !important;
  border-bottom: 1px solid #f0edec !important;
}

.cds--data-table td {
  font-size: 0.8125rem !important;
  /* 500 (Inter medium) per direct user feedback that English table text read too light at
     400; the RTL override in section 18a puts Arabic back to 400 with a lighter color,
     since Arabic script's denser strokes already carry more visual weight than Latin. */
  font-weight: 500 !important;
  color: #3d3838 !important;
  border-bottom: 1px solid #f0edec !important;
  vertical-align: top !important;
  padding: 0.75rem 1rem !important;
  line-height: 1.5 !important;
}

/* Service Queues worklist exception: center every cell on one midline. The global
   `vertical-align: top` above suits multi-line clinical tables (medications etc.), but in
   the queue table the Actions cell's fixed-height button block stretches the row, leaving
   top-aligned text visibly higher than the expand chevron and the Call button (which center
   themselves) — reported by the user in both English and Arabic. */
[class*="queue-table__tableContainer"] .cds--data-table td {
  vertical-align: middle !important;
}

.cds--data-table tbody tr:hover {
  background: rgba(130, 27, 59, 0.02) !important;
}

.cds--data-table tbody tr:last-child td {
  border-bottom: none !important;
}

/* --- Pagination --- */
.cds--pagination {
  background: #faf8f5 !important;
  border-top: 1px solid #e8e0da !important;
  font-size: 0.8125rem !important;
}

/* --- Bottom Action Tabs (order basket, forms, visit note) --- */
[class*="actionMenu"] {
  border-top: 1px solid #e8e0da !important;
  background: #ffffff !important;
}

[class*="actionMenu"] button {
  font-size: 0.8125rem !important;
  font-weight: 500 !important;
  color: #5a5353 !important;
}

/* --- Chart Review Content Area ---
   Vertical only, and as longhand. Two reasons, both measured against dev3 at 1280px:

   No horizontal padding, because the stock dashboard inside this element already carries
   `margin: 0 16px`. Adding our own doubled it and cost 32px of content width on every chart
   tab -- the results viewer came out 912px wide here against 944px on dev3, from exactly this.

   Longhand, because `padding` as a shorthand resets every side, and stock sets
   `padding-bottom: 4rem` to keep the last row clear of the action bar. The shorthand was
   silently cutting that to 1rem at desktop widths; section 22 only restores it below 1023px.
   Same trap as CLAUDE_GOTCHAS.md Gotcha 470 -- do not collapse these back into a shorthand.

   The 672px and 480px rules further down deliberately DO keep a small horizontal padding:
   on a phone the content should not touch the screen edge. */
[class*="chartReview"] {
  padding-top: 1rem !important;
  padding-bottom: 4rem !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
  gap: 1rem !important;
}

/* --- Patient Chart Overflow Prevention --- */
/* Extension widgets must not exceed their grid column.
   The grid child (extension) has min-width:auto which lets it grow beyond the
   column track. Force it to respect the parent width so tables scroll inside. */
[class*="dashboard-view__extension"] {
  min-width: 0 !important;
  max-width: 100% !important;
}

[class*="dashboard-view__extensionWrapper"] {
  min-width: 0 !important;
  max-width: 100% !important;
}

/* Vitals & biometrics widget cards — constrain width, let table content scroll */
[class*="vitals-overview__widgetCard"],
[class*="biometrics-base__widgetCard"],
[class*="medications-details__widgetCard"],
[class*="widgetCard"] {
  min-width: 0 !important;
  max-width: 100% !important;
}

/* Data table — the content div handles horizontal scroll.
   Container must not clip it; dashboard-level overflow:hidden prevents page-wide overflow */
.cds--data-table-content {
  overflow-x: auto !important;
  -webkit-overflow-scrolling: touch !important;
}

/* Data table — stop the toolbar sitting on top of the column headings.

   Carbon positions .cds--table-toolbar absolutely, and TableContainer is expected to reserve the
   space for it with its own title/description header. A table given no title renders no header,
   so nothing reserves it and the 48px toolbar lands squarely on the header row: measured as a
   46px overlap on the Subscriptions, Payments and Invoices lists, where the search box and the
   filter dropdown were swallowing every hover and click meant for a column heading.

   The space is reserved with padding on the container, not a margin on the content. A margin
   collapses straight through a container that has no padding or border of its own, so it moved
   the container and the toolbar down together and left the overlap exactly where it was. Padding
   cannot collapse, and the toolbar is anchored at top:2px against the container's padding box,
   which padding-top does not shift — so the headings move down and the toolbar stays put.

   Deliberately narrow. It applies only where that header is genuinely absent, so the tables that
   do carry a title keep the spacing Carbon already gave them — 4 of the 20 in the admin app. The
   :has() guard is what makes that distinction possible; a browser without it simply drops the
   rule and nothing changes. */
.cds--data-table-container:not(:has(.cds--data-table-header)) {
  padding-top: 3rem;
}

/* Navbar global actions — prevent overflow on mobile.

   `overflow` is deliberately `visible`, and must stay that way. This rule used to say
   `hidden`, which clipped away every tooltip on the right-hand navbar icons (Search patient,
   Add patient, Notifications, My Account, App Menu): Carbon renders an icon-button tooltip
   below its trigger, and the trigger sits inside this 48px-tall bar, so a hidden overflow ate
   the label entirely.

   What made that visible rather than merely broken is palmed-rtl-popover-fix.js. Its vertical
   correction is not RTL-gated: it walks up for the nearest ancestor whose overflow-y clips,
   found this bar, and dragged each label back up INSIDE the header — beside the icon instead of
   under it. (It also lost Carbon's own `translateX(-50%)` on the way, since it composes onto the
   inline transform only, which is why the labels ran rightwards from the icon's left edge rather
   than staying centred.) The location button escaped all of this only because it lives in
   `top-nav-info-slot`, outside this bar, and so has no clipping ancestor at all — which is
   exactly why its tooltip has always looked right and the others have not.

   Carbon itself never sets overflow here and explicitly raises the z-index of popovers inside
   this bar (`.cds--header__global .cds--popover`), so escaping the header is the intended
   behaviour. `flex-shrink: 1` and `min-width: 0` below are what actually do the mobile job —
   measured at 360px, scrollWidth == clientWidth, so the hidden overflow was clipping nothing. */
.cds--header__global {
  flex-shrink: 1 !important;
  min-width: 0 !important;
  overflow: visible !important;
}

/* Chart grid container — prevent child overflow */
[class*="dashboard-view__dashboard"] {
  min-width: 0 !important;
  overflow: hidden !important;
}

/* Card header (tabletHeader) — constrain */
[class*="card-header__tabletHeader"] {
  min-width: 0 !important;
  max-width: 100% !important;
}

/* --- Mobile Responsiveness for Patient Chart --- */
@media (max-width: 672px) {
  [class*="patient-banner__container"] {
    padding: 0.75rem !important;
    flex-wrap: wrap !important;
  }

  [class*="esm-patient-banner__patient-banner__patientBanner"] > div > div > div > span {
    font-size: 0.9375rem !important;
  }

  [class*="chartReview"] {
    padding: 0.75rem !important;
    gap: 0.75rem !important;
  }

  /* Constrain the dashboard grid extensions */
  [class*="dashboard-view__dashboard"] {
    max-width: 100% !important;
    overflow: hidden !important;
  }

  /* Table cells — compact on tablet */
  .cds--data-table td {
    font-size: 0.8125rem !important;
    padding: 0.5rem 0.75rem !important;
  }

  .cds--data-table th {
    font-size: 0.75rem !important;
    padding: 0.5rem 0.75rem !important;
  }

  /* Widget card headers — stack controls */
  [class*="tabletHeader"],
  [class*="card-header__tabletHeader"] {
    flex-wrap: wrap !important;
    gap: 0.5rem !important;
  }
}

@media (max-width: 480px) {
  [class*="patient-banner__container"] {
    padding: 0.5rem 0.75rem !important;
  }

  [class*="esm-patient-banner__patient-banner__patientBanner"] > div > div > div > span {
    font-size: 0.875rem !important;
  }

  [class*="patient-banner__container"] [class*="patientAvatar"],
  [class*="patient-banner__container"] [class*="avatar"] {
    width: 2.5rem !important;
    height: 2.5rem !important;
  }

  /* Compact table cells on phone.
     NOT `word-break: break-word`, which this rule used to carry. That value is a
     deprecated alias for `overflow-wrap: anywhere`, and `anywhere` -- unlike
     `break-word` -- also shrinks the element's MIN-CONTENT width, to the width of
     a single character. Every cell in the table therefore reported that it could
     survive at ~8px, the table happily compressed to whatever was left, and
     "03-Sept-2026" came out stacked one character per line. `overflow-wrap:
     break-word` breaks an over-long token the same way without touching
     min-content, so the table keeps an honest minimum and section 21 lets it
     scroll instead of collapse. */
  .cds--data-table td {
    font-size: 0.75rem !important;
    padding: 0.375rem 0.5rem !important;
    word-break: normal !important;
    overflow-wrap: break-word !important;
  }

  .cds--data-table th {
    font-size: 0.6875rem !important;
    padding: 0.375rem 0.5rem !important;
    white-space: nowrap !important;
  }

  /* Tighter chart review padding */
  [class*="chartReview"] {
    padding: 0.5rem !important;
    gap: 0.5rem !important;
  }

  /* Widget section headers — smaller gap */
  [class*="desktopHeading"] h4::before,
  [class*="desktopHeader"] h4::before {
    height: 1.25rem !important;
    width: 3px !important;
  }
}

/* =============================================================================
   14. HIDE LEFT NAV FOR SINGLE-APP-LOCKED ROLES (Lab Technician, Pharmacist)
   RoleAccessGuard (palmed-esm-admin-app) toggles this class on <body> once it
   determines the logged-in user's role is locked to exactly one app (every
   other left-nav destination -- Clinic Dashboard, Service queues,
   Appointments, Patient lists -- just bounces straight back, so showing them
   at all is pure clutter). The stock `<nav aria-label="Left navigation">` is
   fixed-position and 256px wide; the actual page content section reserves
   that same 256px via its own `margin-left` (`esm-home-app`'s
   `dashboardContainer.hasLeftNav` class, confirmed live via computed styles)
   -- both need overriding together, or hiding the nav alone just leaves a
   256px blank gap rather than reclaiming the width.
   ============================================================================= */
/* Matched on the shell's own container id, NOT on the nav's aria-label.
   `aria-label="Left navigation"` is a translated string -- in an Arabic session
   the nav carries the Arabic phrase instead -- so an English literal here
   silently matched nothing for exactly the users this project serves. Measured
   2026-09-08: labtech@palmed.ps, a locked role, carried palmed-hide-left-nav on
   <body> and still rendered a five-link nav, because the selector could not see
   it. Same shape as Gotcha 484 (an English aria-label inside an RTL-only rule).
   #omrs-left-nav-container is a hardcoded <div> in the app shell's index.html,
   so it is language-independent and survives a Carbon or styleguide restyle; it
   also cannot collide with a page's OWN Carbon SideNav (the admin page has one,
   under #omrs-apps-container), which a bare `nav` selector would have hidden. */
body.palmed-hide-left-nav #omrs-left-nav-container {
  display: none !important;
}

/* The SAME nav, reached by a completely different path below desktop width, and hiding the
   container above does nothing about it. `SideMenuPanel` (esm-primary-navigation-app) portals
   `LeftNavMenu` into #omrs-left-nav-container only when `isDesktop(layout)`; on a phone or tablet
   it renders it INLINE inside the top header instead, behind the hamburger. Measured 2026-09-08 at
   390px: the container computed `display: none` exactly as intended while the opened menu sat at
   `display: flex`, 256px wide, listing all five clinical apps -- which is what an admin reported
   seeing on their phone, and what the desktop-only verification had missed.

   Both halves are needed. Hiding only the menu leaves a hamburger that opens nothing; hiding only
   the button leaves the menu reachable if anything else expands it.

   Scoped by `header` rather than by the nav's class: it keeps this off a page's OWN Carbon SideNav
   (the PalMed admin page has one, under #omrs-apps-container, and it must keep working -- it is the
   only navigation an admin has left). `.cds--header__menu-trigger` is a Carbon global class, so
   like the container id above it is language-independent -- see the aria-label note there. */
body.palmed-hide-left-nav .cds--header__menu-trigger,
body.palmed-hide-left-nav header .cds--side-nav {
  display: none !important;
}

body.palmed-hide-left-nav [class*="dashboard-container__dashboardContainer"] {
  margin-left: 0 !important;
  margin-inline-start: 0 !important;
  /* Reclaiming the nav's margin with nothing else left the content flush against the viewport
     edge (confirmed live: the "Tests ordered" tab sat at x:0, padding:0) -- the nav itself used
     to be what visually separated content from the screen edge, so removing it needs a
     replacement gutter. 32px matches this project's own palmed-esm-dispensing-dashboard, the
     other real "no left nav, full width" page already in this codebase. */
  padding-left: 32px !important;
  padding-right: 32px !important;
}

/* On a phone that gutter is two thirds of the fix and one third of the problem: 32px a side is
   64px of a 390px screen, and 64px of a 320px one, taken from a column that already has to hold
   a table. Measured on the Laboratory page at 320px, the usable column was 224px. 16px still
   separates content from the edge -- it is the same inset the registration form and the visit
   note settled on for phones -- and hands back 32px. Symmetric, so there is nothing to mirror. */
@media (max-width: 600px) {
  body.palmed-hide-left-nav [class*="dashboard-container__dashboardContainer"] {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}

/* =============================================================================
   15. ROLE-REDIRECT GATE OVERLAY (palmed-role-redirect-gate.js)
   Covers the whole viewport the instant a single-app-locked role (Pharmacist,
   Lab Technician) lands anywhere but their own app, so the default post-login
   dashboard never gets a visible instant to paint underneath it -- see that
   script's own header comment for the full mechanism. Plain DOM elements
   created directly by the script, not a React/Carbon component, so this has
   to be self-contained (no dependency on any framework class being available
   yet) and just needs to sit above everything else on the page.
   ============================================================================= */
.palmed-role-gate-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--palmed-bg, #faf8f7);
}

.palmed-role-gate-spinner {
  width: 48px;
  height: 48px;
  border: 4px solid var(--palmed-border, #e8e4e2);
  border-top-color: var(--brand-01, #821b3b);
  border-radius: 50%;
  animation: palmed-role-gate-spin 0.8s linear infinite;
}

@keyframes palmed-role-gate-spin {
  to {
    transform: rotate(360deg);
  }
}

/* =============================================================================
   16. PATIENT REGISTRATION — ID CARD FIELD EMPHASIS
   Per explicit user request: the ID Card field (Palestinian Hawiya number,
   optional-but-recommended, see palmed-idcard-format-001) should visually stand
   out from every other optional field on the registration form, since it's the
   one identifier this project actually wants doctors to fill in. Matched by the
   field's own name/for attribute (identifiers.idCard.identifierValue -- a
   stable, semantic key derived from the "ID Card" identifier type's name, not a
   hash-suffixed CSS-module class), so this survives any future rebuild of the
   third-party esm-patient-registration-app bundle. Purely additive styling
   (not hiding/removing anything), so left unscoped by route unlike
   palmed-registration-identifiers.js's hide/translate behavior -- this reads as
   "pay attention here" on the edit-existing-patient flow too, which reuses the
   same component and is harmless to leave styled the same way.
   ============================================================================= */
label[for="identifiers.idCard.identifierValue"] {
  font-weight: 700 !important;
  color: var(--brand-01, #821b3b) !important;
}

input[name="identifiers.idCard.identifierValue"] {
  border-left: 0.25rem solid var(--brand-01, #821b3b) !important;
  background-color: rgba(130, 27, 59, 0.04) !important;
}

input[name="identifiers.idCard.identifierValue"]:focus {
  border-left: 0.25rem solid var(--brand-03, #a8264e) !important;
}

/* =============================================================================
   17. CROSS-CLINIC MEDICATIONS SECTION (Phase 3, medications domain)
   Hand-built plain DOM injected by palmed-cross-clinic-medications.js into the
   stock Medications tab (no extension slot exists there -- see that script's
   own header comment for the full architecture). Mirrors the visual language
   of palmed-esm-lab-results-app's own crossClinicSection/crossClinicHeading
   (lab-results-overview.scss) for consistency between the two cross-clinic
   features, even though this one is plain classes (not CSS modules) since it's
   not a React component.
   ============================================================================= */
.palmed-cross-clinic-medications-section {
  margin: 1rem 1rem 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid #e0e0e0;
}

.palmed-cross-clinic-medications-heading {
  font-size: 0.875rem;
  font-weight: 600;
  color: #525252;
  margin: 0 0 0.5rem 0;
}

.palmed-cross-clinic-medications-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.palmed-cross-clinic-medications-item {
  padding: 0.5rem 0.75rem;
  border-inline-start: 0.25rem solid var(--brand-01, #821b3b);
  background-color: rgba(130, 27, 59, 0.03);
  margin-bottom: 0.5rem;
  border-radius: 0 0.25rem 0.25rem 0;
}

.palmed-cross-clinic-medications-name {
  font-weight: 600;
  color: #161616;
  font-size: 0.9375rem;
}

.palmed-cross-clinic-medications-prn-tag {
  display: inline-block;
  margin-inline-start: 0.5rem;
  padding: 0.0625rem 0.5rem;
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: 999px;
  background-color: rgba(130, 27, 59, 0.12);
  color: var(--brand-01, #821b3b);
  vertical-align: middle;
}

.palmed-cross-clinic-medications-details {
  color: #525252;
  font-size: 0.8125rem;
  margin-top: 0.125rem;
}

.palmed-cross-clinic-medications-instructions {
  color: #525252;
  font-size: 0.8125rem;
  font-style: italic;
  margin-top: 0.125rem;
}

/* =============================================================================
   17. FORCE PASSWORD CHANGE OVERLAY
   Styles for palmed-force-password-change.js's full-screen gate (spinner while
   the check is in flight, then a real password-change form if the account was
   created with a temporary password). Same z-index/background convention as
   palmed-role-redirect-gate.js's overlay (.palmed-role-gate-overlay) so the two
   never visually conflict if one somehow follows the other.
   ============================================================================= */
.palmed-force-pwd-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--palmed-bg, #faf8f7);
}

.palmed-force-pwd-spinner {
  width: 48px;
  height: 48px;
  border: 4px solid var(--palmed-border, #e8e4e2);
  border-top-color: var(--brand-01, #821b3b);
  border-radius: 50%;
  animation: palmed-role-gate-spin 0.8s linear infinite;
}

.palmed-force-pwd-card {
  width: 100%;
  max-width: 26rem;
  padding: 2rem;
  margin: 1rem;
  border-radius: 0.5rem;
  background: var(--palmed-surface, #ffffff);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
}

.palmed-force-pwd-card h3 {
  margin: 0 0 0.5rem;
  font-size: 1.25rem;
  font-weight: 600;
  color: #161616;
}

.palmed-force-pwd-subtitle {
  margin: 0 0 1.25rem;
  color: #525252;
  font-size: 0.875rem;
  line-height: 1.4;
}

.palmed-force-pwd-error {
  margin-bottom: 1rem;
  padding: 0.5rem 0.75rem;
  border-inline-start: 0.25rem solid #da1e28;
  background-color: rgba(218, 30, 40, 0.06);
  color: #da1e28;
  font-size: 0.8125rem;
}

.palmed-force-pwd-field {
  margin-bottom: 1rem;
}

.palmed-force-pwd-field label {
  display: block;
  margin-bottom: 0.375rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: #525252;
}

.palmed-force-pwd-field input {
  width: 100%;
  box-sizing: border-box;
  padding: 0.625rem 0.75rem;
  border: 1px solid var(--palmed-border, #e8e4e2);
  border-radius: 0.25rem;
  font-size: 0.9375rem;
}

.palmed-force-pwd-field input:focus {
  outline: 2px solid var(--brand-01, #821b3b);
  outline-offset: 1px;
}

.palmed-force-pwd-submit {
  width: 100%;
  padding: 0.75rem;
  border: none;
  border-radius: 0.25rem;
  background-color: var(--brand-01, #821b3b);
  color: #ffffff;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}

.palmed-force-pwd-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* =============================================================================
   18. ARABIC LEGIBILITY: SMALL TABLE-TEXT FLOOR ON NARROW VIEWPORTS
   Section 13's phone/tablet media queries shrink data-table cell text down to
   0.75rem (12px) and, at the narrowest breakpoint, 0.6875rem (11px) -- a
   reasonable density tradeoff for Latin text at that size, but Arabic script
   (denser connecting strokes, lower apparent x-height at the same point size)
   becomes noticeably harder to read at 11-12px than English does at the same
   size. Scoped to [dir="rtl"] and to only the smallest 2 sizes (0.75rem/
   480px's td, 0.6875rem/480px's th, 0.75rem/672px's th) -- desktop sizes are
   already reasonable (13px) and left untouched in both languages; English
   layouts at every breakpoint are completely unaffected by this section.
   ============================================================================= */
/* 18a. Base (all viewport widths): Arabic table text gets one step more size and
   noticeably more leading than the Latin defaults (td 13px/1.5 elsewhere in this file).
   Arabic script reads smaller than Latin at the same point size and its connecting
   strokes need more vertical room; ~1px more size plus looser line-height is the
   standard adjustment. Deliberately placed BEFORE the narrow-viewport floors below so
   those (same specificity, later in file) still win at phone widths, preserving their
   density tradeoff. English layouts are completely unaffected. */
[dir="rtl"] .cds--data-table td {
  font-size: 0.875rem !important;
  line-height: 1.7 !important;
  /* Arabic reads darker/heavier than Latin at the same weight and color (denser connecting
     strokes, more ink coverage), and the user asked for it lighter: regular weight (undoing
     the LTR-oriented 500 bump in the base rule) plus a lighter warm gray than the Latin
     #3d3838, still well past readable contrast on the white/warm table backgrounds. */
  font-weight: 400 !important;
  color: #5a5252 !important;
}

@media (max-width: 672px) {
  [dir="rtl"] .cds--data-table th {
    font-size: 0.8125rem !important;
  }
}

@media (max-width: 480px) {
  [dir="rtl"] .cds--data-table td {
    font-size: 0.8125rem !important;
  }

  [dir="rtl"] .cds--data-table th {
    font-size: 0.75rem !important;
  }
}
/* =============================================================================
   Section 19: a blocked subscriber's shell
   -----------------------------------------------------------------------------
   Set by SubscriptionGuard while a subscription is expired or suspended.

   The redirect alone stops him going anywhere, but leaving the navigation in
   place means every link is an invitation that bounces, and the patient search
   and add-patient buttons in the top bar open workflows that can only end in a
   403. Hiding them is honesty about what the account can currently do, not
   security: the server refuses the data either way.

   Logout and My Subscription both live in the account menu, which is
   deliberately left alone, because those are the two things he still needs.
   ============================================================================= */

body.palmed-subscription-blocked nav[aria-label="Left navigation"] {
  display: none !important;
}

body.palmed-subscription-blocked [class*="dashboard-container__dashboardContainer"] {
  margin-left: 0 !important;
  margin-inline-start: 0 !important;
}

/* Patient search and add-patient in the top bar. Matched by their own aria-labels,
   which are stable across locales because the framework translates the label text
   but keeps these extension slots' identity. */
body.palmed-subscription-blocked [aria-label="Search patient"],
body.palmed-subscription-blocked [aria-label="Add patient"],
body.palmed-subscription-blocked [aria-label="البحث عن مريض"],
body.palmed-subscription-blocked [aria-label="إضافة مريض"] {
  display: none !important;
}

/* =============================================================================
   19. CARBON SEMANTIC TOKEN REMAP — WARM NEUTRALS + BRAND INTERACTION

   WHERE THE GREY CAME FROM. O3's Carbon v11 components resolve every colour
   through var(--cds-*, fallback), and nothing in this stack defines those
   custom properties above component level — so each component fell back to
   Carbon's own stock ramp, which is cold and blue-cast. Measured on the
   patient chart before this section existed: #525252 on 59 text nodes,
   #e0e0e0 on 61 borders/backgrounds, #161616 on 43, #f4f4f4 on 39, against
   only 31 nodes carrying this file's own warm #6b6565. The earlier sections
   fight that per-selector with !important, which is why some warmth got
   through; this section fixes it at the source instead, once.

   THE PALETTE IS THE PUBLIC SITE'S, not a new invention. landing-page/assets/
   styles.css declares the same brand and says of its neutrals: "ink — warm,
   plum-biased neutrals, not pure grey". Its three inks land almost exactly on
   Carbon's three text levels by lightness, so the mapping is a hue shift, not
   a contrast change:

       Carbon            PalMed site        role
       #161616     ->    #241B1E  --ink     primary text
       #525252     ->    #5F5559  --ink-2   secondary text
       #6f6f6f     ->    #6E686C  --ink-3   helper text
       #e0e0e0     ->    #E8E4E2  --rule    hairlines, table header band
       #8d8d8d     ->    #D9D1CE  --rule-strong
       #f4f4f4     ->    #F5F0EE  --surface-2
       #ffffff     ->    #FFFFFF  --surface
       page bg     ->    #FAF8F7  --paper

   Carbon needs two neutral steps the site does not define (placeholder and
   disabled). Those are the only invented values here, and they hold the
   ramp's own hue relationship (red highest, blue second, green lowest, with
   R-G about 6-10 and B-G about 3-4) at Carbon's original lightness, so they
   sit on the same curve rather than reintroducing a flat grey.

   THE DARK RAMP IS USED TOO, and this is not a dark theme. Carbon paints
   tooltips and other inverse surfaces on #393939 — 76 of them on one chart
   page. A light app still needs a dark surface for those, and inventing one
   would put a second neutral family back into the design, so they take the
   site's dark tokens, exactly as the site itself uses --band-bg for a dark
   band inside a light page.

   INTERACTION COLOUR. Carbon's stock blue (#0f62fe) on links, ghost buttons
   and focus rings was the one place a second, unrelated brand hue appeared
   next to the maroon. Every interactive token now derives from the brand.
   Semantic colours are deliberately NOT touched: error red, success green
   and warning yellow carry meaning a clinician reads, and are not ours to
   restyle for consistency.

   THE TRAP, and the reason a partial version of this silently fails:
   .cds--layer-two and .cds--layer-three wrapper divs re-point the un-numbered
   tokens at their -02/-03 variants. Remapping only the base and -01 tokens
   leaves anything inside a layered component on Carbon's cold fallback, with
   no error and no warning — a table header stays #e0e0e0 while everything
   around it warms up. Whenever a --cds-* token is added or changed below,
   define its -02/-03 variants in the same edit.
   ============================================================================= */

/* Declared on :root plus Carbon's own light theme-zone classes, so a zone
   element cannot reintroduce the stock values underneath us. This file loads
   after openmrs.css (see index.html), so equal specificity wins. */
:root,
.cds--white,
.cds--g10 {
  /* --- Interaction: every interactive colour derives from the brand ------ */
  --cds-link-primary: #a8264e;
  --cds-link-primary-hover: #821b3b;
  --cds-link-secondary: #821b3b;
  /* Carbon's visited link is purple; left alone it would reintroduce a third
     hue on exactly the surfaces this section is clearing blue off. */
  --cds-link-visited: #6e1732;
  --cds-focus: #a8264e;
  --cds-interactive: #821b3b;
  --cds-border-interactive: #821b3b;
  --cds-button-primary: #821b3b;
  --cds-button-primary-hover: #6e1732;
  --cds-button-primary-active: #5c1329;

  /* --- Text: the site's three inks --------------------------------------- */
  --cds-text-primary: #241b1e;
  --cds-text-secondary: #5f5559;
  --cds-text-helper: #6e686c;
  /* Derived, not from the site: Carbon's placeholder and disabled steps at
     their original lightness, moved onto the ink ramp's hue. */
  --cds-text-placeholder: #a79da0;
  --cds-text-disabled: #c7bdc0;

  /* --- Hairlines --------------------------------------------------------- */
  --cds-border-subtle: #e8e4e2;
  --cds-border-subtle-00: #e8e4e2;
  --cds-border-subtle-01: #e8e4e2;
  --cds-border-subtle-02: #e8e4e2;
  --cds-border-subtle-03: #e8e4e2;
  --cds-border-strong-01: #d9d1ce;
  --cds-border-strong-02: #d9d1ce;
  --cds-border-strong-03: #d9d1ce;
  --cds-border-disabled: #e8e4e2;

  /* --- Surfaces ---------------------------------------------------------- */
  --cds-background: #faf8f7;
  --cds-layer: #ffffff;
  --cds-layer-01: #ffffff;
  --cds-layer-02: #f5f0ee;
  --cds-layer-03: #f5f0ee;
  /* Carbon's white theme gives layer-accent and border-subtle the same value
     (both gray-20), which is what makes a table header read as a band rather
     than a box. Keeping them equal preserves that. */
  --cds-layer-accent: #e8e4e2;
  --cds-layer-accent-01: #e8e4e2;
  --cds-layer-accent-02: #e8e4e2;
  --cds-layer-accent-03: #e8e4e2;
  --cds-field: #f5f0ee;
  --cds-field-01: #f5f0ee;
  --cds-field-02: #f5f0ee;
  --cds-field-03: #f5f0ee;

  /* Hover and active states. The site has no token for these, so they are one
     step along its own paper-to-rule ramp rather than a new colour. */
  --cds-layer-hover: #f0eae8;
  --cds-layer-hover-01: #f0eae8;
  --cds-layer-hover-02: #f0eae8;
  --cds-layer-hover-03: #f0eae8;
  --cds-field-hover: #efe9e6;
  --cds-field-hover-01: #efe9e6;
  --cds-field-hover-02: #efe9e6;
  --cds-field-hover-03: #efe9e6;
  --cds-background-hover: #f0eae8;

  /* Selection reads as brand, using the site's own wash. */
  --cds-background-selected: #f8edf1;
  --cds-background-selected-hover: #f1dfe6;
  --cds-background-active: #f1dfe6;
  --cds-layer-selected: #f8edf1;
  --cds-layer-selected-01: #f8edf1;
  --cds-layer-selected-02: #f8edf1;
  --cds-layer-selected-03: #f8edf1;
  --cds-layer-selected-hover: #f1dfe6;

  /* --- Inverse surfaces: the site's DARK tokens -------------------------- */
  --cds-background-inverse: #2a2024;
  --cds-background-inverse-hover: #382a2f;
  --cds-text-inverse: #f3edec;
  --cds-border-inverse: #382a2f;
}

/* =============================================================================
   20. DISPLAY TYPEFACE — Noto Kufi Arabic on headings
   Carries the public site's typographic identity into the app. The site sets
   --f-display to Noto Kufi Arabic and its body text to Noto Sans Arabic; this
   section is the same split, applied to the surfaces that are genuinely
   headings. Running text, tables, forms and buttons are untouched — section 1
   still owns those, and a display face there would be wrong.

   THIS IS AN ARABIC-ONLY CHANGE IN PRACTICE. Noto Kufi Arabic ships with the
   arabic unicode-range only (see fetch-self-hosted-fonts.py), and Inter leads
   every stack below, so an English heading resolves exactly as it does today
   and cannot regress. Only Arabic-script headings move to the display face.

   WEIGHTS ARE NEVER SET HERE, only the family. This app has repeatedly and
   deliberately made Arabic headings LIGHTER — the patient name at 400 in
   section 13, the table-text weight split in section 18a — because Arabic
   reads heavier than Latin at the same weight. Changing family and weight
   together would silently reverse those decisions. That is also why four
   weights of Kufi are vendored rather than one: whatever weight a heading is
   already set to, the face has it.
   ============================================================================= */

/* NOTE — the page title and the "PalMed" eyebrow are deliberately NOT styled here.

   The obvious selectors for them are dead. PageHeader renders from the app
   shell's SHARED styleguide, which emits opaque CSS-module class names
   (pPcKj1kNkKP4cQZUtFRU5g== on the container, _3d4ICXZtVrDwUYN1iMMJCA== on the
   title, and no class at all on the eyebrow), so
   [class*="page-header-module__pageName"] matches nothing on any page. The
   readable page-header-module__* strings a grep finds in the deployed bundles
   belong to the privately bundled dead copies several modules ship -- see
   CLAUDE_GOTCHAS.md Gotcha 425, which also records the proof.

   The dispensing header is dead for a different reason:
   [class*="pharmacy-header__pageName"] is the UPSTREAM esm-dispensing-app
   header, which PalMed replaced with its own dashboard. That page's real title
   is an h2 carrying -esm-dispensing-dashboard__dispensing-dashboard__title___*.

   Giving these the display face needs a stable hook on the styleguide's
   PageHeader (a data-* attribute), which means rebuilding the app shell. That
   is a real change with a real cost, not a selector tweak -- do it deliberately
   or not at all, rather than reinstating selectors that quietly match nothing. */


/* Card and section headings. Same selector list as the weight rule in section
   13, which stays the authority on how heavy these are. */
[class*="desktopHeading"] h4,
[class*="desktopHeader"] h4,
[class*="cardHeader"] h4,
[class*="tabletHeader"] h4,
.cds--modal-header__heading,
[class*="esm-patient-banner__patient-banner__patientBanner"] > div > div > div > span {
  font-family: var(--palmed-font-display) !important;
}

/* -----------------------------------------------------------------------------
   Numerals in columns
   The public site marks every figure .num for tabular numerals. In a clinic the
   payoff is larger than on a marketing page: doses, results, identifiers and
   money are read down a column, and proportional digits make that column ragged.
   Inter leads the stack everywhere, so this simply switches on a feature the
   face already has. Restricted to table cells; prose is better with the default.
   -------------------------------------------------------------------------- */
.cds--data-table td,
.cds--data-table th {
  font-variant-numeric: tabular-nums;
}

/* =============================================================================
   21. NARROW VIEWPORTS: WIDE CONTENT SCROLLS, THE PAGE DOES NOT
   A data table with four or more columns cannot be usefully squeezed into a
   390px phone. Squeezing it is what the app used to do: columns collapsed until
   dates broke one character per line, and because the surplus was clipped rather
   than scrollable it was simply unreachable.

   The rule everywhere below is the standard one -- wide content scrolls inside
   its own container, and the page body never scrolls sideways. Carbon already
   ships the scroll container (`.cds--data-table-content` is `overflow-x: auto`);
   what was missing is any reason for the table to reach its natural width, so it
   sized itself to the squeezed container instead and never triggered it.

   Measured on this deployment at 390px: visits 639px, medications 463px,
   conditions 407px, with `document.scrollWidth` staying at 390 in every case.

   Confined to <= 672px (Carbon's `md` breakpoint, the same one section 13 uses),
   so every desktop layout is untouched. Direction-agnostic: this sets no
   physical side, and a `overflow-x: auto` container scrolls from the correct
   edge under `dir="rtl"` on its own.
   ============================================================================= */
@media (max-width: 672px) {
  .cds--data-table-content {
    overflow-x: auto !important;
    /* momentum scrolling on iOS Safari */
    -webkit-overflow-scrolling: touch;
  }

  /* `width: max-content` lets the table reach the width its columns actually
     need; `min-width: 100%` stops a two-column table from sitting in a narrow
     strip with dead space beside it. */
  .cds--data-table {
    width: max-content !important;
    min-width: 100% !important;
  }

  /* Caps a free-text column (a medication's dosing instructions, a note) so one
     long cell cannot drag the table out to a width nobody wants to scroll. The
     text wraps inside the cap rather than being truncated -- nothing clinical is
     hidden behind an ellipsis. */
  .cds--data-table th,
  .cds--data-table td {
    max-width: 18rem;
  }

  /* An expanded row's cell spans every column and holds a whole nested widget,
     so the free-text cap above must not apply to it. `td[colspan]` is exactly
     the expanded-row cell -- Carbon always renders it with a colspan. */
  .cds--data-table td[colspan] {
    max-width: none;
  }

  /* Headers are short labels; wrapping them buys nothing and costs a row of
     height on every table. */
  .cds--data-table th {
    white-space: nowrap !important;
  }
}

/* =============================================================================
   22. TABLET AND PHONE: LEAVE ROOM UNDER THE CHART FOR THE FIXED ACTION BAR

   Below 1024px the patient chart's action menu stops being a right-hand rail and
   becomes a fixed bar pinned to the bottom of the viewport (an `aside`, measured
   65px tall, present at 1023px and gone at 1024px). Nothing reserved space for
   it, so the last of the chart's content sat underneath it -- and because the
   page was already scrolled to its maximum there was no way to bring it out:
   measured at 390px on Conditions, the last condition row ("Asthma") ended 34px
   inside the bar's band, and on Patient Summary and Medications the pagination
   footer ("5 / 6 items") ended 27px inside it.

   `.chartReview` (the chart's own content column) carries `padding-bottom: 4rem`
   in `esm-patient-chart-app`'s SCSS, which would have been enough -- but three
   rules EARLIER IN THIS FILE set the `padding` SHORTHAND on it with `!important`
   (1rem at any width, 0.75rem below 672px, 0.5rem below 480px), and a shorthand
   resets every side, so that 4rem never survived. This rule sets the longhand
   only, and lives at the END of the file deliberately: it has the same
   specificity as those three and is also `!important`, so it wins on source
   order alone. Moving it above them would silently stop it working.

   5rem = the 65px bar plus a small margin, so the last row clears it rather than
   ending flush against it. Direction-agnostic; nothing here needs RTL mirroring.
   ============================================================================= */
@media (max-width: 1023px) {
  [class*='chartReview'] {
    padding-bottom: 5rem !important;
  }
}

/* =============================================================================
   23. A TWO-BUTTON WORKSPACE FOOTER MUST NOT BE WIDER THAN THE SCREEN

   Every workspace footer in the chart is a Carbon `cds--btn-set`: Cancel + Sign
   and close, Discard + Save and close, and so on. Carbon sizes each button
   `width: 100%; max-width: 12.25rem`, and 12.25rem is 196px -- MORE than half of
   a 390px phone. The modules then add `min-width: 50%` of their own, so each
   button resolves to exactly 196px and the pair needs 392px inside a row that is
   373-389px wide.

   Measured at 390px: the order basket's "Sign and close" ran to x=409 and the
   visit note's "Save and close" to x=393. Both are the primary action of the
   form -- the one control that must never be the one you cannot reach.

   `min(12.25rem, 50%)` is the whole fix and needs no breakpoint: on anything wide
   enough, 12.25rem is already less than half the row and this changes nothing, so
   desktop and tablet keep the exact button size they have today. It only binds
   once half the row is narrower than 196px, which is precisely the case that
   overflows. A media query would have to guess the width at which that happens --
   and it varies with each footer's own padding (the order basket's row is inset
   16px, the visit note's is not), so any single breakpoint would be wrong for one
   of them.

   `!important` because Carbon's own rule is equally specific; it carries no
   `!important` of its own, so this wins wherever it lands in the cascade.
   Direction-agnostic -- a width cap needs no RTL mirroring.
   ============================================================================= */
.cds--btn-set .cds--btn {
  max-width: min(12.25rem, 50%) !important;
}

/* =============================================================================
   24. A FULL-SCREEN MODAL MUST NOT KEEP ITS ENTRANCE-ANIMATION OFFSET

   Carbon starts every modal 24px high and animates it down:

     :not(.cds--modal--enable-presence) .cds--modal-container {
       transform: translateY(-24px);
     }

   In this app that offset is never cleared -- the container's computed transform
   stays `matrix(1,0,0,1,0,-24)` for as long as the modal is open. On a desktop
   that is invisible: above 42rem Carbon makes the modal `position: relative;
   height: auto; max-height: 90%` and the flex parent centres it, so 24px of slack
   costs nothing.

   Below 42rem it is a different component. Carbon switches the modal to a
   full-screen sheet -- `position: fixed`, pinned `top: 0; bottom: 0`, the exact
   height of the viewport -- and a sheet already flush with the top edge cannot
   afford to be moved up 24px. Measured at 390px on the end-visit confirmation:
   the container sat at y=-24, its heading was clipped mid-line, and the close
   (x) button was half off the top of the screen.

   Scoped to `max-width: 41.98rem`, which is exactly the range where Carbon uses
   the full-screen variant (its own rule turns the desktop variant on at
   `min-width: 42rem`). The desktop entrance animation is left completely alone.
   ============================================================================= */
@media (max-width: 41.98rem) {
  .cds--modal-container {
    transform: none !important;
  }
}

/* =============================================================================
   25. THE HELP BUTTON IS HIDDEN WHERE THE BOTTOM ACTION BAR EXISTS

   The help menu is a button fixed to the bottom-right corner. Below 1024px the
   patient chart puts a fixed 65px action bar along the bottom edge, and an open
   workspace puts its footer (Cancel / Sign and close, Discard / Save and close)
   directly above that -- so on a phone that corner is occupied in every state
   the chart can be in, and the button was measured stealing taps in two of them:

     * closed workspace -- it covered 40px of "Clinical forms" and a tap there
       hit the help icon;
     * order basket open, after an attempt to fix this by lifting the button
       above the bar -- it then covered 32x33px of "Sign and close", and the tap
       test showed the FAB winning. That is strictly worse: it moved the problem
       from a navigation item onto a primary submit action.

   There is no vertical offset that is clear in both states, because the two
   occupied bands are adjacent and the workspace footer's height varies. Lower
   z-index does not help either: the bar already has a HIGHER z-index (8003 vs
   7900) and the button still won the tap, because the two sit in different
   stacking contexts.

   So it is hidden rather than moved. What it holds is upstream OpenMRS links --
   contact us, documentation, release notes (`help-menu-slot`) -- with nothing
   clinical or PalMed-specific in it, and it is untouched on desktop, where it
   has room and no bar to fight. Trading three reference links for a submit
   button that always works is the right way round on a phone.
   ============================================================================= */
@media (max-width: 1023px) {
  [class*='help-styles__helpMenuButton'] {
    display: none !important;
  }
}

/* =============================================================================
   26. THE VISIT FORM'S SEGMENTED CONTROL MUST NOT CUT ITS OWN LABELS

   "Start a visit" offers New / Ongoing / In the past as a Carbon
   `ContentSwitcher`. It lives in a `<fieldset>`, and a fieldset inside the
   form's flex row is a flex item with `flex-grow: 0`, so it shrink-wraps to
   250px and ignores the space beside it. Three segments of ~83px are not enough
   for the words: measured below 1024px, "Ongoing" needed 53px in a 51px box and
   "In the past" needed 70px in a 50px box, so both rendered ellipsised -- and
   "In the past" lost enough to read as "In the...".

   It is NOT a phone-only bug, which is why this is not scoped to one. Measured
   at three widths: 1280px gives the switcher 387px and every label fits; 900px
   and 390px both shrink-wrap it to the same 250px and cut the same two labels.
   The boundary is the desktop layout, so the fix stops at 1023px -- and desktop,
   having no bug, is left untouched.

   `width: 100%` alone would be wrong at the top of that range: at 900px the form
   is 867px wide and a segmented control stretched across all of it looks like a
   mistake. Capping at 24rem gives the phone the full 357px it has (all three fit),
   the tablet a 384px control that matches what desktop already shows, and nothing
   a label it cannot print.

   `:has()` keeps this to fieldsets that actually contain a segmented control, so
   no other form in the app changes shape. It is supported by every browser this
   runs on (verified at runtime with `CSS.supports('selector(:has(*))')`).
   ============================================================================= */
@media (max-width: 1023px) {
  .cds--fieldset:has(.cds--content-switcher) {
    width: 100% !important;
    max-width: 24rem;
  }
}

/* =============================================================================
   27. A WORKSPACE'S SAVE BUTTONS STICK TO THE BOTTOM OF THE PANEL ON SMALL SCREENS

   A workspace footer (Discard / Save and close, Cancel / Sign and close) is the
   last element of the form, so it scrolls with it. On a desktop side panel that
   is fine. Below 1024px the panel is full-screen, its scrollable area stops
   exactly where the fixed action bar begins, and any form longer than one screen
   pushes its own footer underneath that bar.

   Measured at 390px on the visit note, before touching anything:

     English  "Save and close" y=799..863 -- 0px of 64 visible; a tap in the
              middle of it hit the element behind.
     Arabic   "حفظ وإغلاق"      y=767..831 -- 12px of 64 visible, and a tap in the
              middle hit the ACTION BAR button underneath, not Save.

   Both are recoverable by scrolling the panel, which is what makes this easy to
   miss: it is not that the button cannot be reached, it is that the sliver on
   screen looks like a button and does not behave like one. The English case is
   the more honest of the two -- nothing visible at all is at least not
   misleading.

   `position: sticky; bottom: 0` pins the footer to the bottom of the panel's own
   scroll area, above the bar. After it: 63px of 64 visible in both languages, and
   the centre tap reaches the button. The order basket, whose form is short enough
   that its footer was already fully visible, is byte-for-byte unchanged (64 of 64
   before and after) -- sticky only does anything once there is something to scroll.

   Where there is no scrolling ancestor, `sticky` behaves as `relative` and changes
   nothing, so this cannot disturb a layout it was not needed in. The background is
   there so form content scrolls underneath the footer rather than through it.
   ============================================================================= */
@media (max-width: 1023px) {
  .cds--btn-set {
    position: sticky;
    bottom: 0;
    z-index: 2;
    background-color: var(--cds-layer, #fff);
  }
}

/* =============================================================================
   28. ROW ACTIONS STAY REACHABLE IN A SIDEWAYS-SCROLLING TABLE

   Section 21 lets a wide table scroll inside its own container rather than
   crushing its columns, which is right -- but it left the row-action "..." at the
   far end of the scroll. Measured at 390px on the lab-results table (961px wide,
   a 300px viewport into it): the trigger sat at x=966, needing **621px** of
   sideways scrolling to reach in English and **967px** in Arabic. Opening it
   there also moves the view, which is what this was reported as: "the screen
   jumps to the right to give space to the drop down menu".

   Pinning the actions column to the trailing edge removes the cause rather than
   the symptom -- there is no scrolling to reach the menu, so there is nothing to
   jump. After: the trigger sits at x=305 in English and x=55 in Arabic, on screen
   at rest, with `document.scrollWidth` still equal to the viewport in both.

   Two things had to be undone for `position: sticky` to work on a table cell at
   all, and both are worth knowing:

     * `.cds--data-table { overflow: hidden }` -- an old app-wide rule of ours,
       sitting above in this file. It makes the TABLE the cell's nearest
       scrollport, and since that scrollport does not scroll, a sticky cell has
       nothing to stick within. It is also what clipped the medications
       prescriber tooltip. It is redundant: `.cds--data-table-content` is the real
       scroll container and already clips and scrolls the same content.
     * `border-collapse: collapse` -- sticky does not apply to cells of a
       collapsed-border table, so the actions table is switched to `separate`
       with zero spacing, which renders identically here.

   Confined to tables that actually HAVE a row-action menu in their last column,
   via `:has()`, so no ordinary table changes shape -- and to below 1024px, the
   range where tables scroll sideways at all, so desktop is untouched. Expanded
   rows are excluded by `:not([colspan])`: that cell spans the whole table and
   holds a nested widget, and pinning it would be meaningless.
   ============================================================================= */
@media (max-width: 1023px) {
  .cds--data-table:has(td:last-child .cds--overflow-menu) {
    overflow: visible !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
  }

  .cds--data-table:has(td:last-child .cds--overflow-menu) thead th:last-child,
  .cds--data-table:has(td:last-child .cds--overflow-menu) tbody td:last-child:not([colspan]) {
    position: sticky !important;
    inset-inline-end: 0 !important;
    z-index: 2;
    background-color: var(--cds-layer, #fff) !important;
  }
}

/* =============================================================================
   SECTION 28: Prose-card chart tabs run edge to edge on a phone
   =============================================================================
   Visit Notes and Referrals are each one column of prose cards, and a paragraph
   is the one thing in this chart that genuinely wants every pixel of a 390px
   screen. A referral's reason is exactly the same shape as a note's body: free
   text a doctor wrote for another doctor to read.

   The chart's dashboard grid carries `margin: 1.3125rem` on all four sides
   (esm-patient-chart-app `dashboard-view.scss`, `.dashboard`), and its phone
   breakpoint only changes `display`/`flex-direction` -- the 21px inset stays.
   Measured at 390px: the widget got 332px and the note text 270px, about 38
   characters a line, with 47px of empty space each side. Referrals measured the
   same way at 360px: a 268px card with 234px of reason inside it.

   Only the INLINE margin goes; the 21px above and below is the gap between the
   patient banner and the first card and is right as it is.

   Targeted on `data-extension-slot-name`, which the framework puts on the very
   element carrying that margin -- verified live, it is the same node, not a
   parent or child of it. That matters twice over: a `[class*=...]` selector
   would have to match a content-hashed class, and this element also carries
   `overflow: hidden`, so the alternative of a negative margin on the widget
   inside it would have been CLIPPED rather than widened.

   Scoped to the phone: on a desktop the note text is capped at 78ch anyway, so
   removing the inset there would widen the card without widening a single line
   of prose, and leave a full-bleed card looking unlike every other tab.

   Upstream `dashboard-view.scss` sets a per-slot margin this same way twice
   (encounters and test-results), so that file is the other reasonable home for
   this rule. It lives here instead because it costs no rebuild of a 100-chunk
   module for a change that touches no JavaScript.
   ============================================================================= */
body.omrs-breakpoint-lt-tablet [data-extension-slot-name='palmed-visit-notes-dashboard-slot'],
body.omrs-breakpoint-lt-tablet [data-extension-slot-name='palmed-patient-referrals-slot'] {
  margin-inline: 0 !important;
}

/* With the inset gone the widget's own hairline would sit on the screen edge,
   reading as a clipped card rather than a deliberate border. The cards inside
   keep their own borders, so the widget frame has nothing left to do here.
   Only Visit Notes needs this -- the referrals widget draws no frame of its
   own, so there is nothing there to remove. */
body.omrs-breakpoint-lt-tablet [class*='visit-notes-timeline__widget'] {
  border-inline: none !important;
}

/* =============================================================================
   SECTION 29: A form's fields fill the panel they sit in
   =============================================================================
   Every control the form engine renders -- textareas, combo boxes, text inputs
   -- already fills its own section exactly. What was short was the container
   ABOVE them: `@openmrs/esm-form-engine-lib`'s page renderer sets

       .accordionContainer { width: 95%; }

   with no centring, so the missing 5% is dumped entirely on the trailing side
   and every field stops short of the panel. Measured on the SOAP note: 39px of
   dead space at 1280px, 19px at 390px, against a page content box the accordion
   is otherwise free to fill.

   Nothing occupies that 5%. It reads as a gutter, and the accordion content
   already has one -- Carbon's own 16px `padding-inline`, which is symmetric and
   is what a form field should be inset by. The 5% only adds a second, one-sided
   gap on top of it.

   This lives here rather than in the form engine because that library is an npm
   dependency of the vendored `esm-form-engine-app` wrapper, not vendored source
   we can rebuild -- the same reason every other third-party layout correction in
   this file is here. Its CSS-module class names survive the chart's build
   readably (unlike the app shell's opaque ones, Gotcha 425), so a
   `[class*=...]` selector is a stable hook; verified live against the rendered
   DOM, not by grepping the bundle.

   Deliberately NOT scoped to the SOAP form: the rule is one upstream
   declaration affecting every form the engine renders, there is no per-form
   hook on this container, and a one-sided gap is no more wanted on the visit
   note or a clinical form than it is here.

   The `!important` is load-bearing, not decorative: an attribute selector and
   the library's own single-class selector carry the SAME specificity, and the
   module's stylesheet is injected into the head at runtime, after this file's
   static link. Source order would hand it to the 95% every time -- verified,
   the first attempt without it measured no change at all.
   ============================================================================= */
[class*='page-renderer__accordionContainer'] {
  width: 100% !important;
}

/* The same form is a quarter narrower again in Arabic, and that half is worse.
   Carbon caps an accordion's measure with a 25% inline-end padding, and ships it
   as a `:lang()`-keyed PHYSICAL pair -- `padding-right: 25%` for Latin scripts,
   `padding-left: 25%` for `:lang(ar)` and friends. The form engine already
   decided it does not want that cap on a form, and says so:

       .sectionContainer :global(.cds--accordion__content) { padding-right: 1rem; }

   but a physical `padding-right` only cancels the Latin half. In Arabic the 25%
   survives on the other side -- measured at 192.75px of a 771px panel, against
   16px in English, so an Arabic doctor was writing a note in 562px where an
   English one had 739px.

   Restoring the engine's own intent rather than overriding a design decision:
   16px on both sides, the value it already asked for.

   Written as a physical pair, not `padding-inline`. The same value on both sides
   cannot come out backwards in either direction, which is the cheapest way to be
   sure -- the reasoning the registration-form gutters already use. */
[class*='page-renderer__sectionContainer'] .cds--accordion__content {
  padding-left: 1rem !important;
  padding-right: 1rem !important;
}

/* =============================================================================
   SECTION 30: Printing one document out of a single-page app
   =============================================================================
   A referral letter is the one thing this system produces that leaves it on
   paper, in a patient's hand, addressed to a hospital that has never heard of
   PalMed. It is judged entirely on what comes out of the printer, and nothing
   on screen tells you what that is.

   It came out nearly blank. Measured by printing the real letter to PDF: a
   band about 60px tall carrying the clinic name, the date and a horizontally
   clipped "Urgent", and below it three quarters of a page of empty grey. TO,
   PATIENT, REASON FOR REFERRAL and the signature -- the entire letter -- were
   not on the sheet.

   Why, and it is the shape of the problem rather than one careless rule: the
   letter is rendered inside a Carbon modal. Its ancestors are `position: fixed`
   with a viewport-sized height and `overflow: auto`, so in paged media the
   content is clipped to a scrollport that cannot scroll. The module's own print
   CSS tried to escape that with `position: absolute; inset-block-start: 0`,
   which only re-anchors the letter to the modal -- the very box doing the
   clipping -- and `visibility: hidden` on everything else leaves each hidden
   element still occupying its layout, so even an escaped letter would have been
   pushed down the page by an app shell nobody can see.

   So the fix is not a nudge to the letter, it is isolating it:

     * everything that is neither the document, an ancestor of it, nor inside
       it, is `display: none` -- removed from layout, not merely not painted;
     * every ancestor between <body> and the document stops being a fixed,
       sized, scrolling, centred dialog and becomes ordinary flow content.

   Keyed on `data-palmed-print-document`, a plain attribute the component sets,
   because a global stylesheet cannot name a CSS-Modules class -- it is
   content-hashed, and `[class*=...]` against a hash is the dead-selector trap
   this project has already hit (Gotcha 425).

   Deliberately general rather than referral-specific: the invoice document has
   no print support at all today for exactly the reason above, and this is the
   mechanism it needs. Everything letter-shaped -- the page margin, hiding the
   Print button itself -- stays in the letter's own stylesheet, since only it
   knows what a referral letter looks like.

   `:has()` is what makes "an ancestor of the document" expressible at all. It
   is used elsewhere in this file (section 28) and is the same Chromium these
   clinics run.
   ============================================================================= */
@media print {
  /* The app's warm ground is a screen colour. Left alone it paints the whole
     page box, so the sheet came out with a grey slab under the signature --
     visible in the PDF above because Chromium's PDF export prints backgrounds;
     a doctor pressing Ctrl+P would get it only with "Background graphics" on.
     Either way a letter to a hospital prints on white. */
  html,
  body {
    background: #fff !important;
  }

  /*
     ...and `html` and `body` themselves have to be normalised, not just what is
     under them.

     Found by printing the letter from the PATIENT CHART rather than the inbox,
     where it had only ever been tested. It came out one character per line,
     every Arabic word broken vertically, over four pages. The chain measured
     `width: 0` at every level including `<html>` -- which is the tell, because
     the root element's width comes from the page box and nothing in the
     document can shrink it.

     `esm-patient-orders-app/src/components/order-details-table.scss` carries a
     bare, unscoped `@media print { html, body { width: fit-content; overflow:
     hidden } }`. It is a component stylesheet restyling the root of the
     document, so it applies to anything printed from any page that loads that
     module -- which on the patient chart is every page. With everything else
     hidden by the rule above, `fit-content` resolves to the MIN-content width of
     what is left, and prose can wrap to a single character.

     Hence this is scoped with `:has()` rather than applied to every print: the
     orders table's own printing is that rule's reason for existing, and taking
     it away from them to fix our letter would be trading one broken document
     for another. It engages only when one of our own documents is on the page.

     Do not assume a print stylesheet that works on one route works on another.
     What is loaded differs by route, and a global rule in any module's CSS
     reaches the document root from wherever it happens to be.
  */
  html:has([data-palmed-print-document]),
  body:has([data-palmed-print-document]) {
    display: block !important;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }

  /* Everything that is not the document, its ancestors, or its contents. */
  body *:not(:has([data-palmed-print-document])):not([data-palmed-print-document]):not(
      [data-palmed-print-document] *
    ) {
    display: none !important;
  }

  /* The chain from <body> down to the document: stop being a dialog. */
  body *:has([data-palmed-print-document]) {
    display: block !important;
    position: static !important;
    inset: auto !important;
    transform: none !important;
    width: auto !important;
    max-width: none !important;
    height: auto !important;
    max-height: none !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    overflow: visible !important;
    background: none !important;
    box-shadow: none !important;
    border: none !important;
  }
}
