/* components.css is now loaded explicitly via hooks.py app_include_css +
   web_include_css with the ?v={mtime} cache buster. The previous
   @import url('components.css') was unversioned and combined with
   nginx max-age=31536000 on /assets/, pinned a stale components.css
   in browsers for up to 1 year after any .eh-* atom change. */

/* ── Cairo (self-hosted variable font) ──
   3 woff2 files in public/fonts/cairo/ cover Arabic + Latin + Latin Ext.
   Unicode-range tells the browser to only fetch the subset(s) it needs.
   font-weight: 300 800 declares the variable axis range, so a single file
   serves every weight instead of one per weight.
   font-display: swap renders fallback text immediately, then swaps when
   Cairo loads — avoids invisible-text flash.

   NOTE (cache-busting): these woff2 URLs intentionally carry NO ?v= buster —
   a url() inside a static CSS file can't take the dynamic version hooks.py
   computes. The fonts are effectively immutable; if a Cairo file is ever
   re-subsetted/replaced, RENAME it (e.g. cairo-arabic-v2.woff2) so the URL
   changes — otherwise nginx max-age + Cloudflare serve the old glyphs for up
   to a year. Same caveat applies to the icon paths inside manifest.json. */
@font-face {
	font-family: 'Cairo';
	font-style: normal;
	font-weight: 300 800;
	font-display: swap;
	src: url('/assets/maktab_bouholaigah/fonts/cairo/cairo-arabic.woff2') format('woff2');
	unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC4, U+10EFC-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
@font-face {
	font-family: 'Cairo';
	font-style: normal;
	font-weight: 300 800;
	font-display: swap;
	src: url('/assets/maktab_bouholaigah/fonts/cairo/cairo-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
	font-family: 'Cairo';
	font-style: normal;
	font-weight: 300 800;
	font-display: swap;
	src: url('/assets/maktab_bouholaigah/fonts/cairo/cairo-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* FIX 12 (FIX_PLAN.md item 12): LTR-isolate embedded record IDs so they
   don't pollute Arabic sentence flow. The bidi algorithm otherwise drags
   surrounding punctuation/dashes into the wrong run when codes like
   FB-2026-00302, LEASE-00002, MTX-26-00040 appear mid-AR-sentence in
   activity feeds, detail panels, and admin activity.

   - direction: ltr keeps the digits + dashes in left-to-right order.
   - unicode-bidi: isolate makes the bidi algorithm treat the code as an
     atomic LTR run (won't bleed into neighbouring AR text).
   - display: inline-block prevents the wrapper from breaking lines
     awkwardly mid-word in justify scenarios.

   Use via maktab.ltr_code(name) in JS or maktab.api.utils.ltr_code(name)
   in Python wherever a record ID is rendered inline with prose copy. */
.ltr-code {
	direction: ltr;
	unicode-bidi: isolate;
	display: inline-block;
}

/* ── Version-update banner (replaces Frappe core's version-update msgprint) ──
   Fixed at the top of the viewport, above desk chrome + dialogs. Built on the
   .mkt-banner atom; injected by maktab._show_version_banner(). */
.maktab-version-banner {
	position: fixed;
	top: 0;
	inset-inline: 0;
	z-index: 1090;
	padding: var(--s-3);
	display: flex;
	justify-content: center;
	pointer-events: none;
}
.maktab-version-banner .mkt-banner {
	pointer-events: auto;
	max-width: 640px;
	width: 100%;
	align-items: center;
	box-shadow: var(--shadow-overlay);
}
.maktab-version-banner .mkt-banner__body { font-weight: 600; }
.maktab-version-banner__x {
	appearance: none;
	background: transparent;
	border: none;
	font-size: 20px;
	line-height: 1;
	color: var(--ink-muted);
	cursor: pointer;
	padding: 0 4px;
	flex-shrink: 0;
}
.maktab-version-banner__x:hover { color: var(--ink); }

/* ── Entity-class chrome (FIX 5 — religious-legal classification) ──
   Drives row + pill chrome on E1 (entity-ledger), E2 (reconciliation-report),
   E3 (thilth-report), C5 (expenses-list). CLAUDE.md flags entity-boundary
   confusion (Family heir misreading Khums as Thilth) as a P0 failure mode.
   Tokens defined in the :root block below; classes auto-flip in dark mode
   via the underlying --success/--info/--warn/--ink-muted tokens.
   API: maktab.entity_class(name) → 'charitable'|'passthrough'|'personal'|'operational'
        maktab.entity_pill(name)  → '<span class="entity-pill entity-pill-<cls>">...'  */
/* The .entity-row row-stripe rule was reduced to bare padding in the
   2026-06-01 side-stripe purge and fully retired 2026-06-03 when its last
   emitter (reconciliation_report) moved to the inline .recon-ent chip.
   Nothing emits the .entity-row class anymore. */

/* Outer banner-stripe variant — for single-entity reports (E3 Thilth) where
   per-row chrome is meaningless. Apply to the report wrapper. */
.entity-banner {
	border-top: 4px solid transparent;
	padding-top: var(--s-3);
}
.entity-banner-charitable  { border-top-color: var(--entity-charitable); }
.entity-banner-passthrough { border-top-color: var(--entity-passthrough); }
.entity-banner-personal    { border-top-color: var(--entity-personal); }
.entity-banner-operational { border-top-color: var(--entity-operational); }

/* Brand-text column — wraps Arabic wordmark + sandbox tag vertically.
   Parent .brand is flex-row; .brand-text is flex-column so the tag
   sits on its own line below the wordmark without crowding it. */
.maktab-sidebar .brand .brand-text {
	display: flex;
	flex-direction: column;
	min-width: 0;
	line-height: 1.1;
}
/* Sandbox tag — only renders when hostname starts with "sandbox".
   Visual cue to never confuse it for prod. */
.maktab-sidebar .brand .sandbox-tag {
	font-size: 10px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	opacity: 0.5;
	margin-top: 2px;
	line-height: 1;
}

/* Inline pill — small badge next to a company name.
   Hidden 2026-05-21 per Ahmad — the .entity-row-* / .mkt-pg-head color
   spine carries the same information; the verbal class label next to
   every company was noise. The class survives in DOM (rendered by ~5
   callers + maktab.entity_pill helper) so tooling that reads it still
   works. To re-enable, change display back to inline-block. */
.entity-pill {
	display: none;
	padding: 2px 9px;
	border-radius: var(--r-pill);
	font-size: var(--text-xs);
	font-weight: 600;
	letter-spacing: 0.02em;
	line-height: 1.4;
	border: 1px solid transparent;
	vertical-align: middle;
	white-space: nowrap;
}
.entity-pill-charitable {
	background: var(--entity-charitable-bg);
	color: var(--entity-charitable);
	border-color: var(--entity-charitable);
}
.entity-pill-passthrough {
	background: var(--entity-passthrough-bg);
	color: var(--entity-passthrough);
	border-color: var(--entity-passthrough);
}
.entity-pill-personal {
	background: var(--entity-personal-bg);
	color: var(--warn-text);
	border-color: var(--entity-personal);
}
.entity-pill-operational {
	background: var(--entity-operational-bg);
	color: var(--ink);
	border-color: var(--entity-operational);
}

/* Screen-reader-only utility (WCAG standard) — visually hides content while keeping it available to assistive tech */
.sr-only {
	position: absolute !important;
	width: 1px !important;
	height: 1px !important;
	padding: 0 !important;
	margin: -1px !important;
	overflow: hidden !important;
	clip: rect(0, 0, 0, 0) !important;
	white-space: nowrap !important;
	border: 0 !important;
}

/* ── Page loading placeholder (palm tree logo) ── */
.maktab-page-loading {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 60vh;
	opacity: 0.5;
}
.maktab-page-loading img {
	width: 48px;
	height: 48px;
	animation: maktab-pulse 1.8s ease-in-out infinite;
}
@keyframes maktab-pulse {
	0%, 100% { opacity: 0.3; transform: scale(0.95); }
	50% { opacity: 0.6; transform: scale(1); }
}

/*
 * Maktab Bouholaigah — Hasawi Palm Tree Palette
 *
 * Straw:      #D4C5A0  (light backgrounds, cards)
 * Beige:      #F5F0E6  (page background)
 * Sand:       #C2AD7E  (borders, subtle accents)
 * Brown:      #6B4F36  (headings, primary text)
 * Dark Brown: #4A3728  (navbar, strong accents)
 * Palm Green: #5E7D5E  (success, positive indicators)
 * Leaf Green: #7A9E7A  (secondary green)
 * Sky Blue:   #8FB8D4  (links, info accents)
 * Light Blue: #D4E6F1  (info backgrounds)
 * Cream:      #FAF8F2  (card backgrounds)
 * Red/Warm:   #C0735E  (warnings, alerts — earthy terracotta)
 * Orange:     #D4A05A  (caution — amber/date color)
 */

/* ── CSS Custom Properties ── */
:root {
	/* Legacy --maktab-* palette — bridged to v2 tokens (Phase RS Pass A).
	   Light + dark values come from the v2 :root + [data-theme="dark"] blocks
	   below, so dark mode auto-flips without duplicate overrides. */
	--maktab-beige: var(--beige);
	--maktab-cream: var(--cream);
	--maktab-straw: var(--straw);
	--maktab-sand: var(--sand);
	--maktab-brown: var(--brown);
	--maktab-dark-brown: var(--brown-deep);
	--maktab-green: var(--success);
	--maktab-leaf: #7A9E7A;
	--maktab-sky: #8FB8D4;
	--maktab-sky-hover: #6A9BBF;
	/* Link color — warm brand brown, NOT blue. The historical mapping to
	   var(--info) ("sky-link" in the handoff) leaked Frappe-style blue
	   anchors into every list/detail/panel surface (FB-2026-00222/227/228).
	   Pointing to var(--brown) auto-flips for dark mode via the [data-theme]
	   block above (--brown becomes #C2AD7E sand in dark). All consumers of
	   --maktab-link (.rc-link, .lv-phone, .lv-map-link, .fb-attach-btn,
	   .lv-invoice-link, .ul-tenant-link, plain <a>) now render brand-warm. */
	--maktab-link: var(--brown);
	--maktab-light-blue: #D4E6F1;
	--maktab-terracotta: var(--crit);
	--maktab-amber: var(--warn);
	--maktab-white: #FFFFFF;
	--maktab-text: var(--ink);
	--maktab-text-muted: var(--ink-muted);
	--maktab-border: var(--border);
	--maktab-radius: var(--r-sq);
	--maktab-shadow: none;
	--maktab-shadow-hover: none;
	/* Bridges for page-specific CSS that was authored before the v2 token
	   system landed. Without these, var(--maktab-card-bg, #fff) etc. falls
	   back to the hardcoded Tailwind-style hex, fighting the foundation. */
	--maktab-card-bg: var(--cream);
	--maktab-bg: var(--beige);
	--maktab-surface: var(--cream);
	--maktab-dark-bg: var(--brown-night);
	--maktab-border-light: var(--border-soft);
	--maktab-red: var(--crit);
	--maktab-orange: var(--warn);
	--maktab-amber-dark: var(--sand-deep);
	--maktab-blue: var(--info);
	--maktab-sky-blue: var(--info);
	/* Frappe core variables — bridged to v2 tokens. */
	--bg-color: var(--beige);
	--fg-color: var(--cream);
	--text-color: var(--ink);
	--text-muted: var(--ink-muted);
	--border-color: var(--border);
	--card-bg: var(--cream);
	--subtle-fg: var(--straw);
	--control-bg: #FFFFFF;
}

/* ── v2 Redesign Tokens — LIVE-ONLY REMAINDER ──
   The canonical token definitions (palette, status, basil, entity, type,
   spacing, radii, motion) ship verbatim via `public/css/tokens.css`, loaded
   FIRST in the cascade per hooks.py app_include_css. This block holds only
   tokens NOT defined by the mockup — keeping the mockup as the single
   source of truth eliminates the drift cycle. */
:root {
	/* Warm-amber text on light warn surfaces. Not in mockup tokens.css. */
	--warn-text: #8B6914;

	/* Square radius for filter pills (toggleable, paper-tab feel) — live-only.
	   --r-sm/md/lg/pill come from mockup tokens.css. */
	--r-sq: 2px;

	/* Latin caption helper tracking — live-only. */
	--caption-tracking: 0.08em;
	--caption-tracking-loose: 0.12em;
}

/* v2 dark mode — LIVE-ONLY REMAINDER
   Surface, basil, ink, border tokens ship verbatim via tokens.css.
   This block holds only the dark-mode overrides for the warn-text helper
   that the mockup doesn't define. Status colors (--success/--info/--warn/
   --crit/--overdue) intentionally NOT redefined here — they stay at their
   light values per mockup canonical (the mockup designer chose to keep
   status colors warm in dark, not saturate them). */
[data-theme="dark"] {
	/* warn-text deepens in dark so it stays legible on --warn-bg. */
	--warn-text: #E5BB7A;
}

/* Latin caption helper — small uppercase, letter-spaced.
   Use .caption (0.08em tracking) by default, .caption--loose (0.12em) for
   status pills + section heads. See README §2.8 caption matrix. */
.caption {
	font-family: var(--font-en);
	font-size: var(--text-xs);
	letter-spacing: var(--caption-tracking);
	text-transform: uppercase;
	font-weight: 500;
	color: var(--ink-muted);
}
.caption--loose { letter-spacing: var(--caption-tracking-loose); }

/* The Expiry Center v2-component block (.expiry-dashboard .btn/.pill/
   .f-pill/.stat/.lv-table + sticky + days-cell + dark overrides) was
   removed 2026-06-03 — expiry now ships public/css/expiry_dashboard.css
   (.exp-* div-grid; .mkt-pill status pills; tone-corrected buckets). */

/* ── Global Typography ──
   Cairo single-family for both Arabic and Latin (set in --font-ar/en/num).
   font-feature-settings: "tnum" enables tabular figures so all numerals
   share the same advance width — financial tables align vertically.
   "lnum" forces lining (uppercase-height) figures over old-style. */
body,
.frappe-control,
.page-container,
.modal-dialog,
.body-sidebar,
.frappe-list,
input, select, textarea, button,
.btn, .alert, .badge {
	font-family: var(--font-ar) !important;
	font-feature-settings: "tnum" 1, "lnum" 1;
}

/* ── Color Scheme ── */
:root { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

/* Splash screen handled at end of file — see @media prefers-color-scheme */

/* ── Page Background ──
   html bg controls overscroll bounce color on iOS Safari.
   Set both a raw fallback AND the variable for dark mode. */
html {
	/* Raw color, NOT the CSS variable. The variable gets temporarily
	   overridden to dark by prefers-color-scheme:dark media query before
	   Frappe sets data-theme, which makes Safari cache a dark overscroll. */
	background-color: #F5F0E6 !important;
	overscroll-behavior-x: none !important;
}
/* When modal is open, darken html/body to match the overlay tint.
   Prevents solid beige showing behind iOS address bar. */
html:has(body.modal-open) {
	background-color: #C2BCB3 !important;
	transition: background-color 0.25s ease !important;
}
html[data-theme="dark"] {
	background-color: #18130D !important;
}
html[data-theme="dark"]:has(body.modal-open) {
	background-color: #0F0C09 !important;
}
body {
	background-color: var(--maktab-beige) !important;
	color: var(--maktab-text) !important;
	overflow-x: hidden !important;
	overscroll-behavior-x: none !important;
}
/* FB-2026-00210: only apply the body bg transition AFTER the initial page
   paint has settled. Frappe's desk.html ships with `data-theme="light"` even
   when the user has dark mode preferred via our localStorage flag, so the
   IIFE in maktab.js flips data-theme→dark slightly after first paint. With
   an unconditional `transition: background-color 0.25s` the body then
   animates light→dark over 250ms, while the sidebar/splash with hard-set
   dark backgrounds snap instantly — which the user sees as a "darker block"
   behind the palm tree. Gating the transition on `.maktab-theme-ready`
   (added at first rAF) makes the initial flip instantaneous, while
   subsequent toggle clicks still animate smoothly. */
html.maktab-theme-ready body {
	transition: background-color 0.25s ease !important;
}

/* Language-switch overlay. Toggle handler injects a fixed-position palm-tree
   loading splash that covers everything before reload. Frappe shows its own
   .splash with our palm during boot (see maktab.fix_splash), so the palm
   stays visible across the reload boundary — to the user it looks like the
   page is loading, not blanking out. Pointer-events locked so a stray
   double-click can't fire two reloads. */
.maktab-lang-overlay {
	position: fixed !important;
	inset: 0 !important;
	z-index: 999999 !important;
	background: var(--maktab-beige) !important;
	display: flex !important;
	align-items: center !important;
	justify-content: center !important;
	pointer-events: all !important;
	opacity: 0;
	transition: opacity 0.15s ease;
}
.maktab-lang-overlay.is-shown {
	opacity: 1;
}
.maktab-lang-overlay img {
	width: 64px;
	height: 64px;
	animation: maktab-pulse 1.8s ease-in-out infinite;
}
[data-theme="dark"] .maktab-lang-overlay {
	background: var(--maktab-beige) !important;
}
body.modal-open {
	background-color: #C2BCB3 !important;
}
[data-theme="dark"] body.modal-open {
	background-color: #0F0C09 !important;
}

/* Scroll lock when slide panel is open (iOS needs position:fixed) */
body.maktab-panel-open {
	position: fixed !important;
	width: 100% !important;
	overflow: hidden !important;
}

/* FB-2026-00177/180: scroll lock when the sidebar drawer is open.
   Two earlier attempts both broke things:
   - `html { overflow: hidden }` reset document.scrollingElement.scrollTop
     on WebKit (visible scroll-jump-to-top on open).
   - `body { position: fixed; top: -scrollY }` preserved position but the
     unpin at close-time forced a layout reflow that iOS used to skip the
     drawer's transform animation paint frames (drawer "just disappears").
   Body-only overflow:hidden + touch-action:none preserves scrollY without
   shifting the body, so the close transition can paint cleanly. */
body.maktab-modal-scroll-lock {
	overflow: hidden !important;
	touch-action: none !important;
	overscroll-behavior: none !important;
}

/* Scroll-lock for the .pd-overlay dialog family (openEditDialog /
   openConfirmDialog / the payment dialog). Refcounted in edit-pattern.js
   (installModalBehaviors) so stacked overlays — the discard-guard, a nested
   confirm — don't unlock the page while a parent dialog is still open. Kept
   separate from maktab-modal-scroll-lock so it never fights the bs.modal
   lifecycle's add/remove of that class during the dialog migration.

   position:fixed (NOT just overflow:hidden) is what stops iOS Safari from
   scrolling the whole page up when the soft keyboard opens over a field in a
   bottom-sheet: overflow:hidden blocks finger-scroll but NOT the keyboard's
   auto-scroll-into-view, so the page (and the fixed dialog) slid up. Pinning
   <body> at top:-scrollY (set inline by _pdLock) leaves nothing for iOS to
   scroll. Same pattern the slide-over detail panel uses (maktab-panel-open).
   On desktop scrollY is 0 (the scroll surface is .main-section), so top:0 =
   no shift. touch-action/overscroll-behavior keep the iOS rubber-band off. */
body.maktab-pd-scroll-lock {
	position: fixed !important;
	width: 100% !important;
	overflow: hidden !important;
	touch-action: none !important;
	overscroll-behavior: none !important;
}

/* ── Dark Mode — Palm garden at dusk ──
   Bridged --maktab-* and Frappe core tokens auto-flip via the v2 dark block
   above. Only non-bridgeable legacy tokens (--maktab-leaf, --maktab-sky,
   --maktab-sky-hover, --maktab-light-blue, --maktab-white, --maktab-shadow*)
   plus --control-bg need explicit dark values here. */
[data-theme="dark"] {
	--maktab-leaf: #8FB88F;
	--maktab-sky: #9AC4E0;
	--maktab-sky-hover: #B0D4F0;
	--maktab-light-blue: #1A2A3A;
	--maktab-white: var(--ink);
	--maktab-shadow: none;
	--maktab-shadow-hover: none;
	/* Frappe control bg — slightly lighter than card bg for input contrast */
	--control-bg: #2E2820;
}

/* ── Detail slide panel ── */
/* Grey backdrop — separate element, sits behind the panel.
   Element is created/destroyed in JS so iOS Safari fully repaints
   when it's removed from the DOM (CSS-only hides leave painted pixels
   in the address bar area on iOS). */
.maktab-detail-backdrop {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	/* Warm-brown wash, matches dialog backdrop. Pass E retoken: was a beige
	   tint (rgba(237,229,212,0.55)); now matches the brown-deep semantic. */
	background: rgba(74, 55, 40, 0.32);
	z-index: 1049;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease;
}
.maktab-detail-backdrop.open {
	opacity: 1;
	pointer-events: auto;
}
[data-theme="dark"] .maktab-detail-backdrop {
	background: rgba(0, 0, 0, 0.45);
}
.maktab-detail-panel {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(480px, 92vw);
	/* Pass E: --cream (cards) instead of --beige (page) so the panel
	   reads as a lifted surface, not a continuation of the page.
	   Phase A shadow purge: depth conveyed by border-inline-start + the
	   page scrim, no box-shadow. */
	background: var(--cream);
	z-index: 1050;
	border-inline-start: 1px solid var(--border);
	transform: translateX(100%);
	transition: transform 0.2s ease;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
.maktab-detail-panel.open {
	transform: translateX(0);
}
/* FB-2026-00183: Arabic / RTL — slide in from the visual LEFT edge so
   the panel matches reading direction. Anchor flips, slide-out vector
   flips with it (-100% instead of +100%). */
[dir="rtl"] .maktab-detail-panel {
	right: auto;
	left: 0;
	transform: translateX(-100%);
}
[dir="rtl"] .maktab-detail-panel.open {
	transform: translateX(0);
}
/* FB-2026-00196: on mobile, narrow the panel so the page behind shows
   ~80px strip — comfortable thumb-tap area to dismiss. Desktop max
   (480px) is unchanged. At 393px viewport → 314px panel (79px visible);
   at 768px → 614px capped to 480. */
@media (max-width: 768px) {
	.maktab-detail-panel {
		width: min(480px, 80vw);
	}
}
.maktab-detail-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 14px 20px;
	border-bottom: 1px solid var(--maktab-border);
	flex-shrink: 0;
}
.maktab-detail-title {
	font-size: 16px;
	font-weight: 600;
	color: var(--maktab-text);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	flex: 1;
}
.maktab-detail-back {
	background: none;
	border: none;
	font-size: 22px;
	color: var(--maktab-text-muted);
	cursor: pointer;
	padding: 0 8px 0 0;
	line-height: 1;
	flex-shrink: 0;
}
.maktab-detail-back:hover {
	color: var(--maktab-text);
}
.maktab-detail-close {
	background: none;
	border: none;
	font-size: 24px;
	color: var(--maktab-text-muted);
	cursor: pointer;
	padding: 0 4px;
	line-height: 1;
	flex-shrink: 0;
	margin-inline-start: 12px;
}
.maktab-detail-close:hover {
	color: var(--maktab-text);
}
.maktab-detail-body {
	flex: 1;
	overflow-y: auto;
	/* FB-2026-00216: belt-and-suspenders — even if some descendant has a
	   long unbroken token, the panel itself never grows a horizontal
	   scrollbar. Specific overflow defenses on .fb-panel-ua handle the
	   actual wrap; this is the safety net. */
	overflow-x: hidden;
	padding: 16px 20px 40px;
}
@media (max-width: 768px) {
	.maktab-detail-body { padding: 16px 12px 40px; }
}
/* Reuse lv-card styles in the panel */
.maktab-detail-body .lv-card {
	padding: 16px;
	border-bottom: 1px solid var(--maktab-border);
}
[data-theme="dark"] .maktab-detail-panel {
	/* Use --maktab-cream (slightly lighter than body) so the panel edge
	   stays visible against the dark page background. Thin left border
	   for definition; the backdrop overlay provides the rest of the
	   separation. No shadow per project convention. */
	background: var(--maktab-cream);
	border-inline-start: 1px solid var(--maktab-border);
}
[data-theme="dark"] .maktab-detail-title {
	color: var(--maktab-text);
}

/* ── Navbar ── */
.navbar {
	background-color: var(--maktab-dark-brown) !important;
	border-bottom: 3px solid var(--maktab-sand) !important;
	box-shadow: none !important;
}

.navbar .navbar-brand,
.navbar .nav-link,
.navbar .navbar-nav .nav-link,
.navbar .navbar-brand img + span,
.navbar .dropdown-toggle {
	color: var(--maktab-straw) !important;
}

.navbar .nav-link:hover,
.navbar .dropdown-toggle:hover {
	color: var(--maktab-white) !important;
}

.navbar .navbar-brand {
	font-weight: 700 !important;
	font-size: 1.1rem !important;
	letter-spacing: 0.5px;
}

/* ── Page Head / Titles ── */
.page-head,
.page-head .page-title .title-text {
	color: var(--maktab-text) !important;
}

.page-head {
	background-color: var(--maktab-cream) !important;
	border-bottom: 1px solid var(--maktab-border) !important;
}

.section-head {
	color: var(--maktab-brown) !important;
	font-weight: 600 !important;
	font-size: 1.05rem !important;
	border-bottom: 2px solid var(--maktab-sand) !important;
	padding-bottom: 8px !important;
	margin-bottom: 16px !important;
	margin-top: 24px !important;
}

/* ── Cards (reusable component) ── */
.maktab-card,
.frappe-card,
.widget.widget-shadow,
.wasi-dashboard-container .card,
.thilth-report .col-md-2 > div,
.family-overview .card {
	background: var(--maktab-cream) !important;
	border: 1px solid var(--maktab-border) !important;
	border-radius: var(--maktab-radius) !important;
	box-shadow: var(--maktab-shadow) !important;
	transition: box-shadow 0.2s ease, transform 0.2s ease;
}

.maktab-card:hover,
.widget.widget-shadow:hover,
.wasi-dashboard-container .card:hover,
.thilth-report .col-md-2 > div:hover {
	box-shadow: var(--maktab-shadow-hover) !important;
	transform: translateY(-1px);
}

.wasi-dashboard-container .card h5 {
	color: var(--maktab-text) !important;
	font-weight: 600;
}

/* ── Buttons ── */
.btn-primary,
.btn-primary-dark {
	background-color: var(--maktab-brown) !important;
	border-color: var(--maktab-brown) !important;
	color: var(--maktab-white) !important;
	border-radius: var(--r-md) !important;
	font-weight: 600 !important;
	transition: all 0.2s ease;
}

.btn-primary:hover,
.btn-primary-dark:hover {
	background-color: var(--maktab-dark-brown) !important;
	border-color: var(--maktab-dark-brown) !important;
	transform: translateY(-1px);
	box-shadow: var(--maktab-shadow) !important;
}

.btn-secondary,
.btn-default {
	background-color: var(--maktab-cream) !important;
	border-color: var(--maktab-sand) !important;
	color: var(--maktab-brown) !important;
	border-radius: var(--r-md) !important;
	font-weight: 500 !important;
}

.btn-secondary:hover,
.btn-default:hover {
	background-color: var(--maktab-straw) !important;
	border-color: var(--maktab-brown) !important;
}

/* ── Links ──
   Plain rule wins by cascade order over Frappe's a{color:$text-color}; no
   !important needed. Color comes from --maktab-link (now warm brown — see
   token definition for context). Hover deepens one shade and underlines —
   no blue anywhere in the link state machine. */
a {
	color: var(--maktab-link);
}

a:hover {
	color: var(--brown-deep);
	text-decoration: underline;
}

[data-theme="dark"] a:hover {
	/* Dark-mode --brown-deep is near-black sidebar bg; use --brown (sand) instead. */
	color: var(--sand);
}

/* Defensive: kill any Frappe-injected link-color/text-blue tokens at body scope
   so legacy widgets we haven't retoken'd don't suddenly render Frappe-blue.
   Bridged to --maktab-link so dark-mode flip cascades automatically. */
body {
	--link-color: var(--maktab-link);
	--text-blue: var(--maktab-link);
}

/* Keep button text colors correct */
.btn-primary a, .btn a {
	color: inherit !important;
}

/* ── Tables ── */
.table,
.frappe-list .list-row,
.report-wrapper .dt-scrollable table {
	background-color: var(--maktab-cream) !important;
}

.table th {
	background-color: var(--maktab-straw) !important;
	color: var(--maktab-text) !important;
	font-weight: 600 !important;
	border-bottom: 2px solid var(--maktab-sand) !important;
}

.table td {
	border-color: var(--maktab-border) !important;
	color: var(--maktab-text) !important;
}

.table-bordered {
	border-color: var(--maktab-border) !important;
}

.table tr:hover td {
	background-color: rgba(212, 197, 160, 0.15) !important;
}

/* ── List View ── */
.frappe-list .list-row {
	border-bottom: 1px solid var(--maktab-border) !important;
}

.frappe-list .list-row:hover {
	background-color: rgba(212, 197, 160, 0.1) !important;
}

.frappe-list .list-row-head {
	background-color: var(--maktab-straw) !important;
}

/* ── Form View ── */
.form-section,
.section-body {
	border-color: var(--maktab-border) !important;
}

.frappe-control .control-label,
.form-group label {
	color: var(--maktab-brown) !important;
	font-weight: 500 !important;
}

.form-control,
.frappe-control input,
.frappe-control select,
.frappe-control textarea {
	border-color: var(--maktab-sand) !important;
	border-radius: var(--r-md) !important;
	background-color: var(--maktab-white) !important;
}

.form-control:focus,
.frappe-control input:focus,
.frappe-control select:focus,
.frappe-control textarea:focus {
	border-color: var(--maktab-link) !important;
	box-shadow: none !important;
}

/* ── Alerts ── */
.alert-warning {
	background-color: rgba(212, 160, 90, 0.12) !important;
	border: 1px solid var(--maktab-amber) !important;
	color: var(--text-on-orange) !important;
	border-radius: var(--r-md) !important;
}

.alert-danger,
.alert-error {
	background-color: rgba(192, 115, 94, 0.12) !important;
	border: 1px solid var(--maktab-terracotta) !important;
	color: var(--text-on-red) !important;
	border-radius: var(--r-md) !important;
}

.alert-success {
	background-color: rgba(94, 125, 94, 0.12) !important;
	border: 1px solid var(--maktab-green) !important;
	color: var(--text-on-green) !important;
	border-radius: var(--r-md) !important;
}

.alert-info {
	background-color: rgba(143, 184, 212, 0.12) !important;
	border: 1px solid var(--maktab-sky) !important;
	color: var(--text-on-blue) !important;
	border-radius: var(--r-md) !important;
}

/* ── Indicator Pills ── */
/* Light mode: tinted backgrounds with dark text */
:root,
[data-theme="light"] {
	--bg-green: rgba(94, 125, 94, 0.15);
	--text-on-green: #3A5A3A;
	--bg-orange: rgba(184, 134, 11, 0.15);
	--text-on-orange: #8B6508;
	--bg-red: rgba(192, 115, 94, 0.15);
	--text-on-red: #7A3B2A;
	--bg-blue: rgba(74, 127, 160, 0.15);
	--text-on-blue: #2D6080;
	--bg-grey: rgba(140, 122, 107, 0.18);
	--text-on-grey: #5A4A3C;
	--bg-gray: rgba(140, 122, 107, 0.18);
	--text-on-gray: #5A4A3C;
	--bg-cyan: rgba(91, 158, 166, 0.15);
	--text-on-cyan: #3A7A82;
	--bg-pink: rgba(176, 122, 138, 0.15);
	--text-on-pink: #7A4A5A;
	--bg-yellow: rgba(184, 150, 11, 0.15);
	--text-on-yellow: #8B7208;
	--bg-purple: rgba(122, 107, 158, 0.15);
	--text-on-purple: #4A3D6A;
	--bg-darkgrey: rgba(107, 94, 82, 0.18);
	--text-on-darkgrey: #4A3D32;
	--bg-light-blue: rgba(106, 155, 191, 0.15);
	--text-on-light-blue: #3A6A8A;
}
/* Dark mode: brighter tints on dark background */
[data-theme="dark"] {
	--bg-green: rgba(107, 143, 107, 0.25);
	--text-on-green: #8FB88F;
	--bg-orange: rgba(224, 176, 106, 0.2);
	--text-on-orange: #E0B06A;
	--bg-red: rgba(212, 138, 116, 0.2);
	--text-on-red: #D48A74;
	--bg-blue: rgba(154, 196, 224, 0.2);
	--text-on-blue: #9AC4E0;
	--bg-grey: rgba(154, 138, 122, 0.2);
	--text-on-grey: #B0A090;
	--bg-gray: rgba(154, 138, 122, 0.2);
	--text-on-gray: #B0A090;
	--bg-cyan: rgba(107, 170, 178, 0.2);
	--text-on-cyan: #8FC8D0;
	--bg-pink: rgba(188, 138, 154, 0.2);
	--text-on-pink: #C8A0B0;
	--bg-yellow: rgba(196, 162, 26, 0.2);
	--text-on-yellow: #E0C860;
	--bg-purple: rgba(138, 122, 170, 0.2);
	--text-on-purple: #B0A0D0;
	--bg-darkgrey: rgba(122, 110, 96, 0.2);
	--text-on-darkgrey: #A09080;
	--bg-light-blue: rgba(122, 168, 204, 0.2);
	--text-on-light-blue: #9AC4E0;
}

.indicator-pill,
.indicator-pill-right {
	font-weight: 700 !important;
	font-size: 0.72rem !important;
	padding: 3px 10px !important;
	border-radius: var(--r-lg) !important;
	line-height: 1.4 !important;
	white-space: nowrap !important;
	border: none !important;
	box-shadow: none !important;
	outline: none !important;
	height: auto !important;
}

/* Hide the colored dot before pill text */
.indicator-pill::before,
.indicator-pill-right::after {
	display: none !important;
	content: none !important;
}

/* Inner spans inherit pill color */
.indicator-pill span,
.indicator-pill .ellipsis {
	color: inherit !important;
	background: transparent !important;
}

/* Fix white rectangle: .level-right has white background by default */
.frappe-list .level-right {
	background: transparent !important;
}

/* Hide activity items that create artifacts at end of rows on mobile */
.list-row-activity {
	display: none !important;
}

/* ── Hide Frappe workspace chrome on custom pages ──
   Frappe injects a workspace-container above our page content,
   pushing it ~600px below the fold. Hide it on maktab. */
.page-container[data-page-container="maktab"] .workspace-container,
.page-container[data-page-container="maktab"] .codex-editor,
body[data-route="maktab"] .workspace-container,
body[data-route="maktab"] .codex-editor {
	display: none !important;
}

.badge-success { background-color: var(--bg-green) !important; color: var(--text-on-green) !important; }
.badge-danger { background-color: var(--bg-red) !important; color: var(--text-on-red) !important; }
.badge-warning { background-color: var(--bg-orange) !important; color: var(--text-on-orange) !important; }
.badge-info { background-color: var(--bg-blue) !important; color: var(--text-on-blue) !important; }


/* ── Mobile navbar ── */
@media (max-width: 768px) {
	/* On mobile, the page-head already has the hamburger menu,
	   title, search, and action buttons. The separate navbar
	   is redundant and wastes vertical space. Hide it. */
	.navbar {
		display: none !important;
	}
}

/* Hide Frappe's sidebar-toggle burger at every viewport.
   Our sidebar (v4) is decoupled from Frappe — `<aside class="maktab-sidebar">`
   is a direct body child, and `.body-sidebar-container { display: none }`.
   Frappe's burger toggles its own (hidden) sidebar, so it does nothing
   useful for our users — pure dead UX. Mobile users get the bottom nav
   Menu tab; desktop/tablet users see our maktab-sidebar directly.
   Must hide both the button AND the sidebar-toggle-placeholder SVG
   that Frappe renders independently. */
.page-head .sidebar-toggle-btn,
.page-head .sidebar-toggle-placeholder {
	display: none !important;
}

/* ── Consistent background on all containers ── */
.main-section,
.desk-page,
.page-container,
.page-body,
.layout-main-section,
.layout-main-section-wrapper,
.page-head {
	background-color: var(--maktab-beige) !important;
}

/* ── Minor layout tweaks (all screen sizes) ── */
.codex-editor {
	min-height: auto !important;
}
.page-body {
	padding-bottom: 0 !important;
	border: none !important;
}
.frappe-list,
.frappe-list .result,
.frappe-list .result-container,
.frappe-list .list-row-container,
.layout-side-section {
	border-left: none !important;
	border-right: none !important;
}
/* Remove sticky overlay on right side of list rows and collapse the
   empty .level-right area so data columns can use the full row width.
   Frappe makes .level-right sticky with a background, which creates a
   beige box that clips content. */
.list-row .level-right,
.list-row-head .level-right {
	position: static !important;
	background-color: transparent !important;
	border-left: none !important;
	box-shadow: none !important;
	flex: 0 0 auto !important;
	min-width: 0 !important;
	padding: 0 4px 0 0 !important;
}
/* Let level-left use full row width (Frappe defaults to flex:4 = 80%).
   Since .level-right is collapsed, data columns should fill the row. */
.list-row .level-left,
.list-row-head .level-left {
	min-width: 0 !important;
	flex: 1 1 100% !important;
}
/* Let list columns shrink to fit viewport instead of forcing horizontal scroll.
   Frappe sets min-width:150px + width:fit-content which overflows on narrow screens. */
.frappe-list .result .list-row-container {
	width: 100% !important;
}
.list-row .level-left .list-row-col,
.list-row-head .level-left .list-row-col {
	min-width: 0 !important;
	margin-right: 6px !important;
	flex-shrink: 1 !important;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.page-head {
	border-bottom: 1px solid var(--maktab-border) !important;
}
/* Hide Frappe's vestigial page-head titlebar on every Maktab custom page.
   Each page renders its own head (.adm-title / .el-head / .mkt-pg-head /
   the injected .maktab-page-h1), and no Maktab page uses Frappe page-head
   actions — so the page-head only ever shows a DUPLICATE title. set_page_title
   tags .page-container with .maktab-no-titlebar; this restores the hide the
   surrounding comments assume. Sticky toolbars anchor at top:0. */
.maktab-no-titlebar .page-head {
	display: none !important;
}
/* The modern page title for utility/list pages that don't render their own head
   (injected by maktab.set_page_title when render_h1:true). Replaces the retired
   full-width Frappe titlebar with the canonical short sand underline (matches
   .adm-title / .el-head__title). Centred in the same max-width column as the
   list content (.maktab-list / .maktab-list-page, max-width 1280, s-5 inset) so
   the title left-aligns with the cards below it. */
.maktab-page-h1 {
	max-width: 1280px;
	margin: 0 auto;
	box-sizing: border-box;
	padding: var(--s-6) var(--s-5) 0;
	font-size: var(--text-2xl);
	font-weight: 700;
	color: var(--brown-deep);
	line-height: 1.1;
}
.maktab-page-h1::after {
	content: "";
	display: block;
	width: 38px;
	height: 3px;
	border-radius: 2px;
	background: var(--sand-deep);
	margin-top: var(--s-2);
	margin-bottom: var(--s-4);
}
/* Wasi Dashboard side padding */
.wasi-dashboard-container {
	padding: 0 15px;
}

/* ── Mobile layout fix ──
   On mobile, Frappe's .main-section { overflow: scroll } breaks
   position:sticky for the page-head. Fix by switching scroll root
   to body on mobile only. Desktop keeps Frappe's original layout. */
@media (max-width: 768px) {
	/* Page-head is now hidden via .maktab-no-titlebar — sticky toolbars
	   anchor at top: 0, so scroll-padding-top is also 0. */
	html {
		scroll-padding-top: 0;
		/* Clip the horizontal overflow contributed by the off-screen FIXED
		   sidebar. It's translated off-screen on mobile, but iOS WebKit still
		   counts that fixed box in the document's scrollWidth → a ~40px sideways
		   page drag on every view. body{overflow-x:hidden} (line ~582) can't
		   catch it because a fixed element escapes the body's clip; the root's
		   overflow propagates to the viewport, so clipping it here does. `clip`
		   (NOT `hidden`) is deliberate — it leaves overflow-y visible, so the
		   document scroll + the sticky page-head/tabs (which rely on
		   .main-section{overflow:visible} below) are unaffected. */
		overflow-x: clip;
	}
	.main-section {
		height: auto !important;
		min-height: 100vh !important;
		overflow: visible !important;
		overflow-x: visible !important;
		overflow-y: visible !important;
		flex: 1 !important;
		overscroll-behavior-x: none !important;
	}
	/* FB-073/148: prevent iOS rubber-band from propagating up the document
	   and dislodging the fixed bottom-nav. Containment on the actual scroll
	   container (.main-section is where Round 6c found scrollTop > 0). */
	.main-section,
	.layout-main-section {
		overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
	}
	/* FB-2026-00163: previously locked overscroll-behavior-y on html/body to
	   prevent the iOS rubber-band from dislodging the fixed bottom-nav (FB-073/
	   148 round 6i.4). Side effect: every page lost its bounce-back, which Ahmad
	   found made the app feel rigid. He explicitly preferred a small amount of
	   nav drift on overscroll over the rigid feel. The .main-section containment
	   above still protects against intra-content overscroll. */
	.page-container,
	.layout-main-section,
	.layout-main-section-wrapper {
		min-height: auto !important;
	}
	.frappe-list .result,
	.frappe-list .result-container {
		min-height: auto !important;
		height: auto !important;
	}
	.desk-page,
	.page-container,
	.page-body,
	.page-wrapper,
	.page-content {
		flex: none !important;
		flex-grow: 0 !important;
	}
	/* Form main section must fill the width on mobile.
	   The form sidebar becomes an overlay, so the wrapper should be 100%. */
	.layout-main-section-wrapper {
		flex: 1 1 100% !important;
		width: 100% !important;
		max-width: 100% !important;
	}
	/* Hide form sidebar from flex flow on mobile (it's an overlay) */
	.layout-side-section {
		display: none !important;
	}
	.page-head {
		position: sticky !important;
		top: 0;
		z-index: 1010;
	}
	/* Dropdown menu must appear above the sticky page-head */
	.page-head .dropdown-menu {
		z-index: 1020 !important;
	}
	/* Minimize page-actions so it doesn't create a gap when empty.
	   The .col class gives it flex-grow:1 which fills remaining space.
	   Override to auto-size based on content only. */
	.page-head .page-actions {
		flex-grow: 0 !important;
		flex-basis: auto !important;
		padding: 0 !important;
		min-width: 0 !important;
		width: auto !important;
	}
	/* Hide empty filter/action containers inside page-actions */
	.page-head .page-actions > .filters:empty,
	.page-head .page-actions > .custom-actions,
	.page-head .page-actions > .custom-mobile-actions:empty {
		display: none !important;
	}
}

/* ── Mobile cleanup ── */
@media (max-width: 768px) {
	/* Force form columns to stack vertically on mobile.
	   Bootstrap's base .col-sm-6 { flex: 0 0 50% } applies at all sizes
	   (not scoped to a media query), so we must override with exact classes. */
	.section-body > .form-column.col-sm-6,
	.section-body > .form-column.col-sm-4,
	.section-body > .form-column.col-sm-3,
	.section-body > .form-column.col-sm-20 {
		flex: 0 0 100% !important;
		max-width: 100% !important;
		width: 100% !important;
	}

	/* Hide sort selector, ID filter, page-form */
	.sort-selector,
	.mobile-id-filter,
	.page-form {
		display: none !important;
	}
	/* Hide list/kanban toggle */
	.page-head .page-actions .custom-btn-group {
		display: none !important;
	}

	/* ── Page header layout ── */
	.page-head .container {
		padding-left: 10px !important;
		padding-right: 10px !important;
	}
	.page-head .page-head-content {
		gap: 4px !important;
		max-width: 100% !important;
		overflow: hidden !important;
		margin-right: 0 !important;
		margin-left: 0 !important;
		padding-right: 0 !important;
		padding-left: 0 !important;
	}
	.page-head .page-title {
		flex: 1 !important;
		min-width: 0 !important;
		overflow: hidden !important;
	}
	.page-head .title-text {
		overflow: hidden !important;
		text-overflow: ellipsis !important;
		white-space: nowrap !important;
		font-size: 0.9rem !important;
	}
	/* Allow page title to wrap on maktab detail pages */
	.maktab-page-head .page-title {
		overflow: visible !important;
	}
	.maktab-page-head .navbar-breadcrumbs {
		max-width: calc(100vw - 60px) !important;
		overflow: visible !important;
	}
	.maktab-page-head .maktab-page-title {
		white-space: normal !important;
		overflow: visible !important;
		text-overflow: clip !important;
	}
	.maktab-page-head .maktab-page-title a {
		white-space: normal !important;
	}
	/* Right-align the buttons section, no extra spacing */
	.page-head .standard-items-section {
		margin-left: auto !important;
		margin-right: 0 !important;
		padding-right: 0 !important;
		flex-shrink: 0 !important;
		gap: 4px !important;
	}
	.page-head .page-actions {
		padding-left: 0 !important;
		padding-right: 0 !important;
		gap: 4px !important;
		flex-shrink: 0 !important;
	}

	/* ── CRITICAL: Any button with .hide must stay hidden ──
	   Bootstrap .hide uses display:none!important. Our btn rules below
	   also use !important. We MUST re-enforce .hide AFTER the btn rules. */

	/* ── Visible icon-only buttons — 32x32 squares ──
	   Exclude .primary-action so Save/Submit buttons keep their text. */
	.page-head .standard-actions .btn:not(.hide):not(:empty):not(.primary-action),
	.page-head .page-actions .btn:not(.hide):not(:empty):not(.primary-action) {
		width: 32px !important;
		height: 32px !important;
		min-width: 32px !important;
		min-height: 32px !important;
		max-width: 32px !important;
		max-height: 32px !important;
		padding: 0 !important;
		flex-shrink: 0 !important;
		display: inline-flex !important;
		align-items: center !important;
		justify-content: center !important;
		text-align: center !important;
		font-size: 0 !important;
		line-height: 0 !important;
		border-radius: var(--r-md) !important;
		box-sizing: border-box !important;
	}
	/* Content inside icon-only buttons — centered */
	.page-head .standard-actions .btn:not(.hide):not(.primary-action) > *,
	.page-head .page-actions .btn:not(.hide):not(.primary-action) > * {
		font-size: 14px !important;
		line-height: 1 !important;
		margin: 0 !important;
		padding: 0 !important;
	}
	.page-head .btn:not(.hide):not(.primary-action) .icon,
	.page-head .btn:not(.hide):not(.primary-action) svg {
		margin: 0 !important;
		padding: 0 !important;
	}

	/* ── Primary action button — compact text button on mobile ──
	   On list views this is "+ Add X", on form views it's "Save". */
	.page-head .primary-action:not(.hide):not(:empty) {
		height: 32px !important;
		min-height: 32px !important;
		padding: 0 10px !important;
		flex-shrink: 0 !important;
		display: inline-flex !important;
		align-items: center !important;
		justify-content: center !important;
		border-radius: var(--r-md) !important;
		font-size: 13px !important;
		line-height: 1 !important;
		white-space: nowrap !important;
		gap: 4px !important;
	}
	/* Hide the long "Add Household Staff" text, keep only icon on list pages */
	.page-head .primary-action .hidden-xs {
		display: none !important;
	}

	/* ── Hide indicator pill on mobile to save header space ── */
	.page-head .indicator-pill {
		display: none !important;
	}

	/* ── Force-hide all buttons that have .hide or are empty ── */
	.page-head .btn.hide,
	.page-head .btn:empty,
	.page-head .standard-actions .btn.hide,
	.page-head .standard-actions .btn:empty,
	.page-head .primary-action.hide,
	.page-head .primary-action:empty,
	.page-head .btn-secondary.hide,
	.page-head .btn-secondary:empty {
		display: none !important;
		width: 0 !important;
		height: 0 !important;
		overflow: hidden !important;
	}

	/* ── Hide search icon on mobile — our list pages have inline search ── */
	.page-head .search-bar {
		display: none !important;
	}
	/* ── Suppress tooltips and keyboard shortcut hints on mobile ── */
	.tooltip {
		display: none !important;
	}
	/* Hide keyboard shortcut badges and navigation hints on mobile */
	.modal .keyboard-shortcut,
	.modal .shortcut-key,
	.modal kbd,
	.command-palette .shortcut,
	.command-palette kbd,
	.dropdown-menu kbd,
	.dropdown-menu .shortcut,
	.dropdown-menu .shortcut-key,
	.awesomebar-modal-footer,
	.modal-footer kbd,
	.modal .footer-description {
		display: none !important;
	}

	/* ── Content padding ── */
	.container {
		padding-left: 12px !important;
		padding-right: 12px !important;
	}
	.page-body {
		padding-top: 8px !important;
		border: none !important;
	}

	/* ── Kill bottom dead space on mobile ── */
	.layout-main-section,
	.frappe-list,
	.layout-main-section-wrapper,
	.page-container,
	.codex-editor,
	.page-body,
	.desk-page {
		min-height: auto !important;
		padding-bottom: 0 !important;
	}
	.frappe-list .result,
	.frappe-list .result-container {
		min-height: 0 !important;
		height: auto !important;
	}
	.list-paging-area {
		padding: 8px 0 !important;
		margin-bottom: 0 !important;
	}
	.page-head + .layout-main-section-wrapper {
		margin-bottom: 0 !important;
	}
}

/* ── Thilth Report card top borders ── */
.thilth-report .col-md-2 > div[style*="border-top: 3px solid var(--blue)"] {
	border-top-color: var(--maktab-link) !important;
}

.thilth-report .col-md-2 > div[style*="border-top: 3px solid var(--green)"] {
	border-top-color: var(--maktab-green) !important;
}

.thilth-report .col-md-2 > div[style*="border-top: 3px solid var(--orange)"] {
	border-top-color: var(--maktab-amber) !important;
}

.thilth-report .col-md-2 > div[style*="border-top: 3px solid var(--red)"] {
	border-top-color: var(--maktab-terracotta) !important;
}

/* ── Modals / Dialogs ──
   Full restyle to match Maktab's warm, clean aesthetic. Every Frappe dialog
   (New record, Edit, Upload, Confirm, Message) gets this treatment. */

/* Backdrop — warm brown tint */
/* FB-2026-00162: dropped from 0.85 → 0.55 so content shows through more. */
/* Backdrop — warm brown wash (was beige tint).
   The 0.45 alpha lets the page behind read as faint context, matching
   the dialogs handoff. */
.modal-backdrop { background-color: rgba(74, 55, 40, 0.45) !important; }
.modal-backdrop.show { opacity: 1 !important; }

/* Dialog container — constrained width, centered */
.modal-dialog {
	margin: 2rem auto !important;
	max-width: 460px !important;
}
.modal-dialog.modal-lg { max-width: 580px !important; }
.modal-dialog.modal-sm { max-width: 380px !important; }

/* Outer card — small radius (document aesthetic) + shadow-modal for lift */
.modal-content {
	background-color: var(--maktab-cream) !important;
	border: 1px solid var(--maktab-border) !important;
	border-radius: var(--r-sm) !important;
	overflow: hidden !important;
}

/* ── Header — sand-gold bar ── */
.modal-header {
	background: var(--sand) !important;
	border-bottom: 1px solid var(--maktab-sand) !important;
	border-radius: var(--r-sm) var(--r-sm) 0 0 !important;
	padding: 10px 16px !important;
	align-items: center !important;
	min-height: 44px !important;
}
.modal-header .modal-title,
.modal-header .title-section h4,
.modal-header h4.modal-title {
	color: var(--maktab-dark-brown) !important;
	font-weight: 700 !important;
	font-size: 14px !important;
	letter-spacing: 0.1px !important;
	margin: 0 !important;
	line-height: 1.3 !important;
}
.modal-header .title-section .indicator.hidden { display: none !important; }

/* Close button — clean X, no circle */
.modal-header .btn-modal-close {
	background: transparent !important;
	border: none !important;
	border-radius: var(--r-sm) !important;
	color: var(--maktab-brown) !important;
	width: 28px !important;
	height: 28px !important;
	padding: 0 !important;
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	transition: background 0.15s !important;
}
.modal-header .btn-modal-close:hover {
	background: rgba(42, 32, 24, 0.08) !important;
	color: var(--maktab-dark-brown) !important;
}
.modal-header .btn-modal-close svg {
	width: 16px !important;
	height: 16px !important;
}

/* ── Body ── */
.modal-body {
	background-color: var(--maktab-cream) !important;
	padding: 16px !important;
	color: var(--maktab-text) !important;
}

/* ── Footer — clean action bar ── */
.modal-footer,
.modal .standard-actions {
	background-color: var(--maktab-beige) !important;
	border-top: 1px solid var(--maktab-border) !important;
	border-radius: 0 0 var(--r-sm) var(--r-sm) !important;
	padding: 10px 16px !important;
	gap: 10px !important;
	display: flex !important;
	justify-content: flex-end !important;
}
/* Frappe toggles .hide on the footer when the dialog has no visible
   action buttons (e.g. msgprint with close-in-header). The display:flex
   rule above was silencing that, producing a stranded tan band below
   the message. Respect .hide. */
.modal-footer.hide {
	display: none !important;
}

/* ── Form controls inside dialogs ── */
.modal-body .frappe-control .control-label,
.modal-body label.control-label {
	color: var(--maktab-text-muted) !important;
	font-size: 10px !important;
	font-weight: 700 !important;
	text-transform: uppercase !important;
	letter-spacing: 0.5px !important;
	margin-bottom: 4px !important;
}
.modal-body .form-control,
.modal-body input.input-with-feedback,
.modal-body select.input-with-feedback,
.modal-body textarea.input-with-feedback,
.modal-body .like-disabled-input {
	background-color: #FFFFFF !important;
	border: 1.5px solid var(--maktab-border) !important;
	border-radius: var(--r-md) !important;
	color: var(--maktab-text) !important;
	font-size: 13px !important;
	padding: 7px 10px !important;
	min-height: 36px !important;
	transition: border-color 0.15s, box-shadow 0.15s !important;
}
.modal-body .form-control:focus,
.modal-body input.input-with-feedback:focus,
.modal-body select.input-with-feedback:focus,
.modal-body textarea.input-with-feedback:focus {
	border-color: var(--maktab-brown) !important;
	box-shadow: none !important;
	outline: none !important;
}
.modal-body .form-group { margin-bottom: 12px !important; }
.modal-body .help-box,
.modal-body .help-text { color: var(--maktab-text-muted) !important; font-size: 12px !important; }

/* Checkboxes */
.modal-body .checkbox label,
.modal-body .checkbox .label-area {
	color: var(--maktab-text) !important;
	font-weight: 500 !important;
}

/* ── Footer buttons — polished pill-shaped actions ── */
.modal-footer .btn,
.modal .standard-actions .btn {
	border-radius: var(--r-md) !important;
	padding: 7px 16px !important;
	font-size: 13px !important;
	font-weight: 600 !important;
	min-height: 34px !important;
	border: none !important;
	transition: all 0.15s ease !important;
}
.modal-footer .btn-primary,
.modal .standard-actions .btn-primary {
	background: var(--maktab-brown) !important;
	color: var(--cream) !important;
	box-shadow: none !important;
}
.modal-footer .btn-primary:hover,
.modal .standard-actions .btn-primary:hover {
	background: var(--maktab-dark-brown) !important;
	color: #FFFFFF !important;
	box-shadow: none !important;
}
.modal-footer .btn-secondary,
.modal-footer .btn-default,
.modal .standard-actions .btn-secondary,
.modal .standard-actions .btn-default {
	background: var(--maktab-cream) !important;
	color: var(--maktab-text) !important;
	border: 1.5px solid var(--maktab-border) !important;
}
.modal-footer .btn-secondary:hover,
.modal-footer .btn-default:hover {
	background: var(--maktab-straw) !important;
	border-color: var(--maktab-sand) !important;
	transform: translateY(-1px);
}
/* FB-365: dark-mode contrast — the inherited rule resolved to dark-brown text
   on dark-brown surface in dark mode (var(--cream) is a SURFACE token that
   resolves to #24201A under [data-theme="dark"], NOT a light color). Use
   --ink (light foreground) + a darker surface for contrast. */
[data-theme="dark"] .modal-footer .btn-secondary,
[data-theme="dark"] .modal-footer .btn-default,
[data-theme="dark"] .modal .standard-actions .btn-secondary,
[data-theme="dark"] .modal .standard-actions .btn-default {
	background: transparent !important;
	color: var(--brown, #C2AD7E) !important;
	border: 1.5px solid var(--brown, #C2AD7E) !important;
}
[data-theme="dark"] .modal-footer .btn-secondary:hover,
[data-theme="dark"] .modal-footer .btn-default:hover {
	background: rgba(194, 173, 126, 0.12) !important;
	border-color: var(--brown, #C2AD7E) !important;
	color: var(--brown, #C2AD7E) !important;
	transform: translateY(-1px);
}

/* ── Mobile bottom-sheet (≤ 768px) ──
   Phones AND tablets get bottom-sheet dialogs. align-items sits on .modal
   (the full-viewport overlay), NOT .modal-dialog — that's what makes the
   sheet hug the bottom edge regardless of content height. .modal-content
   uses flex-column so the footer (Cancel/Confirm) is always visible at the
   bottom of the sheet, even when the body would otherwise overflow — body
   scrolls inside its own container, footer stays anchored.

   IMPORTANT: every layout-rule here is scoped to `.modal[style*="block"]`,
   matching Bootstrap's inline `display: block` set during show. Bootstrap's
   close sequence is: (1) remove `.show`, (2) fade out via opacity, (3) set
   inline `display: none`. Scoping to `.show` would un-apply our layout in
   step 1 and the dialog would flash to the default centered desktop layout
   during the fade. Scoping to `[style*="block"]` keeps the bottom-sheet
   layout in place through the fade, then drops it cleanly when Bootstrap
   sets `display: none` (which falls outside the `block` substring match,
   so default Bootstrap `.modal { display: none }` wins). This also kills
   the original ghost-modal bug — a closed modal with `display: none`
   inline style doesn't match. */
@media (max-width: 768px) {
	.modal[style*="block"] {
		display: flex !important;
		align-items: flex-end !important;
		padding: 0 !important;
	}
	.modal[style*="block"] .modal-dialog,
	.modal[style*="block"] .modal-dialog.modal-lg,
	.modal[style*="block"] .modal-dialog.modal-sm {
		margin: 0 !important;
		max-width: 100% !important;
		width: 100% !important;
	}
	.modal[style*="block"] .modal-content {
		width: 100% !important;
		max-height: 90vh !important;
		max-height: 90dvh !important;
		display: flex !important;
		flex-direction: column !important;
		border-radius: var(--r-md) var(--r-md) 0 0 !important;
		animation: maktab-sheet-up var(--dur-slow) var(--ease) !important;
	}
	.modal-header {
		border-radius: 0 !important;
		flex-shrink: 0 !important;
	}
	/* Body scrolls if content exceeds available height; footer stays put.
	   touch-action:pan-y + overscroll-behavior:contain stop iOS Safari from
	   routing the swipe to the (locked) body — without these, the inner scroll
	   appears stuck because the gesture leaks to the page.
	   Selector matches `.modal .modal-body { overflow: visible !important }` at
	   line ~1800 (desktop dropdown-escape rule) so we win on equal specificity
	   via source order. */
	.modal .modal-body {
		flex: 1 1 auto !important;
		overflow-y: auto !important;
		overflow-x: hidden !important;
		min-height: 0 !important;
		touch-action: pan-y !important;
		overscroll-behavior: contain !important;
		-webkit-overflow-scrolling: touch !important;
	}
	.modal-footer,
	.modal .standard-actions {
		border-radius: 0 !important;
		flex-shrink: 0 !important;
	}
}
@keyframes maktab-sheet-up {
	from { transform: translateY(100%); }
	to   { transform: translateY(0); }
}

/* File uploader */
.modal-body .file-upload,
.modal-body .file-uploader {
	background: #FFFFFF !important;
	border: 2px dashed var(--maktab-border) !important;
	border-radius: var(--r-lg) !important;
	padding: 20px !important;
	text-align: center !important;
}
.modal-body .file-upload .btn-file-upload,
.modal-body .file-uploader .btn-file-upload { color: var(--maktab-text) !important; }
.modal-body .file-upload .uploaded-filename,
.modal-body .file-uploader .uploaded-filename { color: var(--maktab-text) !important; }
.modal-body .file-upload-area,
.modal-body .file-uploader .upload-area {
	border: 2px dashed var(--maktab-sand) !important;
	border-radius: var(--r-lg) !important;
	padding: 24px !important;
	background: var(--maktab-beige) !important;
	text-align: center !important;
}
.modal-body .file-uploader .upload-area:hover {
	border-color: var(--maktab-brown) !important;
	background: rgba(212, 197, 160, 0.15) !important;
}

/* File uploader — dark mode (FB-2026-00118: kill the giant white wrapper) */
[data-theme="dark"] .modal-body .file-upload,
[data-theme="dark"] .modal-body .file-uploader {
	background: var(--maktab-cream) !important;
	border-color: var(--maktab-border) !important;
	color: var(--maktab-text) !important;
}
[data-theme="dark"] .modal-body .file-upload .btn-file-upload,
[data-theme="dark"] .modal-body .file-uploader .btn-file-upload {
	color: var(--maktab-text) !important;
}
[data-theme="dark"] .modal-body .file-upload .uploaded-filename,
[data-theme="dark"] .modal-body .file-uploader .uploaded-filename {
	color: var(--maktab-text) !important;
}
[data-theme="dark"] .modal-body .file-upload-area,
[data-theme="dark"] .modal-body .file-uploader .upload-area,
[data-theme="dark"] .modal-body .file-uploader .file-upload-area {
	background: var(--maktab-beige) !important;
	border-color: var(--maktab-sand) !important;
	color: var(--maktab-text) !important;
}
[data-theme="dark"] .modal-body .file-uploader .upload-area:hover,
[data-theme="dark"] .modal-body .file-uploader .file-upload-area:hover {
	border-color: var(--maktab-brown) !important;
	background: rgba(61, 54, 40, 0.4) !important;
}

/* Legacy top-slide-down mobile modal block deleted — replaced by the
   bottom-sheet rule above. The minimize-button hide and form-group
   margin tweaks are folded into ../mobile-bottom-sheet rule above. */

/* ── Dark mode ── */
/* FB-2026-00162: dropped from 0.65 → 0.55 for consistency with the other backdrops. */
[data-theme="dark"] .modal-backdrop { background-color: rgba(0, 0, 0, 0.55) !important; }
[data-theme="dark"] .modal-content {
	background-color: var(--maktab-cream) !important;
	box-shadow: none !important;
}
[data-theme="dark"] .modal-header {
	background: var(--maktab-straw) !important;
	border-bottom-color: var(--maktab-sand) !important;
}
[data-theme="dark"] .modal-header .modal-title,
[data-theme="dark"] .modal-header .title-section h4,
[data-theme="dark"] .modal-header h4.modal-title {
	color: var(--maktab-white) !important;
}
[data-theme="dark"] .modal-body .form-control,
[data-theme="dark"] .modal-body input.input-with-feedback,
[data-theme="dark"] .modal-body select.input-with-feedback,
[data-theme="dark"] .modal-body textarea.input-with-feedback {
	background-color: #2A2418 !important;
	border-color: var(--straw) !important;
	color: var(--maktab-text) !important;
}
[data-theme="dark"] .modal-body .form-control:focus,
[data-theme="dark"] .modal-body input.input-with-feedback:focus {
	border-color: var(--maktab-sand) !important;
	box-shadow: none !important;
}
[data-theme="dark"] .modal-footer,
[data-theme="dark"] .modal .standard-actions {
	background-color: var(--maktab-cream) !important;
	border-top-color: var(--maktab-border) !important;
}
[data-theme="dark"] .modal-footer .btn-secondary,
[data-theme="dark"] .modal-footer .btn-default {
	background: #2A2418 !important;
	color: var(--maktab-text) !important;
}

/* ── Dialog component-level overrides ── */

/* Hide developer-facing noise */
.modal .tooltip-content,
.modal .help-box:empty,
.modal .help:empty { display: none !important; }
.modal .btn-modal-minimize { display: none !important; }

/* Clean form layout */
.modal .form-group.horizontal { border: none !important; margin-bottom: 16px !important; padding: 0 !important; }
.modal .form-group.horizontal .clearfix { margin-bottom: 6px !important; }

/* Remove spurious border lines above buttons */
.modal .standard-actions { border-top: none !important; }
.modal .modal-footer::before { display: none !important; }
.modal .form-group .clearfix { border: none !important; }
.modal .btn { border-top: none !important; }

/* Allow dropdowns to overflow on desktop. Mobile scopes overflow:auto on
   .modal-body inside the bottom-sheet block above so dialogs are scrollable
   when content overflows the 90vh sheet. */
@media (min-width: 769px) {
	.modal .modal-body { overflow: visible !important; }
}
.modal .form-layout,
.modal .form-page,
.modal .form-section,
.modal .section-body,
.modal .form-column { overflow: visible !important; }

/* Select dropdown — custom styled arrow */
.modal select.input-with-feedback {
	text-overflow: unset !important;
	white-space: normal !important;
	padding-right: 36px !important;
	-webkit-appearance: none !important;
	appearance: none !important;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B5A48' stroke-width='2.5'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
	background-repeat: no-repeat !important;
	background-position: right 12px center !important;
}
[dir="rtl"] .modal select.input-with-feedback {
	padding-right: 14px !important;
	padding-left: 36px !important;
	background-position: left 12px center !important;
}
.modal .select-icon { display: none !important; }

/* Checkbox inside modal body — keep it 18×18 even when it's a bare
   input.input-with-feedback (no .checkbox wrapper, e.g. Record Payment
   dialog's "Invoice already issued"). Frappe's default form control
   styling stretches it to 24×18 otherwise. */
.modal .modal-body input[type="checkbox"],
.modal .modal-body input[type="checkbox"].input-with-feedback {
	width: 18px !important;
	height: 18px !important;
	min-width: 18px !important;
	min-height: 18px !important;
	max-width: 18px !important;
	max-height: 18px !important;
	padding: 0 !important;
	border-radius: var(--r-sm) !important;
}

/* Tighten modal footer on desktop — Frappe's .standard-actions adds
   its own 10px vertical padding on top of the .modal-footer's 10px,
   which made the Refresh / Yes-No buttons look stranded in a tall
   empty band. Zeroing the inner padding keeps the button's own height
   and the footer's outer padding intact. */
.modal .modal-footer .standard-actions,
.modal .modal-footer .custom-actions {
	padding: 0 !important;
	margin: 0 !important;
}

/* Hide an empty footer entirely (e.g. msgprint / warn dialogs whose
   close button lives in the header — no primary action needed). Prevents
   the solid tan band that appeared below the message. */
.modal .modal-footer:not(:has(button)) {
	display: none !important;
}

/* Delete-confirm primary action: red (terracotta) button to signal a
   destructive action. Applied by JS to frappe.confirm dialogs whose
   body mentions "delete" — see mobile_fixes / shown.bs.modal handler.
   Selector prefixes (.modal .modal-footer, .modal-header) added so this
   beats the default brown styling on both desktop footer and mobile
   header buttons. */
.modal .modal-footer .maktab-delete-btn {
	background: var(--maktab-terracotta) !important;
	border-color: var(--maktab-terracotta) !important;
	color: #fff !important;
}
.modal .modal-footer .maktab-delete-btn:hover {
	background: #A85A45 !important;
	border-color: #A85A45 !important;
}

/* Custom checkbox */
.modal .checkbox label {
	display: flex !important;
	align-items: center !important;
	gap: 8px !important;
	cursor: pointer !important;
	padding: 4px 0 !important;
	color: var(--maktab-text) !important;
	font-weight: 500 !important;
	font-size: 14px !important;
}
.modal .checkbox input[type="checkbox"] {
	-webkit-appearance: none !important;
	appearance: none !important;
	width: 18px !important;
	height: 18px !important;
	min-width: 18px !important;
	min-height: 18px !important;
	max-width: 18px !important;
	max-height: 18px !important;
	border: 2px solid var(--maktab-border) !important;
	border-radius: var(--r-sm) !important;
	background: #fff !important;
	cursor: pointer !important;
	position: relative !important;
	flex-shrink: 0 !important;
	margin: 0 !important;
	transition: all 0.15s !important;
	display: inline-block !important;
	vertical-align: middle !important;
}
.modal .checkbox input[type="checkbox"]:checked {
	background: var(--maktab-brown, #5C4A3A) !important;
	border-color: var(--maktab-brown, #5C4A3A) !important;
}
.modal .checkbox input[type="checkbox"]:checked::after {
	content: '' !important;
	position: absolute !important;
	left: 4px !important;
	top: 1px !important;
	width: 6px !important;
	height: 10px !important;
	border: solid #fff !important;
	border-width: 0 2px 2px 0 !important;
	transform: rotate(45deg) !important;
}
.modal .checkbox .disp-area { display: none !important; }

/* ── Global checkbox styling (outside modals too) ── */
.checkbox input[type="checkbox"] {
	-webkit-appearance: none !important;
	appearance: none !important;
	width: 18px !important;
	height: 18px !important;
	min-width: 18px !important;
	min-height: 18px !important;
	max-width: 18px !important;
	max-height: 18px !important;
	border: 2px solid var(--maktab-border) !important;
	border-radius: var(--r-sm) !important;
	background: #fff !important;
	cursor: pointer !important;
	position: relative !important;
	flex-shrink: 0 !important;
	margin: 0 !important;
	transition: all 0.15s !important;
}
.checkbox input[type="checkbox"]:checked {
	background: var(--maktab-brown) !important;
	border-color: var(--maktab-brown) !important;
}
.checkbox input[type="checkbox"]:checked::after {
	content: '' !important;
	position: absolute !important;
	left: 4px !important;
	top: 1px !important;
	width: 6px !important;
	height: 10px !important;
	border: solid #fff !important;
	border-width: 0 2px 2px 0 !important;
	transform: rotate(45deg) !important;
}

/* No visual section breaks */
.modal .form-section { border: none !important; padding: 0 !important; margin: 0 !important; }
.modal .section-body { padding: 0 !important; }

/* Required asterisk */
.modal .control-label.reqd::after { color: var(--maktab-terracotta) !important; }

/* Let inputs fill width */
.modal .frappe-control.input-max-width { max-width: 100% !important; }

/* Message/confirm dialogs */
.modal .msgprint {
	color: var(--maktab-text) !important;
	font-size: 14px !important;
	line-height: 1.7 !important;
	padding: 4px 0 !important;
}
.modal .modal-footer .btn-danger,
.modal .modal-footer .btn-primary-dark {
	background: var(--maktab-terracotta) !important;
	color: #fff !important;
	border: none !important;
	border-radius: var(--r-md) !important;
}
.modal .modal-footer .btn-danger:hover { background: #A85A45 !important; }


/* Mobile dialog form-control sizing — keep iOS-zoom-prevention font sizes
   and select chrome separate from the bottom-sheet layout rule above so
   each concern lives in its own block. */
@media (max-width: 768px) {
	/* Larger inputs on mobile — 16px prevents iOS auto-zoom */
	.modal.show .modal-body .form-control,
	.modal.show .modal-body select,
	.modal.show .modal-body textarea,
	.modal.show .modal-body .input-with-feedback:not([type="checkbox"]),
	.modal.show .modal-body .like-disabled-input {
		font-size: 16px !important;
		min-height: 40px !important;
		padding: 10px 12px !important;
		line-height: 1.25 !important;
	}
	/* Checkbox: keep square shape, don't stretch */
	.modal.show .modal-body input[type="checkbox"].input-with-feedback,
	.modal.show .modal-body input[type="checkbox"] {
		width: 20px !important;
		height: 20px !important;
		min-height: 20px !important;
		min-width: 20px !important;
		max-width: 20px !important;
		max-height: 20px !important;
		padding: 0 !important;
		border-radius: var(--r-sm) !important;
	}
	/* Select is a replaced element on WebKit: its text is clamped to the
	   content box, so content-box height must be >= line-box height. */
	.modal.show .modal-body select,
	.modal.show .modal-body select.input-with-feedback,
	.modal.show .modal-body .frappe-control[data-fieldtype="Select"] select {
		min-height: 44px !important;
		padding: 10px 36px 10px 10px !important;
		line-height: 1.4 !important;
	}
	/* Form-group margin / body padding tightening */
	.modal.show .modal-body .frappe-control:last-child .form-group,
	.modal.show .modal-body > .form-group:last-child {
		margin-bottom: 0 !important;
	}
	/* Hide drag-and-drop text on mobile (can't drag on touch) */
	.modal .file-uploader .upload-area .text-muted,
	.modal .file-uploader .upload-area > p,
	.modal .file-upload-area .text-muted,
	.modal .file-upload-area > p:first-child {
		display: none !important;
	}
	/* Hide Frappe minimize button on mobile (no use case) */
	.modal-header .btn-modal-minimize { display: none !important; }
}

/* ── Mobile — small/confirm dialogs stay as bottom sheet ── */
@media (max-width: 768px) {
	.modal.show .modal-dialog.modal-sm,
	.modal.show .modal-dialog.msgprint-dialog {
		top: auto !important;
		bottom: 0 !important;
		height: auto !important;
		min-height: auto !important;
		align-items: flex-end !important;
		margin: 0 !important;
		flex-direction: row !important;
		transform: translateY(100%) !important;
	}
	.modal.show .modal-dialog.modal-sm,
	.modal.show .modal-dialog.msgprint-dialog {
		transform: translateY(0) !important;
	}
	.modal.show .modal-dialog.modal-sm .modal-content,
	.modal.show .modal-dialog.msgprint-dialog .modal-content {
		height: auto !important;
		flex: none !important;
		border-radius: var(--r-lg) var(--r-lg) 0 0 !important;
		max-height: 70vh !important;
	}
	.modal.show .modal-dialog.modal-sm .modal-header,
	.modal.show .modal-dialog.msgprint-dialog .modal-header {
		border-radius: var(--r-lg) var(--r-lg) 0 0 !important;
	}
	/* Small dialogs keep their footer visible */
	.modal.show .modal-dialog.modal-sm .modal-footer,
	.modal.show .modal-dialog.msgprint-dialog .modal-footer {
		display: flex !important;
		border-radius: 0 !important;
		padding-bottom: calc(10px + env(safe-area-inset-bottom)) !important;
	}
}

/* ── Dropdowns ── */
.dropdown-menu {
	background-color: var(--maktab-cream) !important;
	border: 1px solid var(--maktab-border) !important;
	border-radius: var(--r-md) !important;
	box-shadow: var(--maktab-shadow-hover) !important;
}

.dropdown-item:hover {
	background-color: var(--maktab-straw) !important;
	color: var(--maktab-text) !important;
}

/* ── Workspace / Modules page ── */
.module-links .module-link {
	border: 1px solid var(--maktab-border) !important;
	border-radius: var(--maktab-radius) !important;
	background-color: var(--maktab-cream) !important;
}

.module-links .module-link:hover {
	background-color: var(--maktab-straw) !important;
}

/* ── Login Page Overrides ── */
.page-card {
	background: var(--maktab-cream) !important;
	border: 1px solid var(--maktab-border) !important;
	border-radius: var(--r-lg) !important;
	box-shadow: none !important;
}

.page-card .page-card-head {
	background: transparent !important;
	border-bottom: 1px solid var(--maktab-border) !important;
}

.page-card .page-card-head .page-card-title {
	display: none !important;
}

/* Login page body */
/* Login page — fit to viewport, extend into Safari safe areas */
html[data-path="login"],
html:has(body[data-path="login"]) {
	background: var(--maktab-beige, var(--beige)) !important;
}

body[data-path="login"] {
	overflow-x: hidden !important;
	background: var(--maktab-beige, var(--beige)) !important;
}

body[data-path="login"] #page-login {
	min-height: 100vh !important;
	min-height: 100dvh !important;
	display: flex !important;
	justify-content: center !important;
	align-items: center !important;
	padding: 0 !important;
	margin: 0 !important;
}

body[data-path="login"] #page-login .page-content-wrapper {
	width: 100% !important;
	max-width: 100vw !important;
	padding: 0 !important;
	margin: 0 !important;
}

body[data-path="login"] #page-login .container {
	width: 100% !important;
	max-width: 100% !important;
	padding: 0 20px !important;
	margin: 0 !important;
}

body[data-path="login"] #page-login .page_content {
	width: 100% !important;
}

/* Hide everything outside the login form */
body[data-path="login"] .navbar,
body[data-path="login"] .page-breadcrumbs,
body[data-path="login"] .page-header-wrapper,
body[data-path="login"] .for-signup,
body[data-path="login"] .for-forgot,
body[data-path="login"] footer {
	display: none !important;
}

/* Hide default "Login to ..." title */
.for-login > .page-card-head h4 {
	display: none !important;
}

/* Hide "or" divider and "Login with Email Link" */
.login-divider,
.login-with-email-link {
	display: none !important;
}

/* Hide "Powered by" footer and signup message */
.page-card .login-footer,
.page-card-body .or-section,
footer .pull-right,
.login-content .sign-up-message {
	display: none !important;
}

/* Login card */
body[data-path="login"] .login-content.page-card {
	width: 100% !important;
	box-sizing: border-box !important;
}

/* Login branding — brand name injected by maktab_login.js */
.maktab-login-brand {
	text-align: center;
	font-family: 'Cairo', sans-serif;
	font-size: 1.4rem;
	font-weight: 600;
	color: var(--maktab-text);
	padding: 8px 0 16px;
	letter-spacing: 0.5px;
}

/* Center the logo on login */
.for-login > .page-card-head {
	display: flex !important;
	flex-direction: column !important;
	align-items: center !important;
	padding-top: 20px !important;
	border-bottom: none !important;
}

.for-login > .page-card-head .app-logo {
	width: 80px !important;
	height: auto !important;
}

/* ── Scrollbars ── */
::-webkit-scrollbar {
	width: 8px;
	height: 8px;
}

::-webkit-scrollbar-track {
	background: var(--maktab-beige);
}

::-webkit-scrollbar-thumb {
	background: var(--maktab-sand);
	border-radius: var(--r-sm);
}

::-webkit-scrollbar-thumb:hover {
	background: var(--maktab-brown);
}

/* ── Awesomebar (search) ── */
.search-bar .awesomebar {
	background-color: rgba(255, 255, 255, 0.15) !important;
	border: 1px solid rgba(212, 197, 160, 0.3) !important;
	border-radius: var(--r-md) !important;
	color: var(--maktab-straw) !important;
}
/* Hide Frappe search bar on mobile (use per-page search instead) */
@media (max-width: 768px) {
	.navbar .search-bar,
	.navbar #navbar-search { display: none !important; }
}

.search-bar .awesomebar:focus {
	background-color: rgba(255, 255, 255, 0.25) !important;
	border-color: var(--maktab-sand) !important;
}

.search-bar .awesomebar::placeholder {
	color: rgba(212, 197, 160, 0.6) !important;
}

/* ── Frappe-specific overrides ── */
.frappe-control .like-disabled-input {
	background-color: var(--maktab-beige) !important;
}

.comment-box .ql-editor {
	background-color: var(--maktab-white) !important;
}

/* Timeline */
.timeline-item {
	border-color: var(--maktab-border) !important;
}

/* ── Print-friendly ── */
@media print {
	body {
		background: white !important;
		color: black !important;
	}

	.navbar, .body-sidebar, .page-head .page-actions {
		display: none !important;
	}

	.table th {
		background-color: #f0f0f0 !important;
		-webkit-print-color-adjust: exact;
		print-color-adjust: exact;
	}
}

/* ── Mobile Responsive ── */
@media (max-width: 768px) {
	.wasi-dashboard-container .card,
	.maktab-card {
		margin-bottom: 12px;
	}

	.thilth-report .col-md-2 {
		flex: 0 0 50%;
		max-width: 50%;
		margin-bottom: 8px;
	}

	.section-head {
		font-size: 0.95rem !important;
	}

	/* Bigger touch targets for form/modal buttons only.
	   Exclude .icon-btn — icon buttons are 28×28 and 16px horizontal padding
	   squeezes their svg to 0 width (close X disappeared on mobile dialogs). */
	.form-section .btn:not(.icon-btn),
	.modal-content .btn:not(.icon-btn),
	.maktab-wrapper .btn:not(.icon-btn) {
		min-height: 44px;
		padding: 8px 16px !important;
	}

	/* 16px minimum on ALL inputs prevents iOS auto-zoom on focus */
	.frappe-control input,
	.frappe-control select,
	.frappe-control textarea,
	.maktab-list-search-input,
	.lv-search-input,
	input[type="search"],
	input[type="text"],
	input[type="number"],
	input[type="date"],
	input[type="email"],
	input[type="tel"],
	select,
	textarea {
		min-height: 44px;
		font-size: 16px !important;
	}
}

/* ── Home Page Wrapper ── */
.maktab-wrapper {
	padding: 20px;
}
@media (max-width: 768px) {
	.maktab-wrapper {
		padding: 8px 12px 30px;
	}
}

.maktab-header {
	margin-bottom: 24px;
}

.maktab-header h2 {
	color: var(--maktab-text);
	font-weight: 700;
	margin-bottom: 4px;
}

.maktab-header .maktab-subtitle {
	color: var(--maktab-text-muted);
	font-size: 0.9rem;
	margin: 0;
}

/* ── Home page action cards ── */
.maktab-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 16px;
	padding: 16px 0;
	/* CLS reserve removed — forced min-height caused unnecessary vertical scroll */
	min-height: auto;
}

/* Reserve space on the parent .main-section so the root container doesn't
   grow as our custom home/list pages fill in their content. Fixes CLS. */
body.no-breadcrumbs .main-section,
.main-section {
	min-height: auto;
}

/* CLS reserve removed — forced min-height caused unnecessary vertical scroll */
.maktab-wrapper {
	min-height: auto;
}

.maktab-action-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 24px 16px;
	background: #F5EDE0;
	border: none;
	border-radius: 0;
	cursor: pointer;
	transition: all 0.2s ease;
	text-decoration: none !important;
	min-height: 140px;
}

.maktab-action-card:hover {
	box-shadow: none;
	transform: translateY(-2px);
}

.maktab-action-card .card-icon {
	font-size: 2rem;
	margin-bottom: 12px;
	color: var(--maktab-brown);
}

.maktab-action-card .card-title {
	font-size: 1rem;
	font-weight: 600;
	color: var(--maktab-text);
	margin-bottom: 4px;
	text-align: center;
}

.maktab-action-card .card-subtitle {
	font-size: 0.8rem;
	color: var(--maktab-text-muted);
	text-align: center;
}

.maktab-action-card .card-badge {
	margin-top: 8px;
	padding: 2px 10px;
	border-radius: var(--r-lg);
	font-size: 0.75rem;
	font-weight: 600;
}

.card-badge.badge-alert {
	/* WCAG AA: #8C3E28 on #F7E0D7 ≈ 5.3:1 */
	background-color: #F7E0D7;
	color: #8C3E28;
}

.card-badge.badge-ok {
	/* #2D5234 on #E0EAD9 ≈ 6.1:1 */
	background-color: #E0EAD9;
	color: #2D5234;
}

.card-badge.badge-info {
	/* #1F4A6B on #D8E7F1 ≈ 6.3:1 */
	background-color: #D8E7F1;
	color: #1F4A6B;
}

/* ── Home page dark mode ── */
[data-theme="dark"] .maktab-action-card {
	background: #2A2418;
	border-color: var(--straw);
}
[data-theme="dark"] .maktab-action-card:hover {
	background: #3A3020;
	border-color: var(--maktab-brown);
}
[data-theme="dark"] .maktab-action-card .card-title {
	color: #F5E6D3;
}
[data-theme="dark"] .maktab-action-card .card-icon {
	color: var(--maktab-brown);
}
[data-theme="dark"] .maktab-action-card .card-subtitle {
	color: var(--maktab-text-muted);
}
[data-theme="dark"] .maktab-wrapper h2,
[data-theme="dark"] .maktab-wrapper .maktab-subtitle {
	color: var(--maktab-text);
}

/* ── System Dark Mode splash screen ──
   Only applies before Frappe sets data-theme. Once data-theme is set,
   the [data-theme="dark"] rules above take over.
   IMPORTANT: do NOT override body/html background here — it would
   conflict with light mode when the system is dark but app is light. */
@media (prefers-color-scheme: dark) {
	/* The palm loading splash must show THROUGH to whatever page it's on, not
	   impose a color. Forcing var(--beige) here painted a CREAM box behind the
	   palm: on /login (medium-brown #4A3D32 body, no data-theme) --beige resolves
	   to its :root light value #F5F0E6 = cream, so OS-dark-mode users saw a cream
	   rectangle around the palm on the brown login bg. Transparent lets the palm
	   sit directly on the page bg (brown on login, themed on desk) while still
	   overriding Frappe's default dark splash (the black-splash FB this rule was
	   originally added for). */
	.splash {
		background: transparent !important;
		background-image: none !important;
	}
}

/* FB-106 / FB-2026-00210: user-selected dark theme splash — match the page
   bg (--beige in dark = #18130D) NOT --brown-night (#0F0C08, which is the
   sidebar bg). Using --brown-night made the splash render as a noticeably
   darker block than the body during the brief refresh-time window where
   data-theme=dark has been applied but the user hasn't fully painted yet.
   Tracking --beige means splash, body, and html all share one bg color. */
[data-theme="dark"] .splash,
[data-theme-mode="dark"] .splash {
	background: var(--beige) !important;
	background-image: none !important;
}

/* The Reconciliation Report block (RECONCILIATION REPORT + .recon-period /
   .recon-discrepancy / .recon-total-row + .text-green/.text-red/.text-amber)
   was removed 2026-06-03 in the v2 redesign — recon now ships its own
   page-scoped public/css/reconciliation_report.css (.recon-* div-grid,
   .recon-net--pos/neg + .recon-coll__pct.is-* tone-text, full-row
   .recon-row.has-disc tint). Those utilities were recon-only consumers. */

/* ══════════════════════════════════════════════
   MAKTAB LIST — Config-driven shared list page
   ══════════════════════════════════════════════ */

.maktab-list-page {
	max-width: 1200px;
	margin: 0 auto;
	padding: 16px 20px 40px;
}

/* ── Filters ── */
.maktab-filter-row {
	display: flex;
	gap: 12px;
	flex-wrap: wrap;
	margin-bottom: 16px;
	padding: 10px 14px;
	background: var(--maktab-cream);
	border-radius: var(--maktab-radius);
	border: 1px solid var(--maktab-border);
}
.maktab-filter-item {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 140px;
	flex: 1;
}
.maktab-filter-label {
	font-size: 11px;
	font-weight: 600;
	color: var(--maktab-text-muted);
	text-transform: uppercase;
	letter-spacing: 0.3px;
}
.maktab-filter-select,
.maktab-filter-input {
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	padding: 6px 10px;
	font-size: 13px;
	background: var(--control-bg);
	color: var(--maktab-text);
	font-family: inherit;
}
.maktab-filter-select:focus,
.maktab-filter-input:focus {
	outline: none;
	border-color: var(--maktab-brown);
	box-shadow: none;
}

/* ── Hide monitor/desk icon from breadcrumbs (pure CSS, no flash) ── */
.navbar-breadcrumbs li:has(> a[href="/desk"]) {
	display: none !important;
}
.navbar-breadcrumbs li:has(> a[href="/desk"]) + li a:before {
	content: none !important;
}
/* Page title injected by maktab.set_page_title */
.navbar-breadcrumbs li.maktab-page-title a {
	font-weight: 600;
	color: var(--maktab-dark-brown);
}
.navbar-breadcrumbs li.maktab-page-title a:before {
	content: none !important;
}

/* ── Table ── */
.maktab-table {
	width: 100%;
	border-collapse: collapse;
	background: transparent;
	overflow: hidden;
}
.maktab-table thead th {
	background: var(--maktab-beige);
	color: var(--maktab-brown);
	font-weight: 700;
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: 0.3px;
	padding: 10px 12px;
	border-bottom: 2px solid var(--maktab-sand);
	text-align: left;
	white-space: nowrap;
}
.maktab-table tbody td {
	padding: 10px 12px;
	border-bottom: 1px solid var(--maktab-border);
	font-size: 13px;
	vertical-align: middle;
	color: var(--maktab-text);
}
.maktab-table tbody tr:last-child td {
	border-bottom: none;
}

/* Row hover */
.maktab-row {
	cursor: pointer;
	transition: background-color 0.15s ease;
}
.maktab-row:hover {
	background: rgba(107, 79, 54, 0.06) !important;
}

/* Alternating row stripe — subtle */
.maktab-table tbody tr:nth-child(even) {
	background: var(--maktab-beige);
}

/* Row tinting — earthy terracotta/amber from Hasawi palette */
.maktab-row-critical {
	background: var(--bg-red) !important;
}
.maktab-row-warning {
	background: var(--bg-orange) !important;
}

/* ── Links ── */
.maktab-link {
	color: var(--maktab-brown);
	font-weight: 600;
	text-decoration: none;
}
.maktab-link:hover {
	color: var(--brown-deep);
	text-decoration: underline;
}
[data-theme="dark"] .maktab-link:hover { color: var(--sand); }

/* ── Pills (reuse Hasawi palette) ── */
.maktab-pill {
	display: inline-block;
	font-weight: 700;
	font-size: 0.72rem;
	padding: 3px 10px;
	border-radius: var(--r-lg);
	line-height: 1.4;
	white-space: nowrap;
}
.maktab-pill-green  { background: var(--bg-green);  color: var(--text-on-green); }
.maktab-pill-orange { background: var(--bg-orange); color: var(--text-on-orange); }
.maktab-pill-red    { background: var(--bg-red);    color: var(--text-on-red); }
.maktab-pill-grey   { background: var(--bg-grey);   color: var(--text-on-grey); }
.maktab-pill-blue   { background: var(--bg-blue);   color: var(--text-on-blue); }

/* ── Number highlights ── */
.maktab-num-critical { color: var(--text-on-red); }
.maktab-num-warning  { color: var(--text-on-orange); }
.maktab-num-ok       { color: var(--text-on-green); }

/* ── Currency ── */
.maktab-currency {
	font-weight: 600;
	white-space: nowrap;
}

/* ── Pagination ── */
.maktab-pagination {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 12px 0;
}
.maktab-pagination-info {
	font-size: 13px;
	color: var(--maktab-text-muted);
	padding: 12px 0;
}
.maktab-pagination-buttons {
	display: flex;
	gap: 8px;
}
.maktab-pagination-btn {
	background: var(--maktab-cream);
	color: var(--maktab-brown);
	border: 1px solid var(--maktab-sand);
	border-radius: var(--r-md);
	padding: 6px 16px;
	font-weight: 600;
	font-size: 13px;
	cursor: pointer;
}
.maktab-pagination-btn:hover {
	background: var(--maktab-beige);
	border-color: var(--maktab-brown);
}

/* ── Column priority — responsive hiding ── */
/* Priority 3: desktop only */
@media (max-width: 1200px) {
	.maktab-col-p3 { display: none; }
}

/* ── Mobile: card layout ── */
@media (max-width: 768px) {
	.maktab-list-page {
		padding: 10px;
	}
	.maktab-filter-row {
		flex-direction: column;
		gap: 8px;
	}
	.maktab-filter-item {
		min-width: 0;
	}

	/* Hide table header */
	.maktab-table thead {
		display: none;
	}
	.maktab-table,
	.maktab-table tbody,
	.maktab-table tr,
	.maktab-table td {
		display: block;
		width: 100%;
	}
	.maktab-table {
		background: transparent !important;
		border: none;
	}
	.maktab-table tbody tr {
		margin-bottom: 10px;
		border-radius: var(--maktab-radius);
		border: 1px solid var(--maktab-border);
		overflow: hidden;
		background: var(--maktab-cream);
		box-shadow: var(--maktab-shadow);
	}
	.maktab-table tbody td {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 8px 14px;
		border-bottom: 1px solid var(--maktab-border);
		font-size: 13px;
		min-height: 44px; /* Touch target */
	}
	.maktab-table tbody td::before {
		content: attr(data-label);
		font-weight: 600;
		color: var(--maktab-text-muted);
		font-size: 12px;
		margin-right: 12px;
		flex-shrink: 0;
	}
	.maktab-table tbody td:last-child {
		border-bottom: none;
	}
	/* Add button right padding on mobile */
	.page-container[data-page-container="maktab-list"] .page-head .page-actions {
		padding-right: 10px;
	}
	/* Priority 2: hidden on mobile, shown when expanded */
	.maktab-col-p2 {
		display: none;
	}
	.maktab-expanded .maktab-col-p2 {
		display: flex;
	}
	/* Add expand indicator on first cell */
	.maktab-table tbody tr td:first-child::after {
		content: '▸';
		color: var(--maktab-text-muted);
		font-size: 14px;
		margin-left: 8px;
		transition: transform 0.2s ease;
	}
	.maktab-expanded td:first-child::after {
		content: '▾';
	}
	/* Pagination */
	.maktab-pagination {
		flex-direction: column;
		gap: 8px;
		text-align: center;
	}
}

/* ── Dark mode ── */
[data-theme="dark"] .maktab-table {
	background: var(--maktab-cream);
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-table thead th {
	background: var(--maktab-dark-brown);
	color: var(--maktab-straw);
	border-color: var(--maktab-sand);
}
[data-theme="dark"] .maktab-table tbody td {
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-row:hover {
	background: rgba(212, 197, 160, 0.08) !important;
}
[data-theme="dark"] .maktab-link {
	color: var(--maktab-straw);
}
[data-theme="dark"] .maktab-row-critical {
	background: rgba(212, 138, 116, 0.15) !important;
}
[data-theme="dark"] .maktab-row-warning {
	background: rgba(224, 176, 106, 0.12) !important;
}
[data-theme="dark"] .maktab-filter-row {
	background: var(--maktab-cream);
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-filter-select,
[data-theme="dark"] .maktab-filter-input {
	background: var(--control-bg);
	border-color: var(--maktab-border);
	color: var(--maktab-text);
}
[data-theme="dark"] .maktab-pagination-btn {
	background: var(--maktab-cream);
	color: var(--maktab-straw);
	border-color: var(--maktab-sand);
}
@media (max-width: 768px) {
	[data-theme="dark"] .maktab-table tbody tr {
		background: var(--maktab-cream);
		border-color: var(--maktab-border);
	}
}

/* ===== Utility helpers ========================================
   Tiny single-purpose classes safe to use anywhere.
   - .f-text-muted: secondary text colour token
   - .f-italic: italic emphasis (used for "absence" labels like "No role")
*/
.f-text-muted { color: var(--ink-muted); }
.f-italic { font-style: italic; }

/* ===== Rent Collection (Phase 3 Stage 5 — modernized) =========
   2B-aesthetic rebuild. .rc-* namespace (no v2 suffix — this IS v2).
   Built on tokens.css + components.css + eh-pg-head atom (from
   components.css). Mock source: phase3-handoff/mockups/
   rent-collection-modernized.css.

   NOTE: The full vanilla port of this page's CSS now ships verbatim from
   rent-collection-modernized.css (loaded AFTER maktab.css → wins the
   cascade). The bulk of the .rc-* rules that used to live here were dead
   duplicates and have been removed. What remains below is ONLY the
   uniquely-live residue: rules that rcm does NOT define but the live
   page / controller still depends on (the route chrome-hide, the
   .rc-page* shell, .rc-page__content responsive padding) plus the
   [data-theme] dark overrides (rcm carries no dark .rc-* rules) and the
   handful of selectors emitted by the live controller markup
   (.rc-card--due-soon, .rc-card__name-link, .rc-tag,
   .rc-unit__label-link, .rc-unit__notes--crit/--warn).
   ============================================================== */

.rc-page {
	/* Live container — body has page-bg (--beige); cards use --cream. */
	min-height: 100vh;
	font-family: var(--font-ar);
	color: var(--ink);
}

.rc-page__content {
	max-width: 1280px;
	margin-inline: auto;
	padding: var(--s-5) var(--s-6) var(--s-8);
	display: flex; flex-direction: column;
	gap: var(--s-5);
}

/* Hide Frappe's default page-head/breadcrumb chrome on the rent-collection
   page — our custom .rc-page__head replaces it. Same pattern as
   FB-2026-00050 for the home page. rcm depends on this rule (it does not
   define it) — KEEP. */
body[data-route^="rent-collection"] .page-head,
body[data-route^="rent-collection"] .page-title {
	display: none !important;
}

/* Page head — overrides the bare eh-pg-head atom border-radius/padding
   so it integrates with the page padding above. */
.rc-page__head {
	margin-bottom: 0;
}

.rc-page__title {
	font-size: var(--text-3xl);
	font-weight: 600;
	color: var(--brown-deep);
	margin: 0;
	line-height: 1.2;
}
[data-theme="dark"] .rc-page__title { color: var(--ink); }

.rc-page__sub {
	font-size: var(--text-sm);
	color: var(--ink-muted);
}

.rc-page__actions { display: flex; gap: var(--s-2); align-items: center; }

/* ─── KPI / card dark overrides (rcm ships no dark .rc-* rules) ── */
[data-theme="dark"] .rc-kpi__value { color: var(--ink); }
[data-theme="dark"] .rc-kpi--crit .rc-kpi__value { color: var(--crit); }

/* ─── Tenant card: live-emitted accent + name link ─────────────── */

[data-theme="dark"] .rc-card__name { color: var(--ink); }

.rc-card__name-link {
	color: inherit;
	text-decoration: none;
}
.rc-card__name-link:hover { color: var(--maktab-link); }

.rc-tag {
	font-family: var(--font-en);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.08em;
	padding: 2px 6px;
	background: var(--straw);
	color: var(--brown-deep);
	border-radius: 2px;
}

[data-theme="dark"] .rc-contact__phone { color: var(--ink); }

[data-theme="dark"] .rc-card__credit b { color: var(--ink); }

/* ─── Unit row: live-emitted label link + notes variants ───────── */
.rc-unit__label-link {
	text-decoration: none;
	color: inherit;
}
.rc-unit__label-link:hover { color: var(--maktab-link); }

[data-theme="dark"] .rc-unit__label { color: var(--ink); }

[data-theme="dark"] .rc-unit__v--big { color: var(--ink); }

[data-theme="dark"] .rc-unit__notes { color: var(--basil-flower); }
.rc-unit__notes--crit { background: var(--crit-bg); color: var(--overdue); font-style: normal; }
.rc-unit__notes--warn { background: var(--warn-bg, #fff3d6); color: var(--warn-deep, #aa7600); font-style: normal; }

/* ─── History dark overrides (rcm ships no dark .rc-* rules) ───── */
[data-theme="dark"] .rc-history__title { color: var(--ink); }
[data-theme="dark"] .rc-history__total b { color: var(--ink); }
[data-theme="dark"] .rc-history__amount { color: var(--ink); }

/* ─── Responsive ────────────────────────────────────────────── */

@media (max-width: 960px) {
	.rc-kpis { grid-template-columns: repeat(2, 1fr); }
	.rc-card__head { flex-direction: column; gap: var(--s-3); }
	.rc-unit__grid { grid-template-columns: 1fr 1fr; }
	.rc-filters__search { min-width: 0; width: 100%; order: -1; }
	.rc-page__content { padding: var(--s-3) var(--s-3) var(--s-8); }
}

@media (max-width: 480px) {
	.rc-kpis { grid-template-columns: 1fr; }
	.rc-unit__grid { grid-template-columns: 1fr; }
	.rc-history__row { grid-template-columns: auto 1fr auto; }
	.rc-history__row .rc-history__view { grid-column: 1 / -1; justify-self: end; margin-top: 2px; }
}

/* ─── Loading skeleton (preserved + shape-matched to new layout) ── */

.skel {
	background: linear-gradient(
		90deg,
		var(--straw) 0%,
		rgba(255, 255, 255, 0.55) 50%,
		var(--straw) 100%
	);
	background-size: 200% 100%;
	animation: skel-shimmer 1.4s linear infinite;
	border-radius: var(--r-sm);
	height: 14px;
}
[data-theme="dark"] .skel {
	background: linear-gradient(
		90deg,
		rgba(212, 197, 160, 0.18) 0%,
		rgba(212, 197, 160, 0.45) 50%,
		rgba(212, 197, 160, 0.18) 100%
	);
}
@keyframes skel-shimmer {
	0% { background-position: 200% 0; }
	100% { background-position: -200% 0; }
}
/* ═══════════════════════════════════════════
   Lease View — Custom lease detail page
   ═══════════════════════════════════════════ */

/* Dead container selectors removed 2026-06 (pages deleted/folded, 0 emitters):
   payments-list / units-list / collectors-list / collector-view /
   households-list / expenses-list. See docs/SURFACE_RECONCILIATION.md. */
.lease-view-container, .tenant-view-container, .property-view-container,
.payment-view-container,
.unit-view-container, .maintenance-view-container,
.leases-list-container, .properties-list-container, .tenants-list-container,
.staff-list-container, .vehicles-list-container,
.doc-view-container {
	max-width: 1100px; margin: 0 auto; padding: 16px 20px 40px;
	container-type: inline-size;
}
@media (max-width: 768px) {
	.lease-view-container, .tenant-view-container, .property-view-container,
	.payment-view-container,
	.unit-view-container, .maintenance-view-container,
	.leases-list-container, .properties-list-container, .tenants-list-container,
	.staff-list-container, .vehicles-list-container,
	.doc-view-container { padding: 8px 12px 30px; }
}

/* Status bar */
/* Edit toolbar */
.lv-toolbar {
	display: flex;
	gap: 8px;
	padding: 4px 16px;
	margin-bottom: 4px;
	max-width: 900px;
	margin-left: auto;
	margin-right: auto;
}
.lv-toolbar-btn {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 5px 12px;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	background: transparent;
	color: var(--maktab-text);
	font-size: 13px;
	cursor: pointer;
	transition: background 0.15s;
}
.lv-toolbar-btn:hover { background: rgba(139,125,107,0.08); }
.lv-toolbar-btn svg { opacity: 0.7; }
.lv-delete-btn { color: var(--overdue); border-color: var(--overdue); }
.lv-delete-btn:hover { background: rgba(139,58,37,0.08); }
.lv-archive-active { color: var(--sand-deep); border-color: var(--sand-deep); }
.lv-archive-active:hover { background: rgba(139,105,20,0.08); }
.lv-cancel-btn { color: var(--sand-deep); border-color: var(--sand-deep); }
.lv-cancel-btn:hover { background: rgba(139,105,20,0.08); }
.lv-amend-btn { color: #6B8F71; border-color: #6B8F71; }
.lv-amend-btn:hover { background: rgba(107,143,113,0.08); }
[data-theme="dark"] .lv-cancel-btn { color: #E0B06A; border-color: #E0B06A; }
[data-theme="dark"] .lv-amend-btn { color: #A8D4A0; border-color: #A8D4A0; }

/* Per-page list search */
/* List-page toolbar row: + New button sits beside the search wrapper. When
   both are rendered on the same page (via attach_new_button + attach_list_search)
   they appear side-by-side on desktop and stack on narrow screens. */
.lv-new-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 8px 14px;
	height: 38px;
	background: var(--maktab-brown);
	color: #fff;
	border: 1px solid var(--maktab-brown);
	border-radius: var(--r-md);
	font-size: 13px;
	font-weight: 600;
	font-family: inherit;
	cursor: pointer;
	margin: 0 0 16px 0;
	transition: background 0.15s;
	white-space: nowrap;
}
.lv-new-btn:hover { background: #3a2f23; }  /* literal — brown-deep flips in dark, but :11090 sidebar scope-lock doesn't apply here; dark sister rule at :4349 already handles dark */
.lv-new-btn:focus-visible { outline: 2px solid var(--maktab-amber); outline-offset: 2px; }
.lv-new-btn svg { flex-shrink: 0; }
/* When the + New button is immediately followed by a search wrap, pair them
   into a toolbar row on desktop. */
.lv-new-btn + .lv-search-wrap {
	flex: 1;
	min-width: 0;
}
.lv-new-btn + .lv-search-wrap,
.lv-search-wrap:has(+ .lv-new-btn) {
	display: inline-flex;
}
/* Toolbar row wrapper — created by JS when we have both buttons + search */
.lv-list-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin: 0 0 16px 0;
}
.lv-list-toolbar .lv-new-btn,
.lv-list-toolbar .lv-search-wrap {
	margin: 0;
}
.lv-list-toolbar .lv-search-wrap {
	flex: 1;
	min-width: 240px;
}
[data-theme="dark"] .lv-new-btn {
	background: var(--maktab-brown);
	color: var(--maktab-cream);
}
[data-theme="dark"] .lv-new-btn:hover {
	background: #8B6F4C;
}

.lv-search-wrap {
	position: relative;
	margin: 0 0 16px 0;
	display: flex;
	align-items: center;
}
.lv-search-icon {
	position: absolute;
	inset-inline-start: 12px;
	color: var(--maktab-text-muted);
	pointer-events: none;
}
.lv-search-input {
	width: 100%;
	height: 38px;
	padding: 0 14px 0 38px;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	background: var(--card-bg, #fff);
	color: var(--maktab-text);
	font-size: 13px;
	transition: border-color 0.15s;
}
[dir="rtl"] .lv-search-input { padding: 10px 38px 10px 14px; }
.lv-search-input:focus {
	outline: none;
	border-color: var(--maktab-brown);
}
.lv-search-input::placeholder { color: var(--maktab-text-muted); }
.lv-search-clear {
	position: absolute;
	inset-inline-end: 10px;
	background: none;
	border: none;
	font-size: 20px;
	color: var(--maktab-text-muted);
	cursor: pointer;
	line-height: 1;
	padding: 0 6px;
}
.lv-search-clear:hover { color: var(--maktab-text); }

/* Documents card header (title + actions on same row) */
.lv-doc-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.lv-doc-header .lv-card-title { margin-bottom: 0; }
.lv-doc-header-actions { display: flex; gap: 6px; }
.lv-doc-header-actions .lv-toolbar-btn { padding: 4px 10px; font-size: 12px; }
.lv-show-archived-btn { padding: 4px 8px !important; }
.lv-show-archived-btn.lv-archive-active { background: rgba(139,105,20,0.15); color: var(--sand-deep); border-color: var(--sand-deep); }

.lv-attachment-row { position: relative; }
.lv-doc-menu-btn {
	background: transparent;
	border: none;
	color: var(--ink-muted);
	font-size: 18px;
	cursor: pointer;
	padding: 0 6px;
	margin-inline-start: 4px;
	line-height: 1;
}
.lv-doc-menu-btn:hover { color: var(--maktab-text); }
.lv-doc-archived { opacity: 0.55; font-style: italic; }
.lv-doc-archived .lv-file-link::after { content: ' (' attr(data-archived-label) ')'; font-size: 10px; color: var(--sand-deep); }

/* Primary receipt — small inline badge after filename. The row gets a subtle
   left border (in LTR) / right border (in RTL) to reinforce that this
   attachment is the canonical receipt for the MTX. */
.lv-receipt-badge {
	display: inline-block;
	margin-inline-start: 6px;
	padding: 1px 6px;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	background: rgba(139,105,20,0.14);
	color: var(--sand-deep);
	border-radius: 4px;
	vertical-align: middle;
}
/* FB-2026-00296: the inline-start accent border on a primary receipt
   document looked like a stray vertical line on the left of the
   payment-view DOCUMENTS section. The "RECEIPT" badge next to the
   filename is the canonical indicator — drop the redundant chrome. */
.lv-doc-primary-receipt { /* receipt status indicated by .lv-receipt-badge */ }

.lv-doc-menu {
	background: #fff;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	box-shadow: none;
	min-width: 140px;
	padding: 4px 0;
}
.lv-doc-menu-item {
	display: block;
	width: 100%;
	background: none;
	border: none;
	text-align: start;
	padding: 8px 14px;
	font-size: 13px;
	cursor: pointer;
	color: var(--maktab-text);
}
.lv-doc-menu-item:hover { background: rgba(139,125,107,0.08); }
.lv-doc-menu-danger { color: var(--crit); }
[data-theme="dark"] .lv-doc-menu { background: #2A2418; border-color: var(--straw); box-shadow: none; }
[data-theme="dark"] .lv-doc-menu-item { color: var(--straw); }
[data-theme="dark"] .lv-doc-menu-item:hover { background: rgba(255,255,255,0.06); }
[data-theme="dark"] .lv-doc-menu-danger { color: #D48A74; }
[data-theme="dark"] .lv-doc-menu-btn { color: #9A8A7A; }
[data-theme="dark"] .lv-doc-menu-btn:hover { color: var(--straw); }

/* Collapsible sections (W3-W5) */
.lv-collapsible-title {
	cursor: pointer;
	user-select: none;
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 4px 0;
}
.lv-collapsible-title > span:first-child {
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.4px;
	font-size: 12px;
	color: var(--maktab-text-muted);
}
.lv-meta-summary {
	font-size: 12px;
	font-weight: 500;
	color: var(--maktab-text-muted);
	flex: 1 1 auto;
	min-width: 0;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	text-transform: none;
	letter-spacing: 0;
}
/* Hide the header summary when the card is expanded — user doesn't need
   "X changes · 2 days ago" next to "Activity" when the full list is visible. */
.lv-card.lv-expanded .lv-meta-summary { display: none; }

.lv-meta-inline { font-weight: 400; font-size: 12px; color: var(--maktab-text-muted); }

/* Bigger, more visible collapse arrow. Rotates on expand instead of swapping
   between ▸ and ▾ so it's smoother. Text is still ▸/▾ for fallback. */
.lv-collapse-icon {
	font-size: 22px;
	line-height: 1;
	color: var(--maktab-text-muted);
	margin-inline-start: auto;
	transition: transform 0.15s;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	flex-shrink: 0;
	cursor: pointer;
}
[dir="rtl"] .lv-collapse-icon {
	margin-inline-start: auto;
}
[data-theme="dark"] .lv-meta-summary,
[data-theme="dark"] .lv-meta-inline { color: var(--maktab-text-muted); }

/* Icon-only buttons used in Documents card header (Upload, Show archived) */
.lv-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	background: transparent;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	color: var(--maktab-text-muted);
	cursor: pointer;
}
.lv-icon-btn:hover {
	background: rgba(212, 197, 160, 0.10);
	color: var(--maktab-text);
	border-color: var(--maktab-sand);
}
.lv-icon-btn.lv-archive-active {
	background: rgba(139, 105, 20, 0.15);
	color: var(--sand-deep);
	border-color: var(--sand-deep);
}
.lv-icon-btn:focus-visible { outline: 2px solid var(--maktab-amber); outline-offset: 2px; }
[data-theme="dark"] .lv-icon-btn {
	border-color: var(--maktab-sand);
	color: var(--maktab-text);
}
[data-theme="dark"] .lv-icon-btn:hover {
	background: rgba(212, 197, 160, 0.08);
	border-color: var(--maktab-sand);
}
.lv-doc-header-actions {
	display: flex;
	gap: 6px;
	align-items: center;
	margin-inline-start: auto;
	flex-shrink: 0;
}
.lv-collapsible-title:has(.lv-doc-header-actions) .lv-collapse-icon {
	margin-inline-start: 0;
}

/* ── Row-level 3-dot menu button (shared: documents, comments, contacts) */
.lv-row-menu-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	padding: 0;
	background: transparent;
	border: none;
	border-radius: var(--r-md);
	color: var(--maktab-text-muted);
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	font-weight: bold;
	flex-shrink: 0;
}
.lv-row-menu-btn:hover {
	background: rgba(212, 197, 160, 0.15);
	color: var(--maktab-text);
}
.lv-row-menu-btn:focus-visible { outline: 2px solid var(--maktab-amber); outline-offset: 2px; }
[data-theme="dark"] .lv-row-menu-btn { color: var(--maktab-straw); }
[data-theme="dark"] .lv-row-menu-btn:hover { background: rgba(212, 197, 160, 0.10); }

/* Floating row menu (used by show_row_menu helper) */
.maktab-row-menu {
	position: fixed;
	background: #fff;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	box-shadow: none;
	min-width: 140px;
	padding: 4px;
	z-index: 10000;
	display: flex;
	flex-direction: column;
	gap: 2px;
}
.maktab-row-menu-item {
	display: block;
	width: 100%;
	padding: 8px 14px;
	background: transparent;
	border: none;
	border-radius: var(--r-sm);
	text-align: start;
	font-size: 13px;
	color: var(--maktab-text);
	cursor: pointer;
	font-family: inherit;
}
.maktab-row-menu-item:hover {
	background: rgba(212, 197, 160, 0.20);
}
.maktab-row-menu-item.maktab-row-menu-danger { color: var(--overdue); }
.maktab-row-menu-item.maktab-row-menu-danger:hover { background: rgba(139, 58, 37, 0.10); }
.maktab-row-menu-item.maktab-row-menu-disabled {
	color: var(--maktab-text-muted);
	cursor: not-allowed;
	opacity: 0.5;
}
[data-theme="dark"] .maktab-row-menu {
	background: #24201A;
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-row-menu-item { color: var(--maktab-text); }
[data-theme="dark"] .maktab-row-menu-item:hover { background: rgba(212, 197, 160, 0.12); }
[data-theme="dark"] .maktab-row-menu-item.maktab-row-menu-danger { color: #E8A890; }
[data-theme="dark"] .maktab-row-menu-item.maktab-row-menu-danger:hover { background: rgba(212, 138, 116, 0.18); }

/* Document attachment row — 3-dot menu on the right, file name left, meta middle */
.lv-attachment-row {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 0;
	/* FB-117: removed border-bottom — padding alone provides separation */
}
.lv-attachment-row .lv-file-link {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	color: var(--maktab-link);
	text-decoration: none;
	font-size: 13px;
	font-weight: 500;
	/* FB-2026-00246: kill stray underline inherited from the stacked-list
	   .lv-file-link rule (line ~4468). Attachment rows have their own
	   spacing via flex; no per-row border needed. */
	border-bottom: none;
}
.lv-attachment-row .lv-file-link:hover { text-decoration: underline; }
.lv-attachment-row .lv-attachment-meta {
	flex: 0 0 auto;
	font-size: 11px;
	color: var(--ink-muted);
	white-space: nowrap;
}
/* The 3-dot button in the attachment row — same class as elsewhere */
.lv-attachment-row .lv-doc-menu-btn {
	width: 26px;
	height: 26px;
	padding: 0;
	background: transparent;
	border: none;
	border-radius: var(--r-md);
	color: var(--maktab-text-muted);
	cursor: pointer;
	font-size: 18px;
	line-height: 1;
	font-weight: bold;
	flex-shrink: 0;
}
.lv-attachment-row .lv-doc-menu-btn:hover {
	background: rgba(212, 197, 160, 0.15);
	color: var(--maktab-text);
}

/* Comment row — 3-dot menu in the header */
.lv-comment { position: relative; }
.lv-comment-header {
	display: flex;
	align-items: center;
	gap: 8px;
}
.lv-comment-header .lv-comment-author { flex: 1 1 auto; min-width: 0; }
.lv-comment-header .lv-comment-time { margin-inline-start: auto; }
.lv-comment-header .lv-row-menu-btn { margin-inline-start: 6px; }

/* Space below the Activity card so it's not cramped against the next element */
.lv-side > .lv-card:last-child,
.lv-main > .lv-card:last-child {
	margin-bottom: 20px;
}
.lv-activity-card:last-child { padding-bottom: 20px; }

/* Detail view two-column layout: both columns should be independent.
   The left column is the main content (title, info, lease list). The right
   column is the sidebar (notes, contacts, documents, comments, activity).
   Use align-items:flex-start so each column takes its natural height. */
.lv-columns {
	display: grid;
	/* Side column is a fixed 380px track — it never shrinks in 2-col
	   mode. Main column absorbs all the flexibility (minmax 280px…1fr).
	   When main can no longer fit ≥280px next to the 380px side, the
	   JS ResizeObserver swaps the grid to a single 1fr column. */
	grid-template-columns: minmax(280px, 1fr) 380px;
	gap: 20px;
	align-items: start;
	padding: 16px 20px 28px;
	max-width: 900px;
	margin: 0 auto;
}
.lv-main, .lv-side { min-width: 0; }

/* Stack when .lv-columns itself gets narrow. A JS ResizeObserver
   (maktab.watch_detail_columns) toggles .lv-stacked on every resize,
   which is more reliable than Safari's viewport media queries or
   container queries — it fires on the exact element we care about,
   including when the content area reflows without a viewport change. */
.lv-columns.lv-stacked {
	grid-template-columns: 1fr;
	padding: 14px 16px 24px;
	max-width: none;
}
.lv-columns.lv-stacked .lv-main,
.lv-columns.lv-stacked .lv-side { max-width: none; }

/* First-paint guard: on mobile viewports the JS toggler hasn't added
   .lv-stacked yet, so the browser would briefly render the 660px-minimum
   2-col grid and flash a wrong layout. Force single-column via media
   query so the first paint is already correct. JS still runs and keeps
   behaviour consistent on resize. */
@media (max-width: 768px) {
	.lv-columns {
		grid-template-columns: 1fr;
		padding: 14px 16px 24px;
		max-width: none;
	}
	.lv-columns .lv-main,
	.lv-columns .lv-side { max-width: none; }
}

/* Prevent currency values like "30,000.00 ر.س / year" from wrapping
   the unit suffix to a second line. The real problem is that
   frappe.format() wraps currency in a <div> (block) — even with
   white-space:nowrap on the parent, a block child forces line breaks.
   Flattening the div to inline lets the whole value stay on one line. */
.lv-row .lv-value { white-space: nowrap; }
.lv-row .lv-value > div { display: inline; }
/* FB-117: keep file name, meta, and 3-dot menu on a single row even on mobile.
   The duplicate .lv-attachment-row + mobile column-flex rules that used to
   live here have been removed — the canonical rules at ~line 4457 already
   handle layout correctly with flex-row + ellipsis. */
.lv-attachment-info { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }
.lv-attachment-info .lv-file-link { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lv-comment { padding: 10px 0; border-bottom: 1px solid rgba(139,125,107,0.08); }
.lv-comment:last-child { border-bottom: none; }
.lv-comment-header { display: flex; justify-content: space-between; margin-bottom: 4px; }
.lv-comment-author { font-weight: 600; font-size: 13px; color: var(--maktab-text); }
.lv-comment-time { font-size: 11px; color: #A09080; }
.lv-comment-content { font-size: 13px; color: var(--maktab-text); white-space: pre-line; }
.lv-comment-input-wrap { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.lv-comment-input { width: 100%; box-sizing: border-box; border: 1px solid var(--maktab-border); border-radius: var(--r-md); padding: 6px 10px; font-size: 13px; resize: vertical; background: transparent; color: var(--maktab-text); }
.lv-comment-post-btn { width: 100%; padding: 8px 12px; border-radius: var(--r-md); background: var(--maktab-brown); color: #fff; border: none; font-size: 13px; font-weight: 600; cursor: pointer; }
.lv-activity-entry { padding: 8px 0; border-bottom: 1px solid rgba(139,125,107,0.08); }
.lv-activity-entry:last-child { border-bottom: none; }
.lv-activity-header { display: flex; justify-content: space-between; margin-bottom: 4px; }
.lv-activity-change { font-size: 12px; color: var(--ink-muted); padding: 2px 0; }
.lv-activity-field { font-weight: 600; }
.lv-activity-old { text-decoration: line-through; color: var(--crit); }
.lv-activity-new { color: #6B8F71; }

.lv-status-bar {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 10px 16px;
	border-radius: 0;
	margin-bottom: 16px;
	font-size: 14px;
	max-width: 900px;
	margin-left: auto;
	margin-right: auto;
}
.lv-status-label { font-weight: 700; }
.lv-status-detail { color: inherit; opacity: 1; }
.lv-status-active { background: #E5EFE0; color: #3A5F3A; }
.lv-status-expired { background: #F5E0D0; color: #7A4E2D; }
.lv-status-terminated { background: #F0E6F6; color: #6B3FA0; }
.lv-status-pending { background: #F8F0E0; color: #5C4510; }
.lv-status-thilth { background: #E5EFE0; color: #3A5F3A; }
.lv-status-khums { background: #F0E6F6; color: #6B3FA0; }
.lv-unit-occupied { color: #3A5F3A; font-weight: 600; }
.lv-unit-vacant { color: var(--ink-muted); }
.lv-text-muted { color: var(--ink-muted); }
.lv-empty { text-align: center; padding: 20px; color: var(--ink-muted); }

/* (Two-column layout rules are defined at ~line 3451 — single source of truth) */

/* Cards */
.lv-card {
	background: transparent;
	border: none;
	border-bottom: 1px solid var(--maktab-border);
	padding: 16px;
	margin-bottom: 0;
}
.lv-card:last-child { border-bottom: none; }

/* Summary cards on list pages — filled backgrounds, no outlines */
.ll-summary-card.lv-card, .prl-summary-card.lv-card, .tl-summary-card.lv-card,
.ul-summary-card.lv-card, .pl-summary-card.lv-card {
	background: #F5EDE0;
	border: none;
	border-bottom: none;
	border-radius: 0;
	padding: 16px;
}
/* Table wrapper card — no outline */
.ll-table-card.lv-card, .prl-table-card.lv-card, .tl-table-card.lv-card,
.ul-table-card.lv-card, .pl-table-card.lv-card {
	padding: 0;
	border: none;
	border-bottom: none;
}
.lv-card-title {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	font-size: 13px;
	font-weight: 700;
	color: var(--maktab-text-muted);
	text-transform: uppercase;
	letter-spacing: 0.5px;
	margin-bottom: 10px;
}

/* Inline add button (e.g. "+" next to a card title) */
.lv-add-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	height: 22px;
	padding: 0;
	border: 1px solid var(--maktab-border);
	border-radius: 50%;
	background: transparent;
	color: var(--maktab-text-muted);
	font-size: 16px;
	font-weight: 400;
	line-height: 1;
	cursor: pointer;
	transition: background 120ms, color 120ms, border-color 120ms;
}
.lv-add-btn:hover {
	background: var(--subtle-fg, rgba(0,0,0,0.04));
	color: var(--maktab-text);
	border-color: var(--maktab-text-muted);
}

/* Rows */
.lv-row {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	column-gap: 12px;
	padding: 4px 0;
	font-size: 14px;
}
/* Stacked variant — label on top, value below (used for long-text fields
   like Notes where multi-line content would collide with an inline label) */
.lv-row.lv-row-stacked {
	flex-direction: column;
	align-items: stretch;
	gap: 4px;
}
.lv-row.lv-row-stacked .lv-value { text-align: start; white-space: normal; }
.lv-row.lv-row-stacked .lv-value > div { display: block; }
.lv-label { color: var(--maktab-text-muted); }
.lv-value { color: var(--maktab-text); font-weight: 500; }
.lv-money { font-variant-numeric: tabular-nums; }
.lv-row-total { border-top: 1px solid var(--maktab-border); padding-top: 6px; margin-top: 4px; }
.lv-row-total .lv-value { font-weight: 700; color: var(--maktab-dark-brown); }
.lv-text-warn { color: var(--maktab-terracotta); }
.lv-text-caution {
    color: var(--maktab-orange, var(--warn)) !important;
}
.lv-inline-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: var(--r-sm);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
}
.lv-inline-badge.lv-status-active { background: rgba(94, 125, 94, 0.15); color: var(--maktab-green, var(--success)); }
.lv-inline-badge.lv-status-pending { background: rgba(212, 160, 90, 0.15); color: var(--maktab-orange, var(--warn)); }
.lv-inline-badge.lv-status-terminated { background: rgba(192, 115, 94, 0.15); color: var(--maktab-red, var(--crit)); }

/* Tenant sidebar */
.lv-tenant-name { font-size: 16px; font-weight: 700; color: var(--maktab-text); margin-bottom: 2px; }
.lv-tenant-name-ar { font-size: 14px; color: var(--maktab-text-muted); margin-bottom: 8px; }
.lv-contact { margin-bottom: 4px; }
.lv-phone { color: var(--maktab-link); text-decoration: none; font-size: 14px; font-weight: 500; }
.lv-phone:hover { text-decoration: underline; }
.lv-contact-name { color: var(--maktab-text-muted); font-size: 12px; margin-inline-start: 6px; }
.lv-ejar-contact { font-size: 12px; color: var(--maktab-text-muted); margin-top: 6px; font-style: italic; }

/* Contact cards — stacked layout for slide panels */
.lv-contact-card {
	display: flex;
	flex-direction: column;
	padding: 6px 0;
	border-bottom: 1px solid var(--maktab-border-light, rgba(107, 90, 72, 0.08));
	gap: 2px;
}
.lv-contact-card:last-child { border-bottom: none; }
.lv-contact-card-name {
	font-size: 13px;
	color: var(--maktab-text);
	word-break: break-word;
	overflow-wrap: break-word;
}
.lv-contact-card-phone {
	font-size: 14px;
	font-weight: 500;
	color: var(--maktab-link);
	text-decoration: none;
	direction: ltr;
	unicode-bidi: isolate;
}
.lv-contact-card-phone:hover { text-decoration: underline; }
[data-theme="dark"] .lv-contact-card { border-bottom-color: var(--maktab-border); }

/* Notes */
.lv-notes-input {
	width: 100%;
	min-height: 80px;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	padding: 8px 10px;
	font-size: 13px;
	font-family: inherit;
	color: var(--maktab-text);
	background: var(--maktab-white);
	resize: vertical;
}
.lv-notes-input:focus { outline: none; border-color: var(--maktab-sand); }
.lv-save-notes {
	margin-top: 8px;
	background: var(--maktab-dark-brown);
	color: var(--maktab-cream);
	border: none;
	border-radius: var(--r-md);
	padding: 6px 16px;
	font-size: 12px;
	font-weight: 600;
	cursor: pointer;
	width: 100%;
}
.lv-save-notes:hover { background: var(--maktab-brown); }

/* Documents */
.lv-file-link {
	display: block;
	padding: 6px 0;
	color: var(--maktab-text);
	text-decoration: none;
	font-size: 13px;
	border-bottom: 1px solid var(--maktab-border);
}
.lv-file-link:last-child { border-bottom: none; }
.lv-file-link:hover { color: var(--maktab-link); }
.lv-file-icon { margin-inline-end: 4px; }
/* FB-2026-00120 round 3: keep filename + extension as one LTR run inside an
   RTL row. <bdi> handles isolation by spec, but CSS belt-and-suspenders
   prevents Chromium from splitting "صك ... 3.pdf" across the row. */
.lv-file-link, .lv-file-link bdi {
	unicode-bidi: isolate;
}

/* Payment history table */
.lv-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 13px;
}
.lv-table th {
	text-align: start;
	font-weight: 600;
	color: var(--maktab-text-muted);
	padding: 6px 8px;
	border-bottom: 2px solid var(--maktab-border);
	font-size: 12px;
}
.lv-table td {
	padding: 8px;
	border-bottom: 1px solid var(--maktab-border);
	color: var(--maktab-text);
}
.lv-table tr:last-child td { border-bottom: none; }
.lv-invoice-link { color: var(--maktab-link); text-decoration: none; font-weight: 500; white-space: nowrap; }
.lv-invoice-link:hover { text-decoration: underline; }
.lv-map-link { color: var(--maktab-link); text-decoration: none; font-size: 12px; }

/* Dark mode */
[data-theme="dark"] .lv-status-active { background: rgba(125,155,118,0.15); color: #A8D4A0; }
[data-theme="dark"] .lv-status-expired { background: rgba(196,149,106,0.15); color: #E8C9A0; }
[data-theme="dark"] .lv-status-pending { background: rgba(139,105,20,0.15); color: #D4B96A; }
[data-theme="dark"] .lv-status-thilth { background: rgba(125,155,118,0.15); color: #A8D4A0; }
[data-theme="dark"] .lv-status-khums { background: rgba(107,63,160,0.15); color: #C4A8E8; }

/* Mobile responsive */
@media (max-width: 768px) {
	/* ── Detail view mobile fixes ── */
	/* Toolbar: buttons fill width, original size */
	.lv-toolbar {
		flex-wrap: wrap !important;
		padding: 4px 0 !important;
		gap: 6px !important;
	}
	.lv-toolbar-btn {
		flex: 1 1 0 !important;
		min-width: 0 !important;
		justify-content: center !important;
		padding: 5px 6px !important;
		gap: 3px !important;
	}
	/* Extra buttons (Send Portal Invite, etc.) get full width on their own row */
	.lv-toolbar-btn.lv-extra-btn {
		flex: 1 1 100% !important;
	}
	/* Comment Post button is in a column flex container — take full width */
	.lv-comment-post-btn {
		flex: none !important;
		width: 100% !important;
	}
	/* Reduce gap between status bar and first card */
	.lv-status-bar {
		padding: 6px 12px !important;
		margin-bottom: 0 !important;
	}
	/* Detail column wrapper: remove horizontal padding so cards align with toolbar.
	   Reduce gap from 20px to 8px — on mobile lv-main and lv-side stack vertically
	   and the gap (plus lv-main last-child margin) created a large blank band. */
	.lv-columns {
		padding: 4px 0 24px !important;
		gap: 8px !important;
	}
	/* Remove the extra bottom margin on last card in lv-main — the gap above handles spacing */
	.lv-main > .lv-card:last-child {
		margin-bottom: 0 !important;
	}
	/* Detail cards: vertical padding only — rows align flush with toolbar edge */
	.lv-columns .lv-card {
		padding: 12px 0 !important;
	}
	/* List/summary cards keep inset padding */
	.lv-card {
		padding: 12px !important;
	}
	/* Detail rows: long values wrap gracefully on mobile.
	   No flex-wrap — label stays left, value stays right and word-breaks.
	   For very long values, the flex-shrink on value handles it. */
	.lv-row {
		flex-wrap: nowrap;
		gap: 8px;
	}
	.lv-label {
		flex: 0 0 auto;
		white-space: nowrap;
	}
	.lv-value {
		flex: 1 1 0;
		text-align: right;
		word-break: break-word;
		overflow-wrap: break-word;
		min-width: 0;
	}
	/* Ensure detail view content stays within viewport */
	.lv-columns,
	.lv-card {
		max-width: 100% !important;
		box-sizing: border-box;
	}
	/* Reset flex-basis so stacked columns get natural height,
	   and constrain width so content doesn't overflow parent */
	.lv-main, .lv-side {
		flex-basis: auto !important;
		width: 100% !important;
		max-width: 100% !important;
		overflow-x: hidden !important;
		overflow-wrap: break-word;
	}
}
@media (max-width: 768px) {
	/* ── Stacked card layout for all list tables on mobile ──
	   Targets both the legacy per-page table classes (.tl-table etc.) and
	   the shared renderer's class (.maktab-list-table). */
	.ll-table thead, .prl-table thead, .tl-table thead,
	.ul-table thead, .pl-table thead,
	.maktab-list-table thead, .lv-table thead {
		display: none;
	}
	.ll-table, .prl-table, .tl-table, .ul-table, .pl-table, .maktab-list-table, .lv-table,
	.ll-table tbody, .prl-table tbody, .tl-table tbody,
	.ul-table tbody, .pl-table tbody, .maktab-list-table tbody, .lv-table tbody,
	.ll-table tr, .prl-table tr, .tl-table tr,
	.ul-table tr, .pl-table tr, .maktab-list-table tr, .lv-table tr,
	.ll-table td, .prl-table td, .tl-table td,
	.ul-table td, .pl-table td, .maktab-list-table td, .lv-table td {
		display: block;
		width: 100%;
	}
	.ll-table, .prl-table, .tl-table, .ul-table, .pl-table, .maktab-list-table, .lv-table {
		background: transparent !important;
		border: none;
	}
	.ll-table tbody tr, .prl-table tbody tr, .tl-table tbody tr,
	.ul-table tbody tr, .pl-table tbody tr,
	.maktab-list-table tbody tr.maktab-list-row, .lv-table tbody tr {
		margin-bottom: 10px;
		border-radius: var(--r-lg);
		padding: 12px 14px;
		border: 1px solid var(--maktab-border);
		background: var(--maktab-cream);
		box-shadow: none;
		cursor: pointer;
	}
	.maktab-list-table tbody tr.maktab-list-empty,
	.maktab-list-table tbody tr.maktab-list-loading,
	.maktab-list-table tbody tr.maktab-list-error {
		background: transparent;
		border: none;
		padding: 20px 0;
	}
	.maktab-list-table tbody tr.maktab-list-row:hover {
		border-color: var(--maktab-sand);
	}
	.ll-table tbody td, .prl-table tbody td, .tl-table tbody td,
	.ul-table tbody td, .pl-table tbody td,
	.maktab-list-table tbody td, .lv-table tbody td {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 5px 0;
		border-bottom: none;
		font-size: 13px;
		text-align: end;
		gap: 12px;
	}
	/* First cell in each mobile card = title row (bigger, borderless) */
	.maktab-list-table tbody td:first-child {
		padding-top: 0;
		padding-bottom: 6px;
		margin-bottom: 4px;
		border-bottom: 1px solid var(--maktab-border);
		font-size: 15px;
	}
	.maktab-list-table tbody td:first-child::before {
		display: none;  /* Don't show the label for the title row */
	}
	.ll-table tbody td::before, .prl-table tbody td::before,
	.tl-table tbody td::before, .ul-table tbody td::before,
	.pl-table tbody td::before,
	.maktab-list-table tbody td::before, .lv-table tbody td::before {
		content: attr(data-label);
		font-weight: 600;
		font-size: 11px;
		color: var(--maktab-text-muted);
		text-transform: uppercase;
		letter-spacing: 0.3px;
		flex-shrink: 0;
		text-align: start;
	}
	.ll-num, .prl-num, .tl-num, .ul-num, .pl-num,
	.maktab-list-num {
		text-align: end;
	}
	.pl-row-cancelled { opacity: 0.5; }
	.pl-row-cancelled td { text-decoration: line-through; }
	/* lv-table cards: first cell is card title (unit number) */
	.lv-table tbody td:first-child {
		padding-top: 0;
		padding-bottom: 6px;
		margin-bottom: 4px;
		border-bottom: 1px solid var(--maktab-border);
		font-size: 15px;
		font-weight: 600;
	}
	.lv-table tbody td:first-child::before {
		display: none;
	}
}

/* ═══════════════════════════════════════════════════════
   Maintenance View (mnt-*)
   ═══════════════════════════════════════════════════════ */

/* Priority badges (inline status badges emitted by household_view + property_view) */
.mnt-priority {
	display: inline-block;
	padding: 2px 10px;
	border-radius: var(--r-lg);
	font-size: 11px;
	font-weight: 600;
	white-space: nowrap;
}
.mnt-pri-urgent { background: rgba(192,115,94,0.15); color: var(--maktab-terracotta); }
.mnt-pri-high { background: rgba(212,160,90,0.15); color: #B8860B; }
.mnt-pri-medium { background: rgba(143,184,212,0.15); color: var(--maktab-sky-hover); }
.mnt-pri-low { background: rgba(94,125,94,0.15); color: var(--maktab-green); }

/* Status badges */
.mnt-badge {
	display: inline-block;
	padding: 2px 10px;
	border-radius: var(--r-lg);
	font-size: 11px;
	font-weight: 600;
	white-space: nowrap;
}
.mnt-badge-open { background: rgba(192,115,94,0.15); color: var(--maktab-terracotta); }
.mnt-badge-inprogress { background: rgba(212,160,90,0.15); color: #B8860B; }
.mnt-badge-completed { background: rgba(94,125,94,0.15); color: var(--maktab-green); }
.mnt-badge-cancelled { background: rgba(140,122,107,0.15); color: var(--maktab-text-muted); }

/* ═══════════════════════════════════════════════════════
   Wasi Dashboard (wd-*)
   ═══════════════════════════════════════════════════════ */
.wd-container {
	max-width: 1100px;
	margin: 0 auto;
	padding: 8px 20px 40px;
}

.wd-subtitle {
	text-align: center;
	color: var(--maktab-text-muted);
	font-size: 13px;
	margin-bottom: 18px;
}
.wd-backup-pill {
	display: inline-block;
	font-size: 12px;
	font-weight: 500;
	margin-inline-start: 4px;
}
.wd-backup-pill.wd-backup-ok {
	color: var(--maktab-green, var(--success));
}
.wd-backup-pill.wd-backup-stale {
	color: var(--maktab-terracotta, var(--crit));
}
[data-theme="dark"] .wd-backup-pill.wd-backup-ok {
	color: #6ee7b7;
}
[data-theme="dark"] .wd-backup-pill.wd-backup-stale {
	color: #fca5a5;
}

/* ── Summary row: 4 cards ── */
.wd-summary-row {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 12px;
	margin-bottom: 16px;
}

.wd-summary-card {
	background: #F5EDE0;
	border: none;
	border-radius: 0;
	padding: 16px 14px 12px;
	text-align: center;
	transition: box-shadow 0.2s;
}

.wd-summary-card:hover { box-shadow: none; }

.wd-summary-alert {
	background: #FDF2F0;
}

.wd-summary-icon { font-size: 22px; margin-bottom: 4px; }

.wd-summary-number {
	font-size: 28px;
	font-weight: 700;
	color: var(--maktab-dark-brown);
	line-height: 1.2;
}

.wd-summary-sar { font-size: 20px; }

.wd-summary-label {
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	color: var(--maktab-text-muted);
	letter-spacing: 0.5px;
	margin-top: 2px;
}

.wd-summary-sub {
	font-size: 12px;
	color: var(--maktab-text-muted);
	margin-top: 4px;
}

/* ── Rent mini-bar ── */
.wd-rent-bar {
	display: flex;
	justify-content: center;
	gap: 30px;
	padding: 10px 0;
	margin-bottom: 16px;
	border-bottom: 1px solid var(--maktab-border);
}

.wd-rent-stat-num {
	font-weight: 700;
	color: var(--maktab-dark-brown);
}

.wd-rent-stat-label {
	color: var(--maktab-text-muted);
	font-size: 13px;
}

/* ── Sections ── */
.wd-section {
	margin-bottom: 24px;
}

.wd-section-title {
	font-size: 15px;
	font-weight: 700;
	color: var(--maktab-dark-brown);
	margin-bottom: 12px;
	padding-bottom: 4px;
	border-bottom: 2px solid var(--maktab-straw);
}

/* ── Alerts ── */
.wd-all-clear {
	padding: 16px;
	text-align: center;
	color: var(--maktab-green);
	font-size: 15px;
	font-weight: 600;
	background: #E8F5E8;
	border-radius: var(--maktab-radius);
}

.wd-all-clear-icon { font-size: 18px; }

.wd-alerts-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
	gap: 10px;
}

.wd-alert-card {
	display: block;
	padding: 12px 14px;
	border-radius: var(--maktab-radius);
	text-decoration: none;
	transition: box-shadow 0.2s, transform 0.15s;
	cursor: pointer;
}

.wd-alert-card:hover {
	box-shadow: none;
	transform: translateY(-1px);
	text-decoration: none;
}

.wd-alert-red {
	background: #FDF2F0;
	color: #5C2F1A;
}

.wd-alert-orange {
	background: #FFF8EC;
	color: #4A3508;
}

.wd-alert-yellow {
	background: #FEFCE8;
	color: #3E2E06;
}

.wd-alert-type {
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	margin-bottom: 2px;
}

.wd-alert-title {
	font-size: 14px;
	font-weight: 600;
	margin-bottom: 4px;
}

.wd-alert-days {
	font-size: 12px;
	font-weight: 500;
}

/* ── Quick Actions ── */
.wd-actions-row {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 12px;
}

.wd-action-btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 20px 14px;
	border-radius: var(--maktab-radius);
	text-decoration: none;
	font-weight: 600;
	font-size: 14px;
	transition: box-shadow 0.2s, transform 0.15s;
	cursor: pointer;
	min-height: 90px;
}

.wd-action-btn:hover {
	box-shadow: none;
	transform: translateY(-2px);
	text-decoration: none;
}

.wd-action-icon {
	font-size: 28px;
	margin-bottom: 6px;
}

.wd-action-label {
	font-size: 14px;
}

.wd-action-rent {
	background: #2E5C2E;
	color: #ffffff !important;
}
.wd-action-rent:hover { color: #0B220B !important; }

.wd-action-maint {
	background: var(--maktab-sky);
	color: #15354F !important;
}
.wd-action-maint:hover { color: #0F2940 !important; }

.wd-action-report {
	background: var(--maktab-amber);
	color: #3C2A00 !important;
}
.wd-action-report:hover { color: #2C1E00 !important; }

/* ── Two columns ── */
.wd-columns {
	display: flex;
	gap: 16px;
}

.wd-col {
	flex: 1;
	min-width: 0;
}

.wd-table-sub {
	font-size: 11px;
	color: var(--maktab-text-muted);
}

.wd-empty {
	padding: 20px;
	text-align: center;
	color: var(--maktab-text-muted);
	font-size: 13px;
}

/* ── Status badges ── */
.wd-status-badge {
	display: inline-block;
	padding: 2px 8px;
	border-radius: var(--r-lg);
	font-size: 11px;
	font-weight: 600;
}

.wd-status-open {
	background: #FDF2F0;
	color: #7A3A2A;
}

.wd-status-progress {
	background: #FFF8EC;
	color: #6B4F20;
}

.wd-status-done {
	background: #E8F5E8;
	color: #3A5F3A;
}

/* ── Helper colors ── */
.wd-text-red { color: var(--overdue); }
.wd-text-green { color: var(--maktab-green); }

/* ── Dark mode ── */
[data-theme="dark"] .wd-summary-alert { background: rgba(192,115,94,0.15); }
[data-theme="dark"] .wd-summary-card { background: #2A2418; }
[data-theme="dark"] .wd-all-clear { background: rgba(125,155,118,0.15); color: #A8D4A0; }
[data-theme="dark"] .wd-alert-red { background: rgba(192,115,94,0.12); color: #E8A890; }
[data-theme="dark"] .wd-alert-orange { background: rgba(212,160,90,0.12); color: #E0C080; }
[data-theme="dark"] .wd-alert-yellow { background: rgba(194,173,126,0.12); color: var(--straw); }
[data-theme="dark"] .wd-status-open { background: rgba(192,115,94,0.15); color: #E8A890; }
[data-theme="dark"] .wd-status-progress { background: rgba(212,160,90,0.15); color: #E0C080; }
[data-theme="dark"] .wd-status-done { background: rgba(125,155,118,0.15); color: #A8D4A0; }

/* ── Mobile ── */
@media (max-width: 768px) {
	.wd-container { padding: 8px 12px 30px; }
	.wd-summary-row { grid-template-columns: repeat(2, 1fr); }
	.wd-summary-number { font-size: 22px; }
	.wd-summary-sar { font-size: 17px; }
	.wd-actions-row { grid-template-columns: 1fr; gap: 8px; }
	.wd-action-btn { min-height: 60px; flex-direction: row; gap: 10px; padding: 14px; }
	.wd-action-icon { font-size: 22px; margin-bottom: 0; }
	.wd-columns { flex-direction: column; }
	.wd-alerts-grid { grid-template-columns: 1fr; }
	.wd-rent-bar { flex-direction: column; gap: 6px; align-items: center; }
}

/* ── iPad / tablet ── */
@media (min-width: 769px) and (max-width: 1024px) {
	.wd-summary-row { gap: 8px; }
	.wd-summary-number { font-size: 24px; }
	.wd-action-btn { padding: 16px 10px; min-height: 80px; }
}

/* ═══════════════════════════════════════════════════════════
   Thilth Report (tr-*) — waqf financial summary
   ═══════════════════════════════════════════════════════════ */

.tr-container {
	max-width: 1100px;
	margin: 0 auto;
	padding: 8px 20px 40px;
}

.tr-loading {
	text-align: center;
	padding: 60px;
	color: var(--ink-muted);
}

/* ── Inline toolbar (Print button) ──
   Replaces page.add_inner_button which renders inside .page-head and is
   hidden by .maktab-no-titlebar. FB-2026-00250. */
.tr-toolbar {
	display: flex;
	justify-content: flex-end;
	margin-bottom: 12px;
}

.tr-print-btn {
	background: var(--cream);
	border: 1px solid var(--border);
	border-radius: var(--r-sq);
	padding: 6px 16px;
	font-size: var(--text-sm);
	font-weight: 600;
	color: var(--ink);
	cursor: pointer;
	transition: background 0.2s, border-color 0.2s, color 0.2s;
}

.tr-print-btn:hover {
	background: var(--beige);
	border-color: var(--sand);
}

[data-theme="dark"] .tr-print-btn {
	background: var(--cream);
	color: var(--ink);
	border-color: var(--border);
}

/* ── Year selector bar ── (foundation `.tab` paper-pill feel) */
.tr-year-bar {
	display: flex;
	justify-content: center;
	gap: 8px;
	margin-bottom: 20px;
	flex-wrap: wrap;
}

.tr-year-btn {
	background: var(--cream);
	border: 1px solid var(--border);
	border-radius: var(--r-sq);
	padding: 8px 20px;
	font-size: var(--text-base);
	font-weight: 600;
	color: var(--ink);
	font-variant-numeric: tabular-nums;
	cursor: pointer;
	transition: background 0.2s, border-color 0.2s, color 0.2s;
}

.tr-year-btn:hover {
	background: var(--beige);
	border-color: var(--sand);
}

.tr-year-active {
	background: var(--brown-deep);
	color: var(--cream);
	border-color: var(--brown-deep);
}

.tr-year-active:hover {
	background: var(--brown-night);
	color: var(--cream);
	border-color: var(--brown-night);
}

/* ── Summary cards (4-column grid) ── */
/* FIX 5: entity-header pill row sitting just inside the entity-banner top
   stripe.
   FIX 6: now also hosts the AR-primary report title (Thilth Report — Year YYYY).
   Title takes the inline-start side; pill stays on the inline-end side. */
.tr-entity-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--s-2);
	margin-bottom: var(--s-3);
}

.tr-report-title {
	font-size: var(--text-lg);
	font-weight: 700;
	color: var(--brown-deep);
	margin: 0;
	font-variant-numeric: tabular-nums;
}

[data-theme="dark"] .tr-report-title { color: var(--ink); }

/* FIX 6 — basmala (AR only, rendered before the entity-header).
   Centered, slightly larger, traditional kufic-friendly weight. */
.tr-basmala {
	text-align: center;
	font-size: var(--text-xl);
	font-weight: 700;
	color: var(--brown-deep);
	letter-spacing: 0.02em;
	margin-bottom: var(--s-4);
	padding-bottom: var(--s-3);
	border-bottom: 1px solid var(--border);
}

[data-theme="dark"] .tr-basmala { color: var(--ink); }

/* FIX 6 — section blocks (Charitable / Operational / Properties /
   Beneficiaries / YoY). The Charitable + Operational variants carry a
   colored accent stripe so the religious-vs-running-costs split reads at
   a glance. */
.tr-block {
	margin-top: var(--s-5);
	margin-bottom: var(--s-4);
	background: var(--cream);
	border: 1px solid var(--border);
	border-radius: var(--r-md);
	padding: var(--s-4);
}

[data-theme="dark"] .tr-block {
	background: var(--brown-night);
	border-color: var(--straw);
}

.tr-block-header {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--s-2);
	margin-bottom: var(--s-3);
	padding-bottom: var(--s-2);
	border-bottom: 1px solid var(--border);
}

.tr-block-title {
	font-size: var(--text-lg);
	font-weight: 700;
	color: var(--brown-deep);
}

[data-theme="dark"] .tr-block-title { color: var(--ink); }

.tr-block-total {
	display: inline-flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
}

[dir="rtl"] .tr-block-total { align-items: flex-start; }

.tr-block-total-label {
	font-size: var(--text-xs);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--ink-muted);
}

.tr-block-total-amount {
	font-size: 24px;
	font-weight: 700;
	color: var(--brown-deep);
	font-family: var(--font-num);
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
}

[data-theme="dark"] .tr-block-total-amount { color: var(--ink); }

/* FIX 6 — KPI footer demotes the legacy summary cards to secondary info
   at the bottom of the page. Smaller heading, same card grid below. */
.tr-kpi-footer {
	margin-top: var(--s-5);
	padding-top: var(--s-4);
	border-top: 1px solid var(--border);
}

.tr-kpi-footer-title {
	font-size: var(--text-sm);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--ink-muted);
	margin-bottom: var(--s-3);
	text-align: center;
}

.tr-summary-row {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 12px;
	margin-bottom: 8px;
}

.tr-summary-card {
	background: var(--cream);
	border: 1px solid var(--border);
	border-radius: var(--r-md);
	padding: 16px 14px 12px;
	text-align: center;
}

.tr-summary-card:hover { box-shadow: none; }

.tr-card-label {
	font-size: var(--text-sm);
	font-weight: 700;
	text-transform: uppercase;
	color: var(--ink-muted);
	letter-spacing: 0.5px;
	margin-bottom: 4px;
}

.tr-card-value {
	font-size: var(--text-xl);
	font-weight: 700;
	color: var(--brown-deep);
	font-family: var(--font-num);
	font-variant-numeric: tabular-nums;
	line-height: 1.3;
}

/* ── Net surplus/deficit banner ── */
.tr-net-banner {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 12px;
	padding: 12px 20px;
	border-radius: var(--r-md);
	margin-bottom: 20px;
	font-weight: 700;
}

.tr-net-surplus {
	background: var(--success-bg);
	color: var(--success);
}

.tr-net-deficit {
	background: var(--crit-bg);
	color: var(--overdue);
}

.tr-net-label {
	font-size: var(--text-base);
	text-transform: uppercase;
	letter-spacing: 0.5px;
}

.tr-net-amount {
	font-size: 22px;
	font-family: var(--font-num);
	font-variant-numeric: tabular-nums;
}

/* ── Chart ── */
.tr-chart-wrap {
	margin-bottom: 8px;
}

/* Hide frappe.Chart's built-in legend — its labels are positioned with
   a fixed LTR x-offset and collide when Arabic text expands leftward
   from anchor. We render our own HTML .tr-chart-legend below the chart
   instead (FB-2026-00237 / FB-2026-00243). */
.tr-chart-wrap .chart-legend,
.tr-chart-wrap .legend-dataset-label,
.tr-chart-wrap g.legend,
.tr-chart-wrap [class^="legend"] {
	display: none !important;
}

.tr-css-chart {
	padding: 12px;
}

.tr-chart-legend {
	display: flex;
	justify-content: center;
	gap: 20px;
	margin-bottom: 16px;
	font-size: 13px;
	color: var(--ink-muted);
}

.tr-legend-item {
	display: flex;
	align-items: center;
	gap: 6px;
}

.tr-legend-dot {
	width: 10px;
	height: 10px;
	border-radius: var(--r-sq);
	display: inline-block;
}

.tr-bars-container {
	display: flex;
	justify-content: center;
	gap: 32px;
	align-items: flex-end;
	height: 200px;
	border-bottom: 1px solid var(--border);
	padding-bottom: 0;
}

.tr-bar-group {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex: 0 0 auto;
}

.tr-bar-year {
	font-size: 13px;
	font-weight: 600;
	color: var(--ink-muted);
	font-variant-numeric: tabular-nums;
	margin-top: 8px;
}

.tr-bar-set {
	display: flex;
	gap: 4px;
	align-items: flex-end;
	height: 180px;
}

.tr-bar {
	width: 28px;
	border-radius: var(--r-sm) var(--r-sm) 0 0;
	min-height: 4px;
	transition: height 0.4s ease;
	cursor: default;
}

.tr-bar-rent { background: var(--success); }
.tr-bar-exp { background: var(--crit); }
.tr-bar-dis { background: var(--warn); }

/* ── Tables ── */
.tr-link {
	/* --maktab-link auto-adapts: medium brown on light, light tan on dark
	   (FB-2026-00236). The previous --brown-deep dropped to near-black in
	   dark mode and property names became unreadable. */
	color: var(--maktab-link);
	text-decoration: none;
	font-weight: 500;
}
.tr-link:hover { text-decoration: underline; }

.tr-total-row {
	border-top: 2px solid var(--sand);
}
.tr-total-row td {
	padding-top: 8px;
}

/* ── Dark mode overrides ── */
[data-theme="dark"] .tr-summary-card { background: var(--brown-night); border-color: var(--straw); }
/* --straw (#3D3428) on dark bg was unreadable for inactive year buttons;
   --ink-muted (#A89A82) gives 4.5+:1 contrast. FB-2026-00236. */
[data-theme="dark"] .tr-year-btn { background: var(--brown-night); color: var(--ink-muted); }
[data-theme="dark"] .tr-year-active {
  background: var(--surface-inverse);
  color: var(--brown-deep);
  border-color: var(--brown-deep);
}
[data-theme="dark"] .tr-net-surplus { background: rgba(94,125,94,0.18); color: #A8D4A0; }
[data-theme="dark"] .tr-net-deficit { background: rgba(192,115,94,0.18); color: #E8A890; }
/* --cream is the dark CARD bg (#221C14), not a foreground colour — using it
   as text colour left the summary card values nearly invisible. --ink
   (#E8E0D4) is the canonical dark-mode body text. FB-2026-00236. */
[data-theme="dark"] .tr-card-value { color: var(--ink); }

/* ── Mobile ── */
@media (max-width: 768px) {
	.tr-container { padding: 8px 12px 30px; }
	.tr-summary-row { grid-template-columns: repeat(2, 1fr); }
	.tr-card-value { font-size: 16px; }
	.tr-net-amount { font-size: 18px; }
	.tr-bars-container { gap: 16px; height: 160px; }
	.tr-bar-set { height: 140px; }
	.tr-bar { width: 20px; }
	/* FIX 6 — let the section-block header stack vertically on mobile so
	   the big section total isn't squeezed next to the title. */
	.tr-block { padding: var(--s-3); }
	.tr-block-header {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--s-2);
	}
	[dir="rtl"] .tr-block-header { align-items: flex-end; }
	.tr-block-total {
		align-items: flex-start;
		flex-direction: row;
		gap: var(--s-2);
	}
	[dir="rtl"] .tr-block-total { align-items: flex-end; }
	.tr-block-total-amount { font-size: 20px; }
	.tr-basmala { font-size: 16px; }
	.tr-report-title { font-size: 16px; }
}

/* ── Print styles ── */
@media print {
	.page-head, .navbar, .sidebar, .tr-year-bar, .tr-toolbar,
	.page-container > .page-sidebar, .standard-actions,
	.footer, [data-page-container-footer] { display: none; }
	.tr-container { max-width: 100%; padding: 0; }
	.tr-summary-card { box-shadow: none; border: 1px solid #ccc; }
	.lv-card { box-shadow: none; }
	.tr-link { color: inherit; text-decoration: none; }
	.wd-columns { flex-direction: column; }
	.wd-col { flex: none; width: 100%; }
}

/* === Phase 2B Thilth port === ═══════════════════════════════
   Ported verbatim from
     stage2-handoff/phase2b-handoff/mockups/thilth-home.html  (<style>)
     stage2-handoff/phase2b-handoff/mockups/entity-home-shared.css
       (generic .eh-* live in components.css; the mockup's EhTweaksFab was
        dropped — never ported, so nothing FAB-related lives below)
   Only Thilth-page-scoped pieces below. Shared atoms keep their own
   defaults via components.css; per mockup convention this file MUST NOT
   override .eh-* sizes for compact-mode (Majlis + Maktab follow the same
   don't-override-shared-atoms pattern).
   ─────────────────────────────────────────────────────────── */

.th-page {
	width: 100%;
	max-width: 1180px;
	margin: 0 auto;
	padding: var(--s-8) var(--s-8) var(--s-12);
	color: var(--ink);
	display: flex; flex-direction: column;
	gap: var(--s-6);
	font-weight: 400;
}
.th-page * { box-sizing: border-box; }
.th-loading { text-align: center; padding: 60px; color: var(--ink-muted); }

/* Full-bleed entity-home page-head — pull the shared .eh-pg-head out to the
   page's bleed edges so the entity gradient + the divider line run edge-to-edge
   (no padding gap around the title section). Mirrors the Khums treatment; all
   entity-home containers (.th-page / .mh-shell / .mo-main / .kh-page) share the
   same s-8 (desktop) / s-5·s-4 (mobile) page-pad, so the same pull works for
   each. Khums keeps its own copy in khums.css. */
.th-page .eh-pg-head,
.mh-shell .eh-pg-head,
.mo-main .eh-pg-head {
	margin: calc(-1 * var(--s-8)) calc(-1 * var(--s-8)) 0;
	padding: var(--s-8) var(--s-8) var(--s-5);
}
@media (max-width: 640px) {
	.th-page .eh-pg-head,
	.mh-shell .eh-pg-head,
	.mo-main .eh-pg-head {
		margin: calc(-1 * var(--s-5)) calc(-1 * var(--s-4)) 0;
		padding: var(--s-5) var(--s-4) var(--s-4);
	}
}

/* ── Beneficiary cards — no avatars (m0124), just the data ─── */
.th-ben-grid {
	display: grid; gap: var(--s-3);
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.th-ben-card {
	display: flex; flex-direction: column; gap: var(--s-3);
}
.th-ben-card__head { display: flex; flex-direction: column; gap: 4px; }
.th-ben-card__name {
	font-size: var(--text-lg); font-weight: 600;
	color: var(--brown-deep);
}
.th-ben-card__sub { font-size: var(--text-xs); color: var(--ink-muted); }
.th-ben-card__amt {
	font-size: var(--text-3xl); font-weight: 700;
	color: var(--brown-deep);
	font-feature-settings: "tnum" 1, "lnum" 1;
	line-height: 1;
}
.th-ben-card__amt .unit {
	font-size: var(--text-md); color: var(--ink-muted);
	margin-inline-start: 6px; font-weight: 400;
}
.th-ben-card__meta {
	display: flex; justify-content: space-between; align-items: baseline;
	font-size: var(--text-sm);
	padding-top: var(--s-2);
	border-top: 1px solid var(--border);
}

/* ── Property cards with rent-collection gauge bar ─────────── */
.th-prop-grid {
	display: grid; gap: var(--s-3);
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.th-prop-card {
	display: flex; flex-direction: column;
	gap: var(--s-3);
}
.th-prop-card__head { display: flex; flex-direction: column; gap: 2px; }
.th-prop-card__name {
	font-size: var(--text-md); font-weight: 600;
	color: var(--brown-deep);
}
.th-prop-card__type { font-size: var(--text-xs); color: var(--ink-muted); }
.th-prop-card__amts {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-2) 0;
	border-top: 1px solid var(--border-soft);
	border-bottom: 1px solid var(--border-soft);
}
.th-prop-card__lbl {
	font-size: var(--text-xs); color: var(--ink-muted);
}
.th-prop-card__amt {
	font-size: var(--text-xl); font-weight: 700; color: var(--brown-deep);
	font-feature-settings: "tnum" 1, "lnum" 1;
	line-height: 1.1;
}
.th-prop-card__divider {
	width: 1px; align-self: stretch;
	background: var(--border);
	margin: 0 var(--s-2);
}
.th-prop-card__gauge {
	height: 6px;
	background: var(--straw);
	border-radius: 3px;
	overflow: hidden;
}
.th-prop-card__fill {
	height: 100%;
	background: var(--success);
	transition: width var(--dur-base);
}
.th-prop-card__fill--low { background: var(--warn); }
.th-prop-card__fill--full { background: var(--success); }
.th-prop-card__foot {
	display: flex; justify-content: space-between; align-items: baseline;
	font-size: var(--text-xs);
}
.th-prop-card__foot .num { font-weight: 600; color: var(--brown-deep); }

/* ── Compact mode (page-specific bits only) ──────────────── */
.th-page--compact { gap: var(--s-4); padding-block: var(--s-5); }
.th-page--compact .th-ben-card { padding: var(--s-3); }
.th-page--compact .th-ben-card__amt { font-size: var(--text-2xl); }
.th-page--compact .th-prop-card { padding: var(--s-3); }
.th-page--compact .th-prop-card__amt { font-size: var(--text-lg); }

/* ── Mobile (<640px) — page-specific bits only ─────────────── */
@media (max-width: 640px) {
	.th-page { padding: var(--s-5) var(--s-4) var(--s-10); }
	/* Audit fix L9: the shared atom in components.css collapses
	   .eh-split__head into a column on mobile; the mockup keeps it as a
	   row at all viewports (entity-home-shared.css:124 + media query at
	   338 omits any override). Restore row+baseline+gap-3 inside the
	   Thilth page scope without touching the atom CSS. */
	.th-page .eh-split__head {
		flex-direction: row;
		align-items: baseline;
		gap: var(--s-3);
	}
}

/* ── Print adjustments — page expands. ────── */
@media print {
	.th-page { max-width: 100%; padding: 0; }
	.eh-pg-head__actions { display: none; }
}

/* ── AR-dark basmala color — warm wheat per mockup ─────────── */
[data-theme="dark"] .eh-basmala { color: rgb(232, 220, 186); }

/* ── Page-scoped dark-mode overrides for Thilth (.th-*) ──
   Generic `.eh-*` dark overrides ship from components.css.
   Audit fix T3/T4: in dark mode the mockup resolves `--brown-deep` to
   wheat (#E8DCBA = rgb(232,220,186)), which is the colour th-ben-card
   name+amt elements need. Live's dark `--brown-deep` is intentionally
   structural (sidebar/navbar surface — flip skipped per
   4a811b6 commit message), so we hardcode the wheat tone here in page
   scope. The dashed border on `.th-ben-card__meta` inherits via
   `currentColor` from this colour where needed. */
[data-theme="dark"] .th-ben-card__name,
[data-theme="dark"] .th-ben-card__amt,
[data-theme="dark"] .th-prop-card__name,
[data-theme="dark"] .th-prop-card__amt,
[data-theme="dark"] .th-prop-card__foot .num {
	color: #E8DCBA;
}
/* Match the dashed rule colour to the mockup's wheat tone too. */
[data-theme="dark"] .th-ben-card__meta {
	border-top-color: #E8DCBA;
}
/* === end Phase 2B Thilth port === */

/* ═══════════════════════════════════════════════════════════════════════════
   TENANT PORTAL — Public-facing pages for tenants
   ═══════════════════════════════════════════════════════════════════════════ */

.tenant-portal-page {
	font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
	background: #F5F0E8;
	min-height: 100vh;
	padding: 0;
}
.tp-container {
	max-width: 800px;
	margin: 0 auto;
	padding: 20px 16px 40px;
}
.tp-header {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 12px 0 20px;
	border-bottom: 1px solid #E0D5C5;
	margin-bottom: 20px;
}
.tp-page-title {
	flex: 1;
	font-size: 18px;
	font-weight: 700;
	color: #5a4a3b;
	margin: 0;
}
.tp-logout {
	font-size: 13px;
	color: var(--crit);
}
.tp-welcome {
	margin-bottom: 20px;
}
.tp-welcome-name {
	font-size: 16px;
	font-weight: 600;
	color: #5a4a3b;
}

/* Cards */
.tp-card {
	background: #fff;
	border-radius: var(--r-lg);
	padding: 20px;
	margin-bottom: 16px;
	box-shadow: none;
}
.tp-card-title {
	font-size: 16px;
	font-weight: 700;
	color: #5a4a3b;
	margin-bottom: 12px;
}
.tp-card-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 12px;
}

/* Info grid */
.tp-info-grid { margin-bottom: 12px; }
.tp-info-row {
	display: flex;
	justify-content: space-between;
	padding: 6px 0;
	border-bottom: 1px solid rgba(139,125,107,0.08);
	font-size: 14px;
}
.tp-info-row:last-child { border-bottom: none; }
.tp-info-label { color: var(--ink-muted); }
.tp-info-value { font-weight: 600; color: #5a4a3b; }

/* Outstanding balance */
.tp-outstanding {
	background: #FDF2E9;
	border: 1px solid #E8C9A0;
	border-radius: var(--r-md);
	padding: 12px 16px;
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin: 12px 0;
}
.tp-outstanding-label { font-weight: 600; color: var(--sand-deep); font-size: 14px; }
.tp-outstanding-amount { font-weight: 700; color: var(--crit); font-size: 18px; }

/* Section title */
.tp-section-title {
	font-size: 14px;
	font-weight: 700;
	color: var(--ink-muted);
	margin: 16px 0 8px;
	text-transform: uppercase;
	letter-spacing: 0.5px;
}

/* Tables */
.tp-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 13px;
}
.tp-table th {
	text-align: right;
	padding: 8px 10px;
	color: var(--ink-muted);
	font-weight: 600;
	border-bottom: 2px solid #E0D5C5;
	font-size: 12px;
}
.tp-table td {
	padding: 8px 10px;
	border-bottom: 1px solid rgba(139,125,107,0.08);
	color: #5a4a3b;
}

/* Badges */
.tp-badge {
	display: inline-block;
	font-size: 11px;
	padding: 2px 10px;
	border-radius: var(--r-lg);
	font-weight: 600;
}
.tp-badge-active, .tp-badge-received { background: #E8F5E9; color: #2E7D32; }
.tp-badge-expired { background: #FCE4EC; color: #C62828; }
.tp-badge-pending, .tp-badge-partial, .tp-badge-open { background: #FFF3E0; color: #E65100; }

/* Buttons */
.tp-btn {
	display: inline-block;
	padding: 10px 24px;
	border: none;
	border-radius: var(--r-md);
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	transition: background 0.15s;
}
.tp-btn-primary {
	background: var(--ink-muted);
	color: #fff;
	width: 100%;
}
.tp-btn-primary:hover { background: #7A6A5B; }
.tp-btn-small {
	padding: 6px 14px;
	font-size: 12px;
	background: var(--ink-muted);
	color: #fff;
	border-radius: var(--r-md);
}
.tp-btn-small:hover { background: #7A6A5B; }

/* Signup page */
.tp-signup-container {
	max-width: 400px;
	margin: 60px auto;
	padding: 30px 24px;
	background: #fff;
	border-radius: var(--r-lg);
	box-shadow: none;
}
.tp-logo { text-align: center; margin-bottom: 20px; }
.tp-title {
	text-align: center;
	font-size: 20px;
	font-weight: 700;
	color: #5a4a3b;
	margin-bottom: 8px;
}
.tp-subtitle {
	text-align: center;
	color: var(--ink-muted);
	font-size: 14px;
	margin-bottom: 20px;
}
.tp-field {
	margin-bottom: 16px;
}
.tp-field label {
	display: block;
	font-size: 13px;
	color: var(--ink-muted);
	margin-bottom: 4px;
	font-weight: 600;
}
.tp-field input {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid #E0D5C5;
	border-radius: var(--r-md);
	font-size: 14px;
	background: #FAFAF7;
	color: #5a4a3b;
}
.tp-field input:focus {
	outline: none;
	border-color: var(--ink-muted);
}
.tp-disclosure {
	font-size: 11px;
	color: var(--ink-muted);
	background: rgba(139,125,107,0.06);
	padding: 10px 12px;
	border-radius: var(--r-md);
	margin: 12px 0;
	line-height: 1.5;
	text-align: center;
}
[data-theme="dark"] .tp-disclosure { background: rgba(255,255,255,0.04); color: var(--maktab-text-muted); }

/* Dark mode */
[data-theme="dark"] .tenant-portal-page { background: #1A1510; }
[data-theme="dark"] .tp-card { background: #24201A; box-shadow: none; }
[data-theme="dark"] .tp-page-title, [data-theme="dark"] .tp-card-title,
[data-theme="dark"] .tp-info-value, [data-theme="dark"] .tp-welcome-name { color: #E8DCC8; }
[data-theme="dark"] .tp-table td { color: #E8DCC8; }
[data-theme="dark"] .tp-field input { background: #2A2418; color: #E8DCC8; border-color: #3A3428; }
[data-theme="dark"] .tp-signup-container { background: #24201A; }
[data-theme="dark"] .tp-outstanding { background: rgba(139,105,20,0.15); border-color: rgba(139,105,20,0.3); }

/* ═══════════════════════════════════════════════════════════════════════════
   DARK MODE — Comprehensive overrides (Phase X)
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── LV toolbar, collapsible, attachments, comments, activity ── */
[data-theme="dark"] .lv-toolbar-btn { border-color: var(--maktab-border); color: var(--maktab-text); }
[data-theme="dark"] .lv-toolbar-btn:hover { background: rgba(255,255,255,0.06); }
[data-theme="dark"] .lv-add-btn { border-color: var(--maktab-border); color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-add-btn:hover { background: rgba(255,255,255,0.06); color: var(--maktab-text); border-color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-delete-btn { color: #D48A74; border-color: #D48A74; }
[data-theme="dark"] .lv-delete-btn:hover { background: rgba(212,138,116,0.1); }
[data-theme="dark"] .lv-collapse-icon { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-attachment-row { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-attachment-meta { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-comment { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-comment-author { color: var(--maktab-text); }
[data-theme="dark"] .lv-comment-time { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-comment-content { color: var(--maktab-text); }
[data-theme="dark"] .lv-comment-input { background: var(--control-bg); color: var(--maktab-text); border-color: var(--maktab-border); }
[data-theme="dark"] .lv-comment-post-btn { background: var(--maktab-dark-brown); color: var(--maktab-text); }
[data-theme="dark"] .lv-activity-entry { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-activity-change { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-activity-field { color: var(--maktab-text); }
[data-theme="dark"] .lv-activity-old { color: #D48A74; }
[data-theme="dark"] .lv-activity-new { color: #A8D4A0; }

/* ── LV status bars (terminated was missing) ── */
[data-theme="dark"] .lv-status-terminated { background: rgba(107,63,160,0.15); color: #C4A8E8; }

/* ── LV cards, rows, labels, values ── */
[data-theme="dark"] .lv-card { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-card-title { color: var(--maktab-text); }
[data-theme="dark"] .lv-label { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-value { color: var(--maktab-text); }
[data-theme="dark"] .lv-text-muted { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-text-warn { color: #E0B06A; }
[data-theme="dark"] .lv-empty { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-tenant-name-ar { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-ejar-contact { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-phone { color: var(--maktab-link); }
[data-theme="dark"] .lv-contact-name { color: var(--maktab-text-muted); }
[data-theme="dark"] .lv-file-link { color: var(--maktab-link); }
[data-theme="dark"] .lv-map-link { color: var(--maktab-link); }
[data-theme="dark"] .lv-notes-input { background: var(--control-bg); color: var(--maktab-text); border-color: var(--maktab-border); }
[data-theme="dark"] .lv-save-notes { background: var(--maktab-brown); color: #fff; border-color: var(--maktab-brown); }
[data-theme="dark"] .lv-row { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-row-total { border-top-color: var(--maktab-border); }
[data-theme="dark"] .lv-table th { color: var(--maktab-text-muted); border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-table td { color: var(--maktab-text); border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .lv-invoice-link { color: var(--maktab-link); }

/* ── LV summary cards (list pages) ── */
[data-theme="dark"] .lv-summary-card,
[data-theme="dark"] .ll-summary-card,
[data-theme="dark"] .prl-summary-card,
[data-theme="dark"] .ul-summary-card,
[data-theme="dark"] .tl-summary-card { background: var(--card-bg); }
[data-theme="dark"] .lv-summary-value,
[data-theme="dark"] .ll-summary-value,
[data-theme="dark"] .prl-summary-value,
[data-theme="dark"] .ul-summary-value,
[data-theme="dark"] .tl-summary-value { color: var(--maktab-text); }
[data-theme="dark"] .lv-summary-label,
[data-theme="dark"] .ll-summary-label,
[data-theme="dark"] .prl-summary-label,
[data-theme="dark"] .ul-summary-label,
[data-theme="dark"] .tl-summary-label { color: var(--maktab-text-muted); }

/* ── List page rows ── */
[data-theme="dark"] .ll-row,
[data-theme="dark"] .prl-row,
[data-theme="dark"] .ul-row,
[data-theme="dark"] .tl-row { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .ll-row:hover,
[data-theme="dark"] .prl-row:hover,
[data-theme="dark"] .ul-row:hover,
[data-theme="dark"] .tl-row:hover { background: rgba(255,255,255,0.03); }
[data-theme="dark"] .ll-tenant-link,
[data-theme="dark"] .ul-tenant-link { color: var(--maktab-link); }

/* ── PL (Payments List) ── */
[data-theme="dark"] .pl-summary-card { background: var(--card-bg); }
[data-theme="dark"] .pl-summary-value { color: var(--maktab-text); }
[data-theme="dark"] .pl-summary-label { color: var(--maktab-text-muted); }
[data-theme="dark"] .pl-table th { color: var(--maktab-text-muted); border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .pl-table td { color: var(--maktab-text); border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .pl-table-card { background: var(--card-bg); }
[data-theme="dark"] .pl-clickable-row:hover { background: rgba(255,255,255,0.04); }
[data-theme="dark"] .pl-cancelled-badge { background: rgba(192,115,94,0.15); color: #D48A74; }

/* ── WD (Wasi Dashboard) extras ── */
[data-theme="dark"] .wd-action-card { background: var(--card-bg); }
[data-theme="dark"] .wd-action-card:hover { background: var(--subtle-fg); }
[data-theme="dark"] .wd-stat-value { color: var(--maktab-text); }
[data-theme="dark"] .wd-stat-label { color: var(--maktab-text-muted); }

/* ── TP (Tenant Portal) — full coverage ── */
[data-theme="dark"] .tenant-portal-page { background: #1A1510; }
[data-theme="dark"] .tp-header { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .tp-logout { color: #D48A74; }
[data-theme="dark"] .tp-info-label { color: var(--maktab-text-muted); }
[data-theme="dark"] .tp-info-row { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .tp-section-title { color: var(--maktab-text-muted); }
[data-theme="dark"] .tp-table th { color: var(--maktab-text-muted); border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .tp-table td { border-bottom-color: var(--maktab-border); }
[data-theme="dark"] .tp-outstanding-label { color: #D4B96A; }
[data-theme="dark"] .tp-outstanding-amount { color: #D48A74; }
[data-theme="dark"] .tp-badge-active, [data-theme="dark"] .tp-badge-received { background: rgba(125,155,118,0.2); color: #A8D4A0; }
[data-theme="dark"] .tp-badge-expired { background: rgba(192,115,94,0.2); color: #D48A74; }
[data-theme="dark"] .tp-badge-pending, [data-theme="dark"] .tp-badge-partial,
[data-theme="dark"] .tp-badge-open { background: rgba(139,105,20,0.2); color: #D4B96A; }
[data-theme="dark"] .tp-btn-primary { background: var(--maktab-brown); color: #fff; }
[data-theme="dark"] .tp-btn-primary:hover { background: #A08A6A; }
[data-theme="dark"] .tp-btn-small { background: var(--maktab-brown); color: #fff; }
[data-theme="dark"] .tp-btn-small:hover { background: #A08A6A; }
[data-theme="dark"] .tp-title { color: #E8DCC8; }
[data-theme="dark"] .tp-subtitle { color: var(--maktab-text-muted); }
[data-theme="dark"] .tp-field label { color: var(--maktab-text-muted); }
[data-theme="dark"] .tp-field input:focus { border-color: var(--maktab-brown); }
[data-theme="dark"] .tp-logo img { filter: brightness(0.9); }

/* ── Not-linked (show_not_tenant) branded recovery state ─────────────── */
.tp-not-linked { max-width: 540px; margin: 0 auto; }
.tp-not-linked-brand {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	margin-bottom: 24px;
}
.tp-not-linked-brand img { display: block; }
.tp-not-linked-brandline {
	font-size: 18px;
	font-weight: 600;
	color: #5a4a3b;
	letter-spacing: 0.5px;
}
.tp-not-linked-brandline .tp-brand-sep {
	color: #B8A898;
	margin: 0 6px;
}
.tp-not-linked-title {
	color: #C0735E;
	font-size: 22px;
	font-weight: 700;
	margin: 0 0 16px;
}
.tp-not-linked-copy {
	color: #6F5F4F;
	font-size: 15px;
	line-height: 1.6;
	margin: 0 auto 18px;
	max-width: 460px;
}
.tp-not-linked-contact {
	list-style: none;
	padding: 16px 20px;
	margin: 0 auto 24px;
	max-width: 380px;
	background: #fff;
	border-radius: var(--r-md, 8px);
	border: 1px solid #E0D5C5;
	text-align: left;
}
.tp-not-linked-contact li {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 6px 0;
	font-size: 14px;
}
.tp-not-linked-contact li + li {
	border-top: 1px solid rgba(139,125,107,0.10);
}
.tp-contact-label {
	color: #8C7A6B;
	font-weight: 600;
	min-width: 60px;
}
.tp-contact-value {
	color: #5a4a3b;
	text-decoration: none;
}
.tp-contact-value:hover { text-decoration: underline; }
.tp-not-linked-logout {
	margin-top: 28px;
	font-size: 13px;
}
.tp-not-linked-logout a {
	color: var(--crit, #C0735E);
	text-decoration: none;
}
[data-theme="dark"] .tp-not-linked-brandline { color: #E8DCC8; }
[data-theme="dark"] .tp-not-linked-copy { color: #C8BCAB; }
[data-theme="dark"] .tp-not-linked-contact {
	background: #24201A;
	border-color: var(--maktab-border, #3a3329);
}
[data-theme="dark"] .tp-contact-value { color: #E8DCC8; }

/* Mobile */
@media (max-width: 768px) {
	.tp-container { padding: 12px 10px 30px; }
	.tp-card { padding: 14px; }
	.tp-table { font-size: 12px; }
	.tp-table th, .tp-table td { padding: 6px 6px; }
	.tp-outstanding { flex-direction: column; gap: 4px; text-align: center; }
	.tp-not-linked { padding: 40px 16px; }
	.tp-not-linked-title { font-size: 20px; }
	.tp-not-linked-contact { max-width: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE CARDS — Convert list page tables to card layout on mobile
   Tables with data-label="X" attributes on each <td> become stacked cards.
   Applied to: hh-table, hs-table, vh-table, he-table, ll-table, etc.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
	.hh-table, .hs-table, .vh-table, .he-table {
		display: block;
	}
	.hh-table thead, .hs-table thead, .vh-table thead, .he-table thead {
		display: none;
	}
	.hh-table tbody, .hs-table tbody, .vh-table tbody, .he-table tbody {
		display: block;
	}
	.hh-table tr, .hs-table tr, .vh-table tr, .he-table tr {
		display: block;
		background: var(--card-bg, #fff);
		border: 1px solid var(--maktab-border);
		border-radius: var(--r-md);
		padding: 12px 14px;
		margin-bottom: 10px;
		box-shadow: none;
	}
	.hh-table td, .hs-table td, .vh-table td, .he-table td {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 6px 0;
		border: none;
		border-bottom: 1px solid rgba(139,125,107,0.08);
		font-size: 13px;
	}
	.hh-table td:last-child, .hs-table td:last-child,
	.vh-table td:last-child, .he-table td:last-child {
		border-bottom: none;
	}
	.hh-table td::before, .hs-table td::before,
	.vh-table td::before, .he-table td::before {
		content: attr(data-label);
		font-weight: 600;
		color: var(--maktab-text-muted);
		font-size: 11px;
		text-transform: uppercase;
		letter-spacing: 0.4px;
		margin-inline-end: 12px;
	}
	/* First cell becomes the card title */
	.hh-table td:first-child, .hs-table td:first-child,
	.vh-table td:first-child, .he-table td:first-child {
		font-size: 15px;
		font-weight: 700;
		color: var(--maktab-text);
		padding-bottom: 8px;
		margin-bottom: 4px;
		border-bottom: 1px solid rgba(139,125,107,0.15);
	}
	.hh-table td:first-child::before, .hs-table td:first-child::before,
	.vh-table td:first-child::before, .he-table td:first-child::before {
		display: none;
	}
}

/* Expenses: cards by default, list toggle. Hidden on desktop. */
.he-view-toggle { display: none; }
@media (max-width: 768px) {
	.he-view-toggle {
		display: inline-flex;
		gap: 4px;
		padding: 4px;
		background: rgba(139,125,107,0.08);
		border-radius: var(--r-md);
		margin-bottom: 12px;
	}
	.he-view-toggle button {
		padding: 4px 12px;
		border: none;
		background: transparent;
		color: var(--maktab-text-muted);
		font-size: 12px;
		cursor: pointer;
		border-radius: var(--r-sm);
	}
	.he-view-toggle button.active {
		background: var(--card-bg);
		color: var(--maktab-text);
		box-shadow: none;
	}
	/* When in list mode, override the card display */
	.he-table.he-list-mode { display: table; }
	.he-table.he-list-mode thead { display: table-header-group; }
	.he-table.he-list-mode tbody { display: table-row-group; }
	.he-table.he-list-mode tr { display: table-row; background: transparent; border: none; padding: 0; margin: 0; box-shadow: none; }
	.he-table.he-list-mode td { display: table-cell; padding: 8px 6px; border-bottom: 1px solid var(--maktab-border); font-size: 12px; }
	.he-table.he-list-mode td::before { display: none; }
	.he-table.he-list-mode td:first-child { font-size: 12px; font-weight: 400; padding: 8px 6px; margin: 0; border-bottom: 1px solid var(--maktab-border); }
}

/* Wasi dashboard: section title contrast + tone down the quick-action
   buttons per user feedback (they stand out too hard in dark mode). */
[data-theme="dark"] .wd-section-title,
[data-theme="dark"] .wd-summary-label,
[data-theme="dark"] .wd-alert-days {
	color: #B8A890 !important;
}
[data-theme="dark"] .wd-action-rent {
	background: #1E3A1E !important;
	color: var(--ink) !important;
}
[data-theme="dark"] .wd-action-rent:hover {
	background: #15281D !important;
	color: #FFFFFF !important;
}
[data-theme="dark"] .wd-action-maint {
	background: #1E3A55 !important;
	color: var(--ink) !important;
}
[data-theme="dark"] .wd-action-maint:hover {
	background: #15283F !important;
	color: #FFFFFF !important;
}
[data-theme="dark"] .wd-action-report {
	background: #4A3A00 !important;
	color: var(--ink) !important;
}
[data-theme="dark"] .wd-action-report:hover {
	background: #3A2A00 !important;
	color: #FFFFFF !important;
}

/* Home page action cards — make sure titles + subtitles pass contrast */
[data-theme="dark"] .maktab-action-card .card-title,
[data-theme="dark"] .maktab-action-card .card-subtitle {
	color: var(--straw) !important;
}


/* Generic Frappe buttons in dark mode — force tan → dark */
[data-theme="dark"] .btn.btn-primary,
[data-theme="dark"] button.btn-primary {
	background: var(--brown-night) !important;
	border-color: var(--brown-night) !important;
	color: var(--ink) !important;
}
[data-theme="dark"] .btn.btn-primary:hover,
[data-theme="dark"] button.btn-primary:hover {
	background: #1A1510 !important;
	color: #FFFFFF !important;
}
[data-theme="dark"] .btn.btn-secondary,
[data-theme="dark"] button.btn-secondary {
	background: #24201A !important;
	border-color: var(--maktab-border) !important;
	color: var(--straw) !important;
}

/* Dialog form inputs — Frappe's .form-control needs a dark-mode bg */
[data-theme="dark"] .form-control,
[data-theme="dark"] .modal .form-control {
	background: #1A1510 !important;
	color: var(--ink) !important;
	border-color: var(--maktab-border) !important;
}
[data-theme="dark"] .form-control::placeholder {
	color: #8A7A6A !important;
}

/* Remaining individual one-offs from the final sweep */
[data-theme="dark"] .wd-summary-number,
[data-theme="dark"] .wd-summary-sar {
	color: var(--ink) !important;
}
[data-theme="dark"] .wd-summary-sub.wd-text-red {
	color: #E8A890 !important;
}
[data-theme="dark"] .tr-year-btn.tr-year-active {
	background: var(--brown-night) !important;
	color: #FFFFFF !important;
	border-color: var(--brown-night) !important;
}
[data-theme="dark"] .tr-year-btn {
	background: #24201A !important;
	color: var(--straw) !important;
	border-color: var(--maktab-border) !important;
}

/* Audit fix R2: tenant-view delete button + attachment metadata were
   below WCAG AA in both modes — tenant-view wasn't in the sprint
   sweep baseline so the violations slipped through. */
[data-theme="dark"] .lv-delete-btn { color: #E8A890 !important; border-color: #E8A890 !important; }
[data-theme="dark"] .lv-attachment-meta { color: #B8A890 !important; }

/* Dark-mode legibility for plain Bootstrap `<small class="text-muted">`
   (Frappe's #9a8a7a fails against dark backgrounds). The
   .reconciliation-report-scoped selectors were dropped 2026-06-03 (recon
   is now a .recon-* div-grid, no Bootstrap table cells); the generic
   selector is kept for any other surface that still uses the markup. */
[data-theme="dark"] small.text-muted {
	color: #B8A890 !important;
}

/* Audit second-pass: detail views (tenant-view, property-view,
   lease-view, unit-view, payment-view) had contrast issues in both
   modes because the shared .lv-* classes used muted colors that
   hadn't been dark-mode-audited. Fix them once here. */

/* .lv-save-notes — button uses --maktab-brown bg (which is the tan
   #C4A882 in dark mode) with white text = 2.26. Force dark bg. */
.lv-save-notes {
	background: var(--brown-night) !important;
	color: #FFFFFF !important;
	border-color: var(--brown-night) !important;
}
.lv-save-notes:hover {
	background: #1A1510 !important;
	color: #FFFFFF !important;
}

/* .lv-status-detail — was #5c7c5b on a light green bg = 3.95 (barely
   fails). Darken the text. */
.lv-status-detail { color: #2E5C2E !important; }
[data-theme="dark"] .lv-status-detail { color: #9ED29E !important; }

/* .lv-unit-occupied — same pattern, dark green on dark bg in dark mode */
.lv-unit-occupied,
.lv-unit-vacant {
	color: #2E5C2E !important;
}
[data-theme="dark"] .lv-unit-occupied,
[data-theme="dark"] .lv-unit-vacant {
	color: #9ED29E !important;
}

/* .lv-cancel-btn — the cancel action in the edit toolbar used amber
   var(--sand-deep) on cream which is 4.47 (fails 4.5 strict). Darken slightly. */
.lv-cancel-btn {
	color: #7A5510 !important;
	border-color: #7A5510 !important;
}
.lv-cancel-btn:hover { background: rgba(122, 85, 16, 0.08) !important; }
[data-theme="dark"] .lv-cancel-btn {
	color: #E8C88A !important;
	border-color: #E8C88A !important;
}
[data-theme="dark"] .lv-cancel-btn:hover { background: rgba(232, 200, 138, 0.10) !important; }

/* Light-mode lease view: inline `<div style="text-align:right">` for
   money values was inheriting var(--crit) from a parent — target the
   class `lv-money` directly for the money color. */
.lv-money { color: var(--brown-night) !important; }
[data-theme="dark"] .lv-money { color: var(--ink) !important; }

/* Shared empty-state text for list/comment/activity sections — replaces
   hardcoded inline #B8A898 which was failing WCAG AA in light mode. */
.lv-empty-inline {
	color: var(--ink-muted);
	font-size: 13px;
	font-style: italic;
}
[data-theme="dark"] .lv-empty-inline { color: #B8A890; }

/* ──────────────────────────────────────────────────────────────────────
   Shared list renderer (maktab.render_rich_list)
   Uses the proven .lv-table class for the table itself — this block only
   styles the wrapper, summary cards, toolbar, and pills. Mobile card
   transformation is done via the .lv-table media query below.
   ────────────────────────────────────────────────────────────────────── */
.maktab-list {
	padding: 16px 20px 32px;
	max-width: 100%;
}
/* NOTE: .maktab-list-summary / .maktab-list-card* base + tone rules were
   consolidated into rich-list.css (the sole owner). The fade-in keyframe
   and summary load-state moved with them. */

/* ── New-record button — standalone base styles (no parent dependency) ──
   Applies wherever .maktab-new-btn is used: list toolbars, pv-units-toolbar,
   hv-staff-toolbar, mv-events-toolbar, etc. */
.maktab-new-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 8px 10px;
	min-width: 40px;
	min-height: 40px;
	background: var(--maktab-brown);
	color: #fff;
	border: none;
	border-radius: var(--r-md);
	font-size: 14px;
	font-weight: 600;
	font-family: inherit;
	cursor: pointer;
	white-space: nowrap;
	flex: 0 0 auto;
}
.maktab-new-btn:hover { background: #3a2f23; }  /* literal — brown-deep flips to cream in dark, breaks hover direction */
.maktab-new-btn svg { flex-shrink: 0; }
.maktab-new-btn:focus-visible { outline: 2px solid var(--maktab-amber); outline-offset: 2px; }

/* Toolbar — one row: [+ New] [pills] [search]. Wraps on narrow screens. */
.maktab-list-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin-bottom: 16px;
	position: sticky;
	top: 0;
	z-index: 2;
	background: var(--maktab-beige);
	padding: 8px 0;
}

.maktab-list-toolbar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; width: 100%; }
.maktab-list-toolbar-row .maktab-new-btn { flex: none; }
.maktab-list-pills { flex: 0 1 auto; min-width: 0; display: flex; flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.maktab-list-pills::-webkit-scrollbar { display: none; }
.maktab-list-pill { flex-shrink: 0; }
.maktab-list-search { flex: 1 1 240px; min-width: 0; }

/* When the toolbar lives inside a .pv-tab-body (property-view,
   household-view, majlis-view), only the .pv-tab-strip (~38px) sits
   above it now — the page-head is hidden — so stack at 38px. */
.pv-tab-body .maktab-list-toolbar {
	top: 38px;
}
/* .maktab-list-toolbar .maktab-new-btn — no additional overrides needed;
   base styles above handle it fully. */

.maktab-list-pills {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 6px;
	flex: 0 1 auto;
}
.maktab-list-pill {
	display: inline-flex;
	align-items: center;
	padding: 8px 14px;
	height: 38px;
	background: transparent;
	color: var(--maktab-text);
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	font-size: 13px;
	font-weight: 600;
	font-family: inherit;
	cursor: pointer;
	transition: background 0.15s, border-color 0.15s, color 0.15s;
	white-space: nowrap;
}
.maktab-list-pill:hover {
	background: var(--maktab-beige);
	border-color: var(--maktab-sand);
}
.maktab-list-pill.active {
	background: var(--maktab-brown);
	color: #fff;
	border-color: var(--maktab-brown);
}

/* ── Active filter pill: always-light text ──
   var(--cream) flips to dark cocoa in dark mode, which loses contrast
   against the always-dark --brown-deep active bg. Lock active-pill text
   to the light cream hex regardless of theme. Same trick the sidebar
   uses for "brand chrome that doesn't theme-flip". */
.aa-action-pill.active,
.mo-pill.active,
.au-filter-pill.active,
.f-pill.is-active,
.tr-year-tab.is-active,
.tr-year-tab.active {
	color: #F5F0E6 !important;
}

/* ── FB-2026-00205 (round 2): entity-ledger source pills retoken'd to canonical
   .f-pill foundation — see .el-container .f-pill block below. Round 1's
   bespoke .el-source-pill rules (JS-injected base + CSS overrides here) were
   replaced wholesale: the canonical .f-pill rule already provides hover,
   focus-visible, .is-active flip, and dark-mode contrast. */

/* ── Entity Ledger filter pills — canonical .f-pill, page-scoped ──
   Toggleable filter-pill chrome (sizing, transitions, light/dark contrast,
   .is-active flip). The income/expense color dot prefix is added on top. */
.el-container .f-pills,
.el-container .el-source-pills {
	display: flex;
	gap: var(--s-2);
	flex-wrap: wrap;
	align-items: center;
}
.el-container .f-pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 12px;
	font-size: var(--text-sm);
	font-weight: 500;
	border-radius: var(--r-sq);
	background: var(--cream);
	color: var(--ink);
	border: 1px solid var(--border);
	cursor: pointer;
	font-family: var(--font-ar);
	transition: background-color var(--dur-fast) ease,
	            color var(--dur-fast) ease,
	            border-color var(--dur-fast) ease;
	line-height: 1.4;
}
.el-container .f-pill:hover { border-color: var(--sand); }
.el-container .f-pill.is-active {
	background: var(--brown-deep);
	color: var(--cream);
	border-color: var(--brown-deep);
}
.el-container .f-pill:focus-visible {
	outline: 2px solid var(--maktab-amber);
	outline-offset: 2px;
}
/* Dark-mode: --brown-deep and --cream both flip toward dark-on-dark; promote
   active state to --sand bg for distinct contrast against inactive --cream. */
[data-theme="dark"] .el-container .f-pill.is-active {
	background: var(--sand);
	border-color: var(--sand);
	color: var(--ink) !important;
}
[data-theme="dark"] .el-container .f-pill:not(.is-active) {
	background: transparent;
	border-color: var(--border);
}

.maktab-list-pill.active:hover {
	background: var(--brown-deep);
	border-color: var(--brown-deep);
	color: #fff;
}
.maktab-list-pill-count {
	margin-inline-start: 4px;
	opacity: 0.75;
	font-weight: 500;
	font-size: 12px;
}
.maktab-list-pill:focus-visible { outline: 2px solid var(--maktab-amber); outline-offset: 2px; }

/* Search — grows to fill remaining row on desktop, full-width on mobile */
.maktab-list-search {
	position: relative;
	display: flex;
	align-items: center;
	flex: 1 1 220px;
	min-width: 180px;
	height: 40px;
}
.maktab-list-search-icon {
	position: absolute;
	inset-inline-start: 12px;
	color: var(--maktab-text-muted);
	pointer-events: none;
}
.maktab-list-search-input {
	width: 100%;
	height: 40px;
	padding: 0 14px 0 38px;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-md);
	background: var(--card-bg, #fff);
	color: var(--maktab-text);
	font-size: 14px;
	font-family: inherit;
}
[dir="rtl"] .maktab-list-search-input { padding: 0 38px 0 14px; }
.maktab-list-search-input:focus { outline: none; border-color: var(--maktab-brown); }
.maktab-list-search-input::placeholder { color: var(--maktab-text-muted); }
.maktab-list-search-clear {
	position: absolute;
	inset-inline-end: 10px;
	background: none;
	border: none;
	font-size: 20px;
	color: var(--maktab-text-muted);
	cursor: pointer;
	line-height: 1;
	padding: 0 6px;
}

/* Table wrapper — keep the proven .lv-table styles doing the heavy lifting */
.maktab-list-table-wrap {
	padding: 16px 18px;
}
.maktab-list-table-wrap .lv-table.maktab-list-table {
	margin: 0;
}
.maktab-list-table.lv-table {
	table-layout: auto;
	width: 100%;
}
.maktab-list-table thead th {
	white-space: nowrap;
}
.maktab-list-table tbody tr.maktab-list-row {
	transition: background 0.1s;
}
.maktab-list-table tbody tr.maktab-list-row:hover td {
	background: rgba(212, 197, 160, 0.08);
}
.maktab-list-table tr.maktab-list-loading td,
.maktab-list-table tr.maktab-list-empty td,
.maktab-list-table tr.maktab-list-error td {
	padding: 40px 20px;
	text-align: center;
	color: var(--maktab-text-muted);
	font-style: italic;
}
.maktab-list-table tr.maktab-list-error td { color: var(--overdue); }
/* FB-2026-00299: header cells in numeric columns also need text-align:end —
   without this the column header is left-aligned while the values float to
   the right (bidi-driven for SAR currency formatted "ر.س 4,400.00"), so
   the title visibly drifts away from the column contents. */
.maktab-list-table td.maktab-list-num,
.maktab-list-table th.maktab-list-num { text-align: end; }
.maktab-list-table td,
.maktab-list-table th {
	padding: 10px 12px;
}

/* Mobile layout: toolbar stacks, summary cards go 2-wide. TABLES become
   cards via the lv-table mobile media query extension below. */
@media (max-width: 768px) {
	.maktab-list {
		padding: 12px 0 24px;
	}
	/* .maktab-list-summary / .maktab-list-card mobile overrides moved to
	   rich-list.css (sole owner of the summary/card family). */
	/* Mobile toolbar: [+ New] and pills on first row, search on second row.
	   Layout lives on .maktab-list-toolbar-row (the actual flex child). */
	.maktab-list-toolbar { display: block !important; }
	.maktab-list-toolbar-row { gap: 8px; }
	.maktab-list-toolbar-row .maktab-new-btn { width: 40px; height: 40px; padding: 0; justify-content: center; }
	.maktab-list-toolbar-row .maktab-new-btn .maktab-new-btn-label,
	.maktab-list-toolbar-row .maktab-new-btn span { display: none; }
	.maktab-list-pill { padding: 6px 10px !important; height: 36px !important; font-size: 12px !important; }
	.maktab-list-search { flex-basis: 200px; }
	.maktab-list-table-wrap {
		padding: 0;
		background: transparent !important;
		border: none;
		box-shadow: none;
	}
}

/* Dark mode */
[data-theme="dark"] .maktab-new-btn {
  background: var(--surface-inverse);
  color: var(--brown-deep);
  border: 1px solid var(--brown-deep);
}
[data-theme="dark"] .maktab-new-btn:hover {
  background: var(--brown-night, #14100B);
}
[data-theme="dark"] .maktab-list-pill-count { opacity: 1; }
/* [data-theme="dark"] .maktab-list-card-* value tones moved to rich-list.css. */
[data-theme="dark"] .maktab-list-pill {
	background: #1A1510;
	color: var(--maktab-text);
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-list-pill:hover {
	background: #24201A;
	border-color: var(--maktab-sand);
}
[data-theme="dark"] .maktab-list-pill.active {
	background: var(--maktab-brown);
	color: var(--maktab-cream);
	border-color: var(--maktab-brown);
}
[data-theme="dark"] .maktab-list-search-input {
	background: #1A1510;
	color: var(--maktab-text);
	border-color: var(--maktab-border);
}
[data-theme="dark"] .maktab-list-search-input::placeholder { color: var(--maktab-text-muted); }
[data-theme="dark"] .maktab-list-table tbody tr.maktab-list-row:hover td {
	background: rgba(212, 197, 160, 0.05);
}

/* Helper classes — kept under the old .rich-list-* names because per-page
   render functions still output them. Safe to leave alone. */
.rich-list-name-cell { font-weight: 600; color: var(--maktab-text); }
.rich-list-badge {
	display: inline-block;
	padding: 3px 10px;
	border-radius: var(--r-lg);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.3px;
	white-space: nowrap;
}
.rich-list-badge-thilth   { background: #e3f2fd; color: #0d47a1; }
.rich-list-badge-khums    { background: #f3e5f5; color: #4a148c; }
.rich-list-badge-personal { background: #fff3e0; color: #7a3f00; }
.rich-list-badge-active,
.rich-list-badge-occupied,
.rich-list-badge-scheduled { background: #e8f5e8; color: #1b5e20; }
.rich-list-badge-expired,
.rich-list-badge-overdue,
.rich-list-badge-cancelled { background: #ffebee; color: #8b1a1a; }
.rich-list-badge-pending,
.rich-list-badge-draft,
.rich-list-badge-requested,
.rich-list-badge-expiring-soon,
.rich-list-badge-on-leave { background: #fff8e1; color: #7a4f00; }
.rich-list-badge-vacant,
.rich-list-badge-inactive,
.rich-list-badge-completed { background: #f5f5f5; color: #616161; }
/* FIX 2 redo 2: distinct Terminated badge — purple, matches the existing
   .lv-status-terminated panel-bar color (#F0E6F6 / #6B3FA0). Reused tokens,
   no new hex values introduced. */
.rich-list-badge-terminated { background: #F0E6F6; color: #6B3FA0; }
.rich-list-badge-confirmed { background: #e1f5fe; color: #01579b; }
.rich-list-badge-distributed,
.rich-list-badge-approved { background: #f1f8e9; color: #33691e; }
.rich-list-badge-neutral { background: var(--beige); color: #5a4a3b; }
[data-theme="dark"] .rich-list-badge-thilth   { background: rgba(144, 202, 249, 0.16); color: #90caf9; }
[data-theme="dark"] .rich-list-badge-khums    { background: rgba(206, 147, 216, 0.16); color: #ce93d8; }
[data-theme="dark"] .rich-list-badge-personal { background: rgba(255, 167, 38, 0.16); color: #ffb74d; }
[data-theme="dark"] .rich-list-badge-active,
[data-theme="dark"] .rich-list-badge-occupied,
[data-theme="dark"] .rich-list-badge-scheduled { background: rgba(143, 184, 143, 0.18); color: #9ed29e; }
[data-theme="dark"] .rich-list-badge-expired,
[data-theme="dark"] .rich-list-badge-overdue,
[data-theme="dark"] .rich-list-badge-cancelled { background: rgba(212, 138, 116, 0.18); color: #e8a890; }
[data-theme="dark"] .rich-list-badge-pending,
[data-theme="dark"] .rich-list-badge-draft,
[data-theme="dark"] .rich-list-badge-requested,
[data-theme="dark"] .rich-list-badge-expiring-soon,
[data-theme="dark"] .rich-list-badge-on-leave { background: rgba(224, 176, 106, 0.18); color: #e8c88a; }
[data-theme="dark"] .rich-list-badge-vacant,
[data-theme="dark"] .rich-list-badge-inactive,
[data-theme="dark"] .rich-list-badge-completed { background: rgba(212, 197, 160, 0.12); color: #b8a890; }
[data-theme="dark"] .rich-list-badge-terminated { background: rgba(107,63,160,0.18); color: #C4A8E8; }
[data-theme="dark"] .rich-list-badge-confirmed { background: rgba(129, 212, 250, 0.18); color: #81d4fa; }
[data-theme="dark"] .rich-list-badge-distributed,
[data-theme="dark"] .rich-list-badge-approved { background: rgba(170, 214, 107, 0.18); color: #aad66b; }
[data-theme="dark"] .rich-list-badge-neutral { background: rgba(212,197,160,0.10); color: var(--straw); }

/* FB-92 — Theme 7. FB-93: side padding aligned with peer pages.
   FB-2026-00195 (re-opened): removed `container-type: inline-size` — it
   established CSS containment that froze the sticky `.fb-filter-row`
   layout context across viewport-breakpoint crossings (sidebar collapse
   animation changing the container's inline-size left the sticky
   descendant's containing block stale until a hover triggered a recalc).
   No `@container` queries depend on this anchor (verified via grep on
   maktab.css), so the property was dormant — safe to remove. */
.feedback-list-container {
	/* 760px keeps the 6 summary cards in a clean 4+2 wrap instead of an
	   awkward 5+1 (FB-2026-00234). Below 4-per-row the auto-fit grid still
	   collapses gracefully. */
	max-width: 760px; margin: 0 auto; padding: 0 16px;
}
/* end FB-92 */

@media (max-width: 768px) {
	.feedback-list-container {
		padding: 8px 12px 30px;
	}
	/* WebKit UA sheet adds overflow:hidden to <select appearance:none>,
	   which clips descenders (g, y, p) at the bottom of the text box.
	   Desktop Chromium doesn't do this — reset to match. */
	select {
		overflow: visible !important;
	}
}

/* ═══ Feedback list cards ═══ */
/* FB-2026-00209: card bg differentiated from page bg via --cream (canonical
   card surface) — page is --beige. 1px border in --border defines the edge.
   Dark mode auto-flips via the token (cream=#221C14 over beige=#18130D). */
.fb-card {
	margin-bottom: 16px;
	padding: 16px;
	background: var(--cream);
	border: 1px solid var(--border);
	border-radius: var(--r-md);
}
/* Feedback row status stripe retired — status is carried by the inline
   .maktab-pill on each card. */

.fb-card .rc-card-header { flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.fb-left-badges { display: flex; gap: 6px; flex-wrap: wrap; }
.fb-right-meta  { display: flex; gap: 10px; font-size: 12px; color: var(--maktab-text-muted); flex-wrap: wrap; align-items: center; }
.fb-meta        { color: var(--maktab-text-muted); }
/* FB-2026-00211: surface the Feedback name (FB-YYYY-NNNNN) on every card so
   the user can copy it when reporting. Monospace, muted, selectable, no bg. */
.fb-card-id {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 11px;
	color: var(--maktab-text-muted);
	letter-spacing: 0.2px;
	user-select: text;
	-webkit-user-select: text;
}

.fb-description {
	white-space: pre-wrap;
	word-wrap: break-word;
	margin: 12px 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--maktab-text);
}

.fb-context {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 12px 0;
}
.fb-context-chip {
	font-size: 11px;
	padding: 3px 8px;
	border: 1px solid var(--maktab-border);
	border-radius: var(--r-lg);
	color: var(--maktab-text-muted);
	background: var(--maktab-cream);
}

.fb-attachment { margin: 12px 0; }
.fb-attach-btn { padding: 6px 14px !important; font-size: 13px !important; }

/* Feedback list filter row — sticky + scrollable on mobile.
   FB-2026-00379: explicit `display: flex` + `flex-direction: row` so pills
   sit in a single horizontal strip. Previously the row was a block container
   that relied on the adjacent .rc-filters class (now removed in feedback_list.js)
   to provide flex layout; without it pills collapsed to full-width stacked. */
.fb-filter-row {
	position: sticky;
	top: 0;
	z-index: 5;
	background: var(--maktab-beige);
	padding: 8px 0;
	margin-bottom: 16px;
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 6px;
	/* allow internal horizontal scroll without pushing the page wider */
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	flex-wrap: nowrap;
}
.fb-filter-row::-webkit-scrollbar { display: none; }
/* Keep pills on one line so horizontal scroll is meaningful */
.fb-filter-row .maktab-list-pill { flex: 0 0 auto; white-space: nowrap; }
/* Dark mode: use a solid surface so rows scrolling behind remain legible */
[data-theme="dark"] .fb-filter-row { background: var(--maktab-bg); }

.fb-status-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid var(--maktab-border);
}
.fb-status-btn {
	padding: 6px 12px;
	font-size: 13px;
	border: 1px solid var(--maktab-border);
	background: var(--maktab-cream);
	color: var(--maktab-text);
	border-radius: var(--r-md);
	cursor: pointer;
	transition: background 0.15s ease;
}
.fb-status-btn:hover:not(.is-current):not(:disabled) { background: var(--maktab-straw); }
.fb-status-btn.is-current {
	background: var(--maktab-brown);
	color: var(--maktab-white);
	border-color: var(--maktab-brown);
	cursor: default;
}
.fb-status-btn:disabled:not(.is-current) { opacity: 0.5; cursor: wait; }

[data-theme="dark"] .fb-context-chip { background: var(--maktab-straw); }
[data-theme="dark"] .fb-status-btn   { background: var(--maktab-straw); }
[data-theme="dark"] .fb-status-btn.is-current { background: var(--maktab-brown); color: var(--maktab-white); border-color: var(--maktab-brown); }

@media (max-width: 768px) {
	.fb-card { padding: 14px; }
	.fb-status-actions { gap: 8px; }
	.fb-status-btn { flex: 1 1 calc(50% - 8px); min-height: 36px; }
}

/* ── FB-2026-00212: feedback card → opens slide-panel detail view ────── */
.fb-card { cursor: pointer; }
.fb-card:hover { border-color: var(--maktab-brown); }
[data-theme="dark"] .fb-card:hover { border-color: var(--maktab-tan); }
/* Status buttons / attachment links inside the card stay non-pointer for
   the card-click handler (they handle their own clicks via stopPropagation
   via the closest('button,a') check in feedback_list.js). */

/* ── Feedback slide-panel — header card, description, context, comments ─ */
.fb-panel-header {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 12px;
	flex-wrap: wrap;
}
.fb-panel-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.fb-panel-meta {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 12px;
	color: var(--maktab-text-muted);
	text-align: end;
}
.fb-panel-description {
	font-size: 14px;
	line-height: 1.55;
	color: var(--maktab-text);
	white-space: pre-wrap;
	word-break: break-word;
}
.fb-panel-ua {
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 11px;
	color: var(--maktab-text-muted);
	/* FB-2026-00216: user agent strings are one long unbroken token.
	   `.lv-row .lv-value { white-space: nowrap }` (line 4207) wins by
	   specificity, so we re-allow wrap here AND force the long token to
	   break anywhere. overflow-wrap: anywhere covers the modern path. */
	white-space: normal;
	word-break: break-all;
	overflow-wrap: anywhere;
	min-width: 0;
}
/* FB-2026-00216: when the UA value lives inside .lv-row, the row's
   baseline alignment + flex layout can let a long unbroken token push the
   row wider than the panel. Re-allow wrap on the .lv-value when it wraps
   .fb-panel-ua, and switch row alignment so the wrapped lines look clean.
   FB-2026-00224: ALSO force the label to a single line and add a gap so the
   "User agent" / "متصفح المستخدم" label doesn't wrap into two lines that sit
   flush against the value (regression from the FB-216 fix above). */
.lv-row:has(> .lv-value > .fb-panel-ua) { align-items: flex-start; gap: 12px; }
.lv-row:has(> .lv-value > .fb-panel-ua) > .lv-label { white-space: nowrap; flex: 0 0 auto; }
.lv-row > .lv-value:has(> .fb-panel-ua) { white-space: normal; min-width: 0; text-align: end; flex: 1 1 auto; }
.fb-panel-attach-list {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.fb-panel-attach-link {
	color: var(--maktab-sky);
	font-size: 13px;
	text-decoration: none;
}
.fb-panel-attach-link:hover { text-decoration: underline; }

/* Comments thread inside slide-panel */
.fb-comments-card { display: flex; flex-direction: column; gap: 12px; }
.fb-comments-count {
	font-size: 12px;
	font-weight: 500;
	color: var(--maktab-text-muted);
	margin-inline-start: 4px;
}
.fb-comments-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
}
.fb-comments-empty {
	font-size: 13px;
	color: var(--maktab-text-muted);
	padding: 12px 0;
	font-style: italic;
}
.fb-comment {
	display: flex;
	gap: 10px;
	align-items: flex-start;
}
.fb-comment-avatar {
	width: 32px;
	height: 32px;
	flex-shrink: 0;
	border-radius: 50%;
	background: var(--maktab-straw);
	color: var(--maktab-brown);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
}
.fb-comment.is-claude .fb-comment-avatar {
	background: var(--maktab-brown);
	color: var(--maktab-white);
}
.fb-comment-body {
	flex: 1;
	min-width: 0;
}
.fb-comment-head {
	display: flex;
	gap: 8px;
	align-items: baseline;
	flex-wrap: wrap;
	margin-bottom: 4px;
}
.fb-comment-author {
	font-size: 13px;
	font-weight: 600;
	color: var(--maktab-text);
}
.fb-comment-when {
	font-size: 11px;
	color: var(--maktab-text-muted);
}
.fb-comment-content {
	font-size: 13px;
	line-height: 1.5;
	color: var(--maktab-text);
	word-break: break-word;
}
.fb-comment-content p { margin: 0 0 6px; }
.fb-comment-content p:last-child { margin-bottom: 0; }

.fb-comment-input-wrap {
	display: flex;
	flex-direction: column;
	gap: 8px;
	border-top: 1px solid var(--maktab-border);
	padding-top: 12px;
}
.fb-comment-textarea {
	width: 100%;
	box-sizing: border-box;
	padding: 8px 10px;
	border: 1px solid var(--maktab-border);
	border-radius: 6px;
	font-size: 13px;
	font-family: inherit;
	line-height: 1.5;
	color: var(--maktab-text);
	background: var(--maktab-white);
	resize: vertical;
	min-height: 64px;
}
.fb-comment-textarea:focus {
	outline: none;
	border-color: var(--maktab-brown);
}
.fb-comment-input-actions {
	display: flex;
	justify-content: flex-end;
}
.fb-comment-post-btn {
	padding: 6px 16px;
	border: 1px solid var(--maktab-brown);
	background: var(--maktab-brown);
	color: var(--maktab-white);
	font-size: 13px;
	font-weight: 500;
	border-radius: 6px;
	cursor: pointer;
	min-height: 32px;
}
.fb-comment-post-btn:hover:not(:disabled) { background: var(--maktab-brown-dark, var(--maktab-brown)); }
.fb-comment-post-btn:disabled { opacity: 0.5; cursor: not-allowed; }

[data-theme="dark"] .fb-comment-avatar { background: var(--maktab-straw); }
[data-theme="dark"] .fb-comment.is-claude .fb-comment-avatar {
	background: var(--maktab-tan);
	color: var(--maktab-cream);
}
[data-theme="dark"] .fb-comment-textarea {
	background: var(--maktab-cream);
	color: var(--maktab-text);
}

@media (max-width: 768px) {
	.fb-panel-header { flex-direction: column; align-items: stretch; }
	.fb-panel-meta { text-align: start; flex-direction: row; gap: 12px; }
}

/* Native file upload button in feedback dialog */
.maktab-fb-upload {
	padding: 8px 0;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 8px;
}
.maktab-fb-upload .btn,
.maktab-fb-upload .btn.btn-default,
.maktab-fb-upload .btn.btn-sm {
	min-height: 32px;
	padding: 6px 14px !important;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.3;
	background: var(--maktab-cream);
	color: var(--maktab-text);
	border: 1px solid var(--maktab-brown) !important;
	border-top: 1px solid var(--maktab-brown) !important;
	border-radius: var(--r-md);
	cursor: pointer;
	transition: background 0.15s ease, color 0.15s ease;
}
.maktab-fb-upload .btn:hover:not(:disabled) {
	background: var(--maktab-brown);
	color: var(--maktab-white);
}
.maktab-fb-upload .btn:disabled {
	opacity: 0.55;
	cursor: wait;
}
/* Give the "file chosen" label a little breathing room on its own line if needed */
.maktab-fb-upload #maktab-fb-file-name {
	margin-inline-start: 0;
}
[data-theme="dark"] .maktab-fb-upload .btn {
	background: var(--maktab-straw);
	border: 1px solid var(--maktab-sand) !important;
	border-top: 1px solid var(--maktab-sand) !important;
}
[data-theme="dark"] .maktab-fb-upload .btn:hover:not(:disabled) {
	background: var(--maktab-brown);
	color: var(--maktab-white);
	border-color: var(--maktab-brown);
}


/* The My Account .maktab-ma-* / .maktab-my-account block (incl. the
   my-account route bg override + mobile padding fix) was removed
   2026-06-03 in the v3 rethink — it now ships public/css/my_account.css
   (.ma-* banner + inline-edit + instant prefs + the carried 2FA block). */

/* ── FB-2026-00044 — Safari iOS URL bar transparency ──────────────────────
   Frappe's show_alert() creates #dialog-container > #alert-container in the
   DOM once and leaves them there permanently (individual toasts are removed
   after fade, but the wrappers stay). #alert-container is position:fixed at
   bottom:0 — Safari's compositor sees a fixed-bottom element and switches the
   URL bar to opaque mode. Force #alert-container transparent so Safari sees
   through it. pointer-events:none prevents the empty wrapper intercepting taps.
   Individual .desk-alert toasts keep their own background-color from
   var(--toast-bg) — only the wrapper is affected.

   Round 2 — lift the container off bottom:0 by env(safe-area-inset-bottom)
   so the safe-area strip is never occupied by a fixed element.

   Round 3 (P3.3) — mobile media query at end of file raises the container
   to clear the 72px bottom nav (see P3.3 Toast redesign section below).

   NOTE: Do NOT add pointer-events:none to #dialog-container. Frappe v15 mounts
   ALL modal dialogs (frappe.ui.Dialog) inside #dialog-container. Setting
   pointer-events:none on the container cascades into modals and makes their
   interactive elements (buttons, inputs, textareas) unresponsive to touch —
   causing FB-2026-00046 (dialog dismisses on upload tap) and FB-2026-00048
   (dead zones in feedback dialog). The toast wrapper transparency is achieved
   via #alert-container alone; #dialog-container does NOT host toast alerts. */
#alert-container {
	background: transparent !important;
	pointer-events: none;
	/* 24px fallback ensures we lift off bottom even when env() resolves to 0px
	   (headless / non-notch devices). On notch devices the inset (typically
	   34px on iPhone 14) wins; on flat-bottom devices we still stay 24px up
	   so the container never sits flush against the URL bar zone. */
	bottom: env(safe-area-inset-bottom, 24px) !important;
}
/* Re-enable pointer events on actual toast children so they stay clickable */
#alert-container .desk-alert {
	pointer-events: auto;
}

/* ── Impersonation banner (Phase 5e) ── */
#maktab-impersonation-banner {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	background: #dc2626;
	color: #fff;
	padding: 10px 20px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 14px;
	font-weight: 600;
	z-index: 9999;
	border-bottom: 2px solid #991b1b;
}
#maktab-impersonation-banner button {
	background: #fff;
	color: #dc2626;
	border: none;
	padding: 6px 14px;
	border-radius: var(--r-sm);
	font-weight: 600;
	cursor: pointer;
}
#maktab-impersonation-banner button:hover {
	background: #fee2e2;
}
body.maktab-impersonating {
	padding-top: 44px;
}

/* ── Mobile bottom navigation (Variant D dark) ─────────────────────────────
   5 tabs: Menu (hamburger, sidebar toggle) / Home / Properties / Rent / Households
   Light mode: dark-brown bar, straw inactive, full straw active + top stripe
   Dark mode:  cream bar (slightly lighter than bg), muted inactive, brown active
   iOS: env(safe-area-inset-bottom) guards against notch/home-indicator overlap
   Desktop: hidden via min-width: 769px
   ────────────────────────────────────────────────────────────────────────── */
.maktab-bottom-nav {
	display: none; /* hidden by default; shown only on mobile (see @media below) */
}

@media (max-width: 768px) {
	/* FB-73: bottom nav is position:fixed. Add will-change:transform + transform:translateZ(0)
	   to promote to compositing layer — prevents iOS rubber-band scroll from moving the bar. */
	.maktab-bottom-nav {
		display: flex;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		background: var(--maktab-dark-brown);
		border-top: none;
		padding-bottom: env(safe-area-inset-bottom, 0px);
		z-index: 1010;
		-webkit-transform: translateZ(0);
		transform: translateZ(0);
		will-change: transform;
		/* Ensure it sits above page content but below the mobile sidebar (1050)
		   and its backdrop (1049) */
	}

	[data-theme="dark"] .maktab-bottom-nav {
		background: var(--maktab-cream); /* slightly lighter than page bg (#1A1510) */
		border-top: 1px solid var(--maktab-border);
	}

	/* Shared tab styles.
	   Frappe's global stylesheet applies `color: var(--primary)` to all <a>
	   elements with high specificity. The destination tabs are <a> tags, so we
	   need !important on color here to win the cascade. This is intentional and
	   scoped tightly to .maktab-bottom-nav — it does not affect anything else. */
	.maktab-bn-tab {
		flex: 1;
		padding: 10px 4px 8px;
		display: flex;
		flex-direction: column;
		align-items: center;
		gap: 3px;
		color: rgba(212, 197, 160, 0.6) !important; /* straw at 60% — inactive */
		text-decoration: none !important;
		font-size: 10px;
		font-weight: 600;
		font-family: inherit;
		background: none;
		border: none;
		cursor: pointer;
		position: relative;
		line-height: 1;
		-webkit-tap-highlight-color: transparent;
	}

	[data-theme="dark"] .maktab-bn-tab {
		color: var(--maktab-text-muted) !important; /* inactive in dark mode */
	}

	/* Active tab — straw color + top stripe */
	.maktab-bn-tab.active {
		color: var(--maktab-straw) !important;
	}

	[data-theme="dark"] .maktab-bn-tab.active {
		color: var(--maktab-brown) !important; /* #C4A882 tan in dark mode */
	}

	/* 2px straw stripe at top, centered to 60% width */
	.maktab-bn-tab.active::before {
		content: '';
		position: absolute;
		top: 0;
		left: 20%;
		right: 20%;
		height: 2px;
		background: var(--maktab-straw);
		border-radius: 0 0 var(--r-sq) var(--r-sq);
	}

	[data-theme="dark"] .maktab-bn-tab.active::before {
		background: var(--maktab-brown);
	}

	/* SVG icons inside tabs */
	.maktab-bn-tab svg {
		width: 22px;
		height: 22px;
		flex-shrink: 0;
	}

	/* Menu tab — full-strength color, right separator (LTR).
	   Override the rgba(…, 0.6) inactive rule set on .maktab-bn-tab above. */
	.maktab-bn-menu {
		color: var(--maktab-straw) !important; /* full-strength, always visible */
		border-right: 1px solid rgba(212, 197, 160, 0.18);
	}

	[data-theme="dark"] .maktab-bn-menu {
		color: var(--maktab-text) !important; /* full-strength text in dark mode */
		border-right: 1px solid var(--maktab-border);
	}

	/* RTL: keep flex-direction: row.
	   FB-152: With dir="rtl" on the container, the browser already places
	   first-child (Menu) at the visual right. Adding row-reverse double-flips
	   it back to the left, which is wrong for Arabic — Menu should sit on
	   the right where the user's thumb expects the primary tab. Forcing row
	   here defeats any cascading row-reverse and matches Arabic reading
	   order: Menu | Home | Properties | Rent | Households (right → left). */
	html[dir="rtl"] .maktab-bottom-nav,
	[dir="rtl"] .maktab-bottom-nav {
		flex-direction: row;
	}

	/* RTL: Menu separator stays on the side adjacent to Home tab.
	   With Menu now on the visual right (default RTL flow), the separator
	   that divides Menu from the rest moves to its left edge. */
	html[dir="rtl"] .maktab-bn-menu,
	[dir="rtl"] .maktab-bn-menu {
		border-right: none;
		border-left: 1px solid rgba(212, 197, 160, 0.18);
	}

	[data-theme="dark"] html[dir="rtl"] .maktab-bn-menu,
	html[dir="rtl"] [data-theme="dark"] .maktab-bn-menu,
	[dir="rtl"] [data-theme="dark"] .maktab-bn-menu {
		border-left: 1px solid var(--maktab-border);
		border-right: none;
	}

	/* Push page body up so content isn't hidden behind the nav bar.
	   72px = approx tab height (10+22+3+8+3 padding) + safe area buffer.
	   body is the scroll root on mobile (overflow:visible on .main-section),
	   so padding-bottom here is what actually matters. .main-section is included
	   as a belt-and-suspenders guard for Frappe pages that scroll .main-section. */
	/* FB-2026-00177: was `body:has(.maktab-bottom-nav)`. The bottom nav is
	   always injected on mobile, so a media-query rule is equivalent and
	   doesn't force a `:has()` re-evaluation on every class mutation in
	   body — which was adding ~140ms of style-recalc delay before the
	   sidebar's close transition could paint its first frame. */
	body, body .main-section {
		padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
	}

	/* FB-2026-00179: keep the bottom nav visible when sidebar is open.
	   z-index 1010 sits below sidebar (1050) and backdrop (1049), so the
	   nav is naturally tinted by the backdrop on the side that isn't
	   covered by the sidebar — no layout shift, no apparent disappearance. */
}

/* ════════════════════════════════════════════════════════
   Home V2 — role-aware home page (P2.2)
   ════════════════════════════════════════════════════════ */

.maktab-home-v2 {
	padding: 16px 16px 32px;
}

/* ── Greeting + date ── */
.mh-greeting {
	font-size: 22px;
	font-weight: 700;
	color: var(--maktab-text);
	margin-bottom: 4px;
	line-height: 1.2;
}

.mh-date {
	font-size: 13px;
	color: var(--maktab-text-muted);
	margin-bottom: 18px;
}

/* ── Alert chip strip ── */
.mh-alert-strip {
	display: flex;
	gap: 8px;
	overflow-x: auto;
	padding-bottom: 4px;
	margin: 0 -16px 20px;
	padding-left: 16px;
	padding-right: 16px;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.mh-alert-strip::-webkit-scrollbar {
	display: none;
}

/* Outlined "attention" chips — non-interactive-looking informational pills.
   The Quick Action buttons below are filled (CTA); these are outlined so
   users can distinguish at-a-glance which row is clickable.
   (Chips are still <a> tags so they remain clickable, but they read as
   status indicators rather than primary actions.) */
.mh-alert-chip {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 8px 12px;
	background: transparent;
	color: #8C3E28;
	border: 1px solid #D9A691;
	border-radius: var(--r-lg);
	font-size: 13px;
	font-weight: 500;
	text-decoration: none;
	cursor: pointer;
}
.mh-alert-chip:hover {
	background: rgba(247, 224, 215, 0.4);
	text-decoration: none;
	color: #8C3E28;
}
.mh-alert-chip .mh-chip-num {
	font-size: 16px;
	font-weight: 700;
}
.mh-alert-chip.mh-chip-amber {
	background: transparent;
	color: #6B4A1F;
	border-color: #D6BC85;
}
.mh-alert-chip.mh-chip-amber:hover {
	background: rgba(245, 229, 197, 0.45);
	color: #6B4A1F;
}
.mh-alert-chip.mh-chip-info {
	background: transparent;
	color: #1F4A6B;
	border-color: #9EBED6;
}
.mh-alert-chip.mh-chip-info:hover {
	background: rgba(216, 231, 241, 0.45);
	color: #1F4A6B;
}

/* ── Section title ── */
.mh-section-title {
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	color: var(--maktab-text-muted);
	margin-bottom: 8px;
}

/* ── KPI grid ── */
.mh-kpi-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 8px;
	margin-bottom: 20px;
}

@media (min-width: 769px) {
	.mh-kpi-grid {
		grid-template-columns: repeat(4, 1fr);
	}
}

.mh-kpi {
	background: #F0E4D0;
	padding: 14px;
	border: none;
	text-decoration: none;
	display: block;
	color: inherit;
	cursor: default;
}
a.mh-kpi {
	cursor: pointer;
}
a.mh-kpi:hover {
	background: #E8D8C0;
	text-decoration: none;
	color: inherit;
}

.mh-kpi-label {
	font-size: 11px;
	color: var(--maktab-text-muted);
	text-transform: uppercase;
	letter-spacing: 0.5px;
	margin-bottom: 4px;
}
.mh-kpi-value {
	font-size: 18px;
	font-weight: 700;
	color: var(--maktab-text);
	line-height: 1.2;
}
.mh-kpi-sub {
	font-size: 11px;
	color: var(--maktab-text-muted);
	margin-top: 2px;
}

/* ── Quick action pills ── */
.mh-quick-actions {
	display: flex;
	gap: 8px;
	overflow-x: auto;
	margin: 0 -16px 20px;
	padding: 0 16px 4px;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.mh-quick-actions::-webkit-scrollbar {
	display: none;
}

/* Filled CTA buttons — visually distinct from the outlined attention
   chips above. Larger vertical padding, heavier weight, slight letter
   tracking, and a less-rounded (medium-radius) shape mark these as
   primary actions rather than informational pills. */
.mh-quick-btn {
	flex-shrink: 0;
	padding: 11px 18px;
	background: var(--maktab-dark-brown);
	color: var(--straw);
	border: 1px solid var(--maktab-dark-brown);
	border-radius: var(--r-md);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: 0.2px;
	cursor: pointer;
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-family: inherit;
	white-space: nowrap;
	transition: background-color 0.15s ease, transform 0.05s ease;
}
.mh-quick-btn:hover {
	background: var(--brown-night);
	border-color: var(--brown-night);
	text-decoration: none;
	color: var(--straw);
}
.mh-quick-btn:active {
	transform: translateY(1px);
}

/* ── Recent activity feed ── */
.mh-activity-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

.mh-activity-item {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 10px 0;
	border-bottom: 1px solid var(--maktab-border);
	text-decoration: none;
	color: inherit;
}
.mh-activity-item:last-child {
	border-bottom: none;
}
a.mh-activity-item:hover {
	text-decoration: none;
	color: inherit;
}
a.mh-activity-item:hover .mh-activity-text {
	color: var(--maktab-brown);
}

.mh-activity-dot {
	width: 6px;
	height: 6px;
	background: var(--maktab-brown);
	border-radius: 50%;
	margin-top: 5px;
	flex-shrink: 0;
}
.mh-activity-content {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
}
.mh-activity-text {
	font-size: 13px;
	color: var(--maktab-text);
	line-height: 1.4;
	word-break: break-word;
	display: block;
}
.mh-activity-time {
	font-size: 11px;
	color: var(--maktab-text-muted);
	margin-top: 2px;
	display: block;
}

/* ── Empty state ── */
.mh-empty {
	font-size: 13px;
	color: var(--maktab-text-muted);
	padding: 12px 0;
}

/* ── Skeleton placeholder ── */
.mh-skeleton {
	background: linear-gradient(
		90deg,
		var(--maktab-border) 25%,
		var(--maktab-straw) 50%,
		var(--maktab-border) 75%
	);
	background-size: 200% 100%;
	animation: mh-shimmer 1.4s ease infinite;
	border-radius: var(--r-sm);
	display: inline-block;
}
@keyframes mh-shimmer {
	0%   { background-position: 200% 0; }
	100% { background-position: -200% 0; }
}

/* ── Dark mode ── */
[data-theme="dark"] .mh-kpi {
	background: var(--maktab-cream);
	border: 1px solid var(--maktab-border);
}
[data-theme="dark"] a.mh-kpi:hover {
	background: #2E2820;
}
[data-theme="dark"] .mh-kpi-value {
	color: var(--maktab-text);
}
[data-theme="dark"] .mh-alert-chip {
	background: transparent;
	color: #E8B0A0;
	border-color: #6B3A30;
}
[data-theme="dark"] .mh-alert-chip:hover {
	background: rgba(58, 37, 32, 0.4);
	color: #E8B0A0;
}
[data-theme="dark"] .mh-alert-chip.mh-chip-amber {
	background: transparent;
	color: #E0B06A;
	border-color: #6B5230;
}
[data-theme="dark"] .mh-alert-chip.mh-chip-amber:hover {
	background: rgba(58, 48, 31, 0.4);
	color: #E0B06A;
}
[data-theme="dark"] .mh-alert-chip.mh-chip-info {
	background: transparent;
	color: #9AC4E0;
	border-color: #2F4A66;
}
[data-theme="dark"] .mh-alert-chip.mh-chip-info:hover {
	background: rgba(26, 42, 58, 0.45);
	color: #9AC4E0;
}
[data-theme="dark"] .mh-quick-btn {
	background: var(--maktab-cream);
	color: var(--maktab-text);
	border: 1px solid var(--maktab-cream);
}
[data-theme="dark"] .mh-quick-btn:hover {
	background: #3D3428;
	border-color: #3D3428;
	color: var(--maktab-text);
}
[data-theme="dark"] .mh-activity-dot {
	background: var(--maktab-brown);
}
[data-theme="dark"] .mh-greeting {
	color: var(--maktab-text);
}
[data-theme="dark"] .mh-skeleton {
	background: linear-gradient(
		90deg,
		var(--maktab-border) 25%,
		var(--maktab-sand) 50%,
		var(--maktab-border) 75%
	);
	background-size: 200% 100%;
	animation: mh-shimmer 1.4s ease infinite;
}

/* ── RTL overrides ── */
[dir="rtl"] .mh-alert-strip {
	padding-left: 16px;
	padding-right: 16px;
}
[dir="rtl"] .mh-quick-actions {
	padding-left: 16px;
	padding-right: 16px;
}

/* Desktop padding */
@media (min-width: 769px) {
	.maktab-home-v2 {
		padding: 20px 24px 40px;
		max-width: 900px;
	}
	.mh-kpi-grid {
		gap: 12px;
	}
	.mh-alert-strip {
		margin: 0 0 20px;
		padding-left: 0;
		padding-right: 0;
	}
	.mh-quick-actions {
		margin: 0 0 20px;
		padding-left: 0;
		padding-right: 0;
	}
}

/* ══════════════════════════════════════════════════════════════════════════════
   P3.3 — Toast redesign: no shadow, 1px border, 4px colored left stripe
   Frappe's HTML: <div class="alert desk-alert green" role="alert">
                    <div class="alert-message-container">
                      <span class="indicator-pill green">…</span>
                      <div class="alert-message">…text…</div>
                    </div>
                  </div>
   Colors by indicator class:
     .green          → forest green  (#2D5234 light / #8FB88F dark)
     .red/.orange/.yellow → terracotta (#8C3E28 light / #D48A74 dark)
     .blue/.info     → navy          (#1F4A6B light / #9AC4E0 dark)
   Desktop: max-width 360px (Frappe positions bottom-right by default).
   Mobile:  full-width minus 32px; container lifted above the 72px bottom nav.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── Light mode base ──
   Toasts are overlay surfaces with no scrim, so depth comes from a
   thicker border + cream-on-beige bg contrast (Pattern D from
   docs/SHADOW_REPLACEMENT_PATTERNS.md). Border-left stripe color is
   set per status class below. */
.desk-alert {
	background: var(--maktab-cream) !important;
	border: 1.5px solid var(--maktab-border) !important;
	border-radius: var(--r-md) !important;
	/* FB-51/64: flex container so close button is vertically centred with message */
	padding: 6px 14px !important;
	display: flex !important;
	align-items: center !important;
	gap: 8px;
	color: var(--maktab-text) !important;
	max-width: 360px;
}

/* ── Inner container / message: strip any default margin/padding ── */
.desk-alert .alert-message-container {
	flex: 1 1 auto;
	min-width: 0; /* allow text to shrink and wrap */
	margin: 0 !important;
	padding: 0 !important;
}
.desk-alert .alert-title-container {
	display: flex;
	align-items: center;
	gap: 8px;
}
.desk-alert .alert-message {
	margin: 0 !important;
	padding: 0 !important;
}

/* ── FB-51/64: close button — static so flexbox centres it vertically ──
   Frappe default: position:absolute top-right. On multi-line toasts this
   creates apparent "more space below" because the close floats to the top
   corner while the message runs down. Static + flex-shrink:0 keeps it
   vertically centred at the trailing edge of the flex row. */
.desk-alert .close {
	position: static !important;
	flex-shrink: 0;
	margin: 0 !important;
	align-self: center;
}
html[dir="rtl"] .desk-alert .close,
[dir="rtl"] .desk-alert .close {
	margin-left: 0;
	margin-right: 0;
}

/* ── Light mode — indicator-pill dot carries the severity ── */
.desk-alert.green .indicator-pill,
.desk-alert.green .indicator-pill::before {
	background: #2D5234 !important;
}
.desk-alert.red .indicator-pill,
.desk-alert.red .indicator-pill::before,
.desk-alert.orange .indicator-pill,
.desk-alert.orange .indicator-pill::before,
.desk-alert.yellow .indicator-pill,
.desk-alert.yellow .indicator-pill::before {
	background: #8C3E28 !important;
}
.desk-alert.blue .indicator-pill,
.desk-alert.blue .indicator-pill::before,
.desk-alert.info .indicator-pill,
.desk-alert.info .indicator-pill::before {
	background: #1F4A6B !important;
}

/* ── Light mode — message text ── */
.desk-alert .alert-message {
	color: var(--maktab-text) !important;
}

/* ── Dark mode ── */
[data-theme="dark"] .desk-alert {
	background: var(--maktab-cream) !important; /* dark-token: #24201A */
	border-color: var(--maktab-border) !important;
}

[data-theme="dark"] .desk-alert.green .indicator-pill,
[data-theme="dark"] .desk-alert.green .indicator-pill::before {
	background: #8FB88F !important;
}
[data-theme="dark"] .desk-alert.red .indicator-pill,
[data-theme="dark"] .desk-alert.red .indicator-pill::before,
[data-theme="dark"] .desk-alert.orange .indicator-pill,
[data-theme="dark"] .desk-alert.orange .indicator-pill::before,
[data-theme="dark"] .desk-alert.yellow .indicator-pill,
[data-theme="dark"] .desk-alert.yellow .indicator-pill::before {
	background: #D48A74 !important;
}
[data-theme="dark"] .desk-alert.blue .indicator-pill,
[data-theme="dark"] .desk-alert.blue .indicator-pill::before,
[data-theme="dark"] .desk-alert.info .indicator-pill,
[data-theme="dark"] .desk-alert.info .indicator-pill::before {
	background: #9AC4E0 !important;
}

[data-theme="dark"] .desk-alert .alert-message {
	color: var(--maktab-text) !important;
}

/* ── FB-79 mobile toast — iOS-style slide-down from top ──────────────────────
   FB-79: toasts slide down from above viewport on mobile, matching iOS
   notification behaviour. FB-77 (toast above bottom bar) is superseded —
   toasts are now at the TOP, clear of the bottom nav entirely.

   Container layout:
   - Fixed at top, centered, 16px each side, flex-column so multiple toasts
     stack downward with a gap.
   - top uses safe-area-inset-top so the first toast clears the notch/status
     bar on notched iPhones.
   - bottom/right/left from the global #alert-container rule are overridden.

   Toast appearance:
   - Rounded pill corners (14px).
   - backdrop-filter blur (20px) with translucent background — looks like an
     iOS live-activity / notification tile.
   - border-left stripe kept for colour coding but radius matches the pill.

   Animation:
   - On entry: @keyframes maktab-toast-in slides from translateY(-120%)
     to translateY(0) with an iOS cubic-bezier ease (spring feel).
   - On swipe-up dismiss: JS in maktab.js adds .maktab-dismissing which plays
     maktab-toast-out (slides back up + fades).
   ─────────────────────────────────────────────────────────────────────────── */

@keyframes maktab-toast-in {
	from { transform: translateY(-120%); opacity: 0; }
	to   { transform: translateY(0);     opacity: 1; }
}

@keyframes maktab-toast-out {
	from { transform: translateY(0);     opacity: 1; }
	to   { transform: translateY(-120%); opacity: 0; }
}

@media (max-width: 768px) {
	/* FB-79: move container to the top of the viewport */
	#alert-container {
		/* Override global bottom positioning */
		bottom: auto !important;
		/* Sit just below the notch / status bar */
		top: env(safe-area-inset-top, 0px) !important;
		/* Centered, 16px inset each side */
		left: 16px !important;
		right: 16px !important;
		/* Stack multiple toasts downward */
		display: flex !important;
		flex-direction: column !important;
		gap: 8px !important;
		align-items: center !important;
		/* Transparent wrapper — individual toasts have their own bg */
		background: transparent !important;
		pointer-events: none !important;
	}

	/* FB-79: iOS-style pill toast */
	#alert-container .desk-alert {
		pointer-events: auto !important;
		/* Full container width (container already inset 16px each side) */
		max-width: 100%;
		width: 100%;
		/* Pill corners */
		border-radius: var(--r-lg) !important;
		/* Generous vertical padding */
		padding: 12px 16px !important;
		/* Slide-in animation */
		animation: maktab-toast-in 0.35s cubic-bezier(0.32, 0.72, 0, 1) both;
		/* Position: the container is already centered; keep translateX(-50%) in the
		   JS dismiss path so the out-animation anchors correctly. We don't use
		   position:absolute here — the flex column handles stacking. */
		/* Translucent iOS-style backdrop */
		backdrop-filter: blur(20px) !important;
		-webkit-backdrop-filter: blur(20px) !important;
	}

	/* Light mode: translucent cream with slight opacity */
	#alert-container .desk-alert {
		background: rgba(245, 238, 220, 0.88) !important; /* --maktab-cream at 88% */
	}

	/* Dark mode: translucent dark with slight opacity */
	[data-theme="dark"] #alert-container .desk-alert {
		background: rgba(36, 32, 26, 0.88) !important; /* dark cream token at 88% */
	}

	/* Dismiss animation class added by maktab.js swipe-up handler */
	#alert-container .desk-alert.maktab-dismissing {
		animation: maktab-toast-out 0.25s cubic-bezier(0.32, 0.72, 0, 1) both !important;
	}
}

/* ════════════════════════════════════════════════════════
   Property View — /app/property/<name>  (P4.1 skeleton)
   ════════════════════════════════════════════════════════ */

/* ── Outer shell ── */
.pv-shell {
	max-width: 1100px;
	margin: 0 auto;
	padding: 0 0 32px;
}

/* FB-67 tab strip — Theme 3 */
/* ── Tab strip ── */
.pv-tab-strip {
	display: flex;
	flex-direction: row;
	gap: 0;
	border-bottom: 2px solid var(--maktab-border);
	padding: 0 20px;
	background: var(--maktab-beige);
	overflow-x: auto;
	/* FB-67: overflow-x:auto coerces overflow-y to auto (CSS spec), creating a
	   2px internal vertical scroll (scrollHeight 43 > clientHeight 41, caused by
	   the tabs' margin-bottom:-2px). Fix: explicit overflow-y:hidden stops it. */
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;      /* Firefox */
	-ms-overflow-style: none;   /* IE/Edge */
	/* Keep tabs visible while scrolling the tab body. Page-head is hidden,
	   so the tab strip sticks at the very top of the viewport. */
	position: sticky;
	top: 0;
	z-index: 10;
}
.pv-tab-strip::-webkit-scrollbar { display: none; } /* WebKit */

.pv-tab {
	flex-shrink: 0;
	padding: 10px 14px;
	font-size: 13px;
	font-weight: 500;
	font-family: inherit;
	color: var(--maktab-text-muted);
	background: none;
	border: none;
	/* FB-67: Replaced border-bottom + margin-bottom:-2px (which caused the 2px overflow)
	   with inset box-shadow for the active underline. Inset shadows live inside the
	   border-box and are never counted in scrollHeight — no overflow possible. */
	box-shadow: none;
	margin-bottom: 0;
	cursor: pointer;
	white-space: nowrap;
	transition: color 0.15s, box-shadow 0.15s;
	-webkit-tap-highlight-color: transparent;
	position: relative;
}
.pv-tab:hover {
	color: var(--maktab-brown);
}
.pv-tab:focus-visible {
	outline: 2px solid var(--maktab-amber);
	outline-offset: -2px;
}
.pv-tab.pv-tab-active {
	color: var(--maktab-brown);
	font-weight: 600;
	/* 3px inset bottom shadow = active-tab underline; overlaps the strip's 2px border */
	box-shadow: inset 0 -3px 0 var(--maktab-brown);
}
/* end FB-67 */

/* ── Tab body ── */
.pv-tab-body {
	padding: 20px;
	min-height: 200px;
}

/* ── Placeholder content (P4.1 only) ── */
.pv-placeholder {
	padding: 40px 0;
	text-align: center;
	color: var(--maktab-text-muted);
}
.pv-placeholder h3 {
	font-size: 18px;
	font-weight: 600;
	color: var(--maktab-text);
	margin-bottom: 8px;
}
.pv-placeholder p {
	font-size: 13px;
	margin: 0;
}

/* ── Access denied / error states ── */
.pv-access-denied {
	padding: 60px 20px;
	text-align: center;
	color: var(--maktab-text-muted);
	font-size: 14px;
}
.pv-back-link {
	display: inline-block;
	margin-top: 12px;
	color: var(--maktab-link);
	text-decoration: none;
	font-size: 13px;
}
.pv-back-link:hover { text-decoration: underline; }

/* ── Dark mode ── */
[data-theme="dark"] .pv-tab-strip {
	background: var(--maktab-beige);
	border-bottom-color: var(--maktab-border);
}
[data-theme="dark"] .pv-tab {
	color: var(--maktab-text-muted);
}
[data-theme="dark"] .pv-tab:hover {
	color: var(--maktab-text);
}
[data-theme="dark"] .pv-tab.pv-tab-active {
	color: var(--maktab-brown); /* #C4A882 tan in dark mode */
	box-shadow: inset 0 -3px 0 var(--maktab-brown);
}
[data-theme="dark"] .pv-placeholder h3 {
	color: var(--maktab-text);
}

/* ── RTL ── */
[dir="rtl"] .pv-tab-strip {
	padding: 0 20px;
}

/* ── Mobile ── */
@media (max-width: 768px) {
	.pv-tab-strip {
		padding: 0 8px;
	}
	.pv-tab {
		padding: 10px 10px;
		font-size: 12px;
	}
	.pv-tab-body {
		padding: 12px;
	}
	.pv-shell {
		padding: 0 0 80px; /* extra space above bottom-nav */
	}
}

/* ══════════════════════════════════════════════════════════════
   Household View  (P5.1) — .hv-* classes
   Reuses .pv-*, .lv-*, .maktab-* from property-view.
   ══════════════════════════════════════════════════════════════ */

/* ── Header meta: same structure as property-view ── */
.hv-header-meta {
	padding: 0 var(--maktab-page-x, 20px) 6px;
}

/* ── Quick-stat numbers in overview sidebar ── */
.hv-stat-num {
	font-weight: 600;
	color: var(--maktab-text);
}

/* ── Staff status badges ── */
.hv-staff-status-active     { color: var(--maktab-green); font-weight: 600; }
.hv-staff-status-leave      { color: var(--maktab-amber, #c8933b); font-weight: 600; }
.hv-staff-status-terminated { color: var(--maktab-text-muted); }

/* ── Vehicle status badges ── */
.hv-veh-status-active  { color: var(--maktab-green); font-weight: 600; }
.hv-veh-status-maint   { color: var(--maktab-amber, #c8933b); font-weight: 600; }
.hv-veh-status-sold    { color: var(--maktab-text-muted); }

/* ── Days chip inside iqama cell ── */
.hv-days-chip {
	display: inline-block;
	margin-inline-start: 4px;
	font-size: 11px;
	padding: 1px 5px;
	border-radius: var(--r-md);
	vertical-align: middle;
}

/* ── Expense chart card ── */
.hv-exp-chart-card {
	margin-bottom: 0;
}

/* ── Toolbar flex — same pattern as pv toolbars ── */
.hv-staff-toolbar,
.hv-vehicles-toolbar,
.hv-expenses-toolbar {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 10px var(--maktab-page-x, 20px) 8px;
	flex-wrap: wrap;
}

/* ── Dark theme ── */
[data-theme="dark"] .hv-stat-num    { color: var(--maktab-text); }

/* ── RTL ── */
[dir="rtl"] .hv-staff-toolbar,
[dir="rtl"] .hv-vehicles-toolbar,
[dir="rtl"] .hv-expenses-toolbar {
	flex-direction: row-reverse;
}

/* ── Mobile ── */
@media (max-width: 768px) {
	.hv-staff-toolbar,
	.hv-vehicles-toolbar,
	.hv-expenses-toolbar {
		flex-direction: column;
		align-items: stretch;
	}
}


/* ── Overview tabs (Sprint 3.6) ─────────────────────────────────────────────
   Class prefix: mo- (maktab overview).
   Layout:
     [ KPI row: 4 equal tiles, full width ]
     [ Attention, ~2/3 ] [ Recent, ~1/3 ]
   Skeleton: grey pulse tiles until data arrives.
─────────────────────────────────────────────────────────────────────────── */

.pv-overview-content {
	flex: 1;
}

/* ── KPI row ── */
.mo-overview-wrap {
	display: flex;
	flex-direction: column;
	gap: 16px;
	padding: 4px 0 8px;
}

.mo-kpi-row {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 12px;
}

.mo-kpi-tile {
	background: var(--maktab-card-bg, #fff);
	border: 1px solid var(--maktab-border, #e5e7eb);
	border-radius: var(--r-md);
	padding: 16px 18px 14px;
	min-height: 88px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 4px;
	transition: border-color 0.15s;
}

.mo-kpi-value {
	font-size: 22px;
	font-weight: 700;
	color: var(--maktab-text, #111827);
	line-height: 1.2;
	letter-spacing: -0.02em;
}

.mo-kpi-label {
	font-size: 12px;
	font-weight: 500;
	color: var(--maktab-text-muted, #6b7280);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.mo-kpi-sub {
	font-size: 11px;
	color: var(--maktab-text-muted, #6b7280);
	margin-top: 2px;
}

/* Severity modifiers for KPI tiles */
.mo-kpi-tile.severity-alert {
	border-color: var(--maktab-red, #dc2626);
	background: color-mix(in srgb, var(--maktab-red, #dc2626) 6%, var(--maktab-card-bg, #fff));
}
.mo-kpi-tile.severity-alert .mo-kpi-value {
	color: var(--maktab-red, #dc2626);
}

.mo-kpi-tile.severity-warn {
	border-color: var(--maktab-amber, #d97706);
	background: color-mix(in srgb, var(--maktab-amber, #d97706) 6%, var(--maktab-card-bg, #fff));
}
.mo-kpi-tile.severity-warn .mo-kpi-value {
	color: var(--maktab-amber, #d97706);
}

.mo-kpi-tile.severity-ok {
	border-color: var(--maktab-green, #16a34a);
}
.mo-kpi-tile.severity-ok .mo-kpi-value {
	color: var(--maktab-green, #16a34a);
}

/* ── Sections row ── */
.mo-sections-row {
	display: grid;
	grid-template-columns: 2fr 1fr;
	gap: 12px;
	align-items: start;
}

.mo-sections-left,
.mo-sections-right {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.mo-section {
	background: var(--maktab-card-bg, #fff);
	border: 1px solid var(--maktab-border, #e5e7eb);
	border-radius: var(--r-md);
	padding: 14px 16px;
}

.mo-section-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 10px;
}

.mo-section-title {
	font-size: 13px;
	font-weight: 600;
	color: var(--maktab-text, #111827);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.mo-see-all {
	font-size: 12px;
	color: var(--maktab-blue, #2563eb);
	text-decoration: none;
	white-space: nowrap;
}
.mo-see-all:hover {
	text-decoration: underline;
}

.mo-item-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.mo-item {
	font-size: 13px;
	padding: 6px 10px 6px 12px;
	border-radius: var(--r-sm);
	line-height: 1.4;
}

.mo-item-link {
	color: var(--maktab-text, #111827);
	text-decoration: none;
	display: block;
}
.mo-item-link:hover {
	text-decoration: underline;
	color: var(--maktab-blue, #2563eb);
}

/* Item severity — carried by tinted background in both themes (no side stripe) */
.mo-item-alert {
	background: color-mix(in srgb, var(--maktab-red, #dc2626) 5%, transparent);
}
.mo-item-warn {
	background: color-mix(in srgb, var(--maktab-amber, #d97706) 5%, transparent);
}
.mo-item-ok {
	background: color-mix(in srgb, var(--maktab-green, #16a34a) 5%, transparent);
}
.mo-item-info,
.mo-item-neutral {
	background: transparent;
}

.mo-section-empty {
	font-size: 12px;
	color: var(--maktab-text-muted, #6b7280);
	padding: 4px 0;
}

.mo-section-all-clear .mo-section-title {
	color: var(--maktab-green, #16a34a);
}

.mo-load-error {
	font-size: 13px;
	color: var(--maktab-text-muted, #6b7280);
	padding: 16px 0;
	text-align: center;
}

/* ── Skeleton shimmer ── */
.mo-skeleton {
	pointer-events: none;
}

.mo-skeleton-line {
	border-radius: var(--r-sm);
	background: linear-gradient(
		90deg,
		var(--maktab-border, #e5e7eb) 25%,
		color-mix(in srgb, var(--maktab-border, #e5e7eb) 60%, var(--maktab-card-bg, #fff)) 50%,
		var(--maktab-border, #e5e7eb) 75%
	);
	background-size: 200% 100%;
	animation: mo-shimmer 1.4s infinite;
}

@keyframes mo-shimmer {
	0%   { background-position: 200% 0; }
	100% { background-position: -200% 0; }
}

.mo-skeleton-val  { width: 60%;  height: 22px; margin-bottom: 6px; }
.mo-skeleton-lbl  { width: 40%;  height: 11px; }
.mo-skeleton-title { width: 50%; height: 12px; margin-bottom: 10px; }
.mo-skeleton-item  { width: 90%; height: 10px; margin-bottom: 5px; }

/* Dark mode overrides */
[data-theme="dark"] .mo-kpi-tile {
	background: var(--maktab-card-bg);
	border-color: var(--maktab-border);
}
[data-theme="dark"] .mo-kpi-value { color: var(--maktab-text, #f3f4f6); }
[data-theme="dark"] .mo-section   { background: var(--maktab-card-bg); border-color: var(--maktab-border); }
[data-theme="dark"] .mo-item-link { color: var(--maktab-text, #f3f4f6); }
[data-theme="dark"] .mo-kpi-tile.severity-alert { background: rgba(220,38,38,0.12); }
[data-theme="dark"] .mo-kpi-tile.severity-warn  { background: rgba(217,119,6,0.12); }
[data-theme="dark"] .mo-item-alert { background: rgba(220,38,38,0.08); }
[data-theme="dark"] .mo-item-warn  { background: rgba(217,119,6,0.08); }
[data-theme="dark"] .mo-item-ok    { background: rgba(22,163,74,0.08); }

/* Mobile: stack to single column */
@media (max-width: 768px) {
	.mo-kpi-row {
		grid-template-columns: repeat(2, 1fr);
	}
	.mo-sections-row {
		grid-template-columns: 1fr;
	}
}

@media (max-width: 480px) {
	.mo-kpi-row {
		grid-template-columns: 1fr 1fr;
		gap: 8px;
	}
	.mo-kpi-tile {
		padding: 12px 14px 10px;
		min-height: 72px;
	}
	.mo-kpi-value {
		font-size: 18px;
	}
}

/* ── FB-80 / FB-81: Date input overflow fix on mobile ──────────────────────
   Native <input type="date"> elements in admin-activity and entity-ledger
   filter bars overflow their containers on mobile. The per-page JS already
   sets flex-direction:column + width:100% at max-width:640px, but the
   base min-width:120px on those rules can still cause subtle overflow when
   the page padding is counted. Belt-and-suspenders: globally clamp all
   filter-row date inputs to the viewport on mobile. */
@media (max-width: 768px) {
	/* FB-80: admin-activity date inputs */
	.aa-filter-bar,
	.aa-filter-row {
		box-sizing: border-box;
		max-width: 100%;
	}
	.aa-filter-row input[type="date"] {
		box-sizing: border-box;
		max-width: 100%;
		min-width: 0 !important;
	}
	/* FB-81: entity-ledger date inputs */
	.el-filter-bar,
	.el-filter-row {
		box-sizing: border-box;
		max-width: 100%;
	}
	.el-filter-row input[type="date"] {
		box-sizing: border-box;
		max-width: 100%;
		min-width: 0 !important;
	}
	/* Shared: prevent any custom filter bar from overflowing viewport */
	.aa-container,
	.el-container {
		max-width: 100vw;
		overflow-x: hidden;
	}
}

/* FB-104 / FB-151 / FB-157 (Round 6i.4): at narrow viewports the entity-ledger
   AND admin-activity date pickers were getting cropped because the row didn't
   wrap and the inputs had a min-width. Force wrap + full-width inputs so each
   picker gets its own row. */
@media (max-width: 480px) {
	.el-filter-bar,
	.el-filter-row,
	.aa-filter-bar,
	.aa-filter-row {
		flex-wrap: wrap;
	}
	.el-filter-row .el-filter-start,
	.el-filter-row .el-filter-end,
	.aa-filter-row .aa-filter-start,
	.aa-filter-row .aa-filter-end {
		width: 100%;
		min-width: 0;
	}
}

/* FB-104 / FB-147 / FB-151 / FB-157 (Round 6i.4): iOS Safari renders date-input
   chrome larger than the input box on Ahmad's hardware (headless WebKit can't
   reproduce). Defensive fix covering three hypotheses, applied to BOTH
   entity-ledger (.el-filter-*) and admin-activity (.aa-filter-*):
     (1) iOS native date-picker UI overflowing input bounds → kill native
         appearance + supply our own calendar glyph.
     (2) Invisible borders in dark theme → force a 1px visible border.
     (3) Picker popup overflow from parent row → clip parent.
*/
@media (max-width: 768px) {
	.el-filter-bar .el-filter-row,
	.aa-filter-bar .aa-filter-row {
		/* Catch any iOS date-picker UI that bleeds outside the input */
		overflow: hidden;
	}
	.el-filter-bar input.el-filter-start,
	.el-filter-bar input.el-filter-end,
	.aa-filter-bar input.aa-filter-start,
	.aa-filter-bar input.aa-filter-end,
	/* FB-2026-00215 round 2: include the company <select> so it picks up the
	   exact same height/padding/font-size as the date inputs on mobile. Without
	   this, the select renders shorter than the date inputs (iOS native select
	   chrome adds variable padding). */
	.el-filter-bar select.el-filter-company,
	.aa-filter-bar select[class*="aa-filter"] {
		/* Disable iOS native date-picker chrome that can overflow input bounds. */
		-webkit-appearance: none !important;
		appearance: none !important;
		/* Box constraints */
		width: 100% !important;
		max-width: 100% !important;
		min-width: 0 !important;
		box-sizing: border-box !important;
		height: 44px !important;
		min-height: 44px !important;
		/* FB-2026-00226: tight line-height (was 1.2) inside narrow content area
		   clipped descenders (g/j/p/q/y) in the company select on mobile.
		   Bumped to 1.4 and dropped padding to 8px so the line-box (14×1.4≈19.6)
		   fits comfortably inside the content area (44 − 2 border − 16 padding
		   = 26px). */
		line-height: 1.4 !important;
		/* Visible border so user can see input boundaries (was invisible in dark) */
		border: 1px solid var(--border-color, rgba(212,197,160,0.25)) !important;
		border-radius: var(--r-md) !important;
		padding: 8px 12px !important;
		background-color: var(--card-bg) !important;
		color: var(--maktab-text) !important;
		font-size: 14px !important;
		vertical-align: middle !important;
		margin: 0 !important;
		/* iOS date-picker icon doesn't show with appearance:none — add a small
		   calendar glyph as background so user knows it's a date input. */
		background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23D4C5A0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4' width='18' height='18' rx='2' ry='2'/><line x1='16' y1='2' x2='16' y2='6'/><line x1='8' y1='2' x2='8' y2='6'/><line x1='3' y1='10' x2='21' y2='10'/></svg>") !important;
		background-repeat: no-repeat !important;
		background-position: right 10px center !important;
		padding-right: 36px !important;
	}
	/* Replace the date-input calendar glyph with a chevron for the select */
	.el-filter-bar select.el-filter-company,
	.aa-filter-bar select[class*="aa-filter"] {
		background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23D4C5A0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'></polyline></svg>") !important;
	}
	/* RTL: icon goes on the left */
	[dir="rtl"] .el-filter-bar input.el-filter-start,
	[dir="rtl"] .el-filter-bar input.el-filter-end,
	[dir="rtl"] .aa-filter-bar input.aa-filter-start,
	[dir="rtl"] .aa-filter-bar input.aa-filter-end,
	/* FB-2026-00215 round 2: same RTL flip for the company select */
	[dir="rtl"] .el-filter-bar select.el-filter-company,
	[dir="rtl"] .aa-filter-bar select[class*="aa-filter"] {
		background-position: left 10px center !important;
		padding-right: 12px !important;
		padding-left: 36px !important;
	}
	/* iOS: when the date input is empty/unfocused, hide the placeholder
	   'date' UI which can render larger than the input on some iOS versions */
	.el-filter-bar input[type="date"]::-webkit-date-and-time-value,
	.aa-filter-bar input[type="date"]::-webkit-date-and-time-value {
		text-align: start;
	}
	.el-filter-bar input[type="date"]::-webkit-calendar-picker-indicator,
	.aa-filter-bar input[type="date"]::-webkit-calendar-picker-indicator {
		opacity: 0;
		position: absolute;
		right: 0;
		width: 36px;
		height: 100%;
		cursor: pointer;
	}
}

/* ════════════════════════════════════════════════════════════════════════
   Sidebar v3 — clean rewrite (phase 2, third attempt)
   Markup: <aside class="sidebar"> injected as a direct child of .body-sidebar
   by maktab.setup_sidebar(). All Frappe-native body-sidebar children are
   hidden — we own the sidebar surface end-to-end.
   Visual reference: design_handoff_maktab_redesign/handoff_notes/sidebar/
   ════════════════════════════════════════════════════════════════════════ */

/* ── Hide Frappe's sidebar wrapper entirely. We render aside.maktab-sidebar
   directly under <body>, so Frappe's container is dead weight in DOM and
   doesn't need any of its lifecycle (expand_sidebar / set_height /
   prevent_scroll) reaching anything we draw. */
.body-sidebar-container,
.body-sidebar-placeholder {
	display: none !important;
}

/* Frappe's #freeze overlay flashes on every page navigation — kill it. */
#freeze { display: none !important; }

/* ── FB-2026-00193: suppress sidebar transitions during initial paint ──
   maktab.js adds `is-loading` to <html> synchronously and removes it on
   double-rAF. Killing transitions while that class is present prevents
   the .main-section margin-inline-start animation (and the mobile drawer
   transform) from running on every page refresh — the steady state
   commits in the first paint without animation. Once the class is gone,
   `.is-collapsed` and `.is-open` toggles animate normally. */
html.is-loading aside.maktab-sidebar,
html.is-loading aside.maktab-sidebar ~ .main-section,
html.is-loading .maktab-sidebar-backdrop {
	transition: none !important;
}

/* ── aside.maktab-sidebar — the canonical (only) sidebar element ──
   Direct child of <body>, sibling of .main-section. State classes:
   .is-open      — mobile drawer visible
   .is-collapsed — desktop narrow rail (56px instead of 182px)
*/
aside.maktab-sidebar {
	position: fixed;
	top: 0;
	left: 0;
	height: 100vh;
	max-height: 100vh;
	width: 176px;
	background: var(--brown-deep);
	color: var(--straw);
	/* Long sand vertical line lives on the content-facing edge of the
	   sidebar (i.e. inline-end) so it's consistent across LTR and RTL.
	   Was previously `border-left: 3px solid var(--sand)` (physical),
	   which put it on the inside in RTL but the browser-edge in LTR. */
	border-inline-end: 3px solid var(--sand);
	display: flex;
	flex-direction: column;
	overflow: hidden;
	z-index: 1010;
	font-family: 'Cairo', 'Tajawal', system-ui, sans-serif;
	transition: width 0.2s ease;
}
[dir="rtl"] aside.maktab-sidebar {
	left: auto;
	right: 0;
}

/* ── Desktop: fixed rail; .main-section offsets to clear it ── */
@media (min-width: 769px) {
	aside.maktab-sidebar.is-collapsed {
		width: 56px;
	}
	aside.maktab-sidebar ~ .main-section {
		margin-inline-start: 176px !important;
		width: calc(100% - 176px) !important;
		transition: margin-inline-start 0.2s ease, width 0.2s ease !important;
	}
	aside.maktab-sidebar.is-collapsed ~ .main-section {
		margin-inline-start: 56px !important;
		width: calc(100% - 56px) !important;
	}
	/* Hide Frappe's hamburger between 769..991px (Frappe thinks sidebar is collapsed) */
	.page-head .sidebar-toggle-btn,
	.page-head .sidebar-toggle-placeholder {
		display: none !important;
	}
}

/* ════════════════════════════════════════════════════════════════════════
   The .sidebar component itself — adapted near-verbatim from
   design_handoff_maktab_redesign/handoff_notes/sidebar/sidebar.css
   ════════════════════════════════════════════════════════════════════════ */

/* Sidebar appearance does NOT flip in dark mode — sidebar is brand chrome.
   The bg switches to brown-night for cohesion with the page bg, but every
   accent/text token gets re-locked to its LIGHT value inside the sidebar
   so contrast stays high (otherwise --straw → #3D3428 = dark gray text on
   #0F0C08 near-black bg = invisible). Scoping these vars on the sidebar
   element propagates to all descendants via CSS custom-property inheritance. */
[data-theme="dark"] aside.maktab-sidebar {
	background: var(--brown-night);
	--beige: #F5F0E6;
	--cream: #FAF8F2;
	--straw: #D4C5A0;
	--sand: #C2AD7E;
	--brown: #6B4F36;
	--brown-deep: #1F1A12;  /* keep sidebar surface dark — token flips elsewhere */
}

/* ── Brand mark ── */
aside.maktab-sidebar .brand {
	display: flex;
	align-items: center;
	gap: 8px;
	/* Logical longhand instead of `padding: 16px 14px 14px` so RTL gets
	   the inline-start padding on the correct (right) side. inline-start
	   is 15px (not 14) so the palm-mark (26px wide) sits at the rail's
	   visual midpoint when collapsed — (56-26)/2 = 15. Keeping the same
	   value in expanded eliminates the 1px palm shift Ahmad spotted
	   during the collapse animation. */
	padding-block-start: 16px;
	padding-block-end: 14px;
	padding-inline-start: 15px;
	padding-inline-end: 14px;
	border-bottom: 1px solid rgba(212,197,160,.15);
	cursor: pointer;
	transition: background .15s;
	outline: none;
}
aside.maktab-sidebar .brand:hover {
	background: rgba(212,197,160,.04);
}
aside.maktab-sidebar .brand:hover .ar { color: #FFF8EA; }
aside.maktab-sidebar .brand:focus-visible {
	box-shadow: inset 0 0 0 2px rgba(212,197,160,.5);
}
aside.maktab-sidebar .brand .palm-mark {
	width: 26px;
	height: 30px;
	flex-shrink: 0;
}
aside.maktab-sidebar .brand .ar {
	font-size: 14px;
	font-weight: 700;
	color: var(--beige);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* ── Scrollable nav area ── */
aside.maktab-sidebar .nav-area {
	flex: 1;
	overflow-y: auto;
	padding: 8px 0;
	scrollbar-width: thin;
}
aside.maktab-sidebar .nav-area::-webkit-scrollbar { width: 6px; }
aside.maktab-sidebar .nav-area::-webkit-scrollbar-track { background: transparent; }
aside.maktab-sidebar .nav-area::-webkit-scrollbar-thumb { background: transparent; border-radius: var(--r-sm); }
aside.maktab-sidebar .nav-area:hover::-webkit-scrollbar-thumb { background: rgba(212,197,160,.18); }

/* ── Section header (collapsible) ── */
aside.maktab-sidebar .nav-sect {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 10px 14px 4px;
	font-size: 12px;
	color: rgba(212,197,160,.62);
	font-weight: 600;
	cursor: pointer;
	user-select: none;
	/* Smooth collapse when `.is-collapsed` flips. Without these transitions
	   the headers `display:none` instantly, snapping every icon below them
	   up by ~18px per header while the sidebar width is still animating —
	   the user reads this as icons "jumping up and down" mid-animation.
	   max-height is set to the natural rendered height (32px) so the
	   transition runs visibly from t=0; using a larger value (e.g. 60px)
	   leaves the rendered height clamped to content until max-height
	   crosses below natural, back-loading the visible collapse into the
	   second half of the animation (snap, not smooth). Linear timing on
	   max-height keeps the interpolation visible from frame 0. */
	overflow: hidden;
	max-height: 32px;
	transition: max-height 0.2s linear, padding 0.2s ease, opacity 0.2s ease;
}
/* First section header sits flush to the brand divider; no leading air.
   Tighter max-height to match the reduced padding-top — keeps the linear
   transition snap-free for the first header too. */
aside.maktab-sidebar .nav-area > .nav-sect:first-child {
	padding-top: 6px;
	max-height: 26px;
}
aside.maktab-sidebar .nav-sect:hover { color: rgba(212,197,160,.9); }
aside.maktab-sidebar .nav-sect .caret {
	width: 11px;
	height: 11px;
	opacity: .6;
	transition: transform .25s ease;
	flex-shrink: 0;
}
aside.maktab-sidebar .nav-sect.collapsed .caret { transform: rotate(-90deg); }

/* ── Nav list ── */
aside.maktab-sidebar .nav {
	list-style: none;
	padding: 0;
	margin: 0;
	display: block;
}
/* Items are stacked vertically. The parent .body-sidebar has flex display
   from Frappe's CSS, which would normally cascade flex behavior to .nav
   children — but display: block on .nav makes its <li>s normal block
   elements stacking top-to-bottom (1 per row, even at 56px collapsed). */
aside.maktab-sidebar .nav li {
	display: flex;
	width: 100%;
}
aside.maktab-sidebar .nav-sect + .nav {
	overflow: hidden;
	max-height: 500px;
	transition: max-height .28s ease;
}
aside.maktab-sidebar .nav-sect.collapsed + .nav { max-height: 0; }

aside.maktab-sidebar .nav li {
	display: flex;
	align-items: center;
	gap: 9px;
	/* padding-inline 20px keeps the 16px icon's left edge at the rail-center
	   x-coord (56px wide → (56-16)/2 = 20px). When the sidebar collapses
	   from 182px to 56px the icon stays put; only the label clips. */
	padding: 8px 20px;
	font-size: 14px;
	color: var(--straw);
	cursor: pointer;
	line-height: 1.2;
	outline: none;
	background: transparent;
	/* No borders. The active stripe is rendered via inset box-shadow
	   (see .nav li.active ~11244) so it does not reserve horizontal
	   space, and the icons sit at the rail's visual midpoint in both
	   LTR (sidebar at left) and RTL (sidebar at right). Earlier versions
	   used `border-right: 3px solid transparent` as scaffold for the
	   active stripe — that 3px reservation biased icons by ±3px from
	   the visible center in the collapsed state. */
	border: 0;
}
aside.maktab-sidebar .nav li:hover {
	background: rgba(212,197,160,.06);
	color: var(--beige);
}
aside.maktab-sidebar .nav li:focus-visible {
	background: rgba(212,197,160,.08);
	box-shadow: inset 0 0 0 1px rgba(212,197,160,.4);
}
aside.maktab-sidebar .nav li.active {
	background: rgba(212,197,160,.1);
	color: var(--beige);
	/* Active stripe was previously a physical `border-right-color: var(--sand)`,
	   which painted on the content-edge side in LTR (sidebar at left of
	   viewport → physical right = content edge). Per Ahmad: chip should
	   sit only on the browser-edge side in BOTH languages. Switched to a
	   direction-aware inset box-shadow below — no layout impact, so we
	   can also drop the physical `border-right` scaffold from the base
	   rule's effective offset path (icons now center cleanly at x=20). */
}
/* Active stripe on the browser-edge side (away from page content).
   LTR sidebar lives at viewport-left, so browser-edge = physical left.
   RTL sidebar lives at viewport-right, so browser-edge = physical right.
   inset box-shadow with positive x renders on the left; negative x on
   the right. Logical inset shadows don't exist, hence the explicit pair. */
aside.maktab-sidebar .nav li.active {
	box-shadow: inset 3px 0 0 var(--sand);
}
[dir="rtl"] aside.maktab-sidebar .nav li.active {
	box-shadow: inset -3px 0 0 var(--sand);
}

aside.maktab-sidebar .nav li .ico {
	flex-shrink: 0;
	width: 16px;
	height: 16px;
	color: var(--sand);
	opacity: .8;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
aside.maktab-sidebar .nav li .ico svg {
	width: 16px;
	height: 16px;
	stroke: currentColor;
}
aside.maktab-sidebar .nav li:hover .ico,
aside.maktab-sidebar .nav li.active .ico { opacity: 1; }

aside.maktab-sidebar .nav li .label {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

aside.maktab-sidebar .nav li .badge {
	background: #C2735E;
	color: var(--beige);
	font-size: 10.5px;
	font-weight: 700;
	padding: 1px 6px;
	border-radius: var(--r-lg);
	font-family: 'Cairo', system-ui, sans-serif;
	min-width: 18px;
	text-align: center;
}
aside.maktab-sidebar .nav li .badge[hidden] { display: none; }
aside.maktab-sidebar .nav li .badge.muted {
	background: transparent;
	color: var(--sand);
	border: 1px solid rgba(194,173,126,.45);
	padding: 0 5px;
	font-weight: 600;
}

/* ── User area (footer) ── */
aside.maktab-sidebar .user-area {
	border-top: 1px solid rgba(212,197,160,.15);
	/* No top padding — the divider sits flush above the user-row. */
	padding: 0 14px 6px;
	flex-shrink: 0;
}
aside.maktab-sidebar .user-row {
	display: flex;
	align-items: center;
	gap: 9px;
	margin-bottom: 4px;
	cursor: pointer;
	color: inherit;
	text-decoration: none;
	/* 8px vertical padding lives inside the hover area so it highlights
	   on mouseover (FB-189). The button's top edge still touches the
	   .user-area divider (user-area has padding-top: 0). Negate the
	   .user-area horizontal padding (14px) so the hover bg spans the
	   full sidebar width — same visual treatment as the nav items above.
	   padding-inline-start: 15 (not 14) puts the avatar at x=15 in
	   expanded mode, matching its target position in collapsed (rail
	   visual center). The collapsed override bumps the start padding to
	   22 to compensate for user-area's reduced padding, keeping the
	   avatar at exactly x=15 throughout — no horizontal motion. */
	padding-block: 8px;
	padding-inline-end: 14px;
	padding-inline-start: 15px;
	margin-inline: -14px;
	border-radius: 0;
	transition: background .15s;
}
aside.maktab-sidebar .user-row:hover {
	background: rgba(212,197,160,.06);
	text-decoration: none;
	color: inherit;
}
aside.maktab-sidebar .user-row:focus-visible {
	outline: none;
	background: rgba(212,197,160,.08);
	box-shadow: inset 0 0 0 1px rgba(212,197,160,.4);
}
aside.maktab-sidebar .user-row .avatar {
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: var(--sand);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 12px;
	font-weight: 700;
	color: var(--brown-deep);
	flex-shrink: 0;
}
/* FB-2026-00217: <img> variant of the sidebar avatar — cover the circle,
   no inherited text-flex layout, keep the same 26px footprint. */
aside.maktab-sidebar .user-row .avatar.avatar-img {
	display: block;
	object-fit: cover;
	background: transparent;
}
aside.maktab-sidebar .user-row .name {
	font-size: 13.5px;
	color: var(--beige);
	font-weight: 600;
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* ── User tools — 5 footer buttons ──
   Source order: logout, language, theme, feedback, panel-toggle.
   In RTL row state the last child renders on the LEFT edge.
   In column (collapsed) state the last child renders at the BOTTOM.
   No flex-direction: row-reverse / order:* tricks. */
aside.maktab-sidebar .user-tools {
	display: flex;
	justify-content: space-between;
}
aside.maktab-sidebar .user-tools button {
	background: transparent;
	border: 0;
	color: var(--sand);
	width: 28px;
	height: 28px;
	border-radius: var(--r-sm);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	opacity: .75;
	padding: 0;
}
aside.maktab-sidebar .user-tools button:hover {
	background: rgba(212,197,160,.08);
	opacity: 1;
	color: var(--beige);
}
aside.maktab-sidebar .user-tools .ico {
	width: 15px;
	height: 15px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* ── Collapsed state (56px) ── */
aside.maktab-sidebar.is-collapsed { width: 56px; }
/* Center the palm mark in the rail using flex-start (NOT justify-content:
   center) so the palm stays pinned at padding-inline-start through the
   width animation — same pattern as .nav li. With justify-content:center
   the palm would track the brand's centerpoint, jumping toward the
   page-edge at frame 0 of collapse and sliding back to the browser edge.
   Math: rail visible width 56px, palm 26px wide, so palm-left needs to
   sit at (56-26)/2 = 15px for visual centering. Base padding-block
   (16/14) is preserved so the brand's outer height does not snap by
   2px on collapse (which would shift every icon below). Logical
   padding-inline-start works for both LTR and RTL — in LTR it's
   padding-left; in RTL it's padding-right and the flex-start child
   sits at the right inline-start edge. */
/* Brand padding is set on the base rule (same values in both states)
   so the palm-mark X position does not change on collapse. Only the
   Arabic wordmark needs hiding. */
aside.maktab-sidebar.is-collapsed .brand .ar { display: none; }
/* On sandbox sites the "sandbox" tag normally sits next to the palm
   (under the Arabic wordmark). In the 56px collapsed rail the first
   letter peeks out from behind the palm-mark; hide the text element
   and render a compact "SB" chip at the base of the palm instead so
   the sandbox cue stays visible without overflowing. */
aside.maktab-sidebar.is-collapsed .brand:has(.sandbox-tag) { position: relative; }
aside.maktab-sidebar.is-collapsed .brand .sandbox-tag { display: none; }
aside.maktab-sidebar.is-collapsed .brand:has(.sandbox-tag)::after {
	content: "SB";
	position: absolute;
	bottom: 4px;
	/* Pin to the palm's horizontal column (inset-inline-start matches the
	   brand's padding-inline-start: 15px) with width matching the palm
	   (26px) and text-align center — guarantees SB centers under the
	   palm in both LTR and RTL. Using left:50% would center under the
	   brand element, which sits 1.5px off the sidebar visual center
	   because of the 3px sand `border-inline-end` on the sidebar. */
	inset-inline-start: 15px;
	width: 26px;
	text-align: center;
	font-size: 8px;
	font-weight: 700;
	letter-spacing: 0.04em;
	color: var(--sand);
	opacity: 0.7;
	line-height: 1;
	pointer-events: none;
}
aside.maktab-sidebar.is-collapsed .nav-sect {
	/* Was `display: none`; switched to max-height/opacity so the height
	   change runs alongside the 0.2s width transition instead of snapping
	   at frame 0 (which the user saw as icons jumping up/down). */
	max-height: 0;
	padding-top: 0;
	padding-bottom: 0;
	opacity: 0;
	pointer-events: none;
}
/* Only the current/open section's items show in the collapsed rail.
   Sections marked .collapsed (everything except the active one) keep
   their max-height: 0 from the base rule and stay hidden. Top-level
   items (no preceding .nav-sect) always show. */
aside.maktab-sidebar.is-collapsed .nav-sect:not(.collapsed) + .nav {
	/* Was `max-height: none !important;` — but `none` is a non-interpolatable
	   keyword, so toggling `.is-collapsed` snapped this rule's transition
	   discontinuously at the end of the 0.2s width animation, jolting every
	   icon in the active section by ~13px in a single frame. A large numeric
	   value transitions smoothly while still acting as "unbounded" in
	   practice (no section has > 1000px of items). */
	max-height: 1000px !important;
}
aside.maktab-sidebar.is-collapsed .nav li {
	/* Keep base `padding: 8px 20px` and flex-start alignment so the icon
	   sits at x=20 throughout the width animation — at 56px rail width
	   that's exactly the visual midpoint ((56-16)/2 = 20). Only drop the
	   transparent physical border-right so it doesn't reserve 3px on the
	   content-edge side and bias the icon. The active stripe (was
	   `border-right-color`) is rendered as an inset box-shadow below so
	   it does not affect layout.
	   Earlier attempts using `justify-content: center` made the icon
	   track the li's centerpoint as the width animated 200→56, causing
	   the icon to jump toward the page-edge at frame 0 and then slide
	   back to the browser edge — user complaint "icons jump to the page
	   side and slide back". Flex-start pins the icon at x=20 regardless
	   of li width, so it stays in place. */
	position: relative;
	border-inline-end: 0;
}
/* Active-stripe handled by the general .nav li.active rule (see ~11244)
   via inset box-shadow on the browser-edge side. No collapsed override
   needed — the same rule applies in both expanded and collapsed states. */
aside.maktab-sidebar.is-collapsed .nav li .label { display: none; }
aside.maktab-sidebar.is-collapsed .nav li .badge {
	position: absolute;
	top: 4px;
	right: 8px;
	font-size: 9px;
	padding: 0 4px;
	min-width: 14px;
}

/* ── Panel-toggle chevron orientation ──
   Default SVG draws a left-pointing chevron — correct for LTR-expanded
   ("hide" pushes the sidebar back left). Flips on collapsed state and
   on RTL; both flips cancel for RTL-collapsed. */
aside.maktab-sidebar #maktab-panel-toggle .ico {
	transition: transform .2s ease;
}
aside.maktab-sidebar.is-collapsed #maktab-panel-toggle .ico {
	transform: scaleX(-1);
}
[dir="rtl"] aside.maktab-sidebar #maktab-panel-toggle .ico {
	transform: scaleX(-1);
}
[dir="rtl"] aside.maktab-sidebar.is-collapsed #maktab-panel-toggle .ico {
	transform: scaleX(1);
}
aside.maktab-sidebar.is-collapsed .user-row .name { display: none; }
aside.maktab-sidebar.is-collapsed .user-row {
	/* `justify-content: center` would center the avatar in user-row's
	   animating content width — same trap as user-tools. With user-row's
	   `margin-inline: -14px` extending its content area beyond user-area's
	   padding, the avatar needs `padding-inline-start: 22px` to sit at
	   x=15 (avatar center = 28 = rail visual midpoint). flex-start (the
	   default) then pins the avatar at that position regardless of how
	   the surrounding container width animates. */
	margin-bottom: 6px;
	padding-inline-start: 22px;
}
aside.maktab-sidebar.is-collapsed .user-tools {
	flex-direction: column;
	/* `align-items: flex-start` (not center) pins each button to the
	   inline-start of the user-tools content area regardless of the
	   container's animating width. Center-alignment would put the
	   button at the changing midpoint, jumping it toward the page-edge
	   at frame 0 of collapse and sliding it back to the browser-edge as
	   the sidebar narrowed — same trap as .nav li had with
	   justify-content: center.
	   padding-inline-start: 7px sits the button at (7px from user-area
	   inner) + (7px from user-tools inner) = 14px from sidebar left,
	   placing the 28px-wide button's center at the rail's visual
	   midpoint (x=28). */
	align-items: flex-start;
	padding-inline-start: 7px;
	gap: 4px;
}
/* Same sand-line compensation as .brand and .nav li: add 3px to the
   inline-start padding so the user-row avatar + user-tools column line
   up with the visible center of the rail in both LTR and RTL. */
aside.maktab-sidebar.is-collapsed .user-area {
	padding-block-start: 10px;
	padding-block-end: 6px;
	padding-inline-start: 7px;
	padding-inline-end: 4px;
}

/* Tooltip when collapsed — uses position:fixed + --tip-y so it can escape
   the body-sidebar's overflow:hidden context (set by JS on hover). */
aside.maktab-sidebar.is-collapsed .nav li[data-tip]:hover::after {
	content: attr(data-tip);
	position: fixed;
	left: calc(56px + 8px);
	top: var(--tip-y, 50%);
	transform: translateY(-50%);
	background: #2A1F15;
	color: var(--beige);
	padding: 5px 10px;
	border-radius: var(--r-sm);
	font-size: 12px;
	white-space: nowrap;
	z-index: 10000;
	pointer-events: none;
	box-shadow: 0 2px 8px rgba(0,0,0,.3);
}
[dir="rtl"] aside.maktab-sidebar.is-collapsed .nav li[data-tip]:hover::after {
	left: auto;
	right: calc(56px + 8px);
}

/* ── Mobile drawer (≤768px) ──
   aside.maktab-sidebar IS the drawer — slides in from the inline-start edge
   when .is-open is added. No Frappe wrapper involved.
   v5: drawer width matches desktop (182px RTL, 200px LTR) — just wide
   enough for the longest label. Was 280px which was excessive on small
   phones. max-width: 85% still applies as the safety cap. */
@media (max-width: 768px) {
	aside.maktab-sidebar {
		position: fixed !important;
		top: 0 !important;
		left: 0 !important;
		bottom: 0 !important;
		width: 182px !important;
		max-width: 85% !important;
		height: 100% !important;
		z-index: 1050 !important;
		transform: translate3d(-100%, 0, 0) !important;
		transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
		will-change: transform;
		-webkit-backface-visibility: hidden;
		backface-visibility: hidden;
		padding-top: env(safe-area-inset-top, 0px) !important;
	}
	html[dir="ltr"] aside.maktab-sidebar {
		width: 200px !important;
	}
	html[dir="rtl"] aside.maktab-sidebar {
		left: auto !important;
		right: 0 !important;
		transform: translate3d(100%, 0, 0) !important;
	}
	aside.maktab-sidebar.is-open,
	html[dir="rtl"] aside.maktab-sidebar.is-open {
		transform: translate3d(0, 0, 0) !important;
	}
	/* Mobile drawer is full width of its 280px box — .is-collapsed (desktop
	   rail state) is irrelevant here, but if it lingers from a viewport
	   crossover, ensure inner content stays readable. */
	aside.maktab-sidebar.is-collapsed .brand .ar,
	aside.maktab-sidebar.is-collapsed .nav li .label,
	aside.maktab-sidebar.is-collapsed .user-row .name {
		display: block;
	}
	aside.maktab-sidebar.is-collapsed .nav-sect {
		max-height: 60px;
		padding-top: 10px;
		padding-bottom: 4px;
		opacity: 1;
		pointer-events: auto;
	}
	aside.maktab-sidebar.is-collapsed .nav li { justify-content: flex-start; padding: 8px 14px; }
	aside.maktab-sidebar.is-collapsed .user-tools { flex-direction: row; gap: 0; }
	/* Hide panel-toggle in mobile drawer — the bottom-nav menu tab opens/closes the drawer. */
	aside.maktab-sidebar #maktab-panel-toggle {
		display: none;
	}
	/* Enlarge the remaining 4 footer buttons so they fill the drawer's width. */
	aside.maktab-sidebar .user-tools button {
		flex: 1;
		min-width: 40px;
		min-height: 40px;
		width: auto;
		height: auto;
	}
	aside.maktab-sidebar .user-tools .ico {
		width: 18px;
		height: 18px;
	}

	/* Sidebar backdrop (fades in/out alongside the drawer).
	   FB-2026-00177: keep `display: block` constant on mobile and toggle
	   only opacity/pointer-events. Toggling `display` is not animatable, so
	   the previous `display: none` on close made the scrim vanish instantly
	   and made the entire close feel un-animated even though the sidebar's
	   transform IS interpolating. */
	.maktab-sidebar-backdrop {
		display: block;
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		background: rgba(237, 229, 212, 0.55);
		z-index: 1049;
		opacity: 0;
		pointer-events: none;
		transition: opacity 0.3s ease;
	}
	[data-theme="dark"] .maktab-sidebar-backdrop {
		background: rgba(26, 21, 16, 0.55);
	}
	aside.maktab-sidebar.is-open ~ .maktab-sidebar-backdrop {
		opacity: 1;
		pointer-events: auto;
	}
	/* Frappe's built-in grey overlay inside its (hidden) container — keep
	   the suppression rule for safety, in case the cascade ever revives. */
	.body-sidebar-container .overlay {
		display: none !important;
	}
	/* FB-2026-00177/180: do NOT add overflow:hidden on <html> here — WebKit
	   zeroes scrollY on that. Do NOT recolor <html> either; any flip in html
	   bg becomes visible during the close transition. */
}
/* Desktop: no backdrop. The @media (max-width:768px) rules above set
   display: block on mobile so the opacity transition can run on close;
   without scoping THIS rule to desktop only, it would otherwise re-hide
   the backdrop on mobile (same specificity, later in source = wins). */
@media (min-width: 769px) {
	.maktab-sidebar-backdrop {
		display: none;
	}
}

/* Suppress sidebar transitions while the window is actively resizing
   (prevents a slide animation when crossing the 768px boundary). */
body.maktab-resizing aside.maktab-sidebar,
body.maktab-resizing .maktab-sidebar-backdrop {
	transition: none !important;
}

/* ── Print: hide the sidebar entirely. ── */
@media print {
	aside.maktab-sidebar,
	.maktab-sidebar-backdrop { display: none !important; }
}

/* ════════════════════════════════════════════════════════════════════════
   End sidebar v4
   ════════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════
   Sidebar v5 — m0028 redesign overrides
   ════════════════════════════════════════════════════════════════════════

   Layered on top of v4 rules above. v5 adds:
     - Hierarchical 6-section structure (driven by maktab.NAV)
     - 6px entity color chips on items inside the Entities section
     - Numerical badges (rent_overdue / maintenance_open / expiry_warning)
     - Active-state stripe on inline-START — opposite side from the long
       sand line (which is on inline-end of the sidebar), so the two
       visual indicators don't overlap on the same edge
     - RTL caret rotation correction
     - Dark mode bg matches mockup's warmer #2A2018 (not v4's #0F0C08)

   PRESERVED from v4 (Ahmad's lock):
     - Brown-deep bg + light text in light mode
     - 3px sand vertical line — moved from physical `border-left` to
       logical `border-inline-end` at line 10452 (was on wrong side in LTR)
     - Footer padding/spacing
     - All animations
*/

/* ── Active stripe — superseded by inset box-shadow on .nav li.active
   (see ~line 11244). The previous `border-inline-start: 3px` scaffold
   was reserving 3px of horizontal space on every nav li, biasing the
   icon by +3px toward the content edge in collapsed view (icon at
   x=23 instead of the visual midpoint at x=20). Box-shadow renders
   the same stripe with zero layout impact. Keeping the `border-inline-end: 0`
   reset because the base rule still declares `border-right: 3px solid
   transparent` and we don't want it reserving 3px on the content edge
   either (compounds the issue in the opposite direction in RTL). */
aside.maktab-sidebar .nav li {
	border-inline-end: 0;
}

/* ── Caret RTL rotation: collapsed sections point inline-end ──────── */
[dir="rtl"] aside.maktab-sidebar .nav-sect.collapsed .caret {
	transform: rotate(90deg);
}

/* ── Entity chip — 6px dot that BLEEDS into the start padding ───────
   Negative margin pulls the chip into the item's inline-start padding
   so it doesn't add to the row's content width. Label keeps full space;
   no text truncation. */
aside.maktab-sidebar .mkt-sb__chip {
	flex-shrink: 0;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	display: inline-block;
	/* Bleed back into the 20px padding-inline-start of the nav li.
	   Net: chip sits at ~8px from item edge, doesn't consume row width. */
	margin-inline-start: -14px;
	margin-inline-end: 0;
	/* Nudge 3px toward the icon so the chip sits visually centered
	   between the 3px active stripe (browser-edge box-shadow) and the
	   icon column. position:relative + inset-inline-start shifts the
	   render without affecting layout flow — icon stays at x=21. */
	position: relative;
	inset-inline-start: 3px;
}
aside.maktab-sidebar .mkt-sb__chip--charitable  { background: var(--entity-charitable, #5E7D5E); }
aside.maktab-sidebar .mkt-sb__chip--passthrough { background: var(--entity-passthrough, #3D6D8F); }
aside.maktab-sidebar .mkt-sb__chip--personal    { background: var(--entity-personal, #D4A05A); }
aside.maktab-sidebar .mkt-sb__chip--operational { background: var(--entity-operational, #6B5A48); }
/* When the rail is collapsed (56px), hide chips — only the icon fits. */
aside.maktab-sidebar.is-collapsed .mkt-sb__chip { display: none; }

/* ── Numerical badge ────────────────────────────────────────────────── */
aside.maktab-sidebar .nav li .mkt-sb__badge {
	margin-inline-start: auto;
	background: var(--clay, #C2735E);
	color: var(--cream, #FAF8F2);
	font-size: 10.5px;
	font-weight: 700;
	padding: 1px 6px;
	border-radius: 999px;
	min-width: 18px;
	text-align: center;
	font-family: 'Cairo', system-ui, sans-serif;
	line-height: 1.3;
}
aside.maktab-sidebar .nav li .mkt-sb__badge[hidden] { display: none; }
/* In collapsed-rail mode, badges become tiny corner dots in the top-end
   corner of the item. */
aside.maktab-sidebar.is-collapsed .nav li .mkt-sb__badge {
	position: absolute;
	top: 4px;
	inset-inline-end: 4px;
	min-width: 6px;
	width: 6px;
	height: 6px;
	padding: 0;
	font-size: 0;
	border-radius: 50%;
}
aside.maktab-sidebar.is-collapsed .nav li { position: relative; }

/* ── Dark mode bg: mockup's warmer #2A2018 (not v4's #0F0C08) ───────── */
[data-theme="dark"] aside.maktab-sidebar {
	background: #2A2018;
}

/* ── LTR sidebar width: snug fit for "Dr. Issam's Estate" ──
   Widths measured 2026-05-25 via canvas measureText on each label
   with its actual computed font. AR widest "عقارات د. عصام" = 89px →
   sidebar needs 172px (padding 40 + chip 6 + gap 9 + icon 16 + gap 9
   + text + sand 3) → using 176px with 4px buffer. EN widest "Dr.
   Issam's Estate" = 108px → needs 191px → using 192px with 1px buffer. */
@media (min-width: 769px) {
	html[dir="ltr"] aside.maktab-sidebar { width: 192px; }
	html[dir="ltr"] aside.maktab-sidebar ~ .main-section {
		margin-inline-start: 192px !important;
		width: calc(100% - 192px) !important;
	}
	/* Collapsed rail still 56px regardless of direction. */
	html[dir="ltr"] aside.maktab-sidebar.is-collapsed { width: 56px; }
	/* When the LTR sidebar collapses, .main-section must shrink to clear
	   the 56px rail. The generic `aside.maktab-sidebar.is-collapsed ~ .main-section`
	   rule above (line ~11074) is overridden by the LTR-specific 192px
	   companion above this block, so without this explicit collapse
	   companion the main column stays at margin-inline-start:192px and
	   the page does not resize when the rail shrinks. RTL was unaffected
	   because the generic 176px rule already includes the LTR-specific
	   width override path. */
	html[dir="ltr"] aside.maktab-sidebar.is-collapsed ~ .main-section {
		margin-inline-start: 56px !important;
		width: calc(100% - 56px) !important;
	}
}

/* Sandbox-tagged sidebars don't expand the desk; verified after width
   changes above. If a future label exceeds these widths and truncates,
   re-measure via /tmp/measure_canvas.js (canvas-based) and bump. */

/* ════════════════════════════════════════════════════════════════════════
   End sidebar v5 overrides
   ════════════════════════════════════════════════════════════════════════ */

/* The Counterparty History .ch-* block was removed 2026-06-03 in the v2
   redesign — it now ships public/css/counterparty_history.css (.ch-page
   div-grid; .mkt-pill type tones; .mkt-kpi toned cards, no border stripe). */

/* ── Hijri-primary date pairing ──────────────────────────────────────────
   Output of maktab.fmt_date() in AR mode:
     <span class="date-hijri">١٥ شعبان ١٤٤٧</span>
     <span class="date-greg">2026-04-15</span>
   Hijri stays inline; ISO drops to a small dim line below. Wrap the
   container in `.date-inline` for single-line contexts (toolbars, table
   cells) to suppress the ISO secondary. */
.date-hijri { display: inline; }
.date-greg {
	display: block;
	font-size: 0.75em;
	opacity: 0.55;
	margin-top: 2px;
}
.date-inline .date-greg { display: none; }

/* ── RTL arrow flip ────────────────────────────────────────────────
   Arrows used as directional indicators ("view more", "open record",
   "back") should point in the reading direction. In RTL that means
   right-to-left, so the → glyph after Arabic text must be mirrored.
   We use transform: scaleX(-1) — safer than character substitution
   because it covers ASCII fallbacks and works on any glyph (→, ←,
   &rsaquo;, etc.).

   Scope is restricted to classes that explicitly mark directional
   navigation arrows. Arrows that convey non-directional semantics
   (e.g. activity-log "old → new" state transitions, date ranges
   "start → end", "matched to" relationships) are NOT flipped — they
   keep LTR direction because their meaning is "source → target",
   not "go forward in reading direction". */
[dir="rtl"] .lv-arrow,
[dir="rtl"] .f-arrow,
[dir="rtl"] .maktab-arrow,
[dir="rtl"] .maktab-detail-back {
	display: inline-block;
	transform: scaleX(-1);
}

/* ════════════════════════════════════════════════════════
   Majlis Home — page-scoped `.mh-shell` + `.mj-*`
   Shared `.eh-*` atoms now live in components.css (Step 6).
   ════════════════════════════════════════════════════════ */

.mh-shell {
  display: flex; flex-direction: column;
  gap: var(--s-6);
  padding: var(--s-8) var(--s-8) var(--s-12);
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
}
.mh-shell * { box-sizing: border-box; }

/* ════════════════════════════════════════════════════════
   Majlis Home — page-scoped .mj-*
   Ported from stage2-handoff/phase2b-handoff/mockups/majlis-home.html
   ════════════════════════════════════════════════════════ */

/* ── Hero: next event ──────────────────────────────────── */
.mj-hero {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--s-6);
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-6);
  align-items: center;
}
.mj-hero__left { min-width: 0; }
.mj-hero__tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--text-xs); color: var(--brown);
  background: var(--straw);
  padding: 3px 10px; border-radius: var(--r-pill);
  margin-bottom: var(--s-3);
  font-weight: 600;
  letter-spacing: .02em;
}
.mj-hero__tag svg { width: 12px; height: 12px; }
.mj-hero__type {
  font-size: var(--text-3xl); font-weight: 700;
  color: var(--brown-deep); line-height: 1.1;
  margin: 0 0 var(--s-2);
}
.mj-hero__dates {
  display: flex; align-items: baseline; gap: var(--s-2);
  font-size: var(--text-md); color: var(--ink-muted);
  margin-bottom: var(--s-4);
}
.mj-hero__date-h { color: var(--brown); font-weight: 600; }
.mj-hero__date-sep { opacity: .5; }
.mj-hero__countdown {
  display: inline-flex; align-items: baseline; gap: var(--s-2);
  background: var(--success-bg); color: var(--success);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  font-weight: 600;
}
.mj-hero__countdown-pre { font-size: var(--text-sm); }
.mj-hero__countdown-big {
  font-size: var(--text-4xl); font-weight: 800; line-height: 1;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.mj-hero__countdown-unit { font-size: var(--text-sm); }

.mj-hero__right { min-width: 0; }
.mj-hero__details {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3) var(--s-4);
}
.mj-hero__details > div { min-width: 0; }
.mj-hero__details dt {
  font-size: var(--text-xs); color: var(--ink-muted);
  margin-bottom: 2px;
}
.mj-hero__details dd {
  margin: 0;
  font-size: var(--text-md); font-weight: 600;
  color: var(--brown-deep);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mj-hero__details dd .unit {
  font-size: var(--text-xs); color: var(--ink-muted);
  margin-inline-start: 3px; font-weight: 400;
}

/* ── Upcoming + past events list ──────────────────────── */
.mj-events { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; }
.mj-events__row {
  display: grid;
  grid-template-columns: 130px 1fr auto;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-soft);
  align-items: center;
  cursor: pointer;
}
.mj-events__row:last-child { border-bottom: none; }
.mj-events__row:hover { background: var(--beige); }
.mj-events__when { display: flex; flex-direction: column; gap: 2px; }
.mj-events__when-days {
  display: inline-flex; align-items: baseline; gap: 4px;
  font-size: var(--text-xl); font-weight: 700; color: var(--brown-deep);
  line-height: 1;
}
.mj-events__when-unit { font-size: var(--text-xs); color: var(--ink-muted); font-weight: 400; }
.mj-events__when-dates {
  display: flex; flex-direction: column;
  font-size: var(--text-xs);
}
.mj-events__when-dates > span:first-child { color: var(--brown); }
.mj-events__what { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mj-events__type {
  font-size: var(--text-base); font-weight: 600;
  color: var(--brown-deep);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mj-events__meta {
  font-size: var(--text-xs); color: var(--ink-muted);
  display: flex; align-items: center; gap: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mj-events__sep { opacity: .5; }
.mj-events__nums {
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
}
.mj-events__attendance {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--text-sm); color: var(--brown);
}
.mj-events__attendance svg { width: 12px; height: 12px; }
.mj-events__budget {
  font-size: var(--text-sm); font-weight: 600;
  color: var(--brown-deep);
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.mj-events__budget .unit {
  font-size: var(--text-xs); color: var(--ink-muted); font-weight: 400;
}

/* ── Past events accordion ─────────────────────────────── */
.mj-past { margin-top: var(--s-2); }
.mj-past__toggle {
  background: transparent; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-ar); font-size: var(--text-sm); color: var(--brown);
  padding: 6px 0;
}
.mj-past__toggle:hover {
  text-decoration: underline;
  text-decoration-color: var(--sand);
  text-underline-offset: 3px;
}
.mj-past__toggle svg { width: 14px; height: 14px; }
.mj-events--past {
  margin-top: var(--s-2);
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.mj-events__when--past {
  display: flex; flex-direction: column;
  font-size: var(--text-sm);
}
.mj-events__when--past .num:last-child {
  color: var(--brown-deep); font-weight: 600;
}

/* ── Venue cards ───────────────────────────────────────── */
.mj-venue-grid {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.mj-venue-card { display: flex; flex-direction: column; gap: var(--s-3); }
.mj-venue-card__head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: var(--s-2);
}
.mj-venue-card__name {
  font-size: var(--text-md); font-weight: 600;
  color: var(--brown-deep);
  /* Phase 2 fix (L11): real venue names (e.g. "Majlis al Hajj Hassan
     Bouholaigah") are longer than mockup test fixtures. Allow wrap
     with a tight line-height + cap at 2 lines so the head row stays
     visually balanced with the pill. */
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 0;
}
.mj-venue-card__stats {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) 0;
  border-top: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
}
.mj-venue-card__divider {
  width: 1px; align-self: stretch;
  background: var(--border); margin: 0 var(--s-2);
}
.mj-venue-card__lbl {
  font-size: var(--text-xs); color: var(--ink-muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.mj-venue-card__val {
  font-size: var(--text-xl); font-weight: 700; color: var(--brown-deep);
  font-feature-settings: "tnum" 1, "lnum" 1; line-height: 1.1;
}
.mj-venue-card__val--sm { font-size: var(--text-md); font-weight: 600; }
.mj-venue-card__foot {
  display: flex; justify-content: space-between; align-items: center;
  font-size: var(--text-sm);
}
.mj-venue-card__foot span {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--ink-muted);
}
.mj-venue-card__foot svg { width: 12px; height: 12px; }

/* ── Maintenance list ──────────────────────────────────── */
.mj-maint { list-style: none; padding: 0; margin: 0; }
.mj-maint__row {
  display: grid; grid-template-columns: 90px 1fr auto;
  gap: var(--s-3); align-items: center;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
}
.mj-maint__row:last-child { border-bottom: none; }
.mj-maint__row:hover { background: var(--beige); }
.mj-maint__id {
  font-size: var(--text-xs); color: var(--ink-muted);
  font-family: var(--font-num);
  font-feature-settings: "tnum" 1;
}
.mj-maint__body { min-width: 0; }
.mj-maint__desc {
  font-size: var(--text-sm); font-weight: 500;
  color: var(--brown-deep);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mj-maint__meta {
  font-size: var(--text-xs); color: var(--ink-muted);
  display: flex; align-items: center; gap: 6px;
  margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Empty state ──────────────────────────────────────── */
.mj-empty {
  padding: var(--s-6) var(--s-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--ink-muted);
  /* Phase 2 fix (F5): balance empty-state column heights with their
     populated sibling in .eh-two-col. Flex layout on the parent card
     lets the empty-state stretch; min-height gives a sensible floor
     when both columns are empty. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 220px;
  flex: 1;
}
/* Promote .mh-shell .eh-two-col cards to flex so .mj-empty (flex:1)
   actually fills the available vertical space, balancing against a
   populated sibling table card. Page-scoped to .mh-shell so other
   entity-home pages aren't affected. */
.mh-shell .eh-two-col { align-items: stretch; }
.mh-shell .eh-two-col > .eh-block--col { display: flex; flex-direction: column; }
.mh-shell .eh-two-col > .eh-block--col > .mkt-card {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ── Mobile (page-scoped) — generic .eh-* mobile rules live in components.css ─ */
@media (max-width: 640px) {
  .mh-shell { padding: var(--s-5) var(--s-4) var(--s-10); }
  .mj-hero { grid-template-columns: 1fr; padding: var(--s-4); }
  .mj-hero__details { grid-template-columns: 1fr 1fr; }
  .mj-events__row { grid-template-columns: 70px 1fr auto; gap: var(--s-2); }
  .mj-events__when-days { font-size: var(--text-md); }
  .mj-maint__row { grid-template-columns: 1fr auto; }
  .mj-maint__id { display: none; }
}

/* Very narrow phones (~390px): the secondary date line wraps to 3-4 lines in
   the 70px when-column, making rows tall + ragged. The day-count already
   conveys timing, so drop the redundant date line and let any long
   section/speaker meta wrap instead of truncating. (Note: a grid-area reflow
   to move .mj-events__meta to its own row is NOT possible CSS-only — meta is
   nested inside .mj-events__what, not a direct grid child of the row.) */
@media (max-width: 520px) {
  .mj-events__when-dates { display: none; }
  .mj-events__meta { white-space: normal; }
  /* Past events have no day-count — their when-column is two bare spans:
     Hijri (.num.eh-muted) + Gregorian (.num). Keep the Hijri (primary date
     for religious events, per BUSINESS_LOGIC) and hide the Gregorian, but
     ONLY when the Hijri is also present (:not(:only-child)) so a Hijri-less
     event still shows its date. */
  .mj-events__when--past > .num:not(.eh-muted):not(:only-child) { display: none; }
}

/* ── Dark-mode contrast tuning for entity-home (.mh-shell) ─────
   In live tokens `--brown-deep` flips to a near-black (#1F1A12) in
   dark mode — perfect as a button BG, invisible as text. The atoms
   were transcribed from the mockup which assumed `--brown-deep`
   stayed legible on the cream/beige background. Remap titles /
   prominent text to `--ink` (light in dark mode) when the page is
   inside `.mh-shell`. Scoped to keep light mode untouched.
*/
[data-theme="dark"] .mh-shell .eh-pg-head__title,
[data-theme="dark"] .mh-shell .eh-pg-head__year,
[data-theme="dark"] .mh-shell .eh-basmala,
[data-theme="dark"] .mh-shell .eh-sect-head__title,
[data-theme="dark"] .mh-shell .eh-split__title,
[data-theme="dark"] .mh-shell .eh-split__total-amt,
[data-theme="dark"] .mh-shell .eh-split__legend-amt,
[data-theme="dark"] .mh-shell .eh-recent__party,
[data-theme="dark"] .mh-shell .mj-hero__type,
[data-theme="dark"] .mh-shell .mj-hero__date-h,
[data-theme="dark"] .mh-shell .mj-hero__details dd,
[data-theme="dark"] .mh-shell .mj-events__when-days,
[data-theme="dark"] .mh-shell .mj-events__type,
[data-theme="dark"] .mh-shell .mj-events__when-dates > span:first-child,
[data-theme="dark"] .mh-shell .mj-events__when--past .num:last-child,
[data-theme="dark"] .mh-shell .mj-events__budget,
[data-theme="dark"] .mh-shell .mj-venue-card__name,
[data-theme="dark"] .mh-shell .mj-venue-card__val,
[data-theme="dark"] .mh-shell .mj-maint__desc {
  color: var(--ink);
}

/* The eh-pg-head spine gradient was rgba(0,0,0,.02) — invisible on dark.
   Use a slightly lifted tint so the spine still reads. */
[data-theme="dark"] .mh-shell .eh-pg-head {
  background: linear-gradient(180deg, rgba(255,255,255,.03) 0%, transparent 70%);
}
[data-theme="dark"] .mh-shell .eh-pg-head[data-entity-class="operational"] {
  background: linear-gradient(180deg, rgba(255,255,255,.04) 0%, transparent 70%);
}

/* Row hovers in dark mode — --beige is a near-black, which makes hover
   indistinguishable from default. Use --straw (a lighter brown) instead. */
[data-theme="dark"] .mh-shell .mj-events__row:hover,
[data-theme="dark"] .mh-shell .mj-maint__row:hover,
[data-theme="dark"] .mh-shell .eh-recent__row:hover {
  background: var(--straw);
}

/* Hero countdown badge — success-bg in dark is a deep green, success
   stays a soft sage. Already legible, but force a brighter text shade
   for the big day count so it doesn't blend into the chip. */
[data-theme="dark"] .mh-shell .mj-hero__countdown {
  color: var(--success);
}

/* Dark-mode primary button visibility fix scoped to .mh-shell:
   the existing global override sets `color: var(--brown-deep)` which in dark
   is near-black on near-black. Use --ink (light text) so the button reads. */
[data-theme="dark"] .mh-shell .mkt-btn--primary {
  color: var(--ink);
  border-color: var(--brown);
}

/* === Phase 2B Home / Action Queue ports ============================
   Ported verbatim from stage2-handoff/phase2b-handoff/mockups/
   home-action-queue.html <style> block. All selectors are .aq-*
   prefixed so they cannot bleed into the rest of the design system.
   Composes on top of .mkt-card / .mkt-kpi / .mkt-btn / .mkt-dlg
   primitives in components.css.
================================================================== */

.aq-page {
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: var(--s-8) var(--s-8) var(--s-12);
  color: var(--ink);
}
.aq-page * { box-sizing: border-box; }

/* ── Page-head ────────────────────────────────────────── */
.aq-pg-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-4);
  padding: 0 0 var(--s-5);
  margin-bottom: var(--s-6);
  border-bottom: 1px solid var(--border);
}
.aq-pg-head__main { min-width: 0; }
.aq-pg-head__greet {
  font-size: var(--text-4xl); font-weight: 600;
  color: var(--brown-deep); line-height: 1.1;
  margin: 0 0 6px;
  white-space: nowrap;
}
.aq-pg-head__date {
  font-size: var(--text-md); color: var(--ink-muted);
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.aq-pg-head__actions {
  display: flex; gap: var(--s-2); flex-shrink: 0;
  align-items: center;
}
/* Canonical .mkt-date-pair inside the page-head — sizes ported verbatim
   from the mockup's .aq-pg-head__date rules. */
.aq-pg-head__date .mkt-date-pair__hijri { font-size: var(--text-md); }
.aq-pg-head__date .mkt-date-pair__greg  { font-size: var(--text-sm); }

/* ── Entity filter bar (above the KPI strip) ──────────────
   Pure-frontend chips: All + the 7 entities, each with a client-computed
   count. Active chip fills with the entity color; operational/majlis
   entities resolve to a neutral gray token (special-cased below — expected,
   not a bug). Ported verbatim from the Home v2 mockup. */
.aq-filter-bar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}
.aq-filter-bar__label {
  font-size: var(--text-sm); color: var(--ink-muted);
  margin-inline-end: var(--s-2);
  letter-spacing: .02em;
  font-weight: 500;
}
.aq-filter-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: transparent;
  border: 1px solid var(--border);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: all var(--dur-fast);
  line-height: 1.4;
  white-space: nowrap;
}
.aq-filter-chip:hover { border-color: var(--sand); color: var(--brown); }
.aq-filter-chip__count {
  font-family: var(--font-num);
  font-feature-settings: "tnum" 1, "lnum" 1;
  font-size: var(--text-xs);
  opacity: .65;
}
/* Active chip — fill with entity background + ink */
.aq-filter-chip.is-active {
  background: var(--brown-deep);
  color: var(--cream);
  border-color: var(--brown-deep);
}
.aq-filter-chip.is-active .aq-filter-chip__count { opacity: .8; }
.aq-filter-chip.is-active[data-entity="thilth"]        { background: var(--entity-charitable-bg);  color: var(--entity-charitable);  border-color: var(--entity-charitable); }
.aq-filter-chip.is-active[data-entity="khums"]         { background: var(--entity-passthrough-bg); color: var(--entity-passthrough); border-color: var(--entity-passthrough); }
.aq-filter-chip.is-active[data-entity="issam"],
.aq-filter-chip.is-active[data-entity="family-home"],
.aq-filter-chip.is-active[data-entity="bayt-jadda"]    { background: var(--entity-personal-bg);    color: var(--entity-personal);    border-color: var(--entity-personal); }
.aq-filter-chip.is-active[data-entity="majlis"],
.aq-filter-chip.is-active[data-entity="maktab-ops"]    { background: rgba(107,90,72,.12);          color: var(--entity-operational); border-color: var(--entity-operational); }
[data-theme="dark"] .aq-filter-chip.is-active[data-entity="majlis"],
[data-theme="dark"] .aq-filter-chip.is-active[data-entity="maktab-ops"] { background: rgba(232,220,186,.16); }

/* ── KPI strip ────────────────────────────────────────── */
.aq-kpi-row {
  display: grid; gap: var(--s-3);
  grid-template-columns: repeat(4, 1fr);
  margin-bottom: var(--s-6);
}
.aq-kpi-row .mkt-kpi--card { padding: var(--s-3) var(--s-4); }
.aq-kpi-row .mkt-kpi__value { font-size: var(--text-2xl); }
.aq-kpi-row .mkt-kpi__label { font-size: var(--text-sm); }

/* ── Stack of groups ──────────────────────────────────── */
.aq-stack { display: flex; flex-direction: column; gap: var(--s-5); }

/* ── Group (collapsible heading + body) ──────────────── */
.aq-group { display: flex; flex-direction: column; }
.aq-group__head {
  display: flex; align-items: baseline; gap: var(--s-2);
  padding: var(--s-2) 0;
  cursor: pointer;
  user-select: none;
}
.aq-group__caret {
  background: none; border: none; cursor: pointer;
  width: 22px; height: 22px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--brown);
  padding: 0; margin-inline-end: 2px;
  transition: transform var(--dur-base);
  align-self: center;
}
.aq-group__caret svg { width: 16px; height: 16px; }
.aq-group.is-closed .aq-group__caret { transform: rotate(-90deg); }
[dir="rtl"] .aq-group.is-closed .aq-group__caret { transform: rotate(90deg); }

.aq-group__title {
  font-size: var(--text-xl); font-weight: 600;
  color: var(--brown-deep); margin: 0;
}
.aq-group__count {
  color: var(--ink-muted); font-size: var(--text-md); font-weight: 500;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.aq-group__see {
  margin-inline-start: auto;
  font-size: var(--text-sm); color: var(--brown);
  white-space: nowrap;
}
.aq-group__see:hover {
  text-decoration: underline; text-decoration-color: var(--sand);
  text-underline-offset: 3px;
}

.aq-group__body {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows var(--dur-base) var(--ease);
  margin-top: var(--s-2);
}
.aq-group__body > * {
  overflow: hidden;
  min-height: 0;
}
.aq-group.is-closed .aq-group__body { grid-template-rows: 0fr; margin-top: 0; }
.aq-group.is-closed .aq-group__head { padding-bottom: var(--s-3); }

/* HERO — Today section. Bigger title, wrapped in a card. */
.aq-group--hero {
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--s-5) var(--s-5) var(--s-4);
}
.aq-group--hero > .aq-group__head { padding-block: 0 var(--s-3); }
.aq-group--hero .aq-group__title { font-size: var(--text-2xl); }
.aq-group--hero .aq-group__caret { display: none; }

/* "All done" celebration inside Today when emptied. */
.aq-alldone {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-5) var(--s-4);
  color: var(--success);
}
.aq-alldone__check {
  width: 32px; height: 32px;
  background: var(--success); color: var(--cream);
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.aq-alldone__check svg { width: 18px; height: 18px; }
.aq-alldone__text { font-size: var(--text-lg); font-weight: 600; }
.aq-group.is-emptied { transition: opacity .4s ease; }

/* ── Rows container ───────────────────────────────────── */
.aq-rows {
  display: flex; flex-direction: column;
  background: var(--cream);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.aq-group--hero .aq-rows {
  border: 1px solid var(--border-soft);
  background: var(--beige);
}

/* ════════════════════════════════════════════════════════
   ROW — base. Size modifier (standard / dense) controls layout.
   ════════════════════════════════════════════════════════ */
.aq-row {
  position: relative;
  display: flex; align-items: center; gap: var(--s-3);
  padding-inline-start: var(--s-4);
  padding-inline-end: var(--s-4);
  border-bottom: 1px solid var(--border-soft);
  cursor: pointer;
  transition: background var(--dur-fast);
}
.aq-row:last-child { border-bottom: none; }
/* home-spec §UX: hover bg bumped .10 → .20 */
.aq-row:hover { background: rgba(212,197,160,.20); }

/* §6 rule 4: the 3px entity-color side stripe (.aq-stripe) is removed —
   entity is now conveyed by a labeled chip (.aq-row__chip) at row start.
   The .aq-row--ent-* classes remain on rows for potential future hooks but
   no longer drive any --ent-color stripe. */

.aq-ico {
  width: 18px; height: 18px;
  color: var(--ink-muted);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.aq-ico svg { width: 16px; height: 16px; }
.aq-row--standard .aq-ico { width: 20px; height: 20px; color: var(--brown-deep); }
.aq-row--standard .aq-ico svg { width: 18px; height: 18px; }

.aq-subj {
  font-size: var(--text-base); font-weight: 500;
  color: var(--brown-deep);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aq-sec {
  font-size: var(--text-sm); color: var(--ink-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aq-row--standard .aq-sec::before,
.aq-row--dense .aq-sec--inline::before,
.aq-row--dense .aq-tert::before {
  content: '· '; color: var(--ink-muted); opacity: .65;
}
.aq-tert {
  font-size: var(--text-xs); color: var(--ink-muted);
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
}
.aq-amt {
  font-size: var(--text-base); font-weight: 600;
  color: var(--brown-deep);
  white-space: nowrap;
  font-feature-settings: "tnum" 1, "lnum" 1;
}
.aq-cur {
  font-size: var(--text-xs); color: var(--ink-muted);
  margin-inline-start: 3px; font-weight: 400;
}
/* Due label is now the canonical .mkt-pill .mkt-pill--sm (tones --crit /
   --warn / --neutral) emitted by the renderer. .aq-due-pill is just a
   grid-area hook for the mobile stacked layout — no standalone visuals. */

.aq-action { flex-shrink: 0; }

/* ── Per-row entity chip (replaces the removed .aq-stripe) ──────────────
   Full entity name; auto-hidden when a single-entity filter is active.
   Ported verbatim from the Home v2 mockup (.aq-row__chip). The legacy
   .aq-ent-pill / .aq-ent-short namespaces (never emitted by the renderer)
   are deleted so we don't leave a third dead namespace. */
.aq-row__chip {
  display: inline-flex; align-items: center;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1.5;
  flex-shrink: 0;
  white-space: nowrap;
  background: var(--straw);
  color: var(--brown);
}
.aq-row__chip[data-entity="thilth"]       { background: var(--entity-charitable-bg);  color: var(--entity-charitable); }
.aq-row__chip[data-entity="khums"]        { background: var(--entity-passthrough-bg); color: var(--entity-passthrough); }
.aq-row__chip[data-entity="issam"],
.aq-row__chip[data-entity="family-home"],
.aq-row__chip[data-entity="bayt-jadda"]   { background: var(--entity-personal-bg);    color: var(--entity-personal); }
.aq-row__chip[data-entity="majlis"],
.aq-row__chip[data-entity="maktab-ops"]   { background: rgba(107,90,72,.12);          color: var(--entity-operational); }
[data-theme="dark"] .aq-row__chip[data-entity="majlis"],
[data-theme="dark"] .aq-row__chip[data-entity="maktab-ops"] { background: rgba(232,220,186,.16); }
/* When the entity filter is a single entity (not 'all'), the chip is
   redundant — hide it. */
.aq-page[data-entity-filter]:not([data-entity-filter="all"]) .aq-row__chip { display: none; }

/* STANDARD rows */
.aq-row--standard {
  padding-block: 12px;
  align-items: center;
}
.aq-row--standard .aq-body {
  flex: 1; min-width: 0;
  display: flex; align-items: baseline; gap: 4px;
  overflow: hidden;
}
.aq-row--standard .aq-subj { flex-shrink: 1; }
.aq-row--standard .aq-sec  { flex: 1 1 0; min-width: 0; }

/* DENSE rows */
.aq-row--dense {
  padding-block: 7px;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--text-sm);
}
.aq-row--dense .aq-subj {
  font-size: var(--text-sm); font-weight: 500;
  flex: 0 1 auto;
  max-width: 38%;
}
.aq-row--dense .aq-sec--inline {
  font-size: var(--text-sm);
  flex: 1 1 0; min-width: 0;
}
.aq-row--dense .aq-tert {
  color: rgba(107,90,72,.65);
  flex-shrink: 0;
}
.aq-row--dense .aq-amt { font-size: var(--text-sm); margin-inline-start: auto; }
.aq-row--dense .aq-due-pill { font-size: 10.5px; padding: 1px 6px; }
.aq-row--dense .aq-action { opacity: 1; }

/* Compact tweak */
.aq-page--compact .aq-row--standard { padding-block: 8px; }
.aq-page--compact .aq-row--dense    { padding-block: 4px; font-size: var(--text-xs); }
.aq-page--compact .aq-kpi-row .mkt-kpi--card { padding: var(--s-2) var(--s-3); }
.aq-page--compact .aq-kpi-row .mkt-kpi__value { font-size: var(--text-xl); }
.aq-page--compact .aq-stack { gap: var(--s-4); }
.aq-page--compact .aq-group--hero { padding: var(--s-4); }

/* DONE STATE */
.aq-row--done { background: var(--success-bg); cursor: default; }
.aq-row--done:hover { background: var(--success-bg); }
.aq-ico--check {
  background: var(--success); color: var(--cream);
  border-radius: 50%;
  width: 18px; height: 18px;
}
.aq-ico--check svg { width: 12px; height: 12px; }
.aq-row--standard .aq-ico--check { width: 20px; height: 20px; }
.aq-row--standard .aq-ico--check svg { width: 13px; height: 13px; }
.aq-done-text {
  flex: 1; min-width: 0;
  color: var(--success);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: inherit;
}
.aq-row--standard .aq-done-text { font-size: var(--text-base); font-weight: 500; }
.aq-row--dense .aq-done-text    { font-size: var(--text-sm); }
.aq-undo {
  background: transparent; border: none; cursor: pointer;
  font-family: var(--font-ar); font-weight: 600;
  color: var(--brown);
  padding: 2px 10px; border-radius: var(--r-sm);
  flex-shrink: 0;
}
.aq-undo:hover { background: rgba(74,55,40,.06); }
.aq-row--standard .aq-undo { font-size: var(--text-sm); }
.aq-row--dense    .aq-undo { font-size: var(--text-xs); padding: 1px 8px; }

/* DIALOG */
.aq-dlg__subject {
  font-size: var(--text-lg); color: var(--brown-deep); font-weight: 600;
  margin-bottom: var(--s-3);
}
.aq-dlg__todo {
  display: flex; align-items: flex-start; gap: var(--s-2);
  padding: var(--s-2) var(--s-3); margin-bottom: var(--s-4);
  background: var(--info-bg);
  border-radius: var(--r-sm);
  font-size: var(--text-xs); color: var(--info);
  line-height: 1.45;
}
.aq-dlg__todo svg { width: 14px; height: 14px; flex-shrink: 0; margin-top: 1px; }

.aq-dlg__methods { border: none; padding: 0; margin: 0 0 var(--s-4); }
.aq-dlg__radios { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.aq-dlg__radio {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r-pill);
  background: var(--cream); color: var(--ink);
  border: 1px solid var(--border);
  cursor: pointer;
  font-size: var(--text-sm);
  transition: all var(--dur-fast);
}
.aq-dlg__radio:hover { border-color: var(--sand); }
.aq-dlg__radio input { display: none; }
.aq-dlg__radio.is-active {
  background: var(--brown-deep); color: var(--cream); border-color: var(--brown-deep);
}

/* Dark-mode tweaks.
   The mockup tokens flip --brown-deep to a light cream in dark mode; our
   live token system keeps --brown-deep dark and uses --ink for primary text.
   These rules retarget every .aq-* surface that the mockup colored with
   --brown-deep so it reads against the dark background. */
[data-theme="dark"] .aq-pg-head__greet,
[data-theme="dark"] .aq-group__title,
[data-theme="dark"] .aq-subj,
[data-theme="dark"] .aq-amt,
[data-theme="dark"] .aq-dlg__subject {
  color: var(--ink);
}
[data-theme="dark"] .aq-row--standard .aq-ico { color: var(--ink); }
[data-theme="dark"] .aq-row:hover { background: rgba(232,220,186,.05); }
[data-theme="dark"] .aq-row--done { background: rgba(94,125,94,.16); }
[data-theme="dark"] .aq-done-text { color: var(--basil-leaf); }

.aq-action:focus:not(:focus-visible) { outline: none; }

/* MOBILE — below ~640px */
@media (max-width: 640px) {
  .aq-page { padding: var(--s-5) var(--s-4) var(--s-10); }

  .aq-pg-head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-4);
  }
  .aq-pg-head__greet { font-size: var(--text-3xl); white-space: normal; }
  .aq-pg-head__actions { flex-wrap: wrap; }

  .aq-kpi-row {
    grid-template-columns: repeat(2, 1fr);
  }
  .aq-kpi-row .mkt-kpi__value { font-size: var(--text-xl); }

  .aq-group--hero { padding: var(--s-4) var(--s-3) var(--s-3); }
  .aq-group--hero .aq-group__title { font-size: var(--text-xl); }
  .aq-group__title { font-size: var(--text-lg); }

  .aq-filter-bar { gap: 6px; }
  /* Filter chips: ~32px tap target per MOBILE.md §2 */
  .aq-filter-chip { padding: 4px 11px; font-size: var(--text-xs); min-height: 32px; }

  /* Row collapses to a vertical stack on mobile per MOBILE.md §3.
     Icon spans the full left column as a rail; content (chip, subject,
     secondary, tertiary, amount + action) stacks on the right. Each named
     area MUST form a rectangle — otherwise grid-template-areas silently
     falls back to auto layout and rows render blank. Ported verbatim from
     the Home v2 mockup. */
  .aq-row,
  .aq-row--standard,
  .aq-row--dense {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    grid-template-areas:
      "ico chip chip"
      "ico subj due"
      "ico sec  sec"
      "ico tert tert"
      "ico amt  act";
    column-gap: 10px;
    row-gap: 4px;
    padding: 12px 14px;
    font-size: var(--text-sm);
    min-height: 56px;
  }
  .aq-row .aq-ico { grid-area: ico; align-self: start; margin-top: 4px; }
  .aq-row .aq-row__chip {
    grid-area: chip;
    justify-self: start;
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .aq-row .aq-subj,
  .aq-row--dense .aq-subj {
    grid-area: subj;
    max-width: none;
    font-size: var(--text-base);
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* .aq-body wraps subject + secondary on desktop. On mobile we let its
     children participate in the parent grid via display: contents. */
  .aq-row .aq-body { grid-area: subj; min-width: 0; display: contents; }
  .aq-row .aq-sec,
  .aq-row--dense .aq-sec--inline {
    grid-area: sec;
    font-size: var(--text-sm); color: var(--ink-muted);
    white-space: normal;
    line-height: 1.35;
    max-width: none;
  }
  .aq-row .aq-tert {
    grid-area: tert;
    justify-self: start;
    font-size: var(--text-xs);
    white-space: normal;
    line-height: 1.35;
  }
  /* Desktop "·" separators don't make sense in a stacked layout. */
  .aq-row--standard .aq-sec::before,
  .aq-row--dense .aq-sec--inline::before,
  .aq-row--dense .aq-tert::before { content: none; }

  .aq-row .aq-amt { grid-area: amt; justify-self: start; align-self: center; font-size: var(--text-base); white-space: nowrap; }
  .aq-row .aq-due-pill { grid-area: due; justify-self: end; align-self: start; }
  .aq-row .aq-action {
    grid-area: act;
    justify-self: end;
    align-self: center;
    min-height: 44px;
    padding-inline: 14px;
    font-size: var(--text-sm);
    opacity: 1;
  }

  .aq-row--done {
    grid-template-areas: "ico txt undo" !important;
    grid-template-rows: auto !important;
    column-gap: 10px;
    row-gap: 0;
  }
  .aq-row--done .aq-ico--check { grid-area: ico; }
  .aq-row--done .aq-done-text { grid-area: txt; }
  .aq-row--done .aq-undo { grid-area: undo; justify-self: end; }
  /* (retired Batch 6: the @640 .mkt-dlg/.mkt-dlg-bg fullscreen override — the
     primitive's own @640 bottom-sheet in payment-dialog.css handles mobile now.) */
}
/* === end Phase 2B Home / Action Queue ports ===================== */

/* ─── Dark theme ────────────────────────────────────────────── */

[data-theme="dark"] .pd-overlay { background: rgba(0,0,0,0.55); }
[data-theme="dark"] .pd-panel-scrim { background: rgba(0,0,0,0.5); }
[data-theme="dark"] .pd-modal,
[data-theme="dark"] .pd-panel { border-color: rgba(255,255,255,0.18); }
[data-theme="dark"] .pd-success__check { color: var(--brown-night); }

/* Dark-mode contrast fixes for filled/active buttons inside the payment dialog.
   In dark mode, --cream (#24201A) and --brown-deep (#1F1A12) both resolve to
   near-black, so the light-mode pattern of "cream bg + brown-deep text" (or
   the inverse) renders ~1.05:1 contrast. Repaint with --surface-inverse
   (dark surface) + --ink (light foreground), matching the proven override at
   .mh-shell .mkt-btn--primary above (line 12237). */
[data-theme="dark"] .pd-footer .mkt-btn--primary,
[data-theme="dark"] .pd-footer .mkt-btn--primary:hover {
  background: var(--surface-inverse);
  color: var(--ink);
}
[data-theme="dark"] .pd-footer .mkt-btn--ghost {
  color: var(--ink);
}
[data-theme="dark"] .pd-seg.is-active {
  background: var(--surface-inverse);
  color: var(--ink);
}
[data-theme="dark"] .pd-quick.is-active {
  background: var(--surface-inverse);
  color: var(--ink);
  border-color: var(--brown);
}

/* === end Phase 3 Stage 4 Payment Dialog =========================== */

/* === Phase 3.5: brown-deep flip companions ===========================
   --brown-deep now flips to warm cream (#E8DCBA) in dark mode (token is
   foreground-on-surface, not always-dark structural). These rules repaint
   the surfaces that depended on the old structural direction. Pattern:
   bg=var(--sand-deep), fg=var(--ink), border=var(--sand-deep) — gives a
   readable dark CTA chrome against the cream/beige page bg. */

/* .rc-kpi--clickable.is-active and .rc-pill.is-active / .rc-pill--needs.is-active
   dark-mode overrides deleted — they flipped polarity (dark-bg + cream-fg)
   instead of letting --brown-deep + --cream do their natural flip in dark
   (cream-bg + dark-fg). The mockup wants the active KPI/pill to read as a
   CREAM-FILLED tile in dark — that's the natural cascade now restored. */

[data-theme="dark"] .aq-dlg__radio.is-active {
  background: var(--surface-inverse);
  color: var(--brown-deep);
  border-color: var(--brown-deep);
}

[data-theme="dark"] .pd-datepicker__day.is-selected,
[data-theme="dark"] .pd-datepicker__day.is-selected:hover,
[data-theme="dark"] .pd-datepicker__day.is-today.is-selected {
  background: var(--surface-inverse);
  color: var(--brown-deep);
}

/* === end Phase 3.5 brown-deep flip companions ====================== */
