/* ═══════════════════════════════════════════════════════════════
   Identity layer on top of MudBlazor.

   MudBlazor draws the components; this file adds what it does not know: the colour tokens the rest
   of the code reads, the two Arabic typefaces, soft elevated surfaces instead of hairline boxes,
   the phone shell (a floating bottom bar and sliding sheets), the home hero, request rows and
   service cards. No global element rules (input, table, ...) — those belong to the library,
   and a global rule here fights it silently.
   ═══════════════════════════════════════════════════════════════ */

/* The society's typefaces (identity guide; SCRUM-150), from its licensed files, built by tools/fonts/build.sh: woff2,
   subset to what the app writes, every layout feature kept. Frutiger LT Arabic is the text, GE SS Two the headings with
   Frutiger after it, and Benton Sans Black the Latin of a heading of 800 and over. Each file stands for a weight range, so
   a 500 or a 600 is a real face, never a synthesized one. GE SS Two draws Latin digits as Arabic-Indic ones: it is kept to
   the Arabic letters, and the digits of a heading come from the next face. The metric overrides give every face one
   baseline and one line box (the files disagree: Frutiger's Roman and Bold carry different ones), close to the faces
   they replaced. Each address is the file's fingerprinted name, so it is cached for a year and a new file is a new name;
   SmokeTests.TheFontsAreOursFingerprintedAndWithinTheirBudget says which name to write here when a file changes.
   App.razor preloads the text's regular. */
@font-face { font-family: "Frutiger LT Arabic"; font-weight: 400 500; font-display: swap; src: url("fonts/frutiger-lt-arabic-400.v3f13ul92g.woff2") format("woff2"); ascent-override: 105%; descent-override: 45%; line-gap-override: 0%; }
@font-face { font-family: "Frutiger LT Arabic"; font-weight: 600 900; font-display: swap; src: url("fonts/frutiger-lt-arabic-700.aeqdz4wnd8.woff2") format("woff2"); ascent-override: 105%; descent-override: 45%; line-gap-override: 0%; }
@font-face { font-family: "GE SS Two"; font-weight: 600 900; font-display: swap; src: url("fonts/ge-ss-two-700.g9me5xhg5t.woff2") format("woff2"); unicode-range: U+0020, U+00A0, U+0600-06FF, U+200C-200F, U+FB50-FDFF, U+FE70-FEFF; ascent-override: 105%; descent-override: 45%; line-gap-override: 0%; }
@font-face { font-family: "Benton Sans"; font-weight: 800 900; font-display: swap; src: url("fonts/benton-sans-900.2xx678e3pz.woff2") format("woff2"); unicode-range: U+0021-007E, U+00A1-00FF, U+2013-2014, U+2018-201E, U+2026, U+20AC, U+2122; ascent-override: 105%; descent-override: 45%; line-gap-override: 0%; }

:root {
  /* The three stacks (AppTheme.cs writes the same for the library): the text, a heading, and a heading of 800 and over */
  --font-text: "Frutiger LT Arabic", "Segoe UI", system-ui, sans-serif;
  --font-head: "GE SS Two", "Frutiger LT Arabic", sans-serif;
  --font-head-black: "Benton Sans", "GE SS Two", "Frutiger LT Arabic", sans-serif;
  --paper:      #f5f5ef;
  --surface:    #ffffff;
  --sunk:       #eeeee6;
  --rule:       #e6e5dc;
  --rule-firm:  #d5d3c6;
  --ink:        #15190f;
  --ink-2:      #4b5145;
  --ink-3:      #868b80;
  /* The society's colours (identity guide, pages 17 to 19; Brand.cs holds the same values and IdentityTests pins both).
     Official: --brand Pantone 371, --brand-deep 574, --wheat 116, --blue 279, --move 2728. The other brand and state
     colours are tints (mixed with white) or shades (mixed with black) of one of them, but --stop: the guide has no red. The wheat and the blue are fills, never text on
     a light surface; --gold is the wheat's text colour. */
  --brand:      #53682b;
  --brand-deep: #445026;
  --brand-lift: #647740;
  --brand-soft: #eaede6;
  --wheat:      #ffcb00;
  --wheat-soft: #fff2bf;
  --gold:       #806600;
  --gold-line:  #ffe580;
  --blue:       #4891dc;
  --wait: #8c5900; --wait-soft: #fff2db;
  --move: #004ebc; --move-soft: #e9f2fb;
  --done: #4b782c; --done-soft: #eef6e8;
  --stop: #a02419; --stop-soft: #fbeae7;

  /* One spacing rhythm — no arbitrary sizes */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;

  /* Surfaces: radius and layered shadows instead of borders */
  --r-card: 20px;
  --shadow-card: 0 1px 2px rgba(21,25,15,.04), 0 12px 32px -16px rgba(21,25,15,.18);
  --shadow-lift: 0 2px 4px rgba(21,25,15,.05), 0 20px 44px -18px rgba(21,25,15,.28);
  --glass: rgba(255,255,255,.8);
  --ease: cubic-bezier(.2,.8,.2,1);

  --bottom-nav: 64px;
  --bottom-gap: 10px;
  /* The tallest a dialog's sheet may be on a phone: what the bottom bar, its gaps and 56px above leave */
  --sheet-max: calc(100dvh - var(--bottom-nav) - var(--bottom-gap) * 3 - 56px - env(safe-area-inset-bottom));
}

html { -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--mud-typography-default-family, var(--font-text));
  color: var(--ink);
  overscroll-behavior-y: none;
  /* Two soft glows in the brand colours give the page depth; a flat beige read as a form from 2012 */
  background:
    radial-gradient(900px 520px at 90% -10%, color-mix(in srgb, var(--brand) 12%, transparent), transparent 65%),
    radial-gradient(700px 480px at 0% 30%, color-mix(in srgb, var(--blue) 7%, transparent), transparent 60%),
    var(--paper);
  background-attachment: fixed;
}

/* Tabular digits: dates and counters do not jitter */
body, .num, .req-due, .mud-table { font-variant-numeric: tabular-nums; }

/* Focus ring on the page title after every navigation (FocusOnNavigate) — no visual value */
[tabindex="-1"]:focus, [tabindex="-1"]:focus-visible { outline: none; }

/* Latin keys inside an RTL UI */
/* On a Mud field the class lands on the whole wrapper, and on a labelled field on its block — target the input alone, never the label or the helper text */
.mono:not(.mud-input-control):not(.f-block), .mono input, .mono textarea, .field-key {
  direction: ltr; text-align: left; unicode-bidi: isolate;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .84rem;
}

/* ── Library surfaces: soft elevation, pill buttons ─────────────── */
/* Every outlined card in the app becomes a floating surface — one rule, no markup change */
.mud-paper-outlined { border-color: transparent; border-radius: var(--r-card); box-shadow: var(--shadow-card); }
.mud-paper-outlined .mud-paper-outlined { box-shadow: none; border-color: var(--rule); border-radius: 14px; }
/* A card title always sits 12px above its content — no per-title margin class */
.mud-paper-outlined > .mud-typography-h3 { margin-bottom: var(--s3); }
.mud-table { border-radius: var(--r-card); box-shadow: var(--shadow-card); }
.mud-dialog { border-radius: 24px; }
.mud-expand-panel { border-radius: 14px !important; }

.mud-button-root { transition: transform .12s var(--ease), box-shadow .2s var(--ease), background-color .2s; }
.mud-button { border-radius: 999px; }
.mud-button-filled, .mud-button-outlined { padding-inline: 20px; }
.mud-button-filled.mud-button-filled-primary {
  background-image: linear-gradient(135deg, var(--brand-lift), var(--brand));
  box-shadow: 0 10px 22px -10px color-mix(in srgb, var(--brand) 60%, transparent);
}
.mud-button-filled.mud-button-filled-primary:hover { box-shadow: 0 14px 26px -10px color-mix(in srgb, var(--brand) 70%, transparent); transform: translateY(-1px); }
.mud-button-root:active { transform: scale(.97); }
/* The white fill sits on the wrapper, the border on an absolute fieldset inside it: both must carry the radius,
   or the fill pokes out at the corners of every field */
.mud-input.mud-input-outlined { background: var(--surface); border-radius: var(--mud-default-borderradius); }
.mud-chip { font-weight: 600; border-radius: 999px; }
.steps-list { margin: 0; padding-inline-start: 1.25em; }
.mud-tabs-toolbar { border: 0 !important; }
.mud-tab { text-transform: none; border-radius: 12px; }
/* A tab of AppTabs is a real button under the library's class: it takes the page's type and none of a button's own look.
   At the library's specificity (:where), so its active colour and every bar's own rules still win */
:where(.mud-tabs-tabbar) .mud-tab { border: 0; margin: 0; font-family: inherit; font-size: inherit; color: inherit; background: none; }
/* A bar wider than its place scrolls sideways under the finger or the wheel (the library's arrows were its script's) */
:where(.mud-tabs-tabbar) .mud-tabs-tabbar-content { overflow-x: auto; scrollbar-width: none; }
:where(.mud-tabs-tabbar) .mud-tabs-tabbar-content::-webkit-scrollbar { display: none; }
.mud-tab .mud-icon-root { margin-inline-end: var(--s2); }

/* ── Vertical rhythm: one rule, not a margin per element ──────────
   Every top-level block on a page is 24px from the one before it (16px on phones). A section label sits 12px above
   its list, and a "see all" link 8px under its list. Utility classes (mt-3, mb-4) on top-level blocks are overridden
   on purpose: they are what made the same page read 24px here and 12px there. */
.app-content > *, .req-page > * { margin-top: 0 !important; margin-bottom: 0 !important; }
.app-content > * + *, .req-page > * + * { margin-top: var(--s5) !important; }
.app-content > .section-label + *, .req-page > .section-label + * { margin-top: var(--s3) !important; }
.app-content > .mud-paper + .mud-button-root, .req-page > .mud-paper + .mud-button-root { margin-top: var(--s2) !important; }
@media (max-width: 959.98px) {
  .app-content > * + *, .req-page > * + * { margin-top: var(--s4) !important; }
}

/* Every surface shares the card padding: 20px on desktop, 16px on phones — expansion panels included.
   Selectors at the library's own specificity (.mud-expand-panel .header.gutters), otherwise its 24px wins. */
.mud-expand-panel .mud-expand-panel-header.mud-expand-panel-header-gutters { padding: 14px 20px; min-height: 0; }
.mud-expand-panel .mud-expand-panel-content.mud-expand-panel-gutters { padding: 0 20px 16px; }
.mud-expand-panel + .mud-expand-panel { margin-top: var(--s2); }
@media (max-width: 599.98px) {
  .mud-expand-panel .mud-expand-panel-header.mud-expand-panel-header-gutters { padding: 12px 16px; }
  .mud-expand-panel .mud-expand-panel-content.mud-expand-panel-gutters { padding: 0 16px 12px; }
}
/* A MudGrid offsets its items' 12px padding with negative margins; keep that offset inside the rhythm */
.app-content > .mud-grid, .req-page > .mud-grid { margin-top: calc(var(--s5) - 12px) !important; }
@media (max-width: 959.98px) { .app-content > .mud-grid, .req-page > .mud-grid { margin-top: calc(var(--s4) - 12px) !important; } }

/* Content enters with a short rise, one child after the other — nothing jumps into place.
   fill-mode backwards, not both: "both" leaves an identity transform on every block after the animation, and a
   transformed ancestor traps position:fixed — the date picker's overlay opened inside its card instead of over the page */
.app-content > * { animation: rise .55s var(--ease) backwards; }
.app-content > :nth-child(2) { animation-delay: 50ms; }
.app-content > :nth-child(3) { animation-delay: 100ms; }
.app-content > :nth-child(4) { animation-delay: 150ms; }
.app-content > :nth-child(5) { animation-delay: 200ms; }
.app-content > :nth-child(6) { animation-delay: 250ms; }
.app-content > :nth-child(n+7) { animation-delay: 300ms; }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
/* A signed-in page is drawn twice on its first load: by the server, then again when its live connection takes over,
   and the rise played on both. While the page is connecting its content stands still, so it rises once (SCRUM-147 C3). */
html.connecting .app-content > * { animation: none; }

/* ── Top bar: frosted glass, not a dark block ───────────────────── */
.mud-appbar.topbar {
  padding-inline: var(--s3);
  background: var(--glass); color: var(--ink);
  -webkit-backdrop-filter: saturate(160%) blur(16px); backdrop-filter: saturate(160%) blur(16px);
  box-shadow: 0 1px 0 rgba(21,25,15,.06);
}
.brand { display: flex; align-items: center; gap: var(--s3); min-width: 0; color: inherit; text-decoration: none; }
/* The identity guide's least width for the horizontal logo is 2.5 cm, 95px on a screen (IdentityTests): 38px high read 86 */
.brand-logo { width: 96px; height: auto; flex: none; display: block; }
.brand-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.brand-text strong { font-family: var(--font-head); font-size: .98rem; color: var(--ink); }
.brand-text span { font-size: .72rem; color: var(--ink-3); }

.avatar {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--brand-soft); color: var(--brand); font-weight: 700; font-size: .8rem;
}
.avatar.lg { width: 44px; height: 44px; font-size: .95rem; background: linear-gradient(135deg, var(--brand-lift), var(--brand)); color: #fff; }
.who { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.25; min-width: 0; }
.who .n { font-size: .88rem; font-weight: 700; color: var(--ink); }
.who .r { font-size: .72rem; color: var(--ink-3); }

/* ── Side menu (desktop): pills on the page, no wall ────────────── */
.mud-drawer.side { background: transparent; border: 0; }
.side-nav { padding: var(--s3) var(--s3); }
.side-cta { padding: var(--s2) 0 var(--s4); }
.side-cta .mud-button { height: 46px; font-size: .95rem; }
/* On /new the button is the current place, not an action: olive, flat, not tappable — the disabled grey would read as broken */
/* !important because the library's disabled rule uses it too */
.side-cta .mud-button.here, .side-cta .mud-button.here:disabled {
  background-image: none; background-color: var(--brand-deep) !important; color: #fff !important; box-shadow: none; opacity: 1;
}
.side-cta .mud-button.here .mud-icon-root { color: #fff; }
.side-nav .mud-nav-link { border-radius: 14px; margin-block: 2px; font-weight: 500; }
.side-nav .mud-nav-link.active { background: var(--surface); color: var(--brand); box-shadow: var(--shadow-card); font-weight: 700; }
.side-nav .mud-nav-link.active .mud-icon-root { color: var(--brand); }
.side-foot { margin-top: auto; padding: var(--s3) var(--s3) var(--s4); display: flex; flex-direction: column; gap: var(--s3); }
.side-me { display: flex; align-items: center; gap: var(--s3); padding: var(--s3); background: var(--surface); border-radius: 16px; box-shadow: var(--shadow-card); }
.nav-sep {
  padding: var(--s4) var(--s4) var(--s1);
  font-size: .7rem; font-weight: 700; letter-spacing: .08em; color: var(--ink-3);
}
.nav-count {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
  margin-inline-start: var(--s2); border-radius: 999px;
  background: var(--brand); color: #fff; font-size: .72rem; font-weight: 700;
}
.tab-count {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
  margin-inline-start: var(--s2); border-radius: 999px;
  background: var(--brand-soft); color: var(--brand); font-size: .72rem; font-weight: 700;
}
.mud-tab-active .tab-count { background: var(--brand); color: #fff; }

/* Tabs as the app's own pills — white cards, the active one olive — not the library's sunk grey track */
.seg .mud-tabs-tabbar { background: transparent; padding: 0; }
.seg .mud-tabs-tabbar-inner { min-height: 0; }
/* Each tab is wrapped in a div; the wrappers are the flex items of .mud-tabs-tabbar-wrapper — the gap goes there */
.seg .mud-tabs-tabbar-content { display: flex; width: 100%; }
.seg .mud-tabs-tabbar-wrapper { gap: var(--s2); width: 100%; }
/* Three tabs on a 375px screen: the library's 160px minimum made them scroll with arrows — these always fit */
.seg .mud-tab {
  flex: 0 1 auto; min-height: 40px; min-width: 0 !important; padding: 0 18px; white-space: nowrap;
  border-radius: 999px; background: var(--surface); color: var(--ink-2); box-shadow: var(--shadow-card);
  transition: background .2s var(--ease), color .2s, transform .12s var(--ease);
}
.seg .mud-tab:active { transform: scale(.97); }
.seg .mud-tab.mud-tab-active { background-image: linear-gradient(135deg, var(--brand-lift), var(--brand)); color: #fff; }
.seg .mud-tab.mud-tab-active .mud-icon-root { color: #fff; }
.seg .mud-tab-active .tab-count { background: rgba(255,255,255,.22); color: #fff; }
.seg .mud-tabs-panels { padding-top: var(--s4); }
@media (max-width: 599.98px) {
  /* Three tabs share the width; four or more never wrap to two lines: the row scrolls sideways, without a scrollbar */
  .seg .mud-tabs-tabbar-wrapper > div { flex: 1 0 auto; min-width: 0; }
  .seg .mud-tab { width: 100%; padding: 0 var(--s3); }
}

/* Signed in as someone else: a bar the administrator cannot miss, above every page */
.impersonation-bar { display: flex; align-items: center; gap: var(--s2); flex-wrap: nowrap; padding: 4px var(--s3); background: var(--wheat); color: var(--brand-deep); border-bottom: 1px solid var(--rule); font-size: .82rem; }
.impersonation-bar .text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 0 1 auto; }
.impersonation-bar .switch { display: flex; align-items: center; gap: 2px; flex: 1 1 140px; min-width: 0; max-width: 320px; margin-inline-start: auto; }
.impersonation-bar .switch .mud-select, .impersonation-bar .switch .mud-input-control { flex: 1; min-width: 0; margin: 0; }
.impersonation-bar .back { flex: none; }

/* ── Content ───────────────────────────────────────────────────── */
.app-content { padding-block: var(--s5) var(--s7); }

@media (max-width: 959.98px) {
  .app-content { padding-block: var(--s4) calc(var(--bottom-nav) + var(--bottom-gap) + var(--s6) + env(safe-area-inset-bottom)); }
}

/* ── Bottom bar (phone): a floating glass pill ──────────────────── */
.mud-appbar.bottom-nav {
  /* Above dialogs (1400) and below snackbars (1500): the bar is always visible and always tappable —
     a sheet floats above it instead of covering it */
  z-index: 1450;
  position: fixed; inset-inline: 12px; bottom: calc(var(--bottom-gap) + env(safe-area-inset-bottom));
  width: auto; height: var(--bottom-nav); padding: 0; border: 0; border-radius: 26px;
  background: var(--glass); color: var(--ink-3);
  -webkit-backdrop-filter: saturate(160%) blur(18px); backdrop-filter: saturate(160%) blur(18px);
  box-shadow: 0 18px 40px -18px rgba(21,25,15,.4), 0 0 0 1px rgba(21,25,15,.05);
}
.bottom-nav .mud-toolbar { padding: 0 var(--s2); height: var(--bottom-nav); gap: 0; }
.bnav-item {
  all: unset; box-sizing: border-box; cursor: pointer;
  flex: 1; height: var(--bottom-nav);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: var(--ink-3); text-decoration: none; font-size: .68rem; font-weight: 600;
  -webkit-tap-highlight-color: transparent;
}
.bnav-ico { display: grid; place-items: center; height: 30px; padding: 0 16px; border-radius: 999px; transition: background .2s var(--ease), transform .15s var(--ease); }
.bnav-item .mud-icon-root { font-size: 1.4rem; }
.bnav-item.active { color: var(--brand); }
.bnav-item.active .bnav-ico { background: var(--brand-soft); }
.bnav-item:active .bnav-ico { transform: scale(.9); }
.bnav-new { color: var(--ink-2); }
/* Inside the bar, not overhanging it: a button rising out of the bar collided with every sheet floating above it */
.bnav-fab {
  width: 44px; height: 32px; border-radius: 12px;
  display: grid; place-items: center;
  background: linear-gradient(135deg, color-mix(in srgb, var(--wheat) 70%, #fff), var(--wheat)); color: var(--brand-deep);
  box-shadow: 0 6px 14px -6px color-mix(in srgb, var(--wheat) 80%, transparent);
  transition: transform .15s var(--ease);
}
.bnav-new:active .bnav-fab { transform: scale(.92); }
/* On the new-request pages the tab shows "you are here" and stops being a button: olive, no shadow, no tap */
.bnav-new.active { pointer-events: none; cursor: default; color: var(--brand); }
.bnav-new.active .bnav-fab { background: var(--brand); color: #fff; box-shadow: none; }
.bnav-fab .mud-icon-root { font-size: 1.5rem; }
.bnav-item .mud-badge { font-size: .62rem; }

/* ── Sheet sliding up from the bottom ──────────────────────────── */
/* ── Panels the layout opens in the browser (html[data-open], set by ErpDarAlBer.Web.lib.module.js) ──
   The server is not asked, so they answer a tap at once on any line; they move by transform and opacity only, which a
   phone draws without laying the page out again (the library drawer slid by animating "bottom" and stuttered). */
.panel-scrim {
  position: fixed; inset: 0; z-index: 1440; background: rgba(21,25,15,.38); touch-action: none;
  opacity: 0; visibility: hidden; transition: opacity 200ms var(--ease), visibility 0s 200ms;
}
html[data-open="more"] .panel-scrim { opacity: 1; visibility: visible; transition: opacity 200ms var(--ease); }
/* The "More" sheet: a floating card above the bottom bar, with the same side insets as the bar. The bar is above
   dialogs, so the sheet is above them too; otherwise it opened behind an open dialog */
.more-sheet {
  position: fixed; z-index: 1460; inset-inline: 12px;
  bottom: calc(var(--bottom-nav) + var(--bottom-gap) * 2 + env(safe-area-inset-bottom));
  max-height: 80vh; overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border-radius: 26px; padding-bottom: var(--s4);
  box-shadow: 0 24px 60px -20px rgba(21,25,15,.45), 0 0 0 1px rgba(21,25,15,.05);
  transform: translateY(calc(100% + 140px)); visibility: hidden;
  transition: transform 260ms var(--ease), visibility 0s 260ms;
}
html[data-open="more"] .more-sheet { transform: none; visibility: visible; transition: transform 260ms var(--ease); }
html[data-open="more"] [data-panel-toggle="more"] { color: var(--brand); }
html[data-open="more"] [data-panel-toggle="more"] .bnav-ico { background: var(--brand-soft); }
.sheet-grip { width: 42px; height: 5px; border-radius: 3px; background: var(--rule-firm); margin: 10px auto 6px; }
.sheet-head { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s5) var(--s2); }
.sheet-head .n { font-weight: 700; }
.sheet-head .r { font-size: .78rem; color: var(--ink-3); }
.sheet-close { margin-inline-start: auto; display: grid; place-items: center; width: 48px; height: 48px; padding: 0; border: 0;
  border-radius: 50%; background: none; color: var(--ink-2); cursor: pointer; }
.sheet-close:active { background: var(--sunk); }
.sheet-nav { padding-inline: var(--s3); }
.sheet-nav .mud-nav-link { border-radius: 14px; }
.sheet-foot { padding: var(--s3) var(--s5) 0; }

/* Dialog paddings follow the page rhythm (16/20), not the library's 24 */
.mud-dialog-title { padding: var(--s5) var(--s5) var(--s1); }
.mud-dialog-content { padding: var(--s2) var(--s5); }
.mud-dialog-actions { padding: var(--s3) var(--s5) var(--s5); }

/* Dialogs become bottom sheets on phones — no second code path.
   The sheet floats above the bottom bar (never over it): the bar stays visible and tappable. */
@media (max-width: 599.98px) {
  .mud-dialog-container {
    align-items: flex-end !important; box-sizing: border-box;
    padding: 0 12px calc(var(--bottom-nav) + var(--bottom-gap) * 2 + env(safe-area-inset-bottom));
  }
  /* The library does not animate a dialog on entry; on phones it slides up from the bottom like an app screen */
  .mud-dialog { animation: sheet-up 280ms var(--ease) both; }
  .mud-dialog {
    width: 100% !important; max-width: 100% !important; margin: 0 !important;
    border-radius: 26px !important;
    max-height: var(--sheet-max);
  }
  .mud-dialog-title { padding: var(--s4) var(--s4) var(--s1); }
  .mud-dialog-content { padding: var(--s2) var(--s4); }
  .mud-dialog-actions { padding: var(--s3) var(--s4) var(--s4); flex-wrap: wrap; row-gap: var(--s2); }
  /* A button keeps its words on one line: four of them wrap to a second row rather than into each other */
  .mud-dialog-actions .mud-button-root { white-space: nowrap; }
}
/* Picker dialogs (date, time) are library overlays, not MudDialog containers: give them the same sheet on phones */
@media (max-width: 599.98px) {
  .mud-picker .mud-overlay-dialog {
    display: flex; align-items: flex-end; justify-content: center; box-sizing: border-box;
    padding: 0 12px calc(var(--bottom-nav) + var(--bottom-gap) * 2 + env(safe-area-inset-bottom));
  }
  .mud-picker .mud-overlay-dialog .mud-overlay-content { width: 100%; }
  .mud-picker .mud-picker-paper.mud-dialog { margin: 0 auto !important; }
  /* The calendar keeps the library's 310px; its grid track is centred in the sheet instead of sitting at the start edge,
     which left an empty band on the left that grew with the phone's width */
  .mud-picker .mud-picker-calendar-content { justify-content: center; }
}
/* Snackbars rise above the bar too */
@media (max-width: 959.98px) {
  [class*="mud-snackbar-location-bottom"] { bottom: calc(var(--bottom-nav) + var(--bottom-gap) * 2 + env(safe-area-inset-bottom)); }
}

/* ── Rooms: a week strip, then a card per room with its slots as chips (they wrap on phones, line up on desktop) ─── */
/* The rooms page: a toolbar (room, durations), then one card with the week's navigation, legend and grid */
.rooms-bar { display: flex; align-items: flex-end; gap: var(--s4); flex-wrap: wrap; margin-bottom: var(--s4); }
.rooms-bar-room { flex: 1 1 280px; max-width: 420px; }
.rooms-bar-room .room-pick { max-width: none; }
.rooms-bar-durs { flex: 1 1 320px; min-width: 0; }
.rooms-bar-durs .durs { grid-template-columns: repeat(auto-fill, minmax(84px, max-content)); }
.rooms-bar-actions { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; align-self: flex-end; margin-inline-start: auto; }
/* Manual entry: a second row of the toolbar; the button lines up with the fields' bottom edge */
.manual-entry { flex: 1 1 100%; display: flex; align-items: flex-end; gap: var(--s3); flex-wrap: wrap; padding-top: var(--s2); border-top: 1px solid var(--rule); }
.manual-entry .manual-date { flex: 1 1 160px; max-width: 220px; }
.manual-entry .manual-time { flex: 1 1 140px; max-width: 180px; }
.manual-entry .manual-dur { flex: 1 1 140px; max-width: 200px; }
.manual-entry .manual-go { margin-bottom: 2px; }
.week-nav { display: flex; align-items: center; gap: var(--s1); flex-wrap: wrap; padding: var(--s3) var(--s4) var(--s2); }
.week-nav .week-text { font-size: .8rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.week-nav .day-pick { width: 168px; flex: none; }
.week-nav .legend { margin: 0; }
.legend { display: inline-flex; gap: var(--s1); flex-wrap: wrap; }
/* The legend's three states, read at a glance on the beige page */
.rng { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; padding: 2px 10px; border-radius: 10px; border: 1px solid transparent; font-size: .74rem; font-weight: 500; }
.rng.free { background: var(--surface); color: var(--brand); border-color: color-mix(in srgb, var(--brand) 45%, #fff); }
.rng.held { background: var(--wheat); color: var(--ink); border-color: var(--wheat); }
.rng.booked { background: var(--brand); color: #fff; border-color: var(--brand); }
.room-pick { max-width: 480px; }
/* The rooms page's ruler: the day as a row of slots that scrolls sideways; the pick is a block with two handles over it */
.slotpick { overflow: hidden; }
.ruler { overflow-x: auto; overscroll-behavior-x: contain; padding-bottom: var(--s1); border-top: 1px solid var(--rule); }
.ruler-track { --slot-w: 44px; --day-w: 76px; display: grid; grid-template-rows: 18px; grid-auto-rows: 52px; column-gap: 0; row-gap: 2px; min-width: max-content; position: relative; }
.ruler-corner, .ruler-day { grid-column: 1; position: sticky; inset-inline-start: 0; z-index: 2; background: var(--surface); }
.ruler-corner { grid-row: 1; }
.ruler-day { display: flex; align-items: center; gap: 6px; padding-inline: 8px; border-inline-end: 1px solid var(--rule); font-size: .74rem; color: var(--ink-2); }
.ruler-day .dd { font-weight: 700; font-size: .95rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.ruler-day.today .dd { color: var(--brand); }
.ruler-day.on { background: var(--brand-soft); }
.ruler-hour { grid-row: 1; font-size: .64rem; color: var(--ink-3); border-inline-start: 1px solid var(--rule); padding-inline-start: 4px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ruler-cell { border: 0; border-inline-start: 1px solid var(--rule); border-bottom: 1px solid var(--rule); background: var(--surface); padding: 0; cursor: pointer; }
.ruler-cell.free:hover, .ruler-cell.free:focus-visible { background: var(--brand-soft); outline: none; }
.ruler-cell.held { background: var(--wheat); }
.ruler-cell.booked { background: var(--brand); }
.ruler-cell.blocked { background: repeating-linear-gradient(135deg, var(--sunk) 0 5px, var(--surface) 5px 10px); cursor: default; }
.ruler-cell:disabled { cursor: default; }
.ruler-sel { position: relative; z-index: 1; display: flex; align-items: center; background: var(--wheat); box-shadow: inset 0 0 0 2px var(--brand); border-radius: 10px; color: var(--brand-deep); font-size: .72rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.ruler-sel .body { flex: 1; min-width: 0; text-align: center; white-space: nowrap; overflow: hidden; touch-action: none; cursor: grab; padding: 0 12px; }
/* A block narrower than four cells cannot hold its text between the handles: the time floats above it as a badge */
.ruler-sel { container-type: inline-size; }
@container (max-width: 189px) {
  .ruler-sel .body { overflow: visible; }
  .ruler-sel .body span { position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); z-index: 3;
    background: var(--brand); color: #fff; padding: 2px 10px; border-radius: 999px; font-size: .7rem; white-space: nowrap; box-shadow: 0 2px 6px rgba(0,0,0,.2); }
}
.ruler-sel.dragging .body { cursor: grabbing; }
/* Lifted while dragged: no transition to fight the pointer, above the cells, and the finger never scrolls the ruler instead */
.ruler-sel { touch-action: none; will-change: transform; }
.ruler-sel.dragging { transition: none; z-index: 2; box-shadow: inset 0 0 0 2px var(--brand), 0 6px 16px rgba(0,0,0,.18); }
.ruler-sel .handle { position: absolute; top: 50%; width: 16px; height: 32px; transform: translateY(-50%); background: var(--brand); border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.25); touch-action: none; cursor: ew-resize; }
.ruler-sel .handle::after { content: ""; position: absolute; inset: 9px 6px; border-inline: 1.5px solid rgba(255,255,255,.7); }
.ruler-sel .handle.start { inset-inline-start: -8px; }
.ruler-sel .handle.end { inset-inline-end: -8px; }
.rng.blocked { background: repeating-linear-gradient(135deg, var(--sunk) 0 5px, var(--surface) 5px 10px); color: var(--ink-2); border-color: var(--rule); }
.book-bar .book-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.book-bar .book-text span { font-size: .8rem; color: var(--ink-2); }
/* Choice pills (durations, weekdays): a grid of equal cells, so a row of eleven wraps as tidily as a row of four and no label breaks in two */
.durs { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 6px; }
.durs .f-label { grid-column: 1 / -1; margin: 0; }
.dur { border: 1px solid var(--rule); background: var(--surface); color: var(--ink-2); border-radius: 999px; padding: 6px 10px; font: inherit; font-size: .8rem; cursor: pointer; white-space: nowrap; text-align: center; }
.dur.on { background: var(--brand); color: #fff; border-color: var(--brand); }
.choice { display: flex; align-items: center; gap: var(--s3); padding: var(--s3) var(--s4); border-radius: 14px; background: var(--brand-soft); }
.choice .choice-ico { color: var(--brand); flex: none; }
.choice .choice-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.choice .choice-text span { font-size: .82rem; color: var(--ink-2); }
.choice bdi { white-space: nowrap; }
.choice.empty { background: var(--sunk); flex-wrap: wrap; }
.choice.empty .choice-text { color: var(--ink-3); }
/* ── Plan ── The floor drawing as an image with the rooms drawn over it as percent-positioned buttons; the tip is CSS only */
.map-scroll { max-width: 960px; margin-inline: auto; overflow-x: auto; overscroll-behavior-x: contain; }
.map-close { margin-inline-start: auto; }
.map-bar { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s3); }
.map-bar .durs { display: flex; gap: 6px; }
.map-caption { flex: 1; }
.map { position: relative; direction: ltr; overflow: hidden; border-radius: 12px; background: var(--surface); user-select: none; -webkit-user-select: none; }
.map-floor { position: absolute; inset: 0; transition: transform .45s var(--ease); }
.map-floor[hidden] { display: none; }
.map-floor img { display: block; width: 100%; height: 100%; }
.map-room { position: absolute; border: 1.5px solid; border-radius: 4px; padding: 0; font: inherit; font-size: .68rem; line-height: 1.1;
  display: grid; place-items: center; cursor: pointer; container-type: size;
  animation: map-in .25s var(--ease) calc(var(--i) * 25ms) backwards; transition: background-color .2s, box-shadow .15s, opacity .3s; }
/* The drawing reads through a shape: the shape is multiplied with the plan under it, so the walls and the door arcs
   inside a room stay visible instead of being painted over. The order of the elements and what takes a tap stay as
   they were. */
.map-room { mix-blend-mode: multiply; }
.map-room::after { content: ""; position: absolute; inset: -8px; }      /* the hit pad */
.map-room .lbl { display: none; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; max-width: 100%; }
/* The shape's number: shown on phones only, where the name rarely fits; the list under the plan carries the names */
.map-room .num { display: none; position: absolute; top: 2px; inset-inline-start: 2px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--brand); color: #fff; font-size: .62rem; font-weight: 700; line-height: 16px; text-align: center; }
/* Zoomed, every shape is large enough for its name: the font is divided by the zoom so it fits the layout box, and the numbers step aside */
.map.zoomed .map-room .lbl { display: block; font-size: calc(.72rem / var(--zoom, 1)); }
.map.zoomed .map-room .num { display: none; }
.map-legend { display: none; list-style: none; padding: 0; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s3); }
.map-legend-item { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--rule); border-radius: 999px; padding-block: 4px; padding-inline: 6px 10px;
  background: var(--surface); color: var(--ink); font: inherit; font-size: .8rem; cursor: pointer; }
.map-legend-item .num { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px; background: var(--brand); color: #fff; font-size: .68rem; font-weight: 700; }
.map-legend-item.on { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); font-weight: 600; }
.map-legend-item:disabled { opacity: .6; cursor: not-allowed; }
@container (min-width: 64px) and (min-height: 16px) { .map-room .lbl { display: block; } }
.map-room.free { background: var(--brand-soft); border-color: color-mix(in srgb, var(--brand) 45%, #fff); color: var(--brand-deep); animation: map-in .25s var(--ease) calc(var(--i) * 25ms) backwards, map-breathe 2.4s ease-in-out infinite; }
.map-room.held { background: color-mix(in srgb, var(--wheat) 55%, transparent); border-color: var(--wheat); color: var(--ink); }
.map-room.booked { background: color-mix(in srgb, var(--brand) 22%, transparent); border-color: var(--brand); color: var(--brand-deep); }
.map-room.blocked { background: repeating-linear-gradient(135deg, var(--sunk) 0 5px, var(--surface) 5px 10px); border-color: var(--rule-firm); color: var(--ink-2); }
.map-room.unavailable { background: var(--sunk); border-style: dashed; border-color: var(--rule-firm); pointer-events: none; }
.map-room:hover, .map-room:focus-visible { border-width: 2px; outline: none; z-index: 2; }
.map-room:hover { box-shadow: 0 0 0 4px var(--brand-soft); }
.map-room.on { box-shadow: inset 0 0 0 2px var(--brand); font-weight: 600; z-index: 1; animation: map-pop .3s var(--ease); }
/* The keyboard ring is a brand ring over a surface gap, after .on so the picked room keeps both its inset mark and the ring */
.map-room:focus-visible { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand); }
.map-room.on:focus-visible { box-shadow: inset 0 0 0 2px var(--brand), 0 0 0 2px var(--surface), 0 0 0 4px var(--brand); }
/* The breathe animates box-shadow and would beat the ring on a free room a keyboard user tabs through */
.map-room.free:focus-visible { animation: none; }
.map-room.dim { opacity: .55; }
.map-room:disabled { cursor: not-allowed; opacity: .6; }
.map-tip { position: absolute; z-index: 3; pointer-events: none; opacity: 0; transform: translateY(4px); transition: opacity .15s, transform .15s;
  display: grid; gap: 2px; width: max-content; max-width: 220px; padding: var(--s2) var(--s3); border-radius: 10px;
  background: var(--surface); box-shadow: var(--shadow-lift); font-size: .78rem; }
.map-room:hover + .map-tip, .map-room:focus-visible + .map-tip { opacity: 1; transform: none; }
/* Zoomed, the pane is scaled 2.2x and so would be the tip; the info strip carries the text instead */
.map.zoomed .map-tip { display: none; }
.map-info { min-height: 24px; font-size: .84rem; color: var(--ink-2); margin-top: var(--s3); }
/* The builder: shapes drag (the script owns the drag), the selected one shows four corner handles */
.map.edit .map-room { touch-action: none; cursor: move; }
/* Above the shape's own hit pad (the ::after that widens the target), or the corner cannot be grabbed */
.map.edit .map-room .handle { position: absolute; z-index: 2; width: 12px; height: 12px; border-radius: 3px; background: var(--brand); box-shadow: 0 1px 3px rgba(0,0,0,.25); touch-action: none; }
.map.edit .map-room .handle.nw { top: -6px; left: -6px; cursor: nwse-resize; }
.map.edit .map-room .handle.se { bottom: -6px; right: -6px; cursor: nwse-resize; }
.map.edit .map-room .handle.ne { top: -6px; right: -6px; cursor: nesw-resize; }
.map.edit .map-room .handle.sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
.map.edit.drawing { cursor: crosshair; touch-action: none; }
.map-draft { position: absolute; border: 1.5px dashed var(--brand); background: var(--wheat-soft); pointer-events: none; }
/* A booked room on its request's page: the floor's drawing with the one room filled, a picture with nothing to tap */
.room-spot .map { min-width: 0; border: 1px solid var(--rule); }
.room-spot .map-room { pointer-events: none; background: color-mix(in srgb, var(--brand) 45%, transparent); }
.room-spot-cap { margin-top: var(--s2); font-size: .8rem; color: var(--ink-2); text-align: center; }
/* The small plan opens large on a tap: the button lies over the drawing, its icon in the corner says so */
.room-spot-frame { position: relative; }
.room-spot-open { position: absolute; inset: 0; padding: 0; border: 0; border-radius: 12px; background: none; color: var(--ink-2); cursor: zoom-in; }
.room-spot-open .mud-icon-root { position: absolute; top: var(--s2); inset-inline-end: var(--s2); padding: 3px; border-radius: 8px;
  background: var(--surface); box-shadow: 0 0 0 1px var(--rule); }
.room-spot-open:hover, .room-spot-open:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand); }
.room-spot.big { max-width: none; padding-bottom: var(--s4); }
/* Large, the plan lives in a box it is dragged and pinched in (spot.js): the box scrolls and the drawing grows inside it.
   touch-action: none hands the fingers to the script; without it the browser scrolls and the pinch never arrives.
   A wide screen shows the whole floor; a phone gets a square box, so there is room to move around the room */
.spot-pan { position: relative; display: flex; overflow: hidden; direction: ltr; aspect-ratio: var(--plan-aspect); border: 1px solid var(--rule); border-radius: 12px; touch-action: none; }
.room-spot.big .map { flex: none; width: 100%; margin-block: auto; border: 0; border-radius: 0; }
@media (max-width: 599.98px) { .spot-pan { aspect-ratio: 1; } }
/* A request's data with a feature's picture: under the facts, and beside them once the card is wide enough for both */
.data-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); align-items: start; }
.room-spot { max-width: 480px; margin-inline: auto; }
@media (min-width: 1280px) {
  .data-split { grid-template-columns: minmax(0, 1fr) minmax(0, 340px); gap: var(--s5); }
  .data-split .facts.wrap { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
}
/* The builder's bar: the room list, the mode buttons and the save; under it the selected shape as four numbers */
.plan-bar { display: flex; align-items: flex-end; gap: var(--s2); flex-wrap: wrap; }
.plan-bar .plan-room { flex: 1 1 220px; max-width: 320px; }
.plan-bar .spacer { flex: 1; }
.plan-shape { display: flex; align-items: flex-end; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }
.plan-shape .plan-shape-name { flex: 1 1 100%; }
.plan-shape .plan-num { width: 96px; }
@keyframes map-in { from { opacity: 0; } }
@keyframes map-pop { 50% { transform: scale(1.03); } }
@keyframes map-breathe { 50% { box-shadow: 0 0 0 3px var(--brand-soft); } }
@media (max-width: 599.98px) {
  /* The plan on a phone scrolls sideways at a width that keeps a 5 m wall tappable; a name shows where it fits, and every shape is numbered with its name in the list under the plan */
  .map { min-width: 640px; }
  /* Zoomed, the box fits the screen, so the fly-to-room centres the room in what is visible, not in a box twice the screen's width */
  .map.zoomed { min-width: 0; }
  .map-room { font-size: .6rem; }
  .map-room .num { display: block; }
  .map-legend { display: flex; }
  .room-pick { max-width: none; }
  /* The booking bar on phones: the choice on top, then the two buttons side by side */
  .ruler-track { --slot-w: 40px; --day-w: 64px; grid-auto-rows: 46px; }
  .rooms-bar { gap: var(--s3); }
  /* On a phone the toolbar is a stack: the room, the durations stretched across as one control, the two actions as equal pills */
  .rooms-bar-durs .durs { grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); }
  .rooms-bar-actions { width: 100%; margin-inline-start: 0; display: grid; grid-template-columns: 1fr 1fr; align-self: auto; }
  .rooms-bar-actions .mud-button-root { width: 100%; }
  .manual-entry .manual-date, .manual-entry .manual-time, .manual-entry .manual-dur { flex: 1 1 calc(50% - var(--s3)); max-width: none; }
  .manual-entry .manual-go { flex: 1 1 100%; }
  .plan-shape .plan-num { flex: 1 1 calc(50% - var(--s2)); width: auto; }
  .rooms-bar-room { max-width: none; }
  .week-nav { padding: var(--s2) var(--s3); }
  .week-nav .day-pick { display: none; }
  .week-nav .legend { width: 100%; }
  .book-bar .book-text { flex: 1 1 100%; }
  .book-bar .spacer { display: none; }
  .book-bar .mud-button-filled { flex: 1; }
  .choice .mud-button-root { flex: none; }
}

/* ── Bell ──────────────────────────────────────────────────────── */
/* The bell is a plain round button and its list a panel under it, opened in the browser like the "More" sheet.
   The count wraps the icon inside the button: as inline content the icon sat on a text baseline and the button grew
   taller than the bar; as a flex box it is exactly the icon's size. The count sits on the icon's corner, partly outside
   the button's circle, so the button must not clip (it was cut along the curve). "9+" keeps its order in a
   right-to-left page. */
.bell { position: relative; }
.bell-btn { display: grid; place-items: center; width: 48px; height: 48px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: inherit; cursor: pointer; overflow: visible; }
.bell-btn:active, html[data-open="bell"] .bell-btn { background: var(--sunk); }
.bell-btn .mud-badge-root { display: flex; }
.bell-btn .mud-badge { direction: ltr; }
.bell-panel {
  position: absolute; z-index: 5; top: calc(100% + 6px); inset-inline-end: 0; width: min(360px, calc(100vw - 24px));
  max-height: min(420px, 70vh); overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); color: var(--ink); border-radius: 18px; padding-bottom: var(--s2);
  box-shadow: var(--shadow-lift), 0 0 0 1px rgba(21,25,15,.05);
  opacity: 0; transform: translateY(-8px); visibility: hidden;
  transition: opacity 160ms var(--ease), transform 160ms var(--ease), visibility 0s 160ms;
}
html[data-open="bell"] .bell-panel { opacity: 1; transform: none; visibility: visible; transition: opacity 160ms var(--ease), transform 160ms var(--ease); }
.bell-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s2) var(--s4) var(--s1); }
.bell-empty { padding: var(--s3) var(--s4) var(--s4); color: var(--ink-3); }
.bell-item { display: block; width: 100%; padding: var(--s2) var(--s4); border: 0; background: none; color: inherit; font: inherit;
  text-align: start; cursor: pointer; }
.bell-item:hover { background: var(--sunk); }
.bell-item .k { display: block; font-size: .72rem; font-weight: 700; color: var(--brand); }
.bell-item .t { display: block; font-size: .86rem; white-space: normal; line-height: 1.5; }
.bell-item .w { display: block; font-size: .72rem; color: var(--ink-3); }
.bell-item.unread { background: var(--brand-soft); }

/* ── The society's motif («التكوين الزخرفي», identity guide page 10): an eight-point star lattice, one tile
   (pattern.svg) used as a mask over a token's colour, so its tint is the brand's and one file serves light and dark.
   Decoration only: always a pseudo-element with no text in it, under its parent's content, never moving and never
   filtered, so a phone draws it once (IdentityTests.ThePatternIsAFingerprintedTileUnderNoText). The hero and the
   empty state fade it out before their text with a second, radial mask. ── */
.login-wrap::after, .hero::after, .empty::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  -webkit-mask: url("pattern.uytei3mmgs.svg") 0 0 / 48px 48px; mask: url("pattern.uytei3mmgs.svg") 0 0 / 48px 48px;
}
.hero::after, .empty::before {
  -webkit-mask: url("pattern.uytei3mmgs.svg") 0 0 / 48px 48px, radial-gradient(closest-side, #000 35%, transparent 72%);
  -webkit-mask-composite: source-in;
  mask: url("pattern.uytei3mmgs.svg") 0 0 / 48px 48px, radial-gradient(closest-side, #000 35%, transparent 72%);
  mask-composite: intersect;
}

/* ── Empty state ───────────────────────────────────────────────── */
.empty { position: relative; isolation: isolate; padding: var(--s5) var(--s3); text-align: center; }
/* A wide, low oval: the motif shows beside the icon, never down to the message under it */
.empty::before { top: calc(var(--s5) - 16px); left: 50%; width: 240px; height: 96px; margin-left: -120px; background: var(--brand); opacity: .4; }
.empty-mark { color: var(--brand); font-size: 2.2rem; width: 64px; height: 64px; padding: 16px; border-radius: 22px; background: var(--brand-soft); }
.empty-msg { color: var(--ink-2); }

/* ── Home hero: greeting, summary, and the four numbers on one gradient card ── */
.hero {
  position: relative; overflow: hidden; isolation: isolate;
  border-radius: 28px; padding: var(--s5); color: #fff;
  background: linear-gradient(225deg, var(--brand-deep) 0%, var(--brand-deep) 35%, var(--brand) 100%);
  box-shadow: 0 28px 56px -26px color-mix(in srgb, var(--brand-deep) 70%, transparent);
}
.hero::before {
  content: ""; position: absolute; z-index: -1; border-radius: 50%; pointer-events: none;
  width: 60%; aspect-ratio: 1;
  top: -45%; inset-inline-end: -15%; background: radial-gradient(circle, color-mix(in srgb, var(--wheat) 38%, transparent), transparent 62%);
}
.hero::after { top: -64px; inset-inline-end: -64px; width: 240px; height: 240px; background: var(--wheat); opacity: .22; }
.hero-top { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--s4); flex-wrap: wrap; }
.hero-eyebrow { font-size: .82rem; font-weight: 600; color: var(--wheat); }
.hero-name { font-family: var(--font-head-black); font-size: clamp(1.7rem, 1.3rem + 1.6vw, 2.4rem); font-weight: 800; margin: 2px 0 0; line-height: 1.3; }
.hero-sum { margin: var(--s1) 0 0; opacity: .85; font-size: .95rem; max-width: 48ch; }
.hero-cta {
  display: inline-flex; align-items: center; gap: var(--s2); flex: none;
  padding-block: 11px; padding-inline: 16px 20px; border-radius: 999px; text-decoration: none;
  background: var(--wheat); color: var(--brand-deep); font-weight: 700; font-size: .95rem;
  box-shadow: 0 10px 24px -8px color-mix(in srgb, var(--wheat) 70%, transparent);
  transition: transform .15s var(--ease), box-shadow .2s;
}
.hero-cta:hover { transform: translateY(-1px); box-shadow: 0 14px 28px -8px color-mix(in srgb, var(--wheat) 80%, transparent); }
.hero-cta:active { transform: scale(.97); }
/* One quiet line of numbers under the greeting — the four glass tiles were a dashboard nobody asked for */
.hero-line { margin: var(--s4) 0 0; padding-top: var(--s3); border-top: 1px solid rgba(255,255,255,.14); font-size: .84rem; opacity: .8; }
/* On phones the bar's "+" already leads to a new request */
@media (max-width: 959.98px) {
  .hero { padding: var(--s4); border-radius: 24px; } .hero-cta { display: none; }
  /* The greeting runs nearly the width of a phone: the motif keeps to a smaller corner */
  .hero::after { top: -48px; inset-inline-end: -48px; width: 150px; height: 150px; opacity: .16; }
}

/* ── Status pill: a dot and a tinted capsule ───────────────────── */
.pill {
  display: inline-flex; align-items: center; gap: 6px; padding-block: 3px; padding-inline: 8px 10px;
  border-radius: 999px; font-size: .74rem; font-weight: 700; white-space: nowrap; line-height: 1.5;
  background: var(--sunk); color: var(--ink-2);
}
.pill .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.pill.tone-wait { background: var(--wait-soft); color: var(--wait); }
.pill.tone-move { background: var(--move-soft); color: var(--move); }
.pill.tone-done { background: var(--done-soft); color: var(--done); }
.pill.tone-stop { background: var(--stop-soft); color: var(--stop); }
.pill.tone-brand { background: var(--brand-soft); color: var(--brand-deep); }
.pill.tone-late .dot { animation: blink 1.4s ease-in-out infinite; }
@keyframes blink { 50% { opacity: .25; } }

/* ── Request rows ──────────────────────────────────────────────── */
.req-list { overflow: hidden; }
.req-row {
  position: relative; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); min-height: 74px;
  color: inherit; text-decoration: none; transition: background .15s;
  -webkit-tap-highlight-color: transparent;
}
.req-row + .req-row::before { content: ""; position: absolute; top: 0; inset-inline: var(--s4); height: 1px; background: var(--rule); }
.req-row:hover { background: var(--sunk); }
.req-row:active { background: var(--brand-soft); }
.req-ico, .svc-ico {
  width: 44px; height: 44px; border-radius: 14px; flex: none;
  display: grid; place-items: center; background: var(--brand-soft); color: var(--brand);
}
.req-ico.tone-wh, .svc-ico.tone-wh { background: var(--move-soft); color: var(--move); }
.req-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; color: inherit; text-decoration: none; }
.req-title { font-weight: 700; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.req-sub { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); font-size: .78rem; color: var(--ink-3); }
.req-sub > span + span::before { content: "·"; margin-inline-end: var(--s2); opacity: .6; }
.req-sub .num { white-space: nowrap; }
.req-side { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: none; }
.req-due { font-size: .74rem; color: var(--ink-3); white-space: nowrap; }
.req-due.late { color: var(--stop); font-weight: 700; }
/* The chevron at a row's end, drawn here (the library's ChevronLeft, as a mask in the text colour): an icon per row was
   ~0.3 KB of markup for every row of every list (SCRUM-147 B11) */
.req-go { width: 24px; height: 24px; background: currentColor; color: var(--ink-3); flex: none; transition: transform .2s var(--ease);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E") center / 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z'/%3E%3C/svg%3E") center / 24px no-repeat; }
.req-row:hover .req-go { transform: translateX(-3px); }

@media (max-width: 599.98px) {
  .req-row { padding-inline: var(--s3); }
  .req-go { display: none; }
  /* The side column is the pill's width and the deadline wraps under it: "المهلة حتى نهاية يوم الأربعاء" on one line
     took the title's room, and rows of one service cut their titles at different points */
  .req-side { width: min-content; }
  .req-due { white-space: normal; text-align: end; text-wrap: balance; }
}

/* ── Service cards ─────────────────────────────────────────────── */
.svc-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s3); }
.svc-grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 759.98px) { .svc-grid, .svc-grid.cols-3 { grid-template-columns: 1fr; } }

.svc {
  position: relative; display: flex; align-items: flex-start; gap: var(--s3);
  padding-block: var(--s4); padding-inline: var(--s4) calc(var(--s4) + 20px);
  background: var(--surface); border-radius: 18px; box-shadow: var(--shadow-card);
  color: inherit; text-decoration: none;
  transition: transform .18s var(--ease), box-shadow .18s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.svc:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.svc:active { transform: scale(.985); }
.svc-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.svc-t { font-weight: 700; font-size: .95rem; }
.svc-d { font-size: .8rem; color: var(--ink-3); }
.svc-m { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: var(--s1); font-size: .74rem; color: var(--ink-2); }
.svc-m span { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px; background: var(--sunk); }
.svc-go { position: absolute; inset-inline-end: var(--s3); top: 50%; transform: translateY(-50%); color: var(--ink-3); }
.svc.compact { padding-block: var(--s3); align-items: center; }
.svc.compact .svc-ico { width: 38px; height: 38px; border-radius: 12px; }

/* The launcher search: one big pill */
.search .mud-input.mud-input-outlined { border-radius: 999px; box-shadow: var(--shadow-card); font-size: 1.05rem; }
/* At the library's own specificity (.mud-input.mud-input-outlined > .border), or its 14px wins and the pill fill pokes out */
.search .mud-input.mud-input-outlined > .mud-input-outlined-border { border-radius: 999px; }
.search .mud-input-adornment { margin-inline-start: var(--s2); }

/* ── Menu items inside SelectMenu ──────────────────────────────── */
.sm-group {
  display: block; font-size: .68rem; font-weight: 700; letter-spacing: .06em;
  color: var(--ink-3); margin: 0 0 4px; padding-bottom: 3px; border-bottom: 1px solid var(--rule);
}
.sm-main { display: block; }
.sm-sub { display: block; font-size: .72rem; color: var(--ink-3); }

/* ── Login (plain HTML form — posts to /login) ─────────────────── */
.login-wrap {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: 100dvh; display: grid; place-items: center; padding: var(--s5);
  background: color-mix(in srgb, var(--brand-deep) 55%, #000);
}
/* Three drifting colour fields in the logo colours, blurred into an aurora — the only decoration on the page */
.login-wrap::before {
  content: ""; position: absolute; inset: -25%; z-index: -1;
  background:
    radial-gradient(38% 38% at 25% 30%, color-mix(in srgb, var(--brand-lift) 95%, transparent), transparent 70%),
    radial-gradient(34% 34% at 78% 22%, color-mix(in srgb, var(--blue) 60%, transparent), transparent 70%),
    radial-gradient(30% 30% at 62% 84%, color-mix(in srgb, var(--wheat) 50%, transparent), transparent 70%);
  filter: blur(48px);
  animation: drift 20s ease-in-out infinite alternate;
}
@keyframes drift { to { transform: translate(6%, -5%) rotate(10deg) scale(1.08); } }
.login-wrap::after { inset: 0; background: var(--wheat); opacity: .1; -webkit-mask-size: 96px 96px; mask-size: 96px 96px; }
.login-card {
  position: relative; width: 100%; max-width: 400px; background: var(--surface);
  border-radius: 28px; padding: var(--s6);
  box-shadow: 0 40px 80px -30px rgba(0,0,0,.65), inset 0 1px 0 rgba(255,255,255,.7);
  animation: rise .6s var(--ease) both;
}
.login-logo { display: block; width: 200px; max-width: 70%; height: auto; margin: 0 auto var(--s4); }
.login-card h1 { font-family: var(--font-head-black); font-size: 1.3rem; font-weight: 800; margin: 0 0 2px; }
.login-card .sub { color: var(--ink-3); font-size: .85rem; margin-bottom: var(--s5); }
.login-card .field { margin-bottom: var(--s4); }
.login-card label { display: block; font-weight: 600; font-size: .86rem; margin-bottom: 6px; }
.login-card input {
  width: 100%; box-sizing: border-box; padding: 13px var(--s4); font: inherit; font-size: 1rem;
  border: 1px solid var(--rule-firm); border-radius: 14px; background: var(--surface); color: var(--ink);
  transition: border-color .15s, box-shadow .15s;
}
.login-card input:focus { outline: none; border-color: var(--brand-lift); box-shadow: 0 0 0 4px var(--brand-soft); }
.login-card .submit {
  width: 100%; padding: 14px; margin-top: var(--s2); font: inherit; font-weight: 700; font-size: 1rem;
  border: 0; border-radius: 999px; cursor: pointer; color: #fff;
  background: linear-gradient(135deg, var(--brand-lift), var(--brand));
  box-shadow: 0 12px 24px -10px color-mix(in srgb, var(--brand) 70%, transparent);
  transition: transform .15s var(--ease), box-shadow .2s;
}
.login-card .submit:hover { transform: translateY(-1px); box-shadow: 0 16px 28px -10px color-mix(in srgb, var(--brand) 80%, transparent); }
.login-card .submit:active { transform: scale(.98); }
.login-card .alert { padding: 10px var(--s3); border-radius: 12px; background: var(--stop-soft); color: var(--stop); font-size: .86rem; margin-bottom: var(--s4); }

/* ── A form's actions: a bar where the form ends, in the page's flow. It used to stick to the bottom of the screen
   and float over the form; the owner asked for it to stay with its form, everywhere (2026-10-01) ─────────────── */
.actions-bar {
  display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center;
  padding: var(--s3) var(--s4);
  background: var(--surface);
  border-radius: 22px; box-shadow: var(--shadow-lift), 0 0 0 1px rgba(21,25,15,.05);
}
.actions-bar .spacer { flex: 1; }
@media (max-width: 599.98px) {
  .actions-bar > .mud-button-root { flex: 1 1 auto; }
  .actions-bar > .mud-button-text { flex: 1 1 100%; }
  .actions-bar .spacer { display: none; }
}

/* ── Page headers ──────────────────────────────────────────────── */
.page-head { margin-bottom: 0; }
.page-head.with-actions { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); }
.page-head-text { min-width: 0; }
.page-head .eyebrow { font-size: .76rem; font-weight: 700; letter-spacing: .04em; color: var(--gold); margin-bottom: var(--s1); }
.page-head h1, .page-head .mud-typography-h1 { margin: 0; font-size: clamp(1.6rem, 1.25rem + 1.3vw, 2.1rem); font-weight: 800; }
.page-head p { margin: var(--s1) 0 0; color: var(--ink-3); font-size: .9rem; max-width: 62ch; }
.section-label { font-size: .8rem; font-weight: 700; letter-spacing: .03em; color: var(--ink-2); margin: 0 0 var(--s3); display: flex; align-items: center; gap: var(--s2); }
.section-label .pill { padding: 0 8px; font-size: .72rem; }

/* ── Stats (admin dashboard) ───────────────────────────────────── */
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s3); }
@media (max-width: 759.98px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat { padding: var(--s4); background: var(--surface); border-radius: 18px; box-shadow: var(--shadow-card); }
.stat .n { display: block; font-family: var(--font-head-black); font-size: 1.8rem; font-weight: 800; line-height: 1.2; color: var(--brand); }
.stat .n.zero { color: var(--ink-3); }
.stat .n.tone-wait { color: var(--wait); }
.stat .n.tone-move { color: var(--move); }
.stat .n.tone-alert { color: var(--stop); }
.stat .l { display: block; margin-top: 4px; font-size: .78rem; color: var(--ink-3); }

/* ── Progress track: where the request stands, one glance ──────── */
/* With many stops (approvals, then every tracked execution step) the track scrolls inside itself, never the page;
   the padding keeps the current stop's ring clear of the scroll box */
.track { display: flex; list-style: none; margin: var(--s4) 0 0; padding: var(--s2) 0; overflow-x: auto; }
.track li {
  position: relative; flex: 0 1 44px; display: flex; flex-direction: column; align-items: center; gap: 6px;
  text-align: center; font-size: .72rem; color: var(--ink-3); line-height: 1.35;
}
/* The current stop takes the free width, but its dot is pinned 22px from its start edge — not centred in the
   stretched column — so "1" sits in the same place on every row whatever the number of stops. Only it has a label;
   the other stops are dots, and the approval trail names them. */
.track li.now { flex: 1 1 auto; align-items: flex-start; padding-inline-start: 10px; }
.track li.now::before { width: 22px; }
.track li.now::after { inset-inline-start: 22px; inset-inline-end: 0; width: auto; }
/* Off screen, not gone: a screen reader still reads each stop's name and state on a phone */
.track li:not(.now) .t-l, .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.track li.now .t-l { white-space: nowrap; padding: 0; }
/* Each stop draws its own two half-lines, so nothing reaches past the track — a line drawn from one stop
   to the next overflowed the page on phones, where stops have different widths */
.track li::before, .track li::after { content: ""; position: absolute; top: 11px; width: 50%; height: 2px; background: var(--rule); }
.track li::before { inset-inline-start: 0; }
.track li::after { inset-inline-end: 0; }
.track li:first-child::before, .track li:last-child::after { content: none; }
.track li.done::before, .track li.done::after, .track li.now::before { background: var(--done); }
.t-dot {
  position: relative; z-index: 1; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface); border: 2px solid var(--rule-firm); color: var(--ink-3); font-size: .7rem; font-weight: 700;
}
.t-dot .mud-icon-root { width: 14px; height: 14px; font-size: 14px; }
.track li.done .t-dot { background: var(--done); border-color: var(--done); color: #fff; }
.track li.now .t-dot { background: var(--wheat); border-color: var(--wheat); color: var(--brand-deep); box-shadow: 0 0 0 5px var(--wheat-soft); }
.track li.now { color: var(--ink); font-weight: 700; }
.track li.stop .t-dot { background: var(--stop); border-color: var(--stop); color: #fff; }
.track li.stop { color: var(--stop); }
.t-l { padding: 0 4px; }
/* A step's deadline in words, under its name: hidden with the name on a phone's other stops */
.t-d { display: block; font-weight: 400; color: var(--ink-3); }
/* Wider screens have room: every stop gets its label, at a fixed width so the current dot stays pinned */
/* On a phone the current stop's name wraps: "اعتماد" and a long position pushed every stop after it out of view */
@media (max-width: 599.98px) { .track li.now .t-l { white-space: normal; } }
@media (min-width: 600px) {
  .track li { flex: 0 0 112px; }
  .track li:not(.now) .t-l { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; max-width: 104px; }
}

/* ── The route of a request (RouteTimeline): a timeline with a connecting line. Its stops carry the track's state
   classes (done / now / stop / todo), always under ".chain li"; a step's collected values and photos sit in its body ── */
.chain { list-style: none; margin: 0; padding: 0; }
.chain li { position: relative; display: flex; gap: var(--s3); padding: var(--s2) 0 var(--s4); }
.chain li:last-child { padding-bottom: 0; }
.chain li:not(:last-child)::before { content: ""; position: absolute; top: 40px; bottom: 0; inset-inline-start: 15px; width: 2px; background: var(--rule); }
.chain li.done:not(:last-child)::before { background: color-mix(in srgb, var(--done) 35%, #fff); }
.chain .dot {
  position: relative; z-index: 1; width: 32px; height: 32px; border-radius: 50%; flex: none; display: grid; place-items: center;
  background: var(--sunk); color: var(--ink-3); font-size: .8rem; font-weight: 700;
}
.chain .dot .mud-icon-root { width: 18px; height: 18px; font-size: 18px; }
.chain li.done .dot { background: var(--done); color: #fff; }
.chain li.stop .dot { background: var(--stop); color: #fff; }
.chain li.now .dot { background: var(--wheat); color: var(--brand-deep); box-shadow: 0 0 0 5px var(--wheat-soft); animation: pulse 2.2s ease-in-out infinite; }
@keyframes pulse { 50% { box-shadow: 0 0 0 9px color-mix(in srgb, var(--wheat) 15%, transparent); } }
.chain .body { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; padding-top: 5px; }
.chain .who { font-weight: 700; }
.chain .meta { font-size: .78rem; color: var(--ink-3); }
.chain .note { font-size: .84rem; color: var(--ink-2); background: var(--sunk); padding: 6px var(--s3); border-radius: 10px; margin-top: 4px; }
.chain li.todo .who { color: var(--ink-3); }
.chain .step-data { margin-top: var(--s2); }
/* What a step collected: its values as facts, then each photo field's strip */
.step-data { display: grid; gap: var(--s3); }

/* "Will be approved by" — the route the request will take, drawn as numbered stops */
.route {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--surface); border-radius: 16px; box-shadow: var(--shadow-card); font-size: .86rem;
}
.route .lead { font-weight: 700; color: var(--gold); }
.route .stop-n { display: inline-flex; align-items: center; gap: 6px; padding-block: 3px; padding-inline: 4px 12px; border-radius: 999px; background: var(--brand-soft); color: var(--brand); font-weight: 600; }
.route .stop-n i { font-style: normal; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--brand); color: #fff; font-size: .72rem; }
.route .arr { color: var(--ink-3); }
.route .hint { color: var(--ink-2); }

/* Step indicator of a new request: three numbered pills, the current one filled */
.steps { display: flex; gap: var(--s2); list-style: none; margin: 0; padding: 0; }
.steps li { display: inline-flex; align-items: center; gap: 6px; padding-block: 4px; padding-inline: 5px 12px; border-radius: 999px; background: var(--sunk); color: var(--ink-3); font-size: .8rem; font-weight: 600; }
.steps li i { font-style: normal; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--surface); color: var(--ink-3); font-size: .72rem; }
.steps li.now { background: var(--brand-soft); color: var(--brand); }
.steps li.now i { background: var(--brand); color: #fff; }
.steps li.done { color: var(--done); }
.steps li.done i { background: var(--done); color: #fff; }

/* "What happens after sending": numbered stops, then the sent screen */
.next-steps { list-style: none; margin: 0 0 var(--s4); padding: 0; display: flex; flex-direction: column; gap: var(--s2); }
.next-steps li { display: flex; align-items: center; gap: var(--s3); font-weight: 600; }
.next-steps li i { font-style: normal; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--brand-soft); color: var(--brand); font-size: .78rem; flex: none; }
/* A step's name, then who does a task and its deadline, wrapping under the name on a phone */
.next-steps li .next-step { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s2); min-width: 0; }
.next-steps li .holder { font-weight: 400; color: var(--ink-2); font-size: .85rem; }
.next-steps li .due { font-weight: 400; color: var(--ink-3); font-size: .85rem; }
/* Named "sent", not "done": "done" is a state class on track stops, and a bare .done rule padded every finished stop */
.sent { text-align: center; padding: var(--s6) var(--s4); max-width: 560px; margin: 0 auto; }
.sent-mark { display: grid; place-items: center; width: 88px; height: 88px; margin: 0 auto var(--s4); border-radius: 50%; background: linear-gradient(135deg, color-mix(in srgb, var(--done) 80%, #fff), var(--done)); color: #fff; box-shadow: 0 18px 40px -16px color-mix(in srgb, var(--done) 70%, transparent); animation: pop .6s var(--ease) both; }
.sent-mark .mud-icon-root { width: 44px; height: 44px; }
@keyframes pop { from { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.08); } to { transform: none; opacity: 1; } }
.sent-num { font-size: 1.05rem; color: var(--ink-3); margin: var(--s1) 0 var(--s5); }
.sent .facts { text-align: start; grid-template-columns: 1fr 1fr; }
.sent-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s2); margin-top: var(--s6); }

/* A deleted request row: the restore button sits beside the text on desktop and under it on phones,
   so the meta line keeps its full width instead of wrapping around the button */
.req-row.deleted > .mud-button-root { flex: none; }
@media (max-width: 599.98px) {
  .req-row.deleted > .mud-button-root { flex: 0 0 auto; margin-inline-start: calc(44px + var(--s3)); }
  .req-row.deleted .req-main { flex-basis: calc(100% - 44px - var(--s3)); }
}
/* A request row wraps: a deleted row's restore button drops under its text on phones */
.req-row { flex-wrap: wrap; }

/* The decision sheet: title with number and pill, content spacing */
.sheet-title { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.sheet-title .eyebrow { font-size: .74rem; font-weight: 700; color: var(--gold); }
.decision-sheet .section-label { margin-top: var(--s4); }
.sheet-btns { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); width: 100%; }
.sheet-btns .open-link { order: -1; margin-inline-end: auto; }
@media (max-width: 599.98px) {
  .sheet-btns .mud-button-filled { flex: 1 1 100%; order: -2; }
  .sheet-btns .mud-button-outlined, .sheet-btns .mud-button-text:not(.open-link) { flex: 1 1 40%; }
  .sheet-btns .open-link { flex: 1 1 100%; order: 5; margin: 0; }
}

/* The request page: one column at reading width, a header card, then tabs — not six cards in two uneven columns */
.req-page { max-width: 880px; margin: 0 auto; }
.req-head .page-head { margin-bottom: 0; }
.req-head .facts { grid-template-columns: repeat(4, minmax(0, max-content)); gap: var(--s3) var(--s7); }
.req-head .track { margin-top: var(--s5); }
/* The step's deadline takes two of a phone's three columns: "حتى نهاية يوم الأربعاء" broke after "يوم" in one */
@media (max-width: 599.98px) {
  .req-head .facts { grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: var(--s3); }
  .req-head .fact.due { grid-column: span 2; }
}
/* Logs page: the tool row, then rows of time + what happened */
.log-tools { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-bottom: var(--s3); }
.log-tools .pick { flex: 1 1 180px; min-width: 0; }
.log-tools .mud-input-control { margin: 0; }
.log-row { position: relative; display: flex; gap: var(--s3); padding: var(--s3) var(--s4); font-size: .88rem; }
.log-row + .log-row::before { content: ""; position: absolute; top: 0; inset-inline: var(--s4); height: 1px; background: var(--rule); }
.log-row .when { flex: none; color: var(--ink-3); font-size: .76rem; padding-top: 3px; white-space: nowrap; }
.log-row .body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.log-row .subject { unicode-bidi: isolate; }
/* System-log lines are English: isolated left-to-right so punctuation and ids do not flip inside the RTL page */
.log-row .msg { display: block; direction: ltr; unicode-bidi: isolate; text-align: left; overflow-wrap: anywhere; margin-top: 2px; }
.log-row .src { font-size: .72rem; color: var(--ink-3); direction: ltr; unicode-bidi: isolate; text-align: left; overflow-wrap: anywhere; }
.log-row .note { color: var(--ink-2); background: var(--sunk); padding: 6px var(--s3); border-radius: 10px; margin-top: 4px; font-size: .82rem; overflow-wrap: anywhere; }
.log-row.is-error { background: var(--stop-soft); }
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2); margin-top: var(--s3); font-size: .82rem; }
@media (max-width: 599.98px) { .log-row { flex-direction: column; gap: 4px; } }
/* Sensitive actions: a quiet row of red text buttons at the end of the page */
.danger-zone { display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: flex-end; }
/* Why the requester's cancel is gone: its own line, from the start, a shade apart from the page's text */
.cancel-note { color: var(--ink-2); }
/* "دورك الآن": the one card on the page that asks something of the reader, framed in the brand colour. Its name and
   deadline head it; its buttons end it, flat inside the frame */
.decision { display: grid; gap: var(--s3); }
.mud-paper-outlined.decision { border: 2px solid var(--brand); }
.turn-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.decision .actions-bar { padding: 0; background: none; box-shadow: none; border-radius: 0; }
.turn-note { font-size: .85rem; color: var(--ink-3); }

/* ── Activity log ──────────────────────────────────────────────── */
.log { list-style: none; margin: 0; padding: 0; font-size: .88rem; }
.log li { display: grid; grid-template-columns: 1fr auto; gap: var(--s3); align-items: start; padding: var(--s3) 0; border-bottom: 1px solid var(--rule); }
.log li:first-child { padding-top: 0; }
.log li:last-child { border-bottom: 0; padding-bottom: 0; }
.log .what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.log .who { font-weight: 700; }
.log .act { color: var(--ink-2); }
.log .note { color: var(--ink-2); background: var(--sunk); padding: 6px var(--s3); border-radius: 10px; margin-top: 4px; }
.log .when { color: var(--ink-3); font-size: .76rem; white-space: nowrap; padding-top: 3px; }

/* ── Facts: a label above its value — read in one pass, no sentence to parse ── */
.facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3) var(--s4); margin-top: var(--s4); }
.facts.wrap { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); margin-top: 0; }
.fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fact.wide { grid-column: 1 / -1; }
.fact .k { font-size: .74rem; font-weight: 600; color: var(--ink-3); }
.fact .v { font-size: .98rem; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.fact .v.late { color: var(--stop); }
.fact-group > .group-title { font-size: .95rem; font-weight: 600; color: var(--ink); } /* a group's title reads as the form's legend */
@media (max-width: 599.98px) {
  .facts { grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: var(--s3); }
  .facts.wrap { grid-template-columns: 1fr 1fr; }
  .fact .v { font-size: .92rem; }
}

/* Form labels above the field; help and errors under it, quieter than the value */
.f-label { display: block; font-size: .84rem; font-weight: 600; color: var(--ink-2); margin-bottom: 6px; line-height: 1.4; }
.f-label .req, .field-label .req { color: var(--stop); margin-inline-start: 2px; }
.field-help { display: block; margin-top: 4px; color: var(--ink-3); font-size: .76rem; line-height: 1.5; }
/* A held value another request holds now, greyed in the list picker (LookupBox): the value, then whose and until when */
.lookup-taken { display: flex; flex-direction: column; gap: 2px; }
.lookup-note { color: var(--ink-3); font-size: .76rem; line-height: 1.5; }
.field-error { display: block; margin-top: 4px; font-size: .78rem; }
.field .mud-input-control { margin-top: 0; }

/* ── Attachments ───────────────────────────────────────────────── */
/* The user guide and the changelog (Guide.razor): each section a <details> the browser opens */
.guide-search { max-width: 520px; margin-bottom: var(--s4); }
.guide-group { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: var(--s5); }
.guide-group-title { margin-bottom: var(--s1); }
.guide-section { border: 1px solid var(--rule); border-radius: 14px; background: var(--surface); scroll-margin-top: 80px; }
.guide-section > summary { list-style: none; cursor: pointer; padding: var(--s3) var(--s4); display: flex; flex-direction: column; gap: 2px; }
.guide-section > summary::-webkit-details-marker { display: none; }
.guide-section > summary .t { font-weight: 700; color: var(--ink); }
.guide-section > summary .t::before { content: "+"; display: inline-block; width: 1.2em; color: var(--brand); font-weight: 700; }
.guide-section[open] > summary .t::before { content: "−"; }
.guide-section > summary .s { font-size: .86rem; color: var(--ink-2); padding-inline-start: 1.2em; }
.guide-body { padding: 0 var(--s4) var(--s4); }
.guide-steps { margin: 0; padding-inline-start: 1.4em; display: flex; flex-direction: column; gap: 6px; line-height: 1.8; }
.guide-notes { margin: var(--s3) 0 0; padding: var(--s3); padding-inline-start: 1.6em; border-radius: 12px; background: var(--wheat-soft); color: var(--ink-2); line-height: 1.8; }
.guide-pictures { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s3); margin-top: var(--s4); }
.guide-pictures figure { margin: 0; min-width: 0; }
.guide-pictures img { width: 100%; max-width: 100%; height: auto; border: 1px solid var(--rule); border-radius: 12px; display: block; }
.guide-pictures figcaption { font-size: .8rem; color: var(--ink-3); margin-top: 4px; }
.changelog { display: flex; flex-direction: column; gap: var(--s4); }
.release { padding: var(--s4); }
.release-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: var(--s2); }
.release-date { font-size: .8rem; color: var(--ink-3); }
.release-commit { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.release ul { margin: 0; padding-inline-start: 1.2em; display: flex; flex-direction: column; gap: 6px; line-height: 1.8; }
.change-new { background: var(--brand-soft); color: var(--brand-deep); }
.change-improved { background: var(--wheat-soft); color: var(--brand-deep); }
.change-fixed { background: var(--paper); color: var(--ink-2); }
.f-head { display: flex; align-items: center; gap: 2px; margin-bottom: 2px; }
.f-head .f-label { margin-bottom: 0; }
/* The "?" help tip (HelpTip): the browser's own popover, centred in the top layer, closed by a tap outside it */
.help-tip {
  display: inline-grid; place-items: center; width: 26px; height: 26px; padding: 0; margin-inline-start: 4px;
  border: 0; border-radius: 50%; background: transparent; color: var(--ink-3); cursor: pointer; vertical-align: middle;
}
.help-tip:hover, .help-tip:focus-visible { color: var(--brand); background: var(--brand-soft); outline: none; }
.help-pop {
  /* The app resets every margin to 0, which undid the browser's own centring of a popover */
  margin: auto;
  max-width: min(340px, calc(100vw - 32px)); padding: var(--s3) var(--s4); border: 1px solid var(--rule); border-radius: 14px;
  background: var(--surface); color: var(--ink); box-shadow: 0 12px 40px rgba(21, 25, 15, .18); text-align: start; direction: rtl;
}
.help-pop::backdrop { background: rgba(21, 25, 15, .12); }
/* On a phone the card is centred above the bottom bar and never covers it: the top layer sits above every z-index */
@media (max-width: 959.98px) {
  .help-pop { max-height: calc(100dvh - var(--bottom-nav) - var(--bottom-gap) - 48px); overflow: auto; margin: auto auto calc(var(--bottom-nav) + var(--bottom-gap) + 12px); }
}
.help-pop strong { display: block; margin-bottom: 4px; color: var(--brand-deep); }
.help-pop p { margin: 0; line-height: 1.7; font-size: .92rem; color: var(--ink-2); }
.help-pop a { display: inline-block; margin-top: var(--s2); font-size: .85rem; color: var(--brand); }
/* A field group's formula (the owner, 2026-10-06): the formula a kind stands for, the functions' list, a result in the box */
.formula-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-size: .82rem; color: var(--ink-2); }
.formula-line code { direction: ltr; unicode-bidi: isolate; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--paper); border: 1px solid var(--rule); border-radius: 8px; padding: 2px 8px; }
.formula-help { font-size: .82rem; color: var(--ink-2); }
.formula-help summary { cursor: pointer; font-weight: 600; color: var(--brand); }
.formula-help table { width: 100%; border-collapse: collapse; margin-top: var(--s2); }
.formula-help td { padding: 4px 6px; border-top: 1px solid var(--rule); vertical-align: top; }
.formula-help td.ex { direction: ltr; text-align: left; unicode-bidi: isolate; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
.formula-help .help-scroll { overflow-x: auto; }
.result-box { border: 1px dashed var(--rule-firm); border-radius: 12px; padding: var(--s3); }
.group-result { display: flex; gap: var(--s2); align-items: baseline; font-size: .9rem; color: var(--ink-2); }
.group-result .v { font-weight: 700; color: var(--brand-deep); }
/* An attachment field (SCRUM-137): the template to download, the field's files as cards, a dashed zone that picks more */
.file-field { display: flex; flex-direction: column; gap: var(--s2); }
.file-drop {
  width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  padding: var(--s4) var(--s3); border: 1.5px dashed var(--rule-firm); border-radius: 14px;
  background: var(--surface); color: var(--ink-2); font: inherit; text-align: center; cursor: pointer;
  transition: border-color .15s, background-color .15s;
}
.file-drop:hover, .file-drop:focus-visible { border-color: var(--brand); background: var(--brand-soft); outline: none; }
.file-drop:disabled { opacity: .6; cursor: default; }
.file-drop .ico { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: var(--brand-soft); color: var(--brand); }
.file-drop .t { font-weight: 700; color: var(--ink); }
.file-drop .s { font-size: .76rem; color: var(--ink-3); }
.file-list { display: flex; flex-direction: column; gap: var(--s2); }
.file-chip { display: flex; align-items: center; gap: var(--s2); padding: 6px 12px; border: 1px solid var(--rule); border-radius: 12px; background: var(--surface); color: var(--brand); }
.file-chip.waiting { border-style: dashed; }
.file-chip .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-weight: 600; text-decoration: none; }
.file-chip .sz { font-size: .76rem; color: var(--ink-3); }
.template-card { display: flex; align-items: center; gap: var(--s3); padding: 10px 14px; border-radius: 12px; background: var(--wheat-soft); color: var(--brand-deep); text-decoration: none; }
.template-card .txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.template-card .t { font-weight: 700; }
.template-card .s { font-size: .76rem; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row { display: flex; align-items: center; gap: var(--s2); padding: 8px 0; border-bottom: 1px solid var(--rule); }
.file-row:last-child { border-bottom: 0; }
.file-row .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row .sz { font-size: .76rem; color: var(--ink-3); }

/* ── A step's photos ───────────────────────────────────────────── */
/* Square thumbnails with the server's time under each; the camera fills its dialog with a round shutter under it, and
   the shots not added yet below that, drawn by camera.js, each with its drop button and why it was not added */
.photo-strip { display: flex; flex-wrap: wrap; gap: var(--s3); margin-bottom: var(--s2); }
.photo { position: relative; width: 96px; margin: 0; }
.photo-open { display: block; width: 96px; height: 96px; padding: 0; overflow: hidden; border: 1px solid var(--rule); border-radius: 12px; background: var(--sunk); cursor: zoom-in; }
.photo-open img { display: block; width: 100%; height: 100%; object-fit: cover; }
.photo-open:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand); }
.photo figcaption { margin-top: var(--s1); font-size: .7rem; color: var(--ink-3); text-align: center; font-variant-numeric: tabular-nums; }
.photo-time { white-space: nowrap; }
.photo .photo-remove { position: absolute; top: var(--s1); inset-inline-end: var(--s1); background: var(--surface); box-shadow: var(--shadow-card); }
.photo-large { display: block; width: 100%; height: auto; border-radius: 12px; }
.photo-take { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); }
.photo-take .photo-final { flex-basis: 100%; }
.photo-count { font-size: .84rem; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.camera { display: grid; gap: var(--s3); padding-bottom: var(--s3); }
/* The whole frame shows (contain, not cover): what the shutter takes is what was seen */
.camera-view { display: block; width: 100%; min-height: 240px; max-height: 50vh; object-fit: contain; border-radius: 12px; background: #000; }
/* On a phone the shutter never moves under the thumb: the sheet is as tall as it may be from the start, so a shot listed
   under the shutter scrolls inside it instead of lifting it, and the picture's box is fixed, so the picture arriving does
   not push it down. The box is what the sheet leaves, so the shutter is in view as the window opens, even in Safari with
   its bars: the sheet's own limit, less the window around the picture (title 48, buttons 64, padding 16, the gap and the
   shutter 80, the counter's line 30, the camera's foot 12: 250px) and a little air */
@media (max-width: 599.98px) {
  .camera-sheet { height: var(--sheet-max); }
  .camera-view { min-height: 0; max-height: none; height: calc(var(--sheet-max) - 260px); }
}
.camera-view.camera-shot { animation: camera-shot .25s ease-out; }
@keyframes camera-shot { from { opacity: .15; } to { opacity: 1; } }
/* The shutter in the middle, the counter on its own line under it */
.camera-bar { display: grid; justify-items: center; gap: var(--s2); }
.camera-shutter { display: grid; place-items: center; width: 68px; height: 68px; padding: 0; border: 4px solid var(--brand); border-radius: 50%; background: var(--surface); color: var(--brand); cursor: pointer; }
.camera-shutter:active { transform: scale(.94); }
.camera-shutter:disabled { opacity: .4; cursor: default; }
.camera-list { display: flex; flex-wrap: wrap; gap: var(--s3); }
.camera-list:empty { display: none; }
/* Nothing listed (none taken yet, or the camera did not start): "إضافة" has nothing to add and reads as off */
.camera-sheet:has(.camera-list:empty) .camera-add { opacity: .38; pointer-events: none; }
.camera-list img { display: block; width: 96px; height: 96px; object-fit: cover; border: 1px solid var(--rule); border-radius: 12px; background: var(--sunk); }
/* 40px: the window opens on phones only, and a finger drops a shot from the corner of a 96px picture */
.camera-drop { position: absolute; top: var(--s1); inset-inline-end: var(--s1); display: grid; place-items: center; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 50%; background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card); font-size: 1rem; cursor: pointer; }
.camera-list .camera-why { color: var(--mud-palette-error); text-align: start; }
/* The camera that could not start again as the page came back: camera.js hides the dead picture and says why here */
.camera-view[hidden] { display: none; }
.camera-down { padding: var(--s3); border-radius: 12px; background: var(--sunk); color: var(--ink-2); font-size: .9rem; }
/* A step's photos and values of an earlier round (a returned request's step that came round again, a step the route
   dropped): history, never counted. Headed by a muted capsule, not a field's label, so it never reads as one more label */
.fact > .photos-earlier { align-self: flex-start; }
/* apart from what it follows ("قيم سابقة" opens its tile and needs none), and from what it heads: 2px of the tile's gap
   left the capsule touching the first label under it */
.fact > * + .photos-earlier, .fact > .photos-earlier + * { margin-top: var(--s2); }
.photos-earlier + .photo-strip img { opacity: .7; }
/* muted, still read before they are confirmed again: a shade apart from the labels, at a readable contrast, and plain
   weight where a collected value is bold */
.photos-earlier + .facts .v { color: var(--ink-2); font-weight: 400; }

/* ── Dynamic form grid ─────────────────────────────────────────── */
.form-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--s4) var(--s3); }
.form-grid > .field { grid-column: span 6; }
.form-grid > .field.short { grid-column: span 3; }
.form-grid > .field.wide { grid-column: 1 / -1; }
@media (max-width: 1099.98px) { .form-grid > .field.short { grid-column: span 6; } }
/* On a phone a short field keeps half the line: a date beside a count, a checkbox beside a checkbox */
@media (max-width: 759.98px) { .form-grid > .field { grid-column: 1 / -1; } .form-grid > .field.short { grid-column: span 6; } }
/* A version laid out in rows (the builder, SCRUM-153: FieldGroups.Layout): a row's fields share it equally, up to three,
   on the form and in the data view alike; a phone stacks every row. A version stored before rows flows by the rules above */
.facts.wrap.rows { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.form-grid > .field.cols-1, .facts.rows > .cols-1 { grid-column: 1 / -1; }
.form-grid > .field.cols-2, .facts.rows > .cols-2 { grid-column: span 6; }
.form-grid > .field.cols-3, .facts.rows > .cols-3 { grid-column: span 4; }
@media (max-width: 759.98px) { .form-grid > .field[class*="cols-"], .facts.rows > [class*="cols-"] { grid-column: 1 / -1; } }

/* ── Conditions editor ─────────────────────────────────────────── */
/* One condition = one aligned row: field, operator, value, remove. Never wrapped, so the rows line up. */
.cond { display: grid; grid-template-columns: minmax(0, 1.2fr) 7.5rem minmax(0, 1.2fr) auto; gap: var(--s2); align-items: center; }
.cond > .mud-input-control { min-width: 0; }
.conds { display: flex; flex-direction: column; gap: var(--s2); }
.cond-group { background: var(--sunk); border-radius: 12px; padding: var(--s3); }
.cond-or { display: flex; align-items: center; gap: var(--s3); margin: var(--s2) 0; font-size: .78rem; font-weight: 700; color: var(--ink-3); }
.cond-or::before, .cond-or::after { content: ""; flex: 1; border-top: 1px solid var(--rule-firm); }
@media (max-width: 599.98px) {
  /* The delete belongs to the whole condition: at its top corner beside the field, never centred against the
     comparison; the comparison and the value take the whole row (they left 60px empty beside them) */
  .cond { grid-template-columns: minmax(0, 1fr) auto; }
  .cond > .cond-field { grid-column: 1; }
  .cond > .cond-op, .cond > .cond-val { grid-column: 1 / -1; }
  .cond > .mud-icon-button { grid-column: 2; grid-row: 1; }
  /* Stacked, each row is its own card: otherwise nothing separates one condition's three fields from the next one's */
  .conds { gap: var(--s3); }
  .cond, .opt { background: var(--paper); border: 1px solid var(--rule); border-radius: 12px; padding: var(--s3); }
  .cond-group { padding: var(--s2); }
}
.conds-foot { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; font-size: .82rem; color: var(--ink-3); }

/* ── Admin and catalog editor ── */
/* A switched-off row: grey and struck. The library inks every body cell three classes deep, and a row's name is a
   button, an atomic box the cell's line-through never reaches, so the name carries the mark itself. */
.val-off, .mud-table-root .mud-table-body .mud-table-cell.val-off, .val-off .row-open { color: var(--ink-3); text-decoration: line-through; }
.row-tappable { cursor: pointer; }
.filter { flex: 1 1 240px; min-width: 0; }
.role-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); column-gap: var(--s3); }
.num-col { width: 8rem; font-variant-numeric: tabular-nums; }

/* Editor tables: fields inside cells align to the top */
.etable .mud-table-cell { vertical-align: top; }
.settings { display: flex; flex-direction: column; gap: var(--s3); }
.opts { display: flex; flex-direction: column; gap: var(--s2); }
.opt { display: grid; grid-template-columns: 1fr 1.4fr auto; gap: var(--s2); align-items: start; }
.opt.col { grid-template-columns: 1fr 1.2fr 1fr auto; }
.inline-row { display: flex; gap: var(--s2); align-items: flex-start; flex-wrap: wrap; }
.inline-row > .mud-input-control, .inline-row > .f-block { flex: 1 1 200px; min-width: 0; }
.row-icons { display: flex; flex: none; align-items: center; }
/* Beside labelled fields, the tools line up with the fields, not with their labels */
.inline-row > .row-icons { align-self: flex-end; }
.review-top:focus { outline: none; } /* focused by the page to bring it into view, never tabbed to */
.cond-wait { color: var(--ink-3); }
@media (max-width: 599.98px) {
  .opts { gap: var(--s3); }
  .opt, .opt.col { grid-template-columns: 1fr auto; }
  .opt > .mud-input-control, .opt > .inline-row { grid-column: 1; }
  .opt > .mud-icon-button { grid-column: 2; grid-row: 1; }
}
/* The route tab: a spine from submission to complete. A line runs down each node behind its dot to the next node,
   through the step's card and the "+" row under it; a step is one card read in words, tapped to open its dialog. */
.spine { display: grid; }
.spine-node { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: var(--s3); position: relative; }
.spine-node::before { content: ""; position: absolute; inset-inline-start: 18px; top: 0; bottom: 0; width: 2px; background: var(--rule-firm); }
.spine-node:last-child::before { content: none; }
.spine-dot {
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; position: relative; z-index: 1;
  background: var(--surface); border: 2px solid var(--rule-firm); color: var(--ink-2); font-weight: 700; font-size: .9rem;
}
/* Submission and complete: a mark, not a word (the card beside each says it), so no text is too small to read on a phone */
.spine-dot.ends { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); }
.spine-dot.ends .mud-icon-root { width: 18px; height: 18px; font-size: 18px; }
.spine-body { display: grid; min-width: 0; padding-block-end: var(--s3); }
.spine-card {
  display: grid; gap: var(--s2); min-width: 0; padding: var(--s3) var(--s4); border-radius: 16px;
  background: var(--surface); box-shadow: var(--shadow-card); border: 1px solid transparent; transition: border-color .15s;
}
.spine-card.row-tappable:hover, .spine-card.row-tappable:focus-within { border-color: var(--brand); }
/* The button that opens a card or a row: its title, drawn as text. The arrows sit beside it, never inside it. The library
   draws every button as a centred inline-flex box: a title button that fills its card read in the middle of it (the
   route's steps, the fields), so it starts where its card does */
.row-open, .link-button { padding: 0; margin: 0; border: 0; background: none; color: inherit; font: inherit; text-align: start; justify-content: flex-start; cursor: pointer; }
.link-button { text-decoration: underline; }
.row-open:focus-visible, .link-button:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }
.spine-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); min-width: 0; min-height: 34px; }
.spine-title { flex: 1 1 auto; min-width: 0; font-weight: 700; }
.spine-note { color: var(--ink-3); font-size: .85rem; }
.spine-tools { display: inline-flex; align-items: center; margin-inline-start: auto; color: var(--ink-3); }
.spine-when { color: var(--ink-2); font-size: .88rem; }
.spine-chips { display: flex; flex-wrap: wrap; gap: var(--s2); }
.spine-chips .pill, .field-chips .pill { white-space: normal; }
/* Between two cards, one small "+" on the spine's line (a native details element: it opens in the browser), its two
   choices beside it once open. The gap carries the line on, as a node does */
.spine-gap { position: relative; display: block; padding-block: var(--s1); }
.spine-gap::before { content: ""; position: absolute; inset-inline-start: 18px; top: 0; bottom: 0; width: 2px; background: var(--rule-firm); }
.gap-plus {
  position: relative; z-index: 1; display: inline-grid; place-items: center; width: 26px; height: 26px; margin-inline-start: 6px;
  border-radius: 50%; background: var(--surface); border: 1px solid var(--rule-firm); color: var(--brand); cursor: pointer; list-style: none;
}
.gap-plus::-webkit-details-marker { display: none; }
.gap-plus:hover, .gap-plus:focus-visible { border-color: var(--brand); outline: none; }
.spine-gap[open] > .gap-plus { background: var(--brand); border-color: var(--brand); color: #fff; }
.gap-menu { display: inline-flex; flex-wrap: wrap; gap: var(--s1); margin-inline-start: var(--s3); vertical-align: middle; }
/* A step has no number of its own: one on every request's route has a solid dot, a conditional one a hollow dot and a
   dashed card. The route preview numbers the steps a request with its values takes and dims the rest. */
.spine-dot.mark { width: 14px; height: 14px; justify-self: center; margin-block-start: var(--s3); background: var(--ink-2); border-color: var(--ink-2); }
.spine-dot.mark.conditional { background: var(--surface); }
.spine-dot.lit { background: var(--brand); border-color: var(--brand); color: #fff; }
.spine-card.conditional { border: 1px dashed var(--rule-firm); }
.spine-node.off .spine-card { opacity: .5; }
.route-preview { display: grid; justify-items: start; gap: var(--s3); padding-block-end: var(--s4); }
.route-preview-panel { display: grid; gap: var(--s3); justify-self: stretch; padding: var(--s3) var(--s4); border-radius: 16px; background: var(--sunk); }
.route-preview-says { font-weight: 700; }
/* On a phone the dot narrows, and a step's title takes its own line under its kind and its arrows */
@media (max-width: 599.98px) {
  .spine-node { grid-template-columns: 30px minmax(0, 1fr); gap: var(--s2); }
  .spine-node::before, .spine-gap::before { inset-inline-start: 14px; }
  .gap-plus { margin-inline-start: 2px; }
  .spine-dot { width: 30px; height: 30px; font-size: .8rem; }
  .spine-card { padding: var(--s3); }
  .route-preview-panel { padding: var(--s3); }
  .spine-card.row-tappable .spine-title { order: 1; flex-basis: 100%; }
}
/* The canvas «النموذج والمسار» (SCRUM-153): under each moment's card its fields, in the rows the request form draws. A
   field is one card read as its label, its type and its key (small, under the label), tapped to open its dialog; a row's
   cards share it equally, up to three, and a phone stacks them on the row's own rail. A card is dragged by its grip
   (canvas.js): the grip takes no touch scrolling, the card left behind fades, a copy follows the pointer, and a bar marks
   where it lands (beside a card, or a new row above or below one) */
.stage { display: grid; gap: var(--s2); min-width: 0; }
/* A card's fields sit inside it, under its words, on a sunk ground: the card is the moment, the rows are what it asks */
.card-fields { min-width: 0; padding-block-start: var(--s1); cursor: default; }
.card-fields .field-row { background: var(--sunk); box-shadow: none; }
.spine-card.row-tappable:has(.card-fields:hover) { border-color: transparent; }
/* A field's relationships in words, under its label: one short line each */
.field-rels { grid-column: 1 / -1; display: grid; gap: 2px; color: var(--ink-2); font-size: .82rem; }
/* A tap on a card lights it, the fields it reads and those that read it (canvas.js); the rest is drawn dim */
.canvas.lighting .canvas-cell[data-key]:not(.lit):not(.linked) > .field-row { opacity: .45; }
.canvas-cell.lit > .field-row { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.canvas-cell.linked > .field-row { border-color: var(--brand); background: var(--brand-soft); }
.spine-card.linked { border-color: var(--brand); }
.stage-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2); }
.canvas-rows { display: grid; gap: var(--s2); min-width: 0; }
.canvas-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s2); min-width: 0; }
.canvas-row.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.canvas-row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.canvas-cell { position: relative; min-width: 0; }
.canvas-row.cols-2 .field-row, .canvas-row.cols-3 .field-row { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); }
.canvas-row.cols-2 .field-chips, .canvas-row.cols-3 .field-chips { grid-column: 1 / -1; grid-row: 2; }
.drag-grip { display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; cursor: grab; touch-action: none; color: var(--ink-3); }
.drag-grip:hover { background: var(--sunk); color: var(--ink); }
.canvas.dragging { user-select: none; cursor: grabbing; }
.canvas.dragging .canvas-rows[data-zone="top"] { min-height: 44px; border-radius: 12px; outline: 1px dashed var(--rule-firm); outline-offset: 2px; }
.drag-source { opacity: .35; }
.drag-ghost { position: fixed; top: 0; left: 0; z-index: 1500; pointer-events: none; opacity: .92; box-shadow: var(--shadow-card); border-radius: 12px; }
.canvas-row.drop-above, .canvas-row.drop-below { position: relative; }
.drop-before::after, .drop-after::after, .drop-above::after, .drop-below::after {
  content: ""; position: absolute; z-index: 2; border-radius: 2px; background: var(--brand); pointer-events: none;
}
.drop-before::after { inset-block: 0; inset-inline-start: -6px; width: 3px; }
.drop-after::after { inset-block: 0; inset-inline-end: -6px; width: 3px; }
.drop-above::after { inset-inline: 0; top: -6px; height: 3px; }
.drop-below::after { inset-inline: 0; bottom: -6px; height: 3px; }
.drop-into { outline: 2px solid var(--brand); }
@media (max-width: 599.98px) {
  .canvas-row.cols-2, .canvas-row.cols-3 { grid-template-columns: minmax(0, 1fr); padding-inline-start: var(--s2); border-inline-start: 2px solid var(--brand); }
  .drop-before::after { inset-inline: 0; inset-block: -6px auto; width: auto; height: 3px; }
  .drop-after::after { inset-inline: 0; inset-block: auto -6px; width: auto; height: 3px; }
}
.field-row {
  display: grid; grid-template-columns: minmax(0, max-content) minmax(0, 1fr) auto; align-items: center; gap: var(--s3); min-width: 0;
  padding: var(--s2) var(--s4); border-radius: 12px; background: var(--surface); box-shadow: var(--shadow-card);
  border: 1px solid transparent; transition: border-color .15s;
}
.field-row:hover, .field-row:focus-within { border-color: var(--brand); }
/* A field group (a field of type "مجموعة حقول"): in the fields tab its row, its fields under it on a rule at the start;
   its fields picked as chips in its dialog; on the request form and in the data view, one box under its title */
.check-fields { display: flex; flex-wrap: wrap; gap: var(--s1); }
/* A chip holds a field's name (and its key while a formula is written): a long one wraps inside the chip's border.
   The library draws a chip one line high and never wraps it, so a key ran past the edge of a phone's screen */
.check-fields .mud-chip { height: auto; white-space: normal; padding-block: var(--s1); }
.check-fields .mud-chip > .mud-chip-content { display: block; min-width: 0; overflow-wrap: anywhere; }
.check-fields .mud-chip .mud-chip-icon { vertical-align: middle; }
/* A group is one box: its rail on the start side (the right in Arabic) runs from its title down its fields */
.field-group-block { display: grid; gap: var(--s2); padding: var(--s2); padding-inline-start: var(--s3); border-radius: 12px; border-inline-start: 3px solid var(--brand); background: var(--brand-soft); }
.field-group-block > .group-row, .card-fields .field-group-block > .group-row { background: transparent; box-shadow: none; padding-inline: var(--s1); }
.group-members { display: grid; gap: var(--s2); }
.card-fields .group-members .field-row { background: var(--surface); }
.field-group { min-width: 0; margin: 0; padding: var(--s3) var(--s4) var(--s4); border: 1px solid var(--rule); border-radius: 12px; }
.field-group > legend { padding-inline: var(--s1); font-weight: 600; font-size: .95rem; }
.fact-group { display: grid; gap: var(--s2); padding: var(--s3); border: 1px solid var(--rule); border-radius: 12px; }
/* The name is a button (a keyboard opens the field too): a button shrinks to its text and sits in the middle of its
   cell, so it is told to fill the cell and read from the start, the type badge right after it, the arrows at the end */
.field-name { display: grid; justify-content: start; justify-items: start; justify-self: stretch; width: 100%; min-width: 0; }
.field-label { font-weight: 600; overflow-wrap: anywhere; }
.field-key { justify-self: start; font-size: .74rem; color: var(--ink-3); }
.field-chips { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: var(--s1); }
/* On a phone the chips take their own line under the label and the arrows */
@media (max-width: 599.98px) {
  .field-row { grid-template-columns: minmax(0, 1fr) auto; gap: var(--s1) var(--s3); padding: var(--s2) var(--s3); }
  .field-chips { grid-column: 1 / -1; grid-row: 2; justify-content: flex-start; }
}
/* The tab bar sticks under the top bar so it is not lost on a long page */
.editor-tabs .mud-tabs-tabbar { position: sticky; top: 56px; z-index: 2; background: var(--paper); }
/* The library's slider is placed by measuring the tabs, and in RTL with scroll arrows it stayed under the tab active
   before: the active tab draws its own line */
.editor-tabs .mud-tab-active { box-shadow: inset 0 -2px 0 var(--brand); border-radius: 0; }

/* Permissions matrix: scrolls horizontally with a pinned name column */
.perm-wrap { overflow-x: auto; }
.perm-table th, .perm-table td { white-space: nowrap; }
.perm-name { position: sticky; inset-inline-start: 0; background: var(--surface); z-index: 1; min-width: 200px; }
/* A permission says what it lets its holders do under its name: read by comparing rows, never behind a tap per row */
.perm-name .perm-help { display: block; max-width: 200px; white-space: normal; font-size: .76rem; font-weight: 400; color: var(--ink-2); }
.perm-role { text-align: center; font-weight: 600; }
.perm-cell { text-align: center; }
/* A cell's box is a plain check box drawn as the library's dense MudCheckBox was: the same two icons as masks in the
   primary colour, in a 32px round button at the cell's start with its round hover (SCRUM-148) */
.perm-box { display: flex; justify-content: center; align-items: center; width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
  transition: background-color .2s; }
.perm-box:hover, .perm-box:has(:focus-visible) { background-color: var(--mud-palette-primary-hover); }
.perm-box input { appearance: none; margin: 0; width: 24px; height: 24px; cursor: pointer; outline: none; background: var(--mud-palette-primary);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E") center / 24px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E") center / 24px no-repeat; }
.perm-box input:checked {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z'/%3E%3C/svg%3E"); }
.perm-box:has(:disabled) { cursor: default; background-color: transparent; }
.perm-box input:disabled { cursor: default; background: var(--mud-palette-action-disabled); }

/* Admin dashboard: horizontal bars */
.bars { display: flex; flex-direction: column; gap: var(--s2); }
.bar-row { display: grid; grid-template-columns: minmax(120px, 1fr) 3rem 2fr; gap: var(--s3); align-items: center; }
.bar-row .mud-chip { justify-self: start; }
.bar-n { font-variant-numeric: tabular-nums; font-weight: 600; text-align: center; }
.bar-label { display: flex; flex-direction: column; min-width: 0; }
.bar-label > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-sub { font-size: .8rem; color: var(--ink-3); }
@media (max-width: 599.98px) {
  .bar-row { grid-template-columns: 1fr 3rem; }
  .bar-row .mud-progress-linear { grid-column: 1 / -1; }
}

/* Lookup lists: chips scroll horizontally on phones */
.list-keys { display: flex; flex-wrap: nowrap; overflow-x: auto; gap: var(--s1); padding-bottom: var(--s1); scrollbar-width: none; }
@media (min-width: 600px) { .list-keys { flex-wrap: wrap; } }
.chip-n { font-size: .75rem; opacity: .7; margin-inline-start: var(--s1); }

/* Dynamic form and row table */
.datetime-pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
/* At 390px half a row clipped the date ("2026/10/0"): the day and the time each take the row */
@media (max-width: 599.98px) { .datetime-pair { grid-template-columns: 1fr; } }
.field-check { margin-top: var(--s2); }
.check-row { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); }
.row-card { padding: var(--s3); margin-bottom: var(--s2); }
.row-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--s2); color: var(--ink-3); font-size: .85rem; }
.row-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--s2); }

/* Editor tabs on phones: no 160px minimum and no icons, otherwise only one tab shows */
@media (max-width: 599.98px) {
  .editor-tabs .mud-tab { min-width: 0 !important; padding: 0 var(--s3); }
  .editor-tabs .mud-tab .mud-icon-root { display: none; }
}

/* Second guard on top of MudHidden: before the server knows the screen width, everything is rendered */
/* The frame: both are in the page the server sends, and the width alone picks one. MudHidden drew neither until a
   script had measured the screen, several round trips after the page appeared (SCRUM-147 C1). The library's own
   breakpoint is 960px. */
@media (min-width: 960px) { .bottom-nav, .more-sheet, .panel-scrim, .phone-only { display: none !important; } }
@media (max-width: 959.98px) { .mud-drawer.side, .desk-only { display: none !important; } }

@keyframes sheet-up { from { transform: translateY(48px); opacity: 0; } to { transform: none; opacity: 1; } }
/* ── Reports (SCRUM-132) ──────────────────────────────────────────
   The views bar, the filters, the tools and the table. The table scrolls sideways inside its own box: a report is as
   wide as the columns chosen, and the page itself never scrolls sideways. */
/* The report's three zones: the top strip (saved views, export), the search with the filters the viewer added (one line
   each, the rest offered as chips under "إضافة تصفية"), the display row (grouping as a segmented control, order,
   columns, the count). Nothing is laid out that the viewer did not ask for. */
.report-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s2) var(--s3); padding-block: var(--s2) var(--s3); }
.report-views { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); flex: 1 1 320px; min-width: 0; }
.report-views-icon { color: var(--ink-3); }
.report-views > .mud-select { flex: 0 1 300px; min-width: 0; }
.report-views-actions { display: flex; flex-wrap: wrap; gap: var(--s1); }
.report-where { display: grid; gap: var(--s2); }
.report-where-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.report-where-actions > .filter { flex: 1 1 280px; min-width: 0; }
.report-conds { display: grid; gap: var(--s2); padding: var(--s3); border: 1px solid var(--rule); border-radius: var(--r-card); background: var(--surface); }
.report-cond { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); }
.report-offer { display: flex; flex-wrap: wrap; gap: var(--s1); }
.report-cond-name { flex: 0 0 120px; font-weight: 600; font-size: .9rem; }
.report-cond-value { flex: 0 1 360px; min-width: 0; }
.report-cond > .mud-icon-button { margin-inline-start: auto; }
.report-range { display: flex; align-items: center; gap: var(--s2); }
.report-range > .mud-picker { flex: 1 1 0; min-width: 0; }
.report-display { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); padding-block: var(--s3); }
.report-group { display: flex; align-items: center; gap: var(--s2); min-width: 0; max-width: 100%; }
.report-group > .mud-toggle-group { overflow-x: auto; max-width: 100%; }
/* The library splits the group into equal columns inline; a grouping's name keeps its own width instead */
.report-group > .mud-toggle-group { grid-template-columns: none !important; grid-auto-flow: column; grid-auto-columns: max-content; }
.report-group > .mud-toggle-group > .mud-toggle-item.mud-button-root { white-space: nowrap; padding-inline: var(--s2); }
.report-label { color: var(--ink-3); font-size: .85rem; white-space: nowrap; }
.report-order { display: flex; align-items: center; gap: var(--s1); }
.report-order > .mud-select { flex: 0 1 180px; min-width: 140px; }
.report-display .report-count { margin-inline-start: auto; padding-block: 0; }
@media (max-width: 599px) {
  /* A phone: the saved views beside their save, the export a line of its own, a condition's value under its name */
  .report-views > .mud-select { flex: 1 1 0; min-width: 120px; }
  .report-bar > .mud-button-root { flex: 1 1 100%; }
  .report-cond-name { flex: 1 1 auto; }
  .report-cond-value { flex: 1 1 100%; order: 3; }
  .report-group { flex-wrap: wrap; width: 100%; }
}
.report-count { color: var(--ink-3); font-size: .85rem; padding-block: 0 var(--s2); }
.report-grid { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--r-card); background: var(--surface); }
/* A report's own table (ReportTable): a cell keeps its line and the box scrolls sideways, on a phone too */
.report-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.report-table th { padding: var(--s2) var(--s3); text-align: start; font-weight: 600; color: var(--ink-2); white-space: nowrap; border-bottom: 1px solid var(--rule); }
.report-table td { padding: var(--s2) var(--s3); white-space: nowrap; border-bottom: 1px solid var(--rule); }
.report-table tbody tr:last-child td { border-bottom: 0; }
.report-table tbody tr:hover { background: var(--brand-soft); }
.report-columns { display: grid; gap: var(--s1); }
/* E-mail templates ("دليل الخدمات" → "رسائل البريد"): the tokens a template may carry, and its preview with sample words */
.email-tokens { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
.email-preview { display: grid; gap: var(--s1); padding: var(--s3); border: 1px dashed var(--rule); border-radius: 12px; }
.email-preview-subject { font-weight: 600; }
.email-preview-body { white-space: pre-line; font-size: .9rem; color: var(--ink-2); }
.report-column { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); border-bottom: 1px solid var(--rule); }
.report-column.off { color: var(--ink-2); }
/* ── A phone's graphics chip ──────────────────────────────────────
   The frosted bars re-blur everything that moves under them on every frame, the entry animation staggers each block of
   every page, and a few decorations never stop: a desktop does not notice, a phone drops frames (reported from a real
   phone, 2026-10-01). Under 960px the bars are plain, content enters quickly and at once, and the decorations hold
   still. At rest the page looks the same. */
@media (max-width: 959.98px) {
  .mud-appbar.topbar, .mud-appbar.bottom-nav { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(255,255,255,.97); }
  /* A fixed background is repainted on every frame of a scroll on Android; scrolled with the page it is drawn once (C9),
     and drawn once only: repeated, its glows started again below a short page */
  body { background-attachment: scroll; background-repeat: no-repeat; }
  .app-content > * { animation-duration: .22s; }
  .app-content > :nth-child(n) { animation-delay: 0s; }
  .login-wrap::before, .chain li.now .dot { animation: none; }
  .map-room.free { animation: map-in .25s var(--ease) backwards; }
  /* An iPhone zooms the page into any field whose text is smaller than 16px when it takes the focus, and stays
     zoomed. The app's text is 15.2px, so every field did it. On a phone every field's text is 16px: the library's,
     the reference-number fields (mono) and the login card's own. */
  .mud-input, .mud-input-slot, .mud-input > input, .mud-input > textarea, .mono input, .mono textarea, .login-card input { font-size: 16px; }
}

/* ── A finger's size ──────────────────────────────────────────────
   The library's small buttons are 30px, under a finger's size: under 960px every one is at least 40px (the arrows of
   the editor's cards and rows, a deadline rule's tools, a photo's remove, the small text buttons). One rule, never per page. The bell's list keeps
   the page's 16px gutter on both sides of a phone: anchored to the bell, it ran to the screen's right edge. On a phone
   it hangs from the bar itself (the library's toolbar is positioned), so it sits under the bar whatever height the
   library gives it (49px upright, 42px on its side), never under a height written here. The toolbar sits inside the
   bar's own --s3 padding, so the gutter is measured from there: --s4 alone left 28px. */
@media (max-width: 959.98px) {
  .mud-icon-button.mud-icon-button-size-small { padding: 10px; }
  /* and the small text buttons (the route's "+ اعتماد", a condition's "شرط", "اليوم") and the rooms' duration chips: 31 and 36px */
  .mud-button-text-size-small, .mud-button-outlined-size-small, .mud-button-filled-size-small, .dur { min-height: 40px; }
}
@media (max-width: 599.98px) {
  .bell { position: static; }
  .bell-panel { inset-inline: calc(var(--s4) - var(--s3)); width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .more-sheet, .panel-scrim, .bell-panel, .bnav-ico, .svc, .req-go, .mud-button-root, .map-room, .map-floor, .map-tip { transition: none !important; }
  .mud-dialog, .app-content > *, .login-card, .login-wrap::before, .chain li.now .dot, .pill .dot, .map-room { animation: none !important; }
}

/* The one progress bar, at the top edge of every page (App.razor). Three reasons to show it: the page is drawn but
   not connected yet (connecting), a question to the server is out (pending), or the server says it is busy
   (.server-busy in the main layout). The first two are set by the browser, the only side that can speak on a slow
   line. Each waits 250 ms first, so a fast answer shows nothing: the script counts it for "pending" (only the time a
   question is unanswered), the stylesheet for the other two. A page that never connects stops the bar after 20 seconds. */
.wait-bar { display: none; position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 2000; height: 3px; overflow: hidden; pointer-events: none; background: var(--gold-line); }
.wait-bar::after { content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; width: 40%; background: var(--gold); animation: wait-slide 1.1s ease-in-out infinite; }
html.connecting .wait-bar, html:has(.server-busy:not([hidden])) .wait-bar { display: block; animation: fade-in 0s 250ms both; }
html.connecting:not(:has(.server-busy:not([hidden]))) .wait-bar { animation: fade-in 0s 250ms both, give-up 0s 20s forwards; }
html.pending .wait-bar { display: block; animation: none; }
@keyframes wait-slide { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
[dir="rtl"] .wait-bar::after { animation-name: wait-slide-rtl; }
@keyframes wait-slide-rtl { from { transform: translateX(100%); } to { transform: translateX(-250%); } }
@keyframes give-up { to { visibility: hidden; } }
html.pending, html.pending body { cursor: progress; }
/* The control that was tapped stops taking taps at once, and dims when the bar shows */
.is-pending { pointer-events: none; }
html.pending .is-pending { opacity: .6; }
.loading-block { display: grid; gap: var(--s2); }
/* Which build is this: the side menu, the phone's "more" sheet and the login card end with it */
.app-version { color: var(--ink-3); font-size: .75rem; text-align: center; }
.login-card .app-version { margin-top: var(--s4); }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Editor tables on phones: the label above the field, not beside it — the field needs the full width,
   and the "party" label next to the select left it a third of the screen */
/* MudTable always sets mud-sm-table and scopes phone behaviour to a media query — our rule is scoped the same way,
   otherwise table cells turn into blocks on desktop too */
@media (max-width: 599.98px) {
  .mud-sm-table.etable .mud-table-cell { display: block; padding: var(--s2); }
  .mud-sm-table.etable .mud-table-cell::before {
    display: block; padding: 0; margin-bottom: var(--s1);
    font-size: .74rem; font-weight: 600; color: var(--ink-3);
  }
  .mud-sm-table.etable .mud-table-cell:not([data-label])::before { content: none; }
  .mud-sm-table.etable .mud-table-cell .mud-input-control { width: 100%; }
  /* Each row is a card of its own, so one row's stacked fields are not read as the next row's.
     Two columns: a text field or a select takes the whole line; a time, a number, a checkbox, a name or the
     buttons take half, so a short control never leaves the other half of its line empty. */
  .mud-sm-table.etable .mud-table-row { display: grid; grid-template-columns: 1fr 1fr; align-items: center; border: 1px solid var(--rule); border-radius: 12px; margin: var(--s3); padding: var(--s2) var(--s1); }
  .mud-sm-table.etable .mud-table-row .mud-table-cell { border-bottom: none; }
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control), .mud-sm-table.etable .mud-table-cell:has(.conds) { grid-column: 1 / -1; }
  .mud-sm-table.etable .mud-table-cell:has(.mud-picker), .mud-sm-table.etable .mud-table-cell:has(.mud-input-number-control),
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input) { grid-column: auto; }
  /* A checkbox reads as "label ☑" on one line, the box at the reading edge, like the library's own labelled checkbox */
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input) { display: flex; flex-direction: row-reverse; justify-content: flex-end; align-items: center; gap: var(--s1); }
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input)::before { margin: 0; font-size: .9rem; font-weight: 400; color: var(--ink); }
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input)::before { white-space: nowrap; }
  .mud-sm-table.etable .mud-table-cell .mud-input-control-boolean-input { width: auto; flex: none; }
  /* The lines above are for a cell whose one control is the checkbox. A cell holding a checkbox among other fields (a
     route step: its kind, name, holder and "لا رجوع") stacks them on the whole line like any other cell */
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input):has(.mud-input-control:not(.mud-input-control-boolean-input)) { display: block; grid-column: 1 / -1; }
  .mud-sm-table.etable .mud-table-cell:has(.mud-input-control-boolean-input):has(.mud-input-control:not(.mud-input-control-boolean-input))::before {
    margin: 0 0 var(--s1); font-size: .74rem; font-weight: 600; color: var(--ink-3); white-space: normal;
  }
  .mud-sm-table.etable .cell-head { font-weight: 700; }
  /* Half a line is too narrow for "07:30 ص" beside a clock icon; the field opens on tap without it */
  .mud-sm-table.etable .mud-picker .mud-input-adornment { display: none; }
}

/* The attach button inside MudFileUpload used to stretch across the whole page */
.mud-file-upload .mud-button-root { align-self: flex-start; }

/* The framework's own line when a page breaks (it shows #blazor-error-ui): without it a broken page froze with no word.
   At the top, under the bar, so the phone's bottom bar never covers it. */
#blazor-error-ui { display: none; position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 1999; padding: var(--s3) var(--s4); background: var(--surface); color: var(--ink); box-shadow: var(--shadow-card); text-align: center; }
#blazor-error-ui .reload { margin-inline-start: var(--s2); color: var(--brand); font-weight: 700; }
