*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Accessibility: skip navigation ── */
.skip-to-main {
  position: absolute;
  top: -100px;
  inset-inline-start: 0;
  z-index: 100000;
  background: var(--accent);
  color: var(--accent-text);
  padding: .75rem 1.5rem;
  border-radius: 0 0 8px 0;
  font-size: .9rem;
  text-decoration: none;
  transition: top .2s;
}
.skip-to-main:focus {
  top: 0;
}

/* ── Global custom scrollbar ── */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--accent) transparent;
}
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--accent);
  border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--accent-h);
}

:root {
  /* How far the floating-FAB rail sits from the inline-end edge, BEFORE the
     scrollbar gutter measured into --fab-gutter is added on top. One knob for
     all three FABs (.dap-fab / .feedback-fab / .a11y-fab) — nudge here. */
  --fab-inset: 28px;

  /* ── Floating-FAB rail: vertical slots ────────────────────────────────
     The three FABs stack up the same inline-end edge, so each needs its OWN
     slot. They did not have one: .feedback-fab and .a11y-fab were both
     bottom:100px at the same inset, so the one painted first was permanently
     unclickable — at every screen size, not just on mobile. Nothing caught it
     because each rule is correct in isolation; only the pair is wrong.

     Slots are derived, not hand-typed, so adding a fourth FAB is one line and
     cannot silently land on top of an existing one. --fab-slot is the rail's
     PITCH, not any button's own size: .a11y-fab is 52px while the others are
     48px, and the pitch has to clear the tallest of them plus the gap.

     NOTE, because it changes what this is worth: _adjustFabStack() in app.js
     assigns each FAB an inline `bottom` on load, computed from the same base and
     gap using real rendered heights. So the buttons were never actually on top of
     each other in a browser -- the stylesheet was simply lying about where they
     go, saying 100/100 while the script said 100/160. What these variables buy is
     a correct pre-JS paint, a sane fallback if the script never runs, and one
     place to change the rail instead of two that drift. If you edit the numbers
     here, edit _FAB_BASE / _FAB_GAP in app.js to match. */
  --fab-size: 48px;
  --fab-gap: 12px;
  --fab-slot: calc(var(--fab-size) + var(--fab-gap));
  --fab-base: 40px;
  --fab-slot-1: var(--fab-base);
  --fab-slot-2: calc(var(--fab-base) + var(--fab-slot));
  --fab-slot-3: calc(var(--fab-base) + var(--fab-slot) * 2);

  /* ── Viewport breakpoints ──────────────────────────────────────────────
     Media-query preludes cannot read custom properties, so these are a
     convention plus a guard, not a language feature. They exist so JS can read
     the SAME number the CSS uses instead of hardcoding its own: the app had 21
     width queries across 7 different widths (480/500/600/640/768/900/980) and
     four unrelated JS checks (a UA regex, innerWidth<=768, a bespoke
     matchMedia+touch+1024, and a class lookup), which is how "is this mobile"
     came to have four different answers.

     --bp-compact is 767.98 rather than 768 so a 768pt tablet in portrait counts
     as wide, matching how the platform's own size classes split.

     PARTIALLY MIGRATED, 2026-08-25. The seven `max-width: 768px` queries now read
     767.98px, so nine queries agree on --bp-compact where two did before. That was
     not cosmetic: at exactly 768px the app used to apply SOME mobile rules and not
     others -- the modal viewport cap and the iOS-zoom guard were already on 767.98
     and correctly stayed off, while seven others switched on. One viewport width,
     two answers, which is the same defect this token block was created to end.

     The behaviour change is confined to a viewport of exactly 768px, which now gets
     the wide layout -- the stated intent above. No `min-width` query pairs with 768
     (the only one is 641px, matched to its own 640px), so no width band was left
     uncovered.

     The remaining widths -- 480/500/600/640/900/980 -- are NOT pending migration.
     They express different design intents at different sizes; folding them onto
     767.98 would change what those rules do rather than where they fire, which is a
     per-rule design decision and not a mechanical sweep. Guarded by
     tests/test_mobile_detection_single_source.py and the width ratchet in
     tests/test_breakpoint_consolidation_ratchet.py. */
  --bp-compact: 767.98px;
  --bp-roomy: 1024px;

  /* ── Typography scale (WOW-UX review #4) ────────────────────────────────
     No h1-h6 element rule existed at all -- every heading was either the
     browser's UA default or hand-styled inline/via a bespoke class (660
     font-size declarations app-wide, 62 distinct values -- its own separate
     problem, deliberately not touched here). These tokens + the h1-h4 rules
     below give an otherwise-unstyled heading a real, consistent baseline
     instead of the browser default; anything already carrying its own class
     or inline font-size keeps winning on specificity, so this is purely
     additive -- zero of the 660 existing declarations touched.

     Values are the already-most-common size at each tier among the existing
     62 (not new arbitrary numbers) -- --fs-sm's .85rem alone already
     accounts for 76 of the 660 declarations -- so a new heading doesn't
     suddenly look foreign next to what's already on screen. No margin
     token: the global `* { margin: 0 }` reset (line 1) stays authoritative,
     since every current heading's spacing already comes from its own
     layout/padding, not a heading margin -- adding one here would be a
     layout change, not a typography one. */
  --fs-xs:   .7rem;    /* fine print / dense labels */
  --fs-sm:   .85rem;   /* secondary text -- the single most-used size app-wide */
  --fs-base: 1rem;     /* body */
  --fs-md:   1.2rem;   /* h4 */
  --fs-lg:   1.4rem;   /* h3 */
  --fs-xl:   1.8rem;   /* h2 */
  --fs-2xl:  2.5rem;   /* h1 */

  /* ── Safe area + keyboard ──────────────────────────────────────────────
     env() resolves to 0 on every desktop browser and on any phone without a
     notch, so referencing these costs nothing where they do not apply -- which
     is why the consumers below are plain rules rather than media-query-scoped
     ones. They only report real numbers once the viewport meta carries
     viewport-fit=cover (templates/partials/_head.html); the two halves must ship
     together or the page paints under the system chrome with nothing reserving
     space for it.

     --kb is the on-screen keyboard's height, written by app.js from
     window.visualViewport. CSS cannot observe the keyboard at all: on Android it
     shrinks the layout viewport, on iOS it does not, and neither fires a resize
     you can style on. Bottom-anchored things translate by it. */
  --sa-t: env(safe-area-inset-top, 0px);
  --sa-b: env(safe-area-inset-bottom, 0px);
  --sa-s: env(safe-area-inset-left, 0px);
  --sa-e: env(safe-area-inset-right, 0px);
  --kb: 0px;

  /* Default theme = Quantum brand identity (navy + gold, from logo-he.svg).
     The light theme overrides these via [data-theme="light"]. */
  --bg:       #070E1C;
  --surface:  #0f1f3a;
  --border:   #22406e;
  --accent:   #4C9AFF;
  --accent-rgb: 76,154,255;
  --accent-h: #73B0FF;
  --accent-h-rgb: 115,176,255;
  --accent-lt: #A9CCFF;
  --accent-lt-rgb: 169,204,255;
  /* Dedicated AI-content marker (Signature WOW B, WOW-UX review): distinct from
     --accent on purpose -- every AI-touched surface (chat, translate, summaries)
     used to improvise its own color/icon with nothing shared. Violet reads clearly
     apart from this theme's blue accent; each theme below picks its own violet so
     it never blends into that theme's OWN accent (light theme's accent is already
     indigo). High-contrast themes deliberately alias this to their own --accent --
     they carry a small, curated palette and lean on the sparkle icon + "AI" badge
     for the signal instead of an extra hue. */
  --ai-accent: #a78bfa;
  --ai-accent-rgb: 167,139,250;
  /* Darker companion shade for the chat mascot's gradient/limbs (Stage 2b) --
     reuses the mascot's own original darkest hand-picked stop, now a real
     token instead of a hardcoded, theme-blind hex value. */
  --ai-accent-dark: #5b3fa0;
  --text:     #E8EEF8;
  --muted:    #8ea3c4;
  --danger:   #ff5b52;
  --success:  #3ddc97;
  --success-rgb: 61,220,151;
  --warn:     #E39A3A;
  --warn-rgb: 227,154,58;
  /* UI-0016 (quality-audit): --warning/--warning-rgb/--info were referenced
     by ~25 call sites across 8 JS files (settings/facilities/forum/personal/
     reports/vehicles/voting/admin-users) via var(--x, #fallback) but never
     actually declared anywhere -- every one of those calls always silently
     rendered its hardcoded fallback regardless of theme. Aliased to the
     already-declared, per-theme-tuned --warn/--accent instead of hunting
     down and rewriting every call site individually. */
  --warning:     var(--warn);
  --warning-rgb: var(--warn-rgb);
  --info:        var(--accent);
  /* UI-0004 (quality-audit): notif-bell icon colors with no theme token of
     their own (bulletin_sh/message) -- kept next to --warn/--success since
     all 3 exist only to give .notif-icon.* a theme-scoped source. */
  --notif-purple: #8b5cf6;
  --notif-purple-rgb: 139,92,246;
  --notif-blue: #3b82f6;
  --notif-blue-rgb: 59,130,246;
  /* UI-0042 (quality-audit): the unified-search "matched column" badges hardcoded
     a light pastel hex palette with no theme token -- unlike the adjacent
     help-result badge, which already used notif-purple/rgba. Only 2 genuinely new
     hues were needed (search's other 3 categories reuse success/warn/notif-blue). */
  --search-pink: #f472b6;
  --search-pink-rgb: 244,114,182;
  --search-indigo: #818cf8;
  --search-indigo-rgb: 129,140,248;
  /* UI-0039 (quality-audit): the evacuation status legend/grid/group-list used 8
     hardcoded hex swatches with no theme token of their own — none of the app's
     existing 4-5 generic semantic colors (success/warn/danger/muted) has room
     for 8 distinct evacuation-specific meanings at once. */
  --evac-evacuated-self:     #4caf50;
  --evac-evacuated-org:      #66bb6a;
  --evac-at-home:            #ffa726;
  --evac-not-evacuating:     #ef5350;
  --evac-unknown-location:   #c62828;
  --evac-not-in-settlement:  #78909c;
  --evac-no-contact:         #6a1b9a;
  --evac-not-reported:       #90a4ae;
  --radius:   14px;
  --shadow:   0 22px 50px rgba(0,0,0,.55);
  --accent-text: #08192e;
  /* UI-0100: foreground for anything sitting ON --success, the way --accent-text
     is for --accent. Declared ONCE on purpose: measured against all four themes'
     --success, this dark ink clears WCAG AA everywhere -- 10.00:1 on the default
     mint, 5.36:1 on the light theme's #16a34a, 11.02:1 and 12.87:1 on the two
     high-contrast greens. White clears NONE of them (1.77, 3.30, 1.60, 1.37),
     which is what the all-clear button had been using. */
  --success-text: #08192e;
  --text-primary: #E8EEF8;
  --text-muted:   #8ea3c4;
  --toggle-bg:    #22406e;
  --topbar-bg:    #050B16;
  --subribbon-bg: #0b1830;
  --font:         'Segoe UI', system-ui, sans-serif;
}

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
html[dir="rtl"] body { direction: rtl; }
html[dir="ltr"] body { direction: ltr; }

/* ── Typography scale (WOW-UX review #4) — see the --fs-* tokens above for
   the full rationale. Purely additive: any heading with its own class or
   inline font-size already wins on specificity over these bare element
   rules, so this only fills in the gap where nothing else applies. */
h1, h2, h3, h4 { font-weight: 700; line-height: 1.25; color: var(--text); }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

/* ── Page loader overlay ── */
#page-loader {
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  transition: opacity 0.35s ease;
}
#page-loader.pl-fade { opacity: 0; pointer-events: none; }
#page-loader .pl-spinner {
  color: var(--accent);
}
/* .pl-label/.pl-timer removed (09/10): styled the splash screen's "Loading..."
   caption and an already-unused elapsed-timer span. The caption was dropped
   from templates/dashboard.html's #page-loader -- spinner + brand only now. */

/* ── Splash brand animation (migrated from dashboard.html inline <style> — H1 PR4) ── */
/* <link rel="stylesheet"> in <head> is render-blocking, so style.css is parsed
   before first paint; moving the splash CSS here is safe. */
.pl-brand{display:flex;flex-direction:column;align-items:center;gap:.7rem;margin-bottom:1.6rem}
.pl-mark{width:112px;height:112px;display:block}
.pl-name{font-family:Georgia,'Times New Roman',serif;font-size:1.55rem;line-height:1;
         color:#fff;letter-spacing:-.01em;direction:ltr}
.pl-name span{color:#E3B657}
.pl-tag{font-size:.66rem;letter-spacing:.18em;color:#4C9AFF;margin-top:-.15rem}
/* transform-box:fill-box is load-bearing. Without it the origin resolves
   against the viewBox (0-512) while these paths sit inside a translated and
   scaled <g>, so the fold line lands at 246.6 rather than 256 and the scaleX
   collapses the plane instead of opening it. fill-box measures each path
   against its own bounding box, so "right center" is genuinely its own edge. */
.pl-fold{animation-duration:.94s;animation-fill-mode:both;
         animation-timing-function:cubic-bezier(.2,.7,.25,1);
         transform-box:fill-box}
.pl-fL{animation-name:plFold;transform-origin:right center}
.pl-fR{animation-name:plFold;animation-delay:.26s;transform-origin:left center}
.pl-fT{animation-name:plFoldT;animation-delay:.64s;transform-origin:left center}
.pl-fD{animation-name:plFade;animation-delay:.88s}
.pl-name{animation:plRise .6s 1.1s both cubic-bezier(.2,.7,.25,1)}
.pl-tag{animation:plRise .6s 1.4s both cubic-bezier(.2,.7,.25,1)}
@keyframes plFold{from{transform:scaleX(0);opacity:.2}to{transform:scaleX(1);opacity:1}}
@keyframes plFoldT{from{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}
@keyframes plFade{from{opacity:0}to{opacity:1}}
@keyframes plRise{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
/* Spinner colour: scoped to #page-loader so every other spinner still follows the theme */
#page-loader .sp-bounce i{background:#4C9AFF}
/* Brand splash is intentionally DARK in every theme. Override the base background
   (see #page-loader above). */
#page-loader{background:radial-gradient(120% 120% at 26% 12%,#1c3a63 0%,#0f2137 45%,#060d18 100%)}
/* Motion sensitivity: keep the brand, drop the movement. */
@media (prefers-reduced-motion: reduce){
  html:not([data-motion="full"]) .pl-fold,
  html:not([data-motion="full"]) .pl-name,
  html:not([data-motion="full"]) .pl-tag{animation:plFade .4s both!important;transform:none!important}
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* Background decorative blob */
body::before {
  content: "";
  position: fixed;
  width: 600px; height: 600px;
  background: radial-gradient(circle, rgba(var(--accent-rgb),.15) 0%, transparent 70%);
  top: -100px; inset-inline-start: -100px;
  pointer-events: none;
}

/* Card */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 2.5rem 2rem;
  width: 100%;
  max-width: 400px;
  animation: fadeUp .35s ease;
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Logo / icon area */
.card-icon {
  width: 56px; height: 56px;
  background: var(--accent);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 1.25rem;
  font-size: 1.5rem;
}
/* When a real logo is shown the circle is replaced */
.card-icon:has(.card-logo) {
  background: none;
  border-radius: 0;
  width: auto;
  height: auto;
}
.card-logo {
  width: 120px;
  max-height: 80px;
  object-fit: contain;
  display: block;
}
/* The FULL wordmark on a fixed navy card — like the status-bar tooltip / About —
   so the white "Kesher" reads in BOTH themes (the 2FA page is themeable and its
   card goes light in light mode). Overrides the compact .card-logo sizing. */
.card-logo-wordmark {
  width: 260px;
  max-width: 90%;
  max-height: none;
  background: #0E2340;
  padding: 12px 22px;
  border-radius: 12px;
  box-sizing: border-box;
}

.card h1 {
  text-align: center;
  font-size: 1.4rem;
  font-weight: 700;
  margin-bottom: .4rem;
}
.card .subtitle {
  text-align: center;
  color: var(--text);   /* was var(--muted) -- read dim next to the white card title above it */
  font-size: .875rem;
  margin-bottom: 2rem;
}

/* Form */
.form-group {
  margin-bottom: 1.25rem;
}
label {
  display: block;
  font-size: .8rem;
  font-weight: 600;
  color: var(--text);   /* was var(--muted) -- same fix as .um-label, app-wide this time:
                            a bare <label> (e.g. a checkbox row's text) read dim gray next
                            to the rest of its modal/form's near-white text. */
  margin-bottom: .4rem;
  letter-spacing: .04em;
}
input[type="text"],
input[type="password"],
input[type="email"] {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .95rem;
  padding: .65rem .9rem;
  outline: none;
  transition: border-color .2s, box-shadow .2s;
  text-align: start;
}
/* .um-input and .stg-input are used app-wide as "styled field" classes on
   inputs/selects/textareas, but had no rule of their own — so controls whose
   type the generic rule above misses (number/tel/time/date/datetime-local,
   plus selects and textareas) rendered as raw browser controls. Mirror the
   text-input look so every such field matches, whatever its type. */
.um-input,
.stg-input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .95rem;
  padding: .65rem .9rem;
  outline: none;
  transition: border-color .2s, box-shadow .2s;
  text-align: start;
}
textarea.um-input,
textarea.stg-input { resize: vertical; min-height: 4.5rem; }
/* .um-label is the modal field-label class — written on ~10 labels across the
   settings/profile/document modals but, like .um-input above once was, never
   given a rule of its own. So those labels rendered as bare inline browser
   labels: sitting beside their field instead of stacked above it, without the
   small muted uppercase treatment the rest of the modals hardcode inline.
   Define it once here, matching that inline field-label look. */
.um-label {
  display: block;
  margin-bottom: .4rem;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);   /* was var(--muted) -- matched the modal title (.um-modal-header h3) */
  letter-spacing: .04em;
  text-transform: uppercase;
}
input:focus,
textarea.um-input:focus,
textarea.stg-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2);
}

/* A required field that failed its check — red until the user fixes it. Added by
   validateRequired() (static/js/app.js) and cleared on the next input/change. The
   !important + :focus variant keep the red visible even while the field is focused
   (the focus rule above would otherwise repaint it accent-coloured). Theme-aware
   via var(--danger). See CLAUDE.md "Required fields". */
.field-invalid,
.um-input.field-invalid,
.stg-input.field-invalid,
.mnh-input.field-invalid {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(248,113,113,.18);
}
.field-invalid:focus {
  border-color: var(--danger) !important;
  box-shadow: 0 0 0 3px rgba(248,113,113,.30);
}

/* Spin animation for Phosphor icons — replaces FontAwesome's .fa-spin as icons
   migrate off FA (an <i class="… ph-fill ph-spinner ph-spin">). */
.ph-spin { display: inline-block; animation: ph-spin 1s linear infinite; }
@keyframes ph-spin { to { transform: rotate(360deg); } }

/* OTP input */
.otp-input {
  font-size: 1.8rem !important;
  letter-spacing: .4em;
  text-align: center !important;
  font-weight: 700;
}

/* Button */
.btn {
  display: block;
  width: 100%;
  padding: .75rem;
  border: none;
  border-radius: 8px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter .2s, transform .1s;
}
.btn:active { transform: scale(.98); }
.btn-primary {
  background: var(--accent);
  color: var(--accent-text);
}
.btn-primary:hover { filter: brightness(1.12); }
.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  margin-top: .6rem;
}
.btn-ghost:hover { color: var(--text); border-color: var(--accent); }

/* Alerts */
.alert {
  padding: .7rem 1rem;
  border-radius: 8px;
  font-size: .875rem;
  margin-bottom: 1.25rem;
  display: flex; align-items: center; gap: .5rem;
}
.alert-error   { background: rgba(248,113,113,.12); border: 1px solid rgba(248,113,113,.3); color: var(--danger); }
.alert-info    { background: rgba(var(--accent-rgb),.12);  border: 1px solid rgba(var(--accent-rgb),.3);  color: var(--accent-h); }
.alert-warning { background: rgba(251,191,36,.12);  border: 1px solid rgba(251,191,36,.3);  color: var(--warn); }
.alert-success { background: rgba(52,211,153,.12);  border: 1px solid rgba(52,211,153,.3);  color: var(--success); }

/* Login page — brand badge (bottom-left corner) */
.login-brand-badge {
  /* L10N-0080: was a physical `left`, so the badge sat in the wrong corner in
     the app's 13 LTR languages. */
  position: fixed;
  bottom: 1.25rem;
  inset-inline-start: 1.25rem;
  display: block;
  opacity: .55;
  transition: opacity .2s;
  line-height: 0;
  border-radius: 6px;
}
.login-brand-badge:hover { opacity: 1; }

/* Footer link */
.card-footer {
  text-align: center;
  margin-top: 1.5rem;
  font-size: .8rem;
  color: var(--muted);
}
.card-footer a { color: var(--accent-h); text-decoration: none; }
.card-footer a:hover { text-decoration: underline; }

/* Modal overlay (login forgot-password) */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 9999;
  padding: 1rem;
}

/* Countdown */
.countdown {
  text-align: center;
  color: var(--muted);
  font-size: .8rem;
  margin-top: .75rem;
}
.countdown span { color: var(--accent-h); font-weight: 600; }

/* Dashboard */
.dashboard-card {
  text-align: center;
  padding: 3rem 2rem;
  max-width: 480px;
}
.dashboard-card .welcome-icon {
  font-size: 4rem;
  margin-bottom: 1rem;
}
.dashboard-card h1 { font-size: 1.8rem; margin-bottom: .5rem; }
.dashboard-card p  { color: var(--muted); margin-bottom: 2rem; }
/* How many lists a person appears in, beside their name in the people table.
   Deliberately NOT .badge: that one carries margin-bottom:1.5rem for a standalone
   hero badge and would push every table row apart. Tokens only, so both themes
   follow without a second rule. */
/* "Needs review" marker on a vulnerable-resident row. Warning, not danger: the
   record is not wrong, nobody has vouched for it lately. Tokens only, so it reads
   in both themes. */
.vuln-stale {
  display: inline-block;
  margin-inline-start: .4rem;
  padding: .05rem .4rem;
  border-radius: 99px;
  background: rgba(var(--warning-rgb, 234, 179, 8), .16);
  color: var(--warning);
  border: 1px solid rgba(var(--warning-rgb, 234, 179, 8), .35);
  font-size: .7rem;
  font-weight: 600;
  white-space: nowrap;
}

.pr-count {
  display: inline-block;
  min-width: 1.6rem;
  padding: .1rem .45rem;
  border-radius: 99px;
  background: rgba(var(--accent-rgb), .14);
  color: var(--accent-h);
  border: 1px solid rgba(var(--accent-rgb), .3);
  font-size: .76rem;
  font-weight: 600;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.pr-none { color: var(--muted); }

.badge {
  display: inline-block;
  background: rgba(var(--accent-rgb),.2);
  color: var(--accent-h);
  border: 1px solid rgba(var(--accent-rgb),.4);
  border-radius: 99px;
  padding: .25rem .85rem;
  font-size: .8rem;
  font-weight: 600;
  margin-bottom: 1.5rem;
}

/* ═══════════════════════════════════════════
   APP SHELL (dashboard with ribbon)
   ═══════════════════════════════════════════ */

body.app-body {
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  overflow: hidden;
}
body.app-body::before { display: none; }

/* Shell wrapper — full viewport by default */
.app-shell {
  display: flex;
  flex-direction: column;
  width: 100vw;
  /* UI-0070 (quality-audit): --pwa-banner-h defaults to 0px (pwa.js sets it to the
     offline banner's real rendered height, incl. wrapping, only while it's shown) --
     the banner used to sit position:fixed on top of the topbar's first ~40px instead
     of displacing it. margin-top pushes the shell down by that much; the height
     calc shrinks it by the same amount so the shell's bottom never overflows the
     viewport. Zero effect while online (var is 0px, identical to the old fixed values). */
  margin-top: var(--pwa-banner-h, 0px);
  height: calc(100vh - var(--pwa-banner-h, 0px));    /* fallback for browsers without dynamic viewport units */
  height: calc(100dvh - var(--pwa-banner-h, 0px));   /* mobile browsers shrink this as the URL bar appears/hides;
                       identical to 100vh anywhere without dynamic chrome, so this
                       is desktop-neutral and removes a media-query dependency */
  background: var(--bg);
  transition: all .35s cubic-bezier(.4,0,.2,1);
}

/* Windowed / partial mode */
.app-shell.windowed {
  position: fixed;
  border-radius: 16px;
  border: 1px solid var(--border);
  box-shadow: 0 40px 100px rgba(0,0,0,.7);
  overflow: hidden;
  /* left / top / width / height set via JS */
}

/* Draggable top-bar cursor hint */
.app-shell.windowed .top-bar { cursor: grab; }
.app-shell.windowed .top-bar button,
.app-shell.windowed .top-bar a { cursor: pointer; }

/* ── Resize grips ── */
.resize-grip {
  display: none;
  position: absolute;
  z-index: 100;
}
.app-shell.windowed .resize-grip { display: block; }

/* South edge */
.grip-s  { bottom: 0; inset-inline-start: 6px; inset-inline-end: 6px; height: 6px; cursor: s-resize; }
/* East edge */
.grip-e  { top: 6px; bottom: 6px; inset-inline-end: 0; width: 6px; cursor: e-resize; }
/* West edge */
.grip-w  { top: 6px; bottom: 6px; inset-inline-start: 0; width: 6px; cursor: w-resize; }
/* SE corner */
.grip-se {
  bottom: 0; inset-inline-end: 0;
  width: 18px; height: 18px;
  cursor: se-resize;
  background: linear-gradient(135deg, transparent 40%, var(--border) 40%, var(--border) 55%, transparent 55%,
              transparent 65%, var(--accent) 65%, var(--accent) 80%, transparent 80%);
  border-radius: 0 0 16px 0;
}
/* SW corner */
.grip-sw {
  bottom: 0; inset-inline-start: 0;
  width: 18px; height: 18px;
  cursor: sw-resize;
  background: linear-gradient(225deg, transparent 40%, var(--border) 40%, var(--border) 55%, transparent 55%,
              transparent 65%, var(--accent) 65%, var(--accent) 80%, transparent 80%);
  border-radius: 0 0 0 16px;
}

/* ── Top bar ── */
.top-bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  /* Grow into the notch rather than under it: the box gets taller by the inset and
     the padding pushes the contents clear. env() is 0 everywhere without a notch,
     so this is a no-op on desktop and on older phones. */
  padding: var(--sa-t) calc(1.2rem + var(--sa-e)) 0 calc(1.2rem + var(--sa-s));
  height: calc(52px + var(--sa-t));
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  position: relative;
  user-select: none;
}

.top-bar__brand {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-weight: 700;
  font-size: .95rem;
  color: var(--text);
}
.brand-icon { font-size: 1.2rem; }
/* In flow, not absolutely centred. It used to be position:absolute + left:50%, which
   takes it out of the layout entirely: the browser could not know the title and the
   user chip occupied the same horizontal space, so nothing pushed and nothing clipped
   and on a phone the site name simply drew on top of the avatar. Collision was
   guaranteed below some width rather than accidental, and got worse the longer the
   site name — white-space:nowrap forbade it from ever giving way.

   As a flex item with min-width:0 it takes the space actually left between the logo
   and the chip and ellipsises when that runs out. min-width:0 is the load-bearing
   part: a flex item's default min-width:auto refuses to shrink below its content,
   which would reintroduce the overflow in a different form. */
.brand-name {
  flex: 1 1 auto;
  min-width: 0;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 700;
  font-size: 1rem;
  color: var(--text);
  pointer-events: none;
  white-space: nowrap;
}

.top-bar__user {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin-inline-start: auto;
}
.user-chip {
  display: flex;
  align-items: center;
  gap: .4rem;
  background: rgba(var(--accent-rgb),.15);
  border: 1px solid rgba(var(--accent-rgb),.3);
  border-radius: 99px;
  padding: .25rem .75rem;
  font-size: .8rem;
  color: var(--accent-h);
}
.user-chip-sub {
  font-size: .72rem;
  color: var(--text);   /* was opacity:.65 on the chip's own accent-blue -- read dim/washed-out */
}
.user-chip-profile {
  font-size: .68rem;
  background: rgba(255,255,255,.1);
  padding: .1rem .45rem;
  border-radius: 4px;
  margin-inline-start: .25rem;
  color: var(--accent-h);
  font-weight: 600;
}
/* ── Avatar (profile picture) ── */
.avatar-img  { border-radius: 50%; object-fit: cover; }
.avatar-xs   { width: 16px; height: 16px; }
.avatar-sm   { width: 26px; height: 26px; }
.avatar-md   { width: 48px; height: 48px; }
.avatar-lg   { width: 80px; height: 80px; }
.avatar-initial {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; font-weight: 600; flex-shrink: 0;
  background: rgba(var(--accent-rgb), .18); color: var(--accent-h);
}
.avatar-initial.avatar-xs  { width: 16px; height: 16px; font-size: .5rem;  }
.avatar-initial.avatar-sm  { width: 26px; height: 26px; font-size: .7rem;  }
.avatar-initial.avatar-md  { width: 48px; height: 48px; font-size: 1.1rem; }
.avatar-initial.avatar-lg  { width: 80px; height: 80px; font-size: 1.8rem; }
/* Hover tooltip — enlarged avatar preview (positioned by JS, fixed so it escapes overflow containers) */
.avatar-tip-wrap { cursor: pointer; }
.avatar-tip-wrap .avatar-tip {
  display: none; position: fixed; z-index: 9999;
  width: 160px; height: 160px; border-radius: 50%;
  overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,.35);
  border: 3px solid var(--surface, #fff);
  pointer-events: none;
}
.avatar-tip-wrap .avatar-tip img { width: 100%; height: 100%; object-fit: cover; }
.ps-avatar-preview {
  width: 80px; height: 80px; border-radius: 50%;
  border: 2px dashed rgba(var(--accent-rgb), .3);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; margin: 0 auto .75rem;
}
.ps-avatar-preview img  { width: 100%; height: 100%; object-fit: cover; }
.ps-avatar-preview .app-icon { font-size: 3rem; opacity: .4; }

/* Brand logo (top bar) */
.brand-logo-img {
  height: 32px;
  width: auto;
  max-width: 100px;
  object-fit: contain;
  display: block;
}

.logout-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  color: var(--muted);
  border-radius: 6px;
  text-decoration: none;
  transition: color .2s, background .2s;
}
.logout-btn:hover { color: var(--danger); background: rgba(248,113,113,.1); }

/* ── Notification Bell ── */
.notif-bell-wrap { position: relative; }
.notif-bell {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  background: none; border: none; cursor: pointer;
  color: var(--muted); border-radius: 6px;
  position: relative; transition: color .2s, background .2s;
  font-size: 1rem;
}
.notif-bell:hover { color: var(--accent); background: rgba(var(--accent-rgb),.1); }
.notif-badge {
  position: absolute; top: 2px; inset-inline-end: 1px;
  background: var(--danger); color: #fff;
  border-radius: 10px; font-size: .6rem; font-weight: 700;
  min-width: 15px; height: 15px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 3px; line-height: 1; pointer-events: none;
}
.notif-panel {
  position: absolute; top: calc(100% + 6px); inset-inline-end: 0;
  width: 320px; max-height: 440px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.2);
  z-index: 9990; display: flex; flex-direction: column; overflow: hidden;
}
.notif-panel-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: .7rem 1rem; border-bottom: 1px solid var(--border);
  font-weight: 600; font-size: .88rem; color: var(--text); flex-shrink: 0;
}
.notif-mark-all {
  background: none; border: none; color: var(--accent);
  font-size: .76rem; cursor: pointer; padding: 0;
}
.notif-mark-all:hover { text-decoration: underline; }
.notif-delete-all {
  background: none; border: none; color: var(--danger, #d9534f);
  font-size: .76rem; cursor: pointer; padding: 0; margin-inline-start: .6rem;
}
.notif-delete-all:hover { text-decoration: underline; }
.notif-list { overflow-y: auto; flex: 1; }
/* WOW-UX review #6: day-group section header (Today/Yesterday/Earlier). */
.notif-group-label {
  padding: .5rem 1rem .3rem; font-size: var(--fs-xs); font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
}
.notif-group-label:not(:first-child) { margin-top: .2rem; border-top: 1px solid var(--border); padding-top: .7rem; }
.notif-item {
  display: flex; align-items: flex-start; gap: .65rem;
  padding: .7rem 1rem; border-bottom: 1px solid var(--border);
  cursor: pointer; transition: background .12s; list-style: none;
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover { background: rgba(var(--accent-rgb),.06); }
.notif-item.unread { background: rgba(var(--accent-rgb),.05); }
.notif-item.unread .notif-item-title { font-weight: 600; }
.notif-icon {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: .8rem; flex-shrink: 0; margin-top: 1px;
}
.notif-icon.fan_response   { background: rgba(var(--accent-rgb),.15); color: var(--accent); }
.notif-icon.ticket_new     { background: rgba(var(--warn-rgb),.15); color: var(--warn); }
.notif-icon.ticket_comment { background: rgba(var(--warn-rgb),.10); color: var(--warn); }
.notif-icon.voting_open    { background: rgba(var(--success-rgb),.15); color: var(--success); }
.notif-icon.evacuation     { background: rgba(239,68,68,.15);  color: var(--danger); }
.notif-icon.bulletin_sh    { background: rgba(var(--notif-purple-rgb),.15); color: var(--notif-purple); }
.notif-icon.message        { background: rgba(var(--notif-blue-rgb),.15); color: var(--notif-blue); }
.notif-item-content { flex: 1; min-width: 0; }
.notif-item-title { font-size: .83rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notif-item-body  { font-size: .76rem; color: var(--muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notif-item-time  { font-size: .7rem; color: var(--text); margin-top: 3px; }   /* was var(--muted) */
.notif-dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  padding: .1rem .35rem;
  border-radius: 4px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, color .15s;
}
.notif-item:hover .notif-dismiss { opacity: 1; }
.notif-dismiss:hover { color: var(--danger); }
.notif-empty { text-align: center; color: var(--muted); padding: 2rem 1rem; font-size: .84rem; line-height: 1.6; }
.notif-empty i { display: block; font-size: 1.5rem; margin-bottom: .5rem; opacity: .5; }
/* was an inline style="color:var(--muted)" on the notification-preview popup's
   relative-time row (e.g. "לפני 6 ימים") -- moved to a class so the default-theme
   override below can target it. */
.notif-preview-time { font-size: .78rem; color: var(--muted); display: flex; align-items: center; gap: .35rem; }

/* The personal / general chips. A row of .fan-filter-chip (defined once, further
   down) with only the layout added here -- the chip itself, including its .active
   state and both themes, is already solved and is not re-styled.

   It sits inside .feed-cards-rows as the first child, so the 8-row measurement in
   _feedCapToRows sees it as a row and the panel does not grow by a chip's height
   beyond the cap. */
.wn-chips {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem;
  padding: .1rem .1rem .45rem;
}
.wn-chips .fan-filter-chip { padding: .2rem .6rem; font-size: .76rem; }

/* Only ever seen under a filter: the section is not rendered at all when there are
   no notifications, so this always means "none match this chip", never "nothing
   happened". */
.wn-empty { padding: 1.1rem .5rem; font-size: .8rem; }

/* The "earlier" separator in the what's-new panel: a rule with the label sitting in
   a gap in the middle of it. Drawn with a flex row and two growing lines rather than
   a background gradient behind text, so it works on any panel background and in both
   themes without a second colour to keep in sync. */
.wn-divider {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .35rem .1rem .15rem;
  font-size: .7rem;
  color: var(--muted);
  user-select: none;
}
.wn-divider::before,
.wn-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}
.wn-divider > span { white-space: nowrap; }

/* ── Window controls ── */
.win-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-inline-end: .5rem;
}
.win-btn {
  width: 28px; height: 28px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: .75rem;
  transition: background .2s, color .2s;
}
.win-btn:hover { color: var(--text); }
.win-min:hover  { background: rgba(251,191,36,.2);  color: var(--warn); }
.win-part:hover { background: rgba(var(--accent-rgb),.2);  color: var(--accent-h); }
.win-max:hover  { background: rgba(52,211,153,.2);  color: var(--success); }

/* ── Status bar (footer) ── */
.status-bar {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: .4rem;
  /* Same idea at the bottom edge -- the home-indicator strip. */
  padding: 0 calc(1.2rem + var(--sa-e)) var(--sa-b) calc(1.2rem + var(--sa-s));
  height: calc(28px + var(--sa-b));
  background: var(--surface);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  font-size: .75rem;
  color: var(--text);   /* was var(--muted) -- labels read dim next to their own values (.status-bar-item strong, already var(--text)) */
  user-select: none;
}
.status-bar-item {
  display: flex;
  align-items: center;
  gap: .35rem;
}
.status-bar-item i {
  font-size: .7rem;
  opacity: .7;
}
.status-bar-item strong {
  color: var(--text);
  font-weight: 600;
}
.status-bar-sep {
  color: var(--border);
  margin: 0 .3rem;
  font-size: .65rem;
}
.status-bar-theme {
  margin-inline-start: auto;
  cursor: pointer;
  position: relative;
  padding: 0 .3rem;
  border-radius: 3px;
  transition: background .15s;
}
.status-bar-theme:hover {
  background: rgba(var(--accent-rgb),.1);
}
.sb-theme-menu {
  display: none;
  position: absolute;
  bottom: 100%;
  inset-inline-end: 0;
  margin-bottom: 4px;
  min-width: 150px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
  z-index: 9999;
}
.sb-theme-menu-open { display: block; }
.sb-theme-opt {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .4rem .8rem;
  font-size: .78rem;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s;
}
.sb-theme-opt:first-child { border-radius: 6px 6px 0 0; }
.sb-theme-opt:last-child  { border-radius: 0 0 6px 6px; }
.sb-theme-opt:hover {
  background: var(--accent);
  color: var(--accent-text);
}
.sb-theme-opt.sb-theme-active {
  font-weight: 700;
  color: var(--accent);
}
.sb-theme-opt.sb-theme-active:hover {
  color: var(--accent-text);
}
.sb-theme-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.status-bar-logo {
  position: relative;
  cursor: pointer;
  padding: 0 .3rem;
}
.sb-logo-tooltip {
  display: none;
  position: absolute;
  bottom: 100%;
  inset-inline-end: 0;
  margin-bottom: 6px;
  padding: 10px 14px;
  /* Fixed navy card (mirrors the reports' logo) so the white-"Kesher" dark
     variant reads in BOTH themes — the theme --surface goes white in light
     mode and would hide it. */
  background: #0E2340;
  border: 1px solid #24456e;
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
  z-index: 9999;
}
/* A11Y-0077 (quality-audit): the logo announces as role="button" tabindex="0"
   but the tooltip only ever revealed on :hover -- a keyboard user tabbing to
   it (or a screen-reader user activating it) got nothing. Mirrors the
   existing :hover/:focus-within pairing used elsewhere for this exact
   reveal-on-interaction shape (see .fan-hh-chip). */
.status-bar-logo:hover .sb-logo-tooltip,
.status-bar-logo:focus-within .sb-logo-tooltip {
  display: block;
}
.status-bar-lang {
  cursor: pointer;
  position: relative;
  padding: 0 .3rem;
  border-radius: 3px;
  transition: background .15s;
}
.status-bar-lang:hover {
  background: rgba(var(--accent-rgb),.1);
}
.sb-lang-menu {
  display: none;
  position: absolute;
  bottom: 100%;
  inset-inline-end: 0;
  margin-bottom: 4px;
  min-width: 120px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
  z-index: 9999;
  overflow: visible;
}
.sb-lang-menu-open { display: block; }
.sb-lang-opt {
  padding: .45rem .8rem;
  font-size: .78rem;
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s;
  position: relative;
}
.sb-lang-opt:first-child { border-radius: 6px 6px 0 0; }
.sb-lang-opt:last-child  { border-radius: 0 0 6px 6px; }
.sb-lang-opt:hover {
  background: var(--accent);
  color: var(--accent-text);
}
.sb-lang-opt[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  inset-inline-start: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--accent, #333);
  color: var(--accent-text);
  font-size: .72rem;
  font-weight: 600;
  padding: .3rem .6rem;
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
  box-shadow: 0 3px 12px rgba(0,0,0,.2);
  direction: inherit;
  z-index: 10000;
}
.sb-lang-opt[data-tip]::before {
  content: '';
  position: absolute;
  inset-inline-start: calc(100% + 3px);
  top: 50%;
  transform: translateY(-50%);
  border: 5px solid transparent;
  border-inline-end-color: var(--accent, #333);
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
  z-index: 10000;
}
.sb-lang-opt[data-tip]:hover::after,
.sb-lang-opt[data-tip]:hover::before {
  opacity: 1;
}
.lang-card-tip, .hover-tip {
  position: relative;
}
.lang-card-tip[data-tip]::after, .hover-tip[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  background: var(--accent, #333);
  color: var(--accent-text);
  font-size: .72rem;
  font-weight: 600;
  padding: .3rem .6rem;
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
  box-shadow: 0 3px 12px rgba(0,0,0,.2);
  direction: inherit;
  z-index: 10;
}
.lang-card-tip[data-tip]::before, .hover-tip[data-tip]::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 3px);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-block-start-color: var(--accent, #333);
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s;
  z-index: 10;
}
.lang-card-tip[data-tip]:hover::after, .hover-tip[data-tip]:hover::after,
.lang-card-tip[data-tip]:hover::before, .hover-tip[data-tip]:hover::before {
  opacity: 1;
}
/* .hover-tip (reaction "who reacted" tooltips) can carry several names --
   .lang-card-tip's nowrap is right for its always-short static strings, but
   would push a long name list off-screen here. Applied AFTER the shared rule
   above so it wins on specificity ties without touching .lang-card-tip. */
.hover-tip[data-tip]::after {
  white-space: normal;
  max-width: 220px;
  text-align: center;
  line-height: 1.4;
}
.lang-flag {
  width: 20px;
  height: 14px;
  vertical-align: middle;
  border-radius: 2px;
  object-fit: cover;
  margin-inline-end: 4px;
  box-shadow: 0 0 1px rgba(0,0,0,.25);
}

/* ── Ribbon ── */
.ribbon {
  display: flex;
  align-items: stretch;
  gap: 2px;
  padding: 6px 8px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  flex-shrink: 0;
  scrollbar-width: none;
}
.ribbon::-webkit-scrollbar { display: none; }

/* ── Ribbon / sub-ribbon scroll-overflow arrows + edge fades ── */
.ribbon-scroll-wrap { position: relative; flex: 1 1 auto; min-width: 0; }
.ribbon-scroll-wrap > .ribbon,
.ribbon-scroll-wrap > .sub-ribbon { width: 100%; }
#subRibbonWrap { --_scroll-bg: var(--subribbon-bg); flex-shrink: 0; flex-grow: 0; }
#subRibbonWrap:has(.sub-ribbon.hidden) { display: none; }
.ribbon-fade {
  position: absolute; top: 0; bottom: 0; width: 56px;
  pointer-events: none; z-index: 2; transition: opacity .2s;
}
.ribbon-scroll-wrap { --_scroll-bg: var(--surface); }
.ribbon-fade--start { inset-inline-start: 0; background: linear-gradient(to left, transparent 0%, rgba(var(--accent-rgb),.12) 60%, rgba(var(--accent-rgb),.25) 100%); border-inline-start: 2px solid rgba(var(--accent-rgb),.5); }
.ribbon-fade--end   { inset-inline-end:   0; background: linear-gradient(to right, transparent 0%, rgba(var(--accent-rgb),.12) 60%, rgba(var(--accent-rgb),.25) 100%); border-inline-end: 2px solid rgba(var(--accent-rgb),.5); }
.ribbon-fade--hidden { opacity: 0; }
.ribbon-scroll-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 32px; height: 32px; border-radius: 6px;
  border: 1.5px solid rgba(var(--accent-rgb),.6); background: rgba(var(--accent-rgb),.15);
  color: var(--text); cursor: pointer; font-size: 1rem;
  display: flex; align-items: center; justify-content: center;
  transition: opacity .2s, background .15s, border-color .15s;
  font-family: inherit; padding: 0;
}
.ribbon-scroll-arrow:hover { background: rgba(var(--accent-rgb),.35); border-color: rgba(var(--accent-rgb),.8); }
.ribbon-scroll-arrow--start { inset-inline-start: 6px; }
.ribbon-scroll-arrow--end   { inset-inline-end:   6px; }
.ribbon-scroll-arrow--hidden { opacity: 0; pointer-events: none; }
@media (max-width: 767.98px) {
  .ribbon-fade, .ribbon-scroll-arrow { display: none !important; }
}

/* Ribbon row: the horizontally-scrolling ribbon + the distress button pinned at
   the inline-end (far side per language: left in RTL, right in LTR), OUTSIDE
   the ribbon's scroll so it stays visible. */
.ribbon-row { display: flex; align-items: stretch; background: var(--surface); border-bottom: 1px solid var(--border); }
.ribbon-row > .ribbon-scroll-wrap { flex: 1 1 auto; min-width: 0; }
.ribbon-row > .ribbon-scroll-wrap > .ribbon { border-bottom: none; }
.emergency-ribbon-btn {
  flex-shrink: 0; align-self: center;
  margin: 0 12px 0 14px;
  width: 44px; height: 44px; position: relative;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%;
  cursor: pointer; color: #fff; font-family: inherit; font-size: 1.3rem;
  /* glossy red dome — light top-left highlight → dark bottom (physical button) */
  background: radial-gradient(circle at 38% 30%, #ff8f83, #e5352f 52%, #9c1212 100%);
  box-shadow: inset 0 2px 3px rgba(255,255,255,.55), inset 0 -4px 7px rgba(60,0,0,.45),
              0 6px 16px rgba(0,0,0,.5), 0 0 0 0 rgba(255,60,50,.6);
  animation: emgHalo 1.9s ease-out infinite;
  transition: filter .16s ease, transform .12s ease;
}
/* specular gloss highlight across the top of the dome */
.emergency-ribbon-btn::after {
  content: ""; position: absolute; top: 6px; left: 9px; right: 9px; height: 10px;
  border-radius: 50%; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,.6), transparent);
}
.emergency-ribbon-btn svg {
  position: relative; z-index: 1;
  width: 22px; height: 22px; fill: #fff;
  /* solid white bell (matches the mockup), with a dark edge for crispness */
  filter: drop-shadow(0 1px 1.5px rgba(90,0,0,.55));
}
.emergency-ribbon-btn:hover { filter: brightness(1.08); }
.emergency-ribbon-btn:active { transform: translateY(1px); }
/* pulsing halo — keep the dome's inset+drop shadows, animate only the outer ring */
@keyframes emgHalo {
  0%   { box-shadow: inset 0 2px 3px rgba(255,255,255,.55), inset 0 -4px 7px rgba(60,0,0,.45), 0 6px 16px rgba(0,0,0,.5), 0 0 0 0 rgba(255,60,50,.6); }
  70%  { box-shadow: inset 0 2px 3px rgba(255,255,255,.55), inset 0 -4px 7px rgba(60,0,0,.45), 0 6px 16px rgba(0,0,0,.5), 0 0 0 12px rgba(255,60,50,0); }
  100% { box-shadow: inset 0 2px 3px rgba(255,255,255,.55), inset 0 -4px 7px rgba(60,0,0,.45), 0 6px 16px rgba(0,0,0,.5), 0 0 0 0 rgba(255,60,50,0); }
}
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) .emergency-ribbon-btn { animation: none; } }
/* Mobile: the ribbon becomes a slide-in drawer (#ribbon goes position:fixed),
   so unwrap the row and float the distress button like the old FAB — never
   trapped inside the drawer. It keeps the glossy dome + pulsing halo. */
/* iOS zooms the whole page when a focused field is under 16px, and does not zoom back
   out -- the user is left pinching their way back on every single form. Worse in the
   installed PWA, where there is no browser chrome to reset it from. Nobody reports it
   because it reads as "that is just how phones are".

   Every field in the app was under the line: .um-input/.stg-input are .95rem and
   .mnh-input is .85rem, which at the DEFAULT root of 16px are 15.2px and 13.6px. The
   root is user-configurable (html[data-fontsize] = 14/16/18/20px), so on "small" they
   fall to 13.3px and 11.9px.

   max(16px, 1rem) rather than a flat 16px, deliberately: a flat value would silently
   DEMOTE anyone who chose a larger font size -- a person who set "huge" (20px) for
   readability would get 16px fields. The floor stops the zoom; the 1rem keeps their
   choice whenever it is the bigger of the two. Same max() idiom the 44px tap targets use.

   Checkboxes and radios are excluded: they carry no text, so they never trigger the zoom,
   and sizing them here would just make them bigger for no reason.

   Scoped to body.is-mobile -- the server-side UA sniff this stylesheet already gates ~110
   rules on -- rather than a width breakpoint, because the zoom is a property of the
   device, not of the window. A 360px-wide desktop browser does not zoom. */
body.is-mobile input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
body.is-mobile select,
body.is-mobile textarea {
  /* !important, and not lightly. Measuring in a real mobile browser showed the plain rule
     winning on most fields and losing on the rest -- a handful carry their own, more
     specific font-size from a container rule, and every one of those is still under the
     line that triggers the zoom. A floor that holds for "most" fields does not fix
     anything: the user meets the zoom on whichever form has the exception.

     Same reasoning, and the same author-!important tool, as the modal max-width repair
     this stylesheet already carries -- an accessibility floor is exactly what the escape
     hatch is for. It raises a minimum; it never shrinks anything, because max() keeps
     whatever was larger. */
  font-size: max(16px, 1rem) !important;
}

body.is-mobile .ribbon-row { display: contents; }
body.is-mobile .emergency-ribbon-btn {
  /* Same inline-end as the other floating buttons -- --fab-inset plus the measured
     scrollbar gutter -- so the column lines up. It used to be a bare 16px, which put
     the distress button 12px out of line with the three beside it.

     `bottom` is set by _adjustFabStack() in app.js, which lays this whole column out
     from one ordered list; the value here is only what shows before that first runs.
     Do not hardcode a new one -- that is how this button ended up underneath the help
     and accessibility circles, with 41% of it hit-testable. */
  position: fixed; bottom: 100px;
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px));
  z-index: 9989;
  width: 52px; height: 52px; margin: 0;
}

.ribbon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 72px;
  padding: 8px 10px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: .7rem;
  font-family: inherit;
  font-weight: 500;
  white-space: nowrap;
  transition: background .18s, color .18s;
  flex-shrink: 0;
}
.ribbon-item i {
  font-size: 1.25rem;
  transition: transform .2s;
}
.ribbon-item:hover {
  background: rgba(var(--accent-rgb),.12);
  color: var(--accent-h);
}
.ribbon-item:hover i { transform: translateY(-2px); }
.ribbon-item.active {
  background: rgba(var(--accent-rgb),.2);
  color: var(--accent-h);
  border-bottom: 2px solid var(--accent);
}
/* ── Ribbon drag-and-drop ── */
.ribbon-item[draggable="true"] { cursor: grab; }
.ribbon-item[draggable="true"]:active { cursor: grabbing; }
.ribbon-item.rib-dragging { opacity: .3; }
.ribbon-item.rib-over-start { box-shadow: inset 3px 0 0 var(--accent); }
.ribbon-item.rib-over-end   { box-shadow: inset -3px 0 0 var(--accent); }
.rib-drag-ghost {
  position: fixed; z-index: 9999; opacity: .8; pointer-events: none;
  border-radius: 8px; background: var(--surface);
  box-shadow: 0 4px 12px rgba(0,0,0,.25); padding: 8px 10px;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  font-size: .7rem; color: var(--text);
}

/* ── Sub-ribbon ── */
.sub-ribbon {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px 10px;
  background: var(--subribbon-bg);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  flex-shrink: 0;
  scrollbar-width: none;
  min-height: 44px;
  animation: fadeUp .2s ease;
}
.sub-ribbon::-webkit-scrollbar { display: none; }
.sub-ribbon.hidden { display: none; }

.sub-item {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .4rem .9rem;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: .8rem;
  font-family: inherit;
  font-weight: 500;
  white-space: nowrap;
  transition: background .15s, color .15s, border-color .15s;
  flex-shrink: 0;
}
.sub-item i { font-size: .85rem; }
.sub-item:hover {
  background: rgba(var(--accent-rgb),.1);
  color: var(--text);
}
.sub-item.active {
  background: rgba(var(--accent-rgb),.18);
  color: var(--accent-h);
  border-color: rgba(var(--accent-rgb),.35);
}
/* ── Sub-ribbon drag-and-drop reordering ── */
.sub-item[draggable="true"] { cursor: grab; }
.sub-item--dragging { opacity: .4; cursor: grabbing !important; }
/* Drop-position indicator: inset box-shadow on the insertion side.
   RTL overrides flip the shadow so it always appears between items. */
.sub-item.srd-before { box-shadow: inset  3px 0 0 var(--accent-h); }
.sub-item.srd-after  { box-shadow: inset -3px 0 0 var(--accent-h); }
[dir="rtl"] .sub-item.srd-before { box-shadow: inset -3px 0 0 var(--accent-h); }
[dir="rtl"] .sub-item.srd-after  { box-shadow: inset  3px 0 0 var(--accent-h); }

/* ── Main content ── */
.app-main {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* Reserve the scrollbar track even when there is nothing to scroll: the
     width stops changing between short and long views (no content jump), and
     it gives the floating-FAB rail a fixed gutter to clear — see
     --fab-gutter, measured from this element in _fabGutterSync(). */
  scrollbar-gutter: stable;
  padding: 1.75rem 2rem;
  transition: all .3s ease;
}
.app-main.hidden {
  max-height: 0;
  padding: 0;
  overflow: hidden;
}

/* ── Panels ── */
.panel { display: none; animation: fadeUp .25s ease; }
.panel.active { display: block; }

.panel-header {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: 1.25rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--border);
}
.panel-icon { font-size: 1.4rem; color: var(--accent-h); }
.panel-header h2 { font-size: 1.3rem; font-weight: 700; }

/* ── Sub content area ── */
.content-area { animation: fadeUp .2s ease; }

/* ── Hamburger (hidden on desktop) ── */
.mob-hamburger {
  display: none;
}

/* ── Mobile overlay (hidden on desktop) ── */
#mobRibbonOverlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 998;
}

/* ── Mobile breakpoints ── */
@media (max-width: 767.98px) {
  /* Hamburger button */
  .mob-hamburger {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text);
    font-size: 1.2rem;
    cursor: pointer;
    flex-shrink: 0;
    transition: background .15s;
  }
  .mob-hamburger:hover { background: rgba(var(--accent-rgb),.12); }

  /* Ribbon → side drawer */

  /* Collapse the wrapper the drawer left behind.
     .ribbon-scroll-wrap carries `flex: 1 1 auto`, written for the ROW it normally sits
     in, where it means "take the remaining width". But body.is-mobile gives .ribbon-row
     `display: contents`, which promotes this wrapper to a direct child of .app-shell --
     a COLUMN flex container -- and there the identical declaration means "take the
     remaining HEIGHT". #ribbon itself is position:fixed below and out of flow, so the
     wrapper was reserving 314px of a 740px phone screen for a menu that is not in it.
     Measured: #appMain started at y=398 and was 314px tall; it now starts at 84 and is
     628px. Roughly half the screen, blank, on every module.

     `flex: 0 0 auto` rather than `display: none` -- the drawer is INSIDE this wrapper,
     so hiding it would hide the navigation too. Not `display: contents` either, though
     it measures the same: the box stays position:relative for the scroll fades and
     arrows it anchors (themselves hidden at this width), so this changes one declaration
     instead of removing a containing block. */
  #ribbonWrap { flex: 0 0 auto; }

  #ribbon {
    /* Fixed and full-height, so it clears the system chrome on its own rather than
       inheriting the shell's padding. */
    padding-top: var(--sa-t);
    padding-bottom: var(--sa-b);
    position: fixed;
    top: 0;
    /* Anchored to inline-START (left in LTR, right in RTL) so the drawer opens on
       the SAME side as .mob-hamburger, its own trigger button -- that button is the
       header row's first flex child, so it always sits at the inline-start edge.
       Was inset-inline-end (opposite side from the trigger, in BOTH directions)
       until the owner flagged it from a live RTL screenshot; border/box-shadow
       below were flipped to match. */
    inset-inline-start: -260px;
    width: 230px;
    height: 100dvh;
    flex-direction: column;
    align-items: stretch;
    overflow-y: auto;
    overflow-x: hidden;
    z-index: 999;
    padding: 56px 6px 16px;
    gap: 3px;
    border-bottom: none;
    border-inline-end: 1px solid var(--border);
    background: var(--surface);
    /* box-shadow doesn't flip with dir like the inset above -- it needs its own
       sign per direction so it still falls toward the content, not off-screen.
       Base (LTR) value here; [dir="rtl"] override follows, same pattern already
       used for .sub-item.srd-before/-after above. */
    box-shadow: 4px 0 20px rgba(0,0,0,.3);
    transition: inset-inline-start .25s ease;
  }
  #ribbon.mob-open {
    inset-inline-start: 0;
  }
  [dir="rtl"] #ribbon {
    box-shadow: -4px 0 20px rgba(0,0,0,.3);
  }
  #mobRibbonOverlay.mob-open {
    display: block;
  }

  /* Ribbon items — horizontal layout inside drawer */
  .ribbon-item {
    flex-direction: row;
    justify-content: flex-start;
    min-width: unset;
    width: 100%;
    padding: 10px 14px;
    font-size: .88rem;
    gap: 12px;
    border-radius: 8px;
    text-align: start;
  }
  .ribbon-item i { font-size: 1.1rem; width: 20px; flex-shrink: 0; }
  .ribbon-item:hover i { transform: none; }
  /* Mobile drawer: vertical layout → top/bottom drop indicators */
  .ribbon-item.rib-over-start { box-shadow: inset 0 3px 0 var(--accent); }
  .ribbon-item.rib-over-end   { box-shadow: inset 0 -3px 0 var(--accent); }
  .rib-drag-ghost { flex-direction: row; gap: 10px; font-size: .85rem; padding: 10px 14px; }

  /* Sub-ribbon stays as horizontal bar */
  .sub-ribbon { padding: 3px 6px; min-height: 38px; }
  .sub-item { padding: .3rem .6rem; font-size: .75rem; }

  .top-bar { padding: 0 .6rem; gap: .5rem; height: 46px; }
  .top-bar__brand .logo-text { font-size: .85rem; }
  /* The site name already ellipsises on desktop (.brand-name above) when it's long,
     but at this width the hamburger, logo, name, avatar+username and notification
     bell are all fighting for the same 46px-tall row -- the name is the one that adds
     no information a returning user needs (they know which site they're on) and
     free the space for the pieces that do (the user chip, the bell). Text-only: the
     logo image/emoji in .top-bar__brand stays, so the header keeps a brand mark. */
  .brand-name { display: none; }
  .app-main { padding: 0; }
  .panel-header h2 { font-size: 1.1rem; }
  .proc-wrap { flex-direction: column; height: auto; gap: 0; overflow: visible; }
  .proc-sidebar { width: 100%; height: calc(100dvh - 200px); max-height: none; overflow-y: auto; border-radius: 0 !important; border-inline: none !important; border-block: none !important; }
  .proc-viewer-wrap { height: auto; overflow-y: auto; }
  /* when a doc is selected shrink sidebar so toolbar is visible below */
  body.is-mobile .proc-wrap:has(.reg-toolbar) .proc-sidebar { height: auto; max-height: 38vh; }
  body.is-mobile .proc-wrap:has(.reg-toolbar) .proc-viewer-wrap { flex: 1; }
  .prof-split { flex-direction: column; height: auto; }
  .status-bar { font-size: .65rem; padding: 0 .5rem; }
  .app-shell { height: calc(100dvh - var(--pwa-banner-h, 0px)); }  /* UI-0070: keep the banner-height offset at this breakpoint too */

  /* Drop the username and login time once the bar stops fitting.
     This was gated on `body.is-mobile` -- the user-agent sniff -- while the two rules
     directly above it already treat the status bar as a WIDTH problem. The result was
     that the same 360px page overflowed 154px horizontally on a desktop user agent and
     0px on a phone one: the layout fix existed but only devices got it.
     Measured: hiding these takes 154px of overflow down to 3px, and nothing else
     overflows once they are gone -- so this rule is the whole defect, not a part of it.
     Overflow starts around 500px and grows as the window narrows.

     :has() is load-bearing here (the ids sit on children, and the separator is a
     sibling of the item). Every browser in the support matrix has it; a browser without
     it simply keeps the old, cramped bar rather than breaking. */
  .status-bar-item:has(#sbUsername),
  .status-bar-item:has(#sbLoginTime),
  .status-bar-item:has(#sbUsername)  + .status-bar-sep,
  .status-bar-item:has(#sbLoginTime) + .status-bar-sep { display: none; }

  /* The same defect as the block above, in the header instead of the footer, and the
     residue that rule left behind: it reported "nothing else overflows once they are
     gone", which held for the footer and missed these three.

     .win-controls (minimise / partial / fullscreen) was hidden ONLY by
     `body.is-mobile .win-controls` far below, the user-agent sniff -- so a 360px
     desktop window kept three 28px buttons the header has no room for and scrolled
     11px sideways, while the identical page on a phone scrolled 0.

     The is-mobile rule STAYS, and the pair is not a duplicate: they answer different
     questions. This one is layout -- the bar stopped fitting. That one is product --
     buttons that resize a desktop window mean nothing on a phone, including a phone
     held in landscape past this breakpoint, where this rule does not apply. */
  .win-controls { display: none; }
}
@media (max-width: 480px) {
  .app-main { padding: 0; }
}

/* ═══════════════════════════════════════════
   USERS MANAGER
   ═══════════════════════════════════════════ */

/* padding-top so the first row of controls does not press against the sub-menu
   bar above it. Every screen built on .um-wrap sat flush against it. */
.um-wrap { display: flex; flex-direction: column; gap: 1rem; padding-top: .6rem; }

.um-toolbar {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}
/* ── Sticky list toolbar (reusable) ──────────────────────────────────────────
   Opt-in infrastructure — DO NOT copy these rules per screen. Add the
   `sticky-toolbar` class to any `.um-wrap` list view and its `.um-toolbar`
   (add button + search) stays pinned while the list scrolls. Screens that
   don't add the class are unaffected. In use on: people (אנשים), users (משתמשים).
   To add it elsewhere, just append `sticky-toolbar` to that view's `.um-wrap`. */
.um-wrap.sticky-toolbar { padding-top: 0; }      /* the bar owns the top spacing now */
.um-wrap.sticky-toolbar > .um-toolbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  padding-block: .6rem;
  border-bottom: 1px solid var(--border);
}
/* .app-main (the scroll container) has top padding, so `top:0` pins the bar just
   below the very top — leaving a strip where list rows peek ABOVE it. This
   page-colored cover, attached to the (sticky) bar, fills that strip: invisible at
   rest, hides rows only once the bar is pinned. Height clears .app-main's padding. */
.um-wrap.sticky-toolbar > .um-toolbar::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 100%;
  height: 2.5rem;
  background: var(--bg);
}

/* ── Collapsible sticky panel (reusable) ─────────────────────────────────────
   Pin a whole header block (e.g. summary tiles + toolbar + filters) to the top
   while the list below scrolls, with ONE handle to fold/unfold the entire block.
   Wrap the block with the _stickyPanel(html) helper (app.js) — don't hand-copy this
   markup per screen. Collapsed = only the thin handle bar stays pinned. In use on:
   tickets (שירות: פתוחות/בטיפול/טופלו/שלי). */
.sticky-panel {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  padding-bottom: .35rem;
}
.sticky-panel::before {   /* cover .app-main's top padding so rows can't peek above */
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 100%;
  height: 2.5rem;
  background: var(--bg);
}
.sticky-panel.collapsed .sticky-panel-body { display: none; }
/* The handle's row. The margin that used to sit on the handle moves here, so a panel
   WITHOUT actions renders at exactly the height it always did -- the row is the only child
   and inherits the same spacing. With actions, they sit beside the caret instead of
   costing a second full-width line underneath it. */
.sticky-panel-bar {
  display: flex;
  align-items: stretch;
  gap: .4rem;
  margin-bottom: .5rem;
}
.sticky-panel.collapsed .sticky-panel-bar { margin-bottom: 0; }
/* Sized by its contents, so it takes no space at all when a caller passes none. */
.sticky-panel-actions { display: flex; align-items: center; gap: .4rem; flex: 0 0 auto; }
.sticky-panel-handle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  flex: 1 1 auto;                /* was width:100% -- now the row's flexible child */
  padding: .25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .15s, color .15s;
}
.sticky-panel-handle:hover { color: var(--text); background: var(--bg); }
.sticky-panel-handle .sph-caret { color: var(--accent); font-size: 1.05rem; transition: transform .2s; }
.sticky-panel.collapsed .sticky-panel-handle .sph-caret { transform: rotate(180deg); }
.pop-summary {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding: .6rem 1rem;
  margin-bottom: .5rem;
  background: rgba(var(--accent-rgb), .08);
  border-radius: 8px;
  font-size: .9rem;
  color: var(--text);
}
.pop-summary span {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
}
.pop-summary i {
  color: var(--accent);
  font-size: .85rem;
}

/* ── Search box ── */
.um-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  order: -1;
  margin-inline-end: auto;
}
.um-search-inner {
  position: relative;
  display: inline-flex;
  align-items: center;
}
/* L10N-0054 (quality-audit): was a base (RTL) physical value + an explicit
   [dir="ltr"] override for each rule -- both sides collapse to the SAME logical
   property (verified: base `left`/LTR-override `right` are both inset-inline-end;
   base `padding-left`/LTR-override `padding-right` are both padding-inline-end),
   matching the codebase's established inset-inline-*/padding-inline-* convention
   used elsewhere and halving the rule count. Functionally identical either way. */
.um-search-icon {
  position: absolute;
  inset-inline-end: .75rem;
  color: var(--muted);
  font-size: .8rem;
  pointer-events: none;
}
.um-search {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .85rem;
  font-family: inherit;
  padding: .45rem .75rem;
  padding-inline-end: 2.2rem;
  outline: none;
  width: 280px;
  text-align: start;
  transition: border-color .2s, box-shadow .2s;
}
.um-search:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2);
}
.um-search::placeholder { color: var(--muted); }

.um-search-clear {
  position: absolute;
  inset-inline-end: .5rem;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: var(--muted);
  font-size: .75rem;
  cursor: pointer;
  padding: 2px 5px;
  border-radius: 50%;
  line-height: 1;
  display: none;
  transition: color .15s, background .15s;
}
.um-search-clear:hover {
  color: var(--text);
  background: rgba(var(--accent-rgb),.1);
}
.um-search-wrap.has-value .um-search-clear {
  display: flex;
}
.um-search-wrap.has-value .um-search-icon {
  display: none;
}

.um-btn-add,
.um-btn-export {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.1rem;
  background: transparent;
  color: var(--accent);
  border: 1.5px solid var(--accent);
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.um-btn-add:hover { filter: brightness(1.15); }
.um-btn-add:disabled { opacity: .4; cursor: not-allowed; filter: none; }
.um-btn-export:hover { background: rgba(var(--accent-rgb), .12); }

.um-btn-secondary {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.1rem;
  background: transparent;
  color: var(--accent);
  border: 1.5px solid var(--accent);
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, color .2s;
}
.um-btn-secondary:hover {
  background: rgba(var(--accent-rgb), .12);
}

.um-btn-warn {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.1rem;
  background: var(--danger);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s;
}
.um-btn-warn:hover { filter: brightness(1.12); }

.um-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.um-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .875rem;
}
.um-table th {
  background: var(--topbar-bg);
  color: var(--muted);
  font-weight: 600;
  font-size: .75rem;
  letter-spacing: .04em;
  text-align: start;
  padding: .65rem 1rem;
  border-bottom: 1px solid var(--border);
}
.um-table td {
  padding: .7rem 1rem;
  color: var(--text);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.um-table tbody tr:last-child td { border-bottom: none; }
.um-table tbody tr:hover { background: rgba(var(--accent-rgb),.06); }

.um-id { color: var(--muted); font-size: .78rem; width: 40px; }
/* width:1% + nowrap shrinks the cell to its buttons and keeps them on ONE row
   (the table is layout:auto). Was a fixed 40px sized for a single button, which
   forced a 2nd (edit) button to wrap under the first. */
.um-actions { width: 1%; white-space: nowrap; text-align: center; }

/* ── Sortable column headers ── */
th.um-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: color .18s, background .18s;
}
th.um-sortable:hover {
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.1);
}
th.um-sort-active {
  color: var(--accent);
  background: rgba(var(--accent-rgb), .06);
}
th.um-sort-active .sort-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  background: var(--accent);
  color: #fff;
  border-radius: 3px;
  font-size: 8px;
  margin-inline-start: 4px;
  vertical-align: middle;
  position: relative;
  top: -1px;
  line-height: 1;
}
.sort-arrow {
  font-size: .68rem;
  margin-inline-start: 3px;
  color: var(--muted);
  opacity: .22;
  transition: opacity .12s;
  vertical-align: middle;
}
th.um-sortable:hover:not(.um-sort-active) .sort-arrow {
  opacity: .55;
}

.um-btn-icon {
  width: var(--act-btn); height: var(--act-btn);
  /* No resting frame: the box is transparent until hover / high-contrast, so the
     row action icons read as plain icons rather than boxed buttons. */
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .8rem;
  transition: all .18s;
  margin-inline-end: 4px;
  position: relative;   /* containing block for ::after's tap-target extension below */
}
/* WOW-UX review: every --act-btn density (28/26/32/36px) sits below the
   WCAG-recommended 44x44 minimum tap target -- confirmed by direct
   investigation that a visual box-grow to 44px would be unsafe here (a
   3-button reservation row in vehicles.js has only a 2px gap between
   buttons, no mobile overflow guard; a 5-button admin row has already had a
   real historical wrap bug from a much smaller size change). This extends
   only the CLICKABLE area via an invisible, centered pseudo-element -- the
   visible icon/box stays exactly the size it is today, so no row can grow,
   crowd, or wrap from this change. */
.um-btn-icon::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: max(44px, 100%);
  height: max(44px, 100%);
}

/* Validation message inside a modal form, beside the field it is about, rather
   than a toast that covers the form you are trying to fix. */
.um-inline-err {
  color: var(--danger);
  font-size: .82rem;
  padding: .5rem .7rem;
  border-radius: 6px;
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
}

/* Person picker: the results list under the search box, and the chosen person
   once picked. Capped and scrollable — 232 people will not fit, and the modal
   must not grow past the viewport. */
.pp-results {
  margin-top: .4rem;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  display: none;
}
.pp-results.pp-open { display: block; }
.pp-row {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .5rem .75rem;
  cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.pp-row:last-child { border-bottom: none; }
.pp-row:hover, .pp-row.pp-active { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.pp-row-name { font-weight: 600; }
.pp-row-meta { font-size: .8rem; color: var(--muted); direction: ltr; }
.pp-empty { padding: .75rem; color: var(--muted); font-size: .85rem; text-align: center; }
.pp-chosen {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  padding: .6rem .8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.pp-chosen-meta { font-size: .8rem; color: var(--muted); direction: ltr; }

.um-btn-edit { color: var(--accent-h); }
.um-btn-edit:hover { background: rgba(var(--accent-rgb),.2); border-color: var(--accent); }
/* THE inline row-delete look, and the only place its colour is decided. Owner
   decision 2026-08-28: red at rest, so a delete is identifiable without hovering.
   .um-btn-del rides the .um-btn-icon base — 28px box, transparent, 44px ::after tap
   target. .proc-item-del is grouped in rather than migrated in the markup, because
   module-scoped rules key on that name: the per-module mobile hiding
   (body.is-mobile #content-committees .proc-item-del et al) and the two
   high-contrast variants. Rewriting those 12 call sites would have dropped them
   silently.

   Deliberately NOT grouped here: .ip-topic-remove (a chip's remove-x inside
   .ip-topic-tag, not an entity delete), .notif-dismiss (closes a notification,
   deletes nothing), .stg-btn-remove (a labelled text button). Giving those this
   treatment would make every chip in the app read as a warning. */
.um-btn-del,
.proc-item-del { color: var(--danger); }
/* And the same colour ON THE ICON, which is the half that actually shows.
   [data-icon-style="duotone"] i.app-icon (line ~9070) sets a colour directly on the
   <i>, and a colour merely INHERITED from the button never beats a direct rule no
   matter how specific the button's selector is. The rule above therefore held in
   fill and flat and lost in duotone, where every delete icon came out accent-blue.

   `html` + `i` takes this to (0,2,2) against duotone's (0,2,1), so it wins wherever
   either rule sits in the file. Moving this below line 9070 at equal specificity
   would also work and was rejected: order-dependence is the exact fragility that
   produced the original .um-btn-danger collision.

   The two more specific exceptions below -- .proc-item (0,3,0) and
   #content-regulations (1,3,0) -- still outrank this and still cover their contexts. */
html .um-btn-del    i.app-icon,
html .proc-item-del i.app-icon { color: var(--danger); }
.um-btn-del:hover  { background: rgba(248,113,113,.15); border-color: var(--danger); }

/* ═══ Unified action-icon buttons (round-11 UI) ═════════════════════════════
   One class for every row-action icon — delete / edit / other. Box size, icon
   size, resting colour and the hover animation are all driven by --act-* vars
   set from <html data-act-size / data-act-color> (admin default + personal
   override). With no attribute the defaults are COLORED + REGULAR (12px). */
:root                            { --act-icon: 12px; --act-btn: 28px; }
html[data-act-size="compact"]    { --act-icon: 11px; --act-btn: 26px; }
html[data-act-size="regular"]    { --act-icon: 12px; --act-btn: 28px; }
html[data-act-size="large"]      { --act-icon: 14px; --act-btn: 32px; }
html[data-act-size="accessible"] { --act-icon: 16px; --act-btn: 36px; }

.act-ico {
  --act-tone: var(--accent);
  width: var(--act-btn); height: var(--act-btn); padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 7px; background: transparent;
  color: var(--muted); cursor: pointer;
  transition: color .18s, background .18s, border-color .18s;
}
.act-ico .app-icon { font-size: var(--act-icon); line-height: 1;
  transition: transform .2s cubic-bezier(.34,1.56,.64,1), filter .2s; }
.act-ico.is-del  { --act-tone: var(--danger); color: var(--danger); }
.act-ico.is-edit { --act-tone: var(--accent); color: var(--accent); }

/* WHITE colour-mode: neutral at rest (hover below still reveals the tone) */
html[data-act-color="white"] .act-ico:not(:hover) { color: var(--muted); }

/* hover — LIFT + soft shadow + tone colour, in every colour-mode */
.act-ico:hover           { color: var(--act-tone); }
.act-ico:hover .app-icon { transform: translateY(-3px); filter: drop-shadow(0 3px 4px rgba(0,0,0,.30)); }

/* reduced-motion — OS media query AND the app's own toggle keep the colour, drop the lift */
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) .act-ico:hover .app-icon { transform: none; filter: none; } }
html[data-motion="reduce"] .act-ico:hover .app-icon { transform: none; filter: none; }

.um-loading, .um-empty, .um-error {
  text-align: center;
  padding: 2rem;
  color: var(--muted);
  font-size: .875rem;
}

/* WOW-UX review: shared empty-LIST-state look (icon + one sentence), replacing
   the drifted um-empty/proc-empty/proc-list-empty/forum-empty styling at the
   sites that are genuinely "zero items" -- see emptyStateHtml()/
   emptyStateRowHtml() in app.js. The 4 old classes stay defined/in use for
   their OTHER meanings (permission-denied, not-found, search hints) that
   were never actually "empty list" states to begin with. */
.app-empty {
  text-align: center;
  padding: 2rem;
  color: var(--muted);
  font-size: .875rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .5rem;
}
.app-empty .app-icon { font-size: 1.6rem; opacity: .5; }
.app-empty-row { padding: 1.5rem; }

/* WOW-UX review: shared regional loading overlay -- see showRegionOverlay()/
   hideRegionOverlay() in app.js. Sits on top of a data region's EXISTING
   content (the region needs position:relative, set by showRegionOverlay
   itself) so a refetch/reselect doesn't blank an already-populated view. */
.region-overlay {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--surface, #fff) 80%, transparent);
  display: flex; align-items: center; justify-content: center; gap: .75rem;
  z-index: 10; direction: ltr; color: var(--muted);
}

.um-dept-header,
.um-dept-header td {
  background: color-mix(in srgb, var(--accent) 5%, var(--bg)) !important;
}
.um-dept-header {
  cursor: pointer;
}
.um-dept-header td {
  color: color-mix(in srgb, var(--accent) 55%, var(--text));
  font-weight: 600;
  font-size: .88rem;
  letter-spacing: .02em;
  text-transform: uppercase;
  padding: .38rem .75rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  border-inline-start: 3px solid color-mix(in srgb, var(--accent) 60%, transparent);
  user-select: none;
  width: 100%;
}
.um-dept-header:hover,
.um-dept-header:hover td { background: color-mix(in srgb, var(--accent) 9%, var(--bg)) !important; }
.um-dept-arrow { display: inline-block; font-size: .7rem; margin-inline-end: .45rem; transition: transform .18s; }
.um-dept-arrow--closed { transform: rotate(-90deg); }
.um-dept-count { font-weight: 400; opacity: .6; font-size: .75rem; margin-inline-start: .35rem; }
.um-dept-cell { display: flex; align-items: center; gap: 0; }
.um-dept-add-btn {
  margin-inline-start: auto;
  width: 1.6rem; height: 1.6rem; padding: 0;
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  border-radius: 50%;
  background: transparent; color: var(--accent);
  cursor: pointer; font-size: .7rem; line-height: 1;
  opacity: .45; transition: opacity .15s;
}
.um-dept-header:hover .um-dept-add-btn { opacity: 1; }
.um-dept-add-btn:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.um-btn-group-toggle {
  width: 2rem; height: 2rem; padding: 0;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--muted);
  cursor: pointer; font-size: .8rem;
  transition: color .15s, border-color .15s;
}
.um-btn-group-toggle:hover { color: var(--accent); border-color: var(--accent); }
.um-error { color: var(--danger); }

/* ── Modal ── */
.um-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}
/* QUAL-0091 (quality-audit): vehicles.js hand-typed this exact overlay chrome
   (position/background/display/z-index/padding) as an inline style.cssText
   string, identically, 4 times. .um-modal-overlay above (added later for
   A11Y-0013's focus-trap/Escape-handler hook) has different values -- bg
   opacity .6 not .5, z-index 1000 not 999, a backdrop blur, no padding --
   switching these 4 to rely on it alone would be a real visual change, which
   A11Y-0013's own fix explicitly promised not to make ("same visual layout as
   before"). This class captures that preserved visual instead of leaving it
   duplicated as a raw string; each of the 4 elements carries BOTH classes --
   um-modal-overlay for the JS-side hook, veh-modal-overlay for the look. */
.veh-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; z-index: 999; padding: 1rem; }
/* Same reasoning, facilities.js's own single copy -- different values (z-index
   9000, no padding, starts hidden) so kept as its OWN class rather than
   unified with veh-modal-overlay above; unifying them would change one file's
   stacking order/spacing to match the other's, a real behavior change this
   fix does not make. Starting hidden here is equivalent to the old inline
   version: every open/close still goes through _a11yOpenModal/
   _a11yCloseModal, which set modal.style.display directly either way. */
.fac-modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 9000; align-items: center; justify-content: center; }

/* The shared alert/loading modal (showAlert / showLoading) must float ABOVE
   every content modal — otherwise an error alert fired while another modal is
   open renders underneath it while _a11yOpenModal traps focus on it, so the
   user is stuck on an invisible dialog and never sees the error (audit #12,
   "buried-alert"). It carries .um-modal-overlay (z-index 1000) but content
   overlays climb to 10200; this ID rule (specificity beats the class) lifts it
   above all of them, yet below the initial page-loader (99999) and skip link
   (100000). Guarded by tests/test_alert_modal_zindex.py — keep it above the
   overlays. */
#genAlertModal { z-index: 10500; }

.um-modal-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 30px 80px rgba(0,0,0,.6);
  width: 420px;
  max-width: 95vw;
  /* UI-0077 (quality-audit): most call sites already set their own inline
     max-height/overflow-y (70-90vh); this is the DEFAULT for the ones that
     don't -- without it, a tall body on a short viewport pushed the footer
     (and its buttons) off-screen with no way to scroll to them. An inline
     override on a specific modal still wins over this class rule. */
  max-height: 90vh;
  overflow-y: auto;
  animation: fadeUp .25s ease;
  position: relative;   /* anchor for .modal-resize-grip */
}

/* Drag-resize grip — bottom-inline-start corner (= bottom-right in RTL). Only shown on
   modals that opt in with class="um-modal-box modal-resizable". */
.modal-resize-grip {
  position: absolute;
  bottom: 0;
  inset-inline-start: 0;
  width: 20px;
  height: 20px;
  cursor: sw-resize;
  z-index: 10;
  border-radius: 0 0 0 var(--radius);
  background: linear-gradient(225deg,
    transparent 40%, var(--border) 40%, var(--border) 55%, transparent 55%,
    transparent 65%, var(--accent) 65%, var(--accent) 80%, transparent 80%);
  opacity: .5;
  transition: opacity .15s;
}
.modal-resize-grip:hover { opacity: 1; }
.um-modal-box.um-modal-wide {
  width: 800px;
}

/* Narrow modal, the sibling of .um-modal-wide above. A one-field dialog (a deadline,
   a rename) reads badly at the default width. Added as a CLASS rather than
   style="max-width:..." because an inline cap defeats the responsive rule and overflows
   a phone -- the growth tests/test_inline_modal_width_ratchet.py exists to stop. */
.um-modal-box.um-modal-narrow {
  max-width: 380px;
  width: 100%;
}

.um-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem 1.3rem .9rem;
  border-bottom: 1px solid var(--border);
}
.um-modal-header h3 { font-size: 1rem; font-weight: 700; color: var(--text); }
/* Accent modal header (bulletin form) — gold in most themes; the child title
   inherits the header colour so it flips with it. Quantum override below. */
.um-modal-header-accent { background: var(--accent); color: #fff; }
.um-modal-header-accent .um-modal-title { color: inherit; }
:root:not([data-theme]) .um-modal-header-accent {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: var(--accent-h);
}

.um-modal-close {
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 1rem;
  cursor: pointer;
  width: 28px; height: 28px;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  transition: color .2s, background .2s;
}
.um-modal-close:hover { color: var(--danger); background: rgba(248,113,113,.1); }

.um-form { padding: 1.2rem 1.3rem; display: flex; flex-direction: column; gap: .9rem; }

.um-field label {
  display: block;
  font-size: .75rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: .35rem;
  letter-spacing: .04em;
}
.um-field input {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .9rem;
  padding: .55rem .85rem;
  outline: none;
  font-family: inherit;
  text-align: start;
  transition: border-color .2s, box-shadow .2s;
}
.um-field input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2);
}
/* Read-only fields (name/email/phone on a user) are shown, not edited — they
   come from the person. Muted, no focus ring, cursor says "not here". */
.um-field input.um-readonly,
.um-field input[readonly] {
  background: var(--bg-muted, rgba(127,127,127,.08));
  color: var(--text-muted, #6b7280);
  cursor: default;
}
.um-field input.um-readonly:focus,
.um-field input[readonly]:focus {
  border-color: var(--border);
  box-shadow: none;
}

/* Password-policy live checklist (user modal + create picker + reset page) */
.pw-checklist { margin-top: .5rem; display: flex; flex-direction: column; gap: .25rem; }
.pw-check-item { font-size: .82rem; color: var(--muted, #6b7280); display: flex; align-items: center; gap: .4rem; }
.pw-check-item.ok { color: var(--success, #3ddc97); }
.pw-check-mark { display: inline-block; width: 1em; text-align: center; font-weight: 700; }

/* ── Password-change warning banner (enforcement = "warn") ── */
/* UI-0016 (quality-audit): --warning-bg/--warning-text/--warning-border were
   never declared anywhere -- every var() here always silently rendered its
   hardcoded light-pastel fallback regardless of theme, so this banner never
   actually adapted to dark mode. --warn/--warn-rgb ARE declared (and already
   tuned) in all 4 themes; derive the bg/border from --warn via color-mix
   instead of inventing 3 more never-tested tokens. */
.pw-warn-banner {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  padding: .65rem 1.1rem; margin: .5rem .7rem;
  background: color-mix(in srgb, var(--warn) 15%, var(--surface)); color: var(--text);
  border: 1px solid var(--warn); border-radius: .5rem;
  font-size: .88rem; line-height: 1.4; position: relative; z-index: 10;
}
.pw-warn-banner .pw-warn-close {
  margin-inline-start: auto; background: none; border: none; cursor: pointer;
  color: inherit; font-size: 1rem; padding: .2rem; line-height: 1;
}

.um-modal-footer {
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  padding-top: .4rem;
}

/* Most footers sit inside .um-form and inherit its padding. The ones that sit
   beside it, as a direct child of the box, had none -- so their buttons pressed
   against the modal's edges. Match .um-form's inset so both arrangements look
   the same. */
.um-modal-box > .um-modal-footer {
  padding: .4rem 1.3rem 1.2rem;
}

.um-btn-save {
  display: flex; align-items: center; gap: .4rem;
  padding: .55rem 1.2rem;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 8px;
  font-size: .875rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s;
}
.um-btn-save:hover { filter: brightness(1.15); }

/* WOW-UX review: unified delete-confirmation mechanism -- showConfirm's danger
   opt toggles this alongside .um-btn-save, replacing ~14 copies of the same
   inline style="background:var(--danger, #f87171);color:#fff" that lived on
   each bespoke delete modal's OK button.

   SCOPED to the modal footer on purpose. Unscoped, this was a second definition
   of .um-btn-danger -- the first is ~350 lines above, for the subtle inline
   row-delete icon -- with identical specificity and a later position, so it won
   everywhere and turned nine directory.js screens (people, population, roles,
   services, employees, branches, education, emergency, vulnerable residents)
   into solid red filled squares. That made delete the loudest element in every
   row, which is the opposite of what a destructive action should be. The OK
   button this rule was written for lives in .um-modal-footer
   (_modals_shared.html:105-106), so scoping keeps it and releases the rest. */
.um-modal-footer .um-btn-danger { background: var(--danger); color: #fff; }

.um-btn-cancel {
  padding: .55rem 1rem;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: .875rem;
  font-family: inherit;
  cursor: pointer;
  transition: color .2s, border-color .2s;
}
.um-btn-cancel:hover { color: var(--text); border-color: var(--accent); }

.um-select {
  width: 100%;
  padding: .5rem .65rem;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: .875rem;
  font-family: inherit;
  outline: none;
  transition: border-color .2s;
  cursor: pointer;
}
.um-select:focus { border-color: var(--accent); }

/* Dark-theme native controls (the <select> option list, date/number/time pickers)
   must render in the OS dark scheme, or their popups show dark text on a dark
   background and become unreadable. Only the dark-surface themes need this — the
   light-surface themes render readable already. */
:root:not([data-theme]) select, :root:not([data-theme]) input, :root:not([data-theme]) textarea {
  color-scheme: dark;
}

.um-profile-badge {
  display: inline-block;
  padding: .15rem .55rem;
  font-size: .78rem;
  border-radius: 4px;
  background: rgba(var(--accent-rgb),.12);
  color: var(--accent-h);
  font-weight: 600;
}


/* ═══════════════════════════════════════════
   SETTINGS PANEL
   ═══════════════════════════════════════════ */

.stg-wrap { display: flex; flex-direction: column; max-width: 540px; height: 100%; }
.stg-wrap .stg-section { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.stg-wrap .stg-body { flex: 1; display: flex; flex-direction: column; gap: 1rem; padding: 1.25rem; overflow-y: auto; }
.stg-wrap.stg-wrap-wide { max-width: none; }
.stg-wrap.stg-wrap-row { flex-direction: row; max-width: none; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; }
/* Dim + lock a settings panel until its values finish loading (avoids editing ghost
   defaults that the async load would then clobber). Cleared in the load's finally{}. */
.stg-wrap.stg-loading { opacity: .5; pointer-events: none; transition: opacity .2s; }

.alert-cards-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.2rem; align-items: start; }
.alert-card { padding: 1.2rem; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.alert-card-header { display: flex; align-items: center; gap: .6rem; margin-bottom: .8rem; }
.alert-card-chevron { font-size: .7rem; color: var(--muted); transition: transform .25s; }
.alert-card--collapsed .alert-card-chevron { transform: rotate(-90deg); }
[dir="rtl"] .alert-card--collapsed .alert-card-chevron { transform: rotate(90deg); }
.alert-card--collapsed .alert-card-header { margin-bottom: 0; }
.alert-card-body { overflow: hidden; max-height: 600px; transition: max-height .3s ease, opacity .25s ease; opacity: 1; }
.alert-card--collapsed .alert-card-body { max-height: 0; opacity: 0; }
.alert-card-title { font-weight: 700; font-size: 1rem; }
.alert-card-desc { font-size: .82rem; color: var(--muted); margin-bottom: 1rem; }
.alert-toggle { position: relative; display: inline-block; width: 44px; height: 24px; }
.alert-toggle input { opacity: 0; width: 0; height: 0; }
.alert-toggle-slider { position: absolute; inset: 0; background: var(--border); border-radius: 24px; cursor: pointer; transition: .25s; }
.alert-toggle-slider::before { content: ''; position: absolute; height: 18px; width: 18px; inset-inline-start: 3px; bottom: 3px; background: var(--accent-text, #fff); border-radius: 50%; transition: .25s; }
.alert-toggle input:checked + .alert-toggle-slider { background: var(--accent); }
.alert-toggle input:checked + .alert-toggle-slider::before { transform: translateX(20px); }
[dir="rtl"] .alert-toggle input:checked + .alert-toggle-slider::before { transform: translateX(-20px); }
.alert-recipients-grid { margin-top: .4rem; }
.alert-ms-wrap { position: relative; }
.alert-ms-input { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; min-height: 38px; padding: .35rem .5rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); cursor: pointer; transition: border-color .2s; }
.alert-ms-wrap.alert-ms-open .alert-ms-input { border-color: var(--accent); }
.alert-ms-tags { display: flex; flex-wrap: wrap; gap: .3rem; }
.alert-ms-tag { display: inline-flex; align-items: center; gap: .3rem; padding: .2rem .55rem; border-radius: 6px; background: var(--accent); color: var(--accent-text); font-size: .8rem; white-space: nowrap; }
.alert-ms-tag-remove { cursor: pointer; font-size: .65rem; opacity: .8; margin-inline-start: .2rem; }
.alert-ms-tag-remove:hover { opacity: 1; }
.alert-ms-search { border: none; outline: none; background: transparent; font-size: .85rem; color: var(--text); flex: 1; min-width: 80px; padding: .1rem 0; }
.alert-ms-search::placeholder { color: var(--muted); }
.alert-ms-dropdown { display: none; position: absolute; top: 100%; inset-inline-start: 0; inset-inline-end: 0; z-index: 10; margin-top: 4px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); box-shadow: 0 4px 16px rgba(0,0,0,.15); max-height: 180px; overflow-y: auto; }
.alert-ms-wrap.alert-ms-open .alert-ms-dropdown { display: block; }
.alert-ms-option { padding: .55rem .7rem; font-size: .85rem; cursor: pointer; transition: background .15s; }
.alert-ms-option:hover, .alert-ms-option:focus-visible { background: rgba(var(--accent-rgb),.08); }
/* A11Y-0036 (quality-audit): options are now real Tab stops (tabindex="0") but
   had no visible focus indicator at all -- outline restores one. */
.alert-ms-option:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* A11Y-0063 (quality-audit): the alert-type icon and colour pickers replace their radios
   with the dot beside them, and the radios carried style="display:none". That takes an
   element out of the tab order AND out of the accessibility tree, so neither picker could
   be operated by keyboard or announced at all -- the same failure as the .stg-toggle
   switches, and just as invisible in a screenshot. The radios now use .sr-only, which hides
   them while keeping both.
   box-shadow, not outline, on purpose: the CHECKED state is painted as an inline
   `outline` by the alert-icon-sel / alert-color-sel handlers, and an inline style beats a
   stylesheet rule -- a focus outline here would simply never appear on the checked option,
   which is the one the keyboard lands on first. */
input:focus-visible + .alert-icon-dot,
input:focus-visible + .alert-color-dot {
  box-shadow: 0 0 0 3px var(--accent);
  border-radius: 50%;
}
.alert-channel-row { display: flex; align-items: center; gap: .5rem; font-size: .88rem; margin-top: .3rem; }
.alert-channel-badge { display: inline-block; font-size: .7rem; padding: .1rem .45rem; border-radius: 8px; background: var(--muted); color: #fff; vertical-align: middle; }

.stg-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.stg-section-title {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .85rem 1.2rem;
  background: var(--accent);
  border-bottom: 1px solid var(--border);
  font-size: .85rem;
  font-weight: 700;
  color: var(--accent-text);
}

.stg-body {
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* About page */
.about-logo { width: 340px; max-width: 96%; height: auto; margin: .75rem 0; background: #0E2340; padding: 10px 16px; border-radius: 12px; box-sizing: border-box; }
.about-app-name { margin: 0; font-size: 1.35rem; font-weight: 700; color: var(--text); }
.about-desc { color: var(--muted); font-size: .88rem; line-height: 1.6; margin: .5rem 0 0; max-width: 440px; }
.about-divider { width: 60px; height: 2px; background: var(--border); margin: .5rem auto; border-radius: 2px; }
.about-copyright { font-size: .78rem; color: var(--muted); margin: 0; }
.about-info-row { display: flex; justify-content: space-between; align-items: center; padding: .55rem 0; border-bottom: 1px solid var(--border); }
.about-info-row:last-child { border-bottom: none; }
.about-info-label { font-size: .85rem; color: var(--muted); font-weight: 600; }
.about-info-value { font-size: .85rem; color: var(--text); font-family: 'Consolas', 'Courier New', monospace; }
.cr-notice-main { font-size: 1.05rem; font-weight: 700; color: var(--text); line-height: 1.7; margin: 0; }
.cr-notice-detail { font-size: .85rem; color: var(--muted); line-height: 1.65; margin: 0; }
.cr-link { color: var(--accent); text-decoration: none; font-family: 'Consolas', 'Courier New', monospace; font-size: .85rem; }
.cr-link:hover { text-decoration: underline; }

/* Audit Log */
.audit-row:hover { background: var(--accent-bg, rgba(var(--accent-rgb, 59,130,246), .06)) !important; }
.audit-row.audit-expanded { background: var(--surface); }
/* A11Y-0119 (quality-audit): rows are now keyboard-focusable (role="button"
   tabindex="0") -- shared by pilot-feedback and audit-log rows. */
.audit-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rpt-evac-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.audit-action-badge { display: inline-block; padding: .15rem .5rem; border-radius: 6px; font-size: .78rem; font-weight: 600; background: var(--accent); color: var(--accent-text); white-space: nowrap; }
.audit-detail { padding: .8rem 1.2rem; display: flex; flex-direction: column; gap: .7rem; }
.audit-detail-section { font-size: .85rem; color: var(--text); }
.audit-detail-section strong { color: var(--muted); font-size: .8rem; }
.audit-fields-list code { background: var(--surface); padding: .1rem .35rem; border-radius: 4px; font-size: .78rem; border: 1px solid var(--border); }
.audit-json { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: .6rem .8rem; font-size: .78rem; font-family: 'Consolas', 'Courier New', monospace; overflow-x: auto; max-height: 220px; overflow-y: auto; white-space: pre-wrap; word-break: break-word; margin-top: .3rem; direction: ltr; text-align: left; }
.audit-meta { display: flex; gap: 1.2rem; flex-wrap: wrap; font-size: .8rem; color: var(--muted); }
.audit-detail-row td { padding: 0 !important; border-top: none !important; background: var(--bg); }
.audit-diff-table { width: 100%; border-collapse: collapse; font-size: .82rem; margin-top: .3rem; direction: ltr; text-align: left; }
.audit-diff-table th { background: var(--surface); color: var(--muted); font-weight: 600; padding: .4rem .6rem; border: 1px solid var(--border); font-size: .78rem; }
.audit-diff-table td { padding: .35rem .6rem; border: 1px solid var(--border); vertical-align: top; }
.audit-diff-key code { background: var(--surface); padding: .1rem .3rem; border-radius: 3px; font-size: .78rem; }
.audit-diff-val { font-family: 'Consolas', 'Courier New', monospace; font-size: .78rem; word-break: break-word; }
.audit-diff-changed { background: rgba(var(--accent-rgb, 99,102,241), .08); }
.audit-diff-changed .audit-diff-val:nth-child(2) { color: var(--danger); text-decoration: line-through; opacity: .7; }
.audit-diff-changed .audit-diff-val:nth-child(3) { color: var(--success); font-weight: 600; }
.audit-diff-empty { color: var(--muted); font-style: italic; }

/* Profiles split layout */
.app-main:has(.prof-split) {
  overflow: hidden;
  padding: 0;
}
.prof-split {
  display: flex;
  gap: 0;
  /* Bound the panel to the viewport so .prof-perm-list scrolls internally.
     height:100% is NOT usable here — .app-main is not a definite-height parent,
     so % collapsed to content height (~2600px) and the whole panel overflowed a
     clipped app-main with no way to scroll. The offset is the real chrome:
     ~167px above the split (top-bar + ribbon) + ~28px status bar below ≈ 195px. */
  height: calc(100vh - 195px);
  min-height: 0;
}
.prof-split-right {
  flex: 0 0 30%;
  min-width: 200px;
  border-inline-start: 1px solid var(--border);
  overflow-y: auto;
}
.prof-split-left {
  flex: 1 1 70%;
  min-width: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: .5rem;
}
/* Narrow screens: the panels stack, so scroll the whole app-main instead of
   nesting fixed-height scroll boxes. Must live AFTER the base .prof-split rule
   above — same specificity, later source wins over the height:100% there and the
   height:auto in the earlier @media block. Otherwise the last rows get clipped
   with no way to scroll. */
@media (max-width: 767.98px) {
  .app-main:has(.prof-split) { overflow-y: auto; }
  .prof-split { height: auto; }
  .prof-split-right,
  .prof-split-left { flex: none; width: 100%; overflow: visible; }
  .prof-perm-list { flex: none; overflow: visible; min-height: 0; }
}
.prof-row-active {
  background: rgba(var(--accent-rgb),.12) !important;
  border-inline-end: 3px solid var(--accent);
}
/* A11Y-0120 (quality-audit): the row is now keyboard-focusable (role="button"
   tabindex="0"). */
tr[data-action="prof-select-row"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.prof-perm-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  gap: .8rem;
  color: var(--muted);
  font-size: .95rem;
}
.prof-perm-empty i {
  font-size: 2.2rem;
  opacity: .35;
}
.prof-perm-header {
  font-weight: 700;
  font-size: 1rem;
  padding: .7rem .9rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: .5rem;
  color: var(--accent-h);
}
.prof-perm-list {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: .6rem .5rem;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.prof-perm-module {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .5rem .7rem;
  transition: border-color .15s;
}
.prof-perm-module:hover {
  border-color: var(--accent);
}
.prof-perm-module-title {
  font-weight: 600;
  font-size: .85rem;
  margin-bottom: .35rem;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: .4rem;
}
.prof-perm-module-title i {
  color: var(--accent);
  font-size: .8rem;
  width: 18px;
  text-align: center;
}
/* Collapsible modules: click the title to open/close; caret rotates, body hides. */
.prof-perm-module-title { cursor: pointer; }
.prof-perm-module-title i.prof-perm-caret {
  color: var(--muted);
  font-size: .72rem;
  width: auto;
  transition: transform .15s;
}
.prof-perm-module.collapsed i.prof-perm-caret { transform: rotate(-90deg); }
.prof-perm-module.collapsed > :not(.prof-perm-module-title) { display: none; }
.prof-perm-module.collapsed .prof-perm-module-title { margin-bottom: 0; }
/* Greyed when the module grants nothing (no access). */
.prof-perm-module-empty > .prof-perm-module-title,
.prof-perm-module-empty > .prof-perm-module-title > i { color: var(--muted); }
/* Expand-all / collapse-all controls in the permissions header. */
.prof-perm-eall {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: .1rem .3rem;
  font-size: .95rem;
  display: inline-flex;
  align-items: center;
}
.prof-perm-eall:hover { color: var(--text); }
.prof-perm-checks {
  display: flex;
  gap: .9rem;
  flex-wrap: wrap;
}
.prof-perm-check {
  display: flex;
  align-items: center;
  gap: .3rem;
  font-size: .8rem;
  color: var(--text);
  cursor: pointer;
}
/* Custom high-contrast box so "granted" vs "not granted" reads clearly even in the
   read-only VIEW mode (where every box is disabled). Replaces the old faint
   accent-color box that dimmed to .5 and made checked/unchecked look almost alike. */
.prof-perm-check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  width: 16px;
  height: 16px;
  flex: none;
  margin: 0;
  position: relative;
  border: 1.5px solid var(--muted);   /* bright empty-box border — clearly visible on the dark panel */
  border-radius: 5px;
  background: var(--surface);   /* UI-0106 (quality-audit): was a hardcoded dark-navy hex, invisible against a light-theme panel */
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.prof-perm-check input[type="checkbox"]:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.prof-perm-check input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 4.5px;
  top: 1px;
  width: 4px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.prof-perm-check input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent-h);
  outline-offset: 1px;
}
.prof-perm-disabled {
  cursor: default;
}
/* A disabled box in EDIT mode (a not-applicable sub-permission) keeps a mild dim as
   the "can't edit" cue. */
.prof-perm-disabled input[type="checkbox"] {
  cursor: default;
  opacity: .5;
}
/* But in VIEW mode the whole panel is disabled, so readability wins: full contrast,
   no dim — the filled/empty box carries the meaning. (round-16 view-mode readability) */
.prof-perm-list.viewing .prof-perm-check input[type="checkbox"]:disabled {
  opacity: 1;
}
.prof-perm-sub-header {
  width: 100%;
  font-size: .7rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: .05em;
  text-transform: uppercase;
  padding: .35rem 0 .15rem;
  border-top: 1px solid var(--border);
  margin-top: .2rem;
  display: flex;
  align-items: center;
  gap: .35rem;
  cursor: pointer;
  user-select: none;
}
.prof-perm-sub-header i {
  font-size: .65rem;
  transition: transform .15s;
}
.prof-perm-sub-header.collapsed i {
  transform: rotate(-90deg);
}
.prof-perm-sub-body {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: .9rem;
  overflow: hidden;
  max-height: 600px;
  transition: max-height .2s ease;
}
.prof-perm-sub-body.collapsed {
  max-height: 0;
}
.prof-perm-module-toggle {
  margin-inline-start: auto;
  /* Small inset from the inline-end edge so the wide glyph clears the card border
     and the RTL scrollbar sitting on that side. */
  margin-inline-end: 4px;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  padding: 0;
  border: none;
  transition: color .15s;
  background: none;
}
/* Icon-only now — the switch glyph is the whole control, so size it large.
   The toggle glyph is wider than its font advance (~18px box for a ~34px shape),
   so it painted outside its box and crowded the panel edge. A fixed 1.3em box with
   centred content contains the glyph, so the measured box matches what's drawn. */
.prof-perm-module-toggle i {
  font-size: 1.9rem;
  line-height: 1;
  display: inline-block;
  width: 1.3em;
  text-align: center;
}
/* No background — the glyph colour alone signals state: accent = on, red = off. */
.prof-perm-module-toggle.on  { color: var(--accent); }
.prof-perm-module-toggle.off { color: var(--danger); }
.prof-cell-text {
  padding: .25rem .4rem;
  font-size: .88rem;
}
.prof-detail-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline-end: .7rem;
}
.prof-detail-actions {
  display: flex;
  align-items: center;
}
.prof-edit-btn {
  background: var(--accent);
  color: var(--accent-text) !important;
  border: none;
  border-radius: 8px;
  padding: .5rem 1.1rem;
  font-size: .85rem;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: .45rem;
  transition: background .15s;
}
.prof-edit-btn:hover {
  background: var(--accent-h);
}
.prof-editing-badge {
  display: flex;
  align-items: center;
  gap: .3rem;
  font-size: .78rem;
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.12);
  padding: .3rem .7rem;
  border-radius: 6px;
}
.prof-cancel-btn {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .32rem .75rem;
  font-size: .78rem;
  font-family: inherit;
  color: var(--danger, #f87171);
  background: rgba(248,113,113,.10);
  border: 1px solid rgba(248,113,113,.30);
  border-radius: 6px;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.prof-cancel-btn:hover {
  background: rgba(248,113,113,.22);
  border-color: var(--danger, #f87171);
}
.prof-detail-info {
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: .6rem .9rem;
  border-bottom: 1px solid var(--border);
}
.prof-detail-field {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .88rem;
}
.prof-detail-label {
  color: var(--muted);
  min-width: 50px;
  font-weight: 600;
}
.prof-detail-value {
  color: var(--text);
}

/* Committee read-only mode */
.comm-readonly {
  background: transparent !important;
  border-color: transparent !important;
  pointer-events: none;
  opacity: .85;
}
select.comm-readonly {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
}
.comm-editing-active {
  background: rgba(239,68,68,.15) !important;
  border-color: rgba(239,68,68,.4) !important;
  color: var(--danger) !important;
}
.comm-editing-active:hover {
  background: rgba(239,68,68,.25) !important;
}

/* Preview box */
.stg-preview {
  width: 100%;
  height: 140px;
  background: var(--bg);
  border: 2px dashed var(--border);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color .2s;
  overflow: hidden;
}
.stg-preview:has(.stg-logo-img) { border-style: solid; border-color: var(--border); }
.stg-logo-img {
  max-width: 100%;
  max-height: 136px;
  object-fit: contain;
  display: block;
}
.stg-placeholder-icon { font-size: 2.5rem; color: var(--border); }

/* Action row */
.stg-actions {
  display: flex;
  align-items: center;
  gap: .65rem;
  flex-wrap: wrap;
}

.stg-label-btn { cursor: pointer; }

.stg-btn-remove {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem 1rem;
  background: transparent;
  color: var(--danger);
  border: 1px solid rgba(248,113,113,.4);
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
.stg-btn-remove:hover { background: rgba(248,113,113,.12); border-color: var(--danger); }

/* All three action controls the same height AND aligned. The "choose image"
   control is a <label>: the global `label { margin-bottom: .4rem }` leaked onto
   it, making the flex row taller and pushing it up (looked taller though its box
   was the same 34px) — margin:0 resets that. nowrap keeps its text on one line;
   the transparent 1px border matches the bordered "remove" button's height. */
.stg-actions .um-btn-add,
.stg-actions .stg-btn-remove {
  box-sizing: border-box;
  line-height: 1.2;
  white-space: nowrap;
  margin: 0;
}
.stg-actions .um-btn-add { border: 1px solid transparent; }

.stg-hint {
  font-size: .75rem;
  color: var(--muted);
  margin-top: -.25rem;
}

.ps-totp-status-text {
  color: var(--text-muted);
}

/* ── Toggle switch ── */
.stg-toggle {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 24px;
  flex-shrink: 0;
}
.stg-toggle input { opacity: 0; width: 0; height: 0; }
.stg-toggle-slider {
  position: absolute; inset: 0;
  background: var(--toggle-bg);
  border-radius: 24px;
  cursor: pointer;
  transition: background .25s;
}
.stg-toggle-slider::before {
  content: '';
  position: absolute; top: 3px; inset-inline-start: 3px;
  width: 18px; height: 18px;
  background: var(--accent-text, #fff);
  border-radius: 50%;
  transition: transform .25s;
}
.stg-toggle input:checked + .stg-toggle-slider {
  background: var(--accent);
}
.stg-toggle input:checked + .stg-toggle-slider::before {
  transform: translateX(18px);
}
[dir="rtl"] .stg-toggle input:checked + .stg-toggle-slider::before {
  transform: translateX(-18px);
}
.stg-toggle input:disabled + .stg-toggle-slider {
  opacity: .5;
  cursor: not-allowed;
}
.stg-toggle-locked {
  background: var(--accent) !important;
  opacity: .5;
  cursor: not-allowed;
}
.stg-toggle-locked::before {
  transform: translateX(18px);
}
[dir="rtl"] .stg-toggle-locked::before {
  transform: translateX(-18px);
}

/* ── Module management grid ── */
.stg-modules-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.5rem;
}
.stg-modules-col {
  display: flex;
  flex-direction: column;
}
.stg-module-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .4rem .8rem;
  border-bottom: 1px solid var(--border);
}
.stg-module-row .stg-toggle { flex-shrink: 0; }
.stg-module-wrap { }
.stg-expand-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: 0;
  width: 18px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: color .15s;
  border-radius: 3px;
}
.stg-expand-btn:hover { color: var(--accent); }
.stg-expand-btn i { transition: transform .2s; font-size: .75rem; }
.stg-module-wrap.expanded .stg-expand-btn i { transform: rotate(180deg); }
.stg-subtab-section {
  padding: .3rem .8rem .3rem 3.2rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-alt);
}
[dir="rtl"] .stg-subtab-section { padding: .3rem 3.2rem .3rem .8rem; }
.stg-subtab-hint {
  font-size: .75rem;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: .25rem;
  display: flex;
  align-items: center;
  gap: .3rem;
}
.stg-subtab-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .18rem 0;
  font-size: .82rem;
}
.stg-toggle-sm {
  width: 34px !important;
  height: 18px !important;
}
.stg-toggle-sm .stg-toggle-slider { border-radius: 18px; }
.stg-toggle-sm .stg-toggle-slider::before {
  width: 13px !important;
  height: 13px !important;
  top: 2.5px !important;
  /* L10N-0050 (quality-audit): was the physical `left`, always pinning the
     "off" knob to the left edge even in RTL -- the parent rule's own
     .stg-toggle-slider::before already gets this right via inset-inline-start. */
  inset-inline-start: 2px !important;
}
.stg-toggle-sm input:checked + .stg-toggle-slider::before { transform: translateX(16px) !important; }
[dir="rtl"] .stg-toggle-sm input:checked + .stg-toggle-slider::before { transform: translateX(-16px) !important; }
.stg-expand-all-btn {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .25rem .55rem;
  font-size: .75rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  white-space: nowrap;
  transition: border-color .15s, color .15s;
}
.stg-expand-all-btn:hover { border-color: var(--accent); color: var(--accent); }
.stg-module-col-label {
  font-size: .72rem;
  font-weight: 600;
  color: var(--muted);
  text-align: center;
  width: 52px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .3rem;
}
.stg-module-col-label i { font-size: .7rem; }
.stg-module-locked {
  background: var(--surface-alt, rgba(0,0,0,.03));
  border-radius: 6px 6px 0 0;
}

/* ── Display-Order drag-drop list ────────────────────────────────── */
.do-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 420px;
}
.do-item {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .42rem .7rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: default;
  transition: box-shadow .12s, opacity .12s, background .1s;
  user-select: none;
  outline-offset: 2px;
}
.do-item:focus { outline: 2px solid var(--accent); }
.do-handle {
  cursor: grab;
  color: var(--muted);
  font-size: .85rem;
  flex-shrink: 0;
  padding: 2px 4px;
  border-radius: 3px;
  touch-action: none;
}
.do-handle:active { cursor: grabbing; }
.do-item.is-dragging { opacity: .3; }
.do-item.drag-over[data-drop-half="top"] {
  box-shadow: inset 0 2px 0 var(--accent);
}
.do-item.drag-over[data-drop-half="bottom"] {
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* ═══════════════════════════════════════════
   MANHELET EDITABLE TABLE
   ═══════════════════════════════════════════ */

.mnh-input {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--text);
  font-size: .85rem;
  font-family: inherit;
  text-align: start;
  padding: .2rem .45rem;
  width: 100%;
  min-width: 80px;
  outline: none;
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.mnh-input:hover {
  border-color: var(--border);
  background: rgba(var(--accent-rgb),.08);
}
.mnh-input:focus {
  border-color: var(--accent);
  background: var(--bg);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb),.18);
}
.mnh-date {
  min-width: 140px;
  direction: ltr;
  text-align: start;
  cursor: pointer;
  border-color: var(--border) !important;
  background: var(--bg) !important;
  border-radius: 8px;
  padding: .28rem .5rem;
  color-scheme: dark;
}
[data-theme="light"] .mnh-date { color-scheme: light; }
.mnh-date:hover {
  border-color: var(--accent-h) !important;
}
.mnh-date:focus {
  border-color: var(--accent) !important;
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb),.2) !important;
}

.mnh-select {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: .78rem;
  font-family: inherit;
  font-weight: 600;
  padding: .28rem .8rem;
  outline: none;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.mnh-select:focus { box-shadow: 0 0 0 2px rgba(var(--accent-rgb),.18); }

/* Save button — matches primary style, pulsing to signal unsaved changes */
.mnh-btn-save {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.2rem;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 8px;
  font-size: .85rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s;
  animation: mnh-pulse 1.8s ease-in-out infinite;
}
.mnh-btn-save:hover   { filter: brightness(1.1); }
.mnh-btn-save:disabled { opacity: .65; cursor: not-allowed; animation: none; }
.mnh-btn-nav {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .45rem 1rem;
  background: rgba(var(--accent-rgb),.12);
  color: var(--accent-h);
  border: 1px solid rgba(var(--accent-rgb),.25);
  border-radius: 8px;
  font-size: .8rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
:not(.mnh-btn-nav) + .mnh-btn-nav {
  margin-inline-start: auto;
}
.mnh-btn-nav:hover {
  background: rgba(var(--accent-rgb),.22);
  border-color: var(--accent);
}

@keyframes mnh-pulse {
  0%, 100% { box-shadow: 0 0 0 0   rgba(251,191,36,.55); }
  50%       { box-shadow: 0 0 0 7px rgba(251,191,36,.0);  }
}

/* Population status select */
.pop-status-sel {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: .8rem;
  font-family: inherit;
  padding: .25rem .5rem;
  outline: none;
  cursor: pointer;
  min-width: 120px;
  transition: border-color .15s;
}
.pop-status-sel:focus { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(var(--accent-rgb),.18); }
.pop-birth-input { width: 100%; font-size: .8rem; color: var(--muted); }
.pop-birth-input:focus { color: var(--text); }

/* קלפי — purple/accent */
.mnh-sel-vote {
  color: var(--accent-h);
  border-color: rgba(var(--accent-rgb),.5);
  background: rgba(var(--accent-rgb),.08);
}
/* מתוקף תפקיד — green */
.mnh-sel-role {
  color: var(--success);
  border-color: rgba(52,211,153,.45);
  background: rgba(52,211,153,.07);
}
/* מינוי מקצועי — amber. UI-0055 (quality-audit): was a hardcoded hex identical
   to --warn/--warn-rgb -- now theme-aware (dark/high-contrast/monochrome). */
.mnh-sel-pro {
  color: var(--warn);
  border-color: rgba(var(--warn-rgb),.45);
  background: rgba(var(--warn-rgb),.08);
}
/* התנדבות — pink. UI-0055 (quality-audit): was a hardcoded hex identical to
   --search-pink/--search-pink-rgb -- now theme-aware. */
.mnh-sel-vol {
  color: var(--search-pink);
  border-color: rgba(var(--search-pink-rgb),.45);
  background: rgba(var(--search-pink-rgb),.08);
}

/* QUAL-0041 (quality-audit): was an identical inline style="..." string hand-copied
   at 3 call sites in evacuation.js (skeleton card + 2 live stat-card renders). */
.evac-stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .7rem .5rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}

/* ═══════════════════════════════════════════
   NEW TICKET FORM
   ═══════════════════════════════════════════ */

.ticket-wrap { max-width: 860px; }

.ticket-section-title {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--accent-h);
  margin-bottom: 1.1rem;
  padding-bottom: .65rem;
  border-bottom: 1px solid var(--border);
}

.ticket-form { display: flex; flex-direction: column; gap: 1rem; }

.ticket-layout {
  display: grid;
  grid-template-columns: 1fr 210px;
  gap: 1.5rem;
  align-items: start;
}

.ticket-main { display: flex; flex-direction: column; gap: .85rem; }

.ticket-sidebar {
  display: flex;
  flex-direction: column;
  gap: .85rem;
  background: rgba(var(--accent-rgb),.05);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem 1.1rem;
}

.ticket-sidebar .ticket-btn-save {
  width: 100%;
  justify-content: center;
  margin-top: .25rem;
}

.ticket-row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}

.ticket-field { display: flex; flex-direction: column; gap: .4rem; }

.ticket-field label {
  font-size: .78rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: .04em;
}

.ticket-field select,
.ticket-field textarea,
.ticket-field input[type="text"] {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .9rem;
  font-family: inherit;
  padding: .6rem .85rem;
  outline: none;
  text-align: start;
  transition: border-color .2s, box-shadow .2s;
  width: 100%;
}
.ticket-field select:focus,
.ticket-field textarea:focus,
.ticket-field input[type="text"]:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2);
}
.ticket-field select { cursor: pointer; }
.ticket-field textarea { resize: vertical; min-height: 110px; }

.ticket-readonly {
  opacity: .6;
  cursor: not-allowed !important;
  background: rgba(var(--accent-rgb),.08) !important;
}
/* was an inline style="color:var(--muted)" -- moved to a class so the
   default-theme override below can target it. */
.ticket-optional-note { color: var(--muted); font-weight: 400; }

/* Shared camera+gallery picker (tickets, events, bulletin, messages).
   The camera button is omitted entirely on non-touch devices — decided in JS
   (_canCapture), not by a media query: `(pointer: fine)` fails to match in
   environments that report `pointer: none`, which left the button visible on
   desktop. */
.img-pick-row {
  display: flex;
  gap: .5rem;
  flex-wrap: wrap;
  align-items: center;
  transition: opacity .15s;
}

/* The native input is hidden behind the buttons, which costs its "no file
   chosen" text — this thumbnail is the only confirmation a pick registered. */
.img-pick-thumb {
  max-height: 44px;
  max-width: 72px;
  border-radius: 6px;
  border: 1px solid var(--border);
  object-fit: cover;
}

/* Ticket form shows the photo larger: it is the evidence, not an attachment. */
.img-pick-lg .img-pick-thumb {
  max-height: 120px;
  max-width: 160px;
}

/* Bulletin: five picker+caption rows. Side by side needs min-width:0 or the
   flex children refuse to shrink and the caption is squeezed to a sliver. */
.bulletin-img-row {
  display: flex;
  gap: .5rem;
  align-items: center;
}
.bulletin-img-row .img-pick { flex: 3 1 0; min-width: 0; }
.bulletin-img-row .um-input { flex: 2 1 0; min-width: 0; }

.ticket-upload-label {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.1rem;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: 8px;
  cursor: pointer;
  font-size: .85rem;
  color: var(--muted);
  width: fit-content;
  transition: border-color .2s, color .2s;
}
.ticket-upload-label:hover { border-color: var(--accent); color: var(--accent-h); }

.ticket-img-preview {
  margin-top: .5rem;
  max-width: 220px;
  max-height: 160px;
  border-radius: 8px;
  border: 1px solid var(--border);
  object-fit: contain;
  display: none;
}

.ticket-status-badge {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  background: rgba(52,211,153,.12);
  color: var(--success);
  border: 1px solid rgba(52,211,153,.35);
  border-radius: 20px;
  padding: .3rem .9rem;
  font-size: .82rem;
  font-weight: 600;
  width: fit-content;
}

.ticket-footer { padding-top: .5rem; }

.ticket-btn-save {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .65rem 1.6rem;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 8px;
  font-size: .9rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s, opacity .2s;
}
.ticket-btn-save:hover:not(:disabled) { filter: brightness(1.12); }
.ticket-btn-save:disabled { opacity: .4; cursor: not-allowed; }

.ticket-success {
  background: rgba(52,211,153,.1);
  border: 1px solid rgba(52,211,153,.35);
  border-radius: 10px;
  color: var(--success);
  padding: 1rem 1.25rem;
  font-size: .92rem;
  display: flex;
  align-items: center;
  gap: .65rem;
  animation: fadeUp .3s ease;
}
.ticket-success a { color: var(--accent-h); text-decoration: underline; cursor: pointer; }

/* Info-page upload progress */
.ip-progress-wrap {
  margin-top: 1rem;
  padding: 1rem 1.25rem;
  background: var(--surface, #1e1e2e);
  border: 1px solid var(--border, #333);
  border-radius: 10px;
}
.ip-progress-timer {
  text-align: center;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--accent, #6c63ff);
  margin-bottom: .75rem;
}
.ip-progress-steps {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  margin-bottom: .75rem;
}
.ip-step {
  display: flex;
  align-items: center;
  gap: .5rem;
  color: var(--muted, #888);
  font-size: .88rem;
  transition: color .3s;
}
.ip-step i { width: 1.2em; text-align: center; }
.ip-step.active {
  color: var(--accent, #6c63ff);
  font-weight: 600;
}
.ip-step.done {
  color: var(--success, #34d399);
}
.ip-progress-bar-wrap {
  height: 6px;
  background: var(--border, #333);
  border-radius: 3px;
  overflow: hidden;
}
.ip-progress-bar {
  height: 100%;
  background: var(--accent, #6c63ff);
  border-radius: 3px;
  transition: width .2s ease;
}
.ip-progress-pct {
  text-align: center;
  font-size: .78rem;
  color: var(--muted, #888);
  margin-top: .35rem;
  font-variant-numeric: tabular-nums;
}

/* Info-page dropzone */
.ip-dropzone {
  border: 2px dashed var(--border, #444);
  border-radius: 10px;
  padding: 1rem;
  text-align: center;
  transition: border-color .2s, background .2s;
}
.ip-dropzone.dragover {
  border-color: var(--accent, #6c63ff);
  background: rgba(108,99,255,.08);
}
.ip-dropzone-hint {
  margin-top: .5rem;
  font-size: .8rem;
  color: var(--muted, #888);
}
.ip-dropzone-hint i { margin-inline-end: .3rem; }

/* ═══════════════════════════════════════════
   REGULATION PDF VIEWER
   ═══════════════════════════════════════════ */

.reg-wrap {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  height: calc(100vh - 260px);
  overflow: hidden;
}

.reg-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .75rem;
  padding-bottom: .75rem;
  border-bottom: 1px solid var(--border);
}

.reg-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent-h);
  display: flex;
  align-items: center;
  gap: .5rem;
}

.reg-actions {
  display: flex;
  align-items: center;
  gap: .5rem;
}

.reg-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .45rem 1rem;
  height: 36px;
  line-height: 1;
  border-radius: 8px;
  font-size: .82rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  text-decoration: none;
  transition: filter .2s, background .2s;
  vertical-align: middle;
  box-sizing: border-box;
  margin: 0;
}

.reg-btn-upload {
  background: var(--accent);
  color: var(--accent-text);
  border: none;
}
.reg-btn-upload:hover { filter: brightness(1.12); }

.reg-btn-download {
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  min-width: 145px;
}
.reg-btn-download:hover { filter: brightness(1.12); }
.reg-btn-summary {
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  min-width: 120px;
}
.reg-btn-summary:hover { filter: brightness(1.12); }

.reg-viewer {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface);
}

.reg-iframe {
  width: 100%;
  height: 100%;
  border: none;
  background: var(--bg, #fff);
}

.reg-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  padding: 3rem;
  color: var(--muted);
  font-size: .9rem;
  text-align: center;
}

/* ═══════════════════════════════════════════
   PROCEDURES (נהלים)
   ═══════════════════════════════════════════ */

.proc-wrap {
  display: flex;
  gap: .75rem;
  height: calc(100vh - 260px);
  overflow: hidden;
}

/* ── Households Module ── */
.hh-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  transition: box-shadow .15s;
}
.hh-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,.15); }
.hh-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .6rem .8rem;
  cursor: pointer;
  user-select: none;
  gap: .5rem;
}
.hh-card-header:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: 8px; }
.hh-card-title {
  display: flex;
  align-items: center;
  gap: .45rem;
  font-size: .95rem;
}
.hh-chevron { font-size: .7rem; color: var(--muted); transition: transform .15s; }
/* Report drill-down chevrons -- same treatment as .hh-chevron above. Was an inline
   style repeated at two call sites; a class keeps both branches of the open/closed
   ternary looking identical, which an inline style on one branch did not. */
.rep-chevron { font-size: .7rem; color: var(--muted); }
.hh-card-badges {
  display: flex;
  align-items: center;
  gap: .4rem;
  flex-shrink: 0;
}
.hh-badge {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  background: var(--accent);
  color: #fff;
  font-size: .72rem;
  padding: .15rem .5rem;
  border-radius: 12px;
  font-weight: 600;
}
.hh-badge-dep { background: var(--muted); }
/* UI-0111 (quality-audit): mirrors .hh-badge -- the sysdoc file-type badge
   (regulations.js) used to hardcode background:#12294c inline, the same bug
   class UI-0093 already fixed a few lines above it for the sibling Open/Print
   buttons (an inline style always wins over [data-theme="high-contrast"]'s
   class rule). */
.sysdoc-filetype-badge {
  background: var(--accent);
  color: #fff;
  padding: 1px 8px;
  border-radius: 4px;
  font-size: .75rem;
}
.hh-action-btn {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: .25rem .35rem;
  border-radius: 4px;
  font-size: .8rem;
  transition: color .15s, background .15s;
}
.hh-action-btn:hover { color: var(--accent); background: rgba(var(--accent-rgb),.12); }
.hh-card-body {
  padding: .5rem .8rem .7rem;
  border-top: 1px solid var(--border);
}
.hh-section { margin-bottom: .5rem; }
.hh-section:last-child { margin-bottom: 0; }
.hh-section h4 {
  font-size: .8rem;
  color: var(--muted);
  margin-bottom: .3rem;
  display: flex;
  align-items: center;
  gap: .3rem;
}
.hh-members-list { display: flex; flex-wrap: wrap; gap: .3rem; }
.hh-member-chip {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  background: rgba(var(--accent-rgb),.1);
  color: var(--text);
  font-size: .8rem;
  padding: .2rem .55rem;
  border-radius: 14px;
  border: 1px solid rgba(var(--accent-rgb),.25);
}
.hh-chip-dep {
  background: rgba(128,128,128,.1);
  border-color: rgba(128,128,128,.25);
}
.hh-empty { color: var(--muted); font-size: .8rem; }
/* Household selector (modal) */
.hh-selector-list {
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}
.hh-sel-chips {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  padding: .4rem;
  border-bottom: 1px solid var(--border);
}
.hh-sel-chip {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: var(--accent);
  color: #fff;
  font-size: .78rem;
  padding: .15rem .5rem;
  border-radius: 12px;
}
.hh-chip-remove {
  background: none;
  border: none;
  color: rgba(255,255,255,.7);
  cursor: pointer;
  font-size: .7rem;
  padding: 0;
  line-height: 1;
}
.hh-chip-remove:hover { color: #fff; }
.hh-sel-dropdown { max-height: 130px; overflow-y: auto; }
.hh-sel-option {
  padding: .35rem .6rem;
  cursor: pointer;
  font-size: .82rem;
  color: var(--text);
  transition: background .1s;
}
.hh-sel-option:hover { background: rgba(var(--accent-rgb),.12); }
.hh-sel-empty {
  padding: .5rem .6rem;
  color: var(--muted);
  font-size: .82rem;
  text-align: center;
}

.proc-sidebar {
  width: 260px;
  min-width: 140px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  flex-shrink: 0;
}

.proc-splitter {
  width: 6px;
  cursor: col-resize;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.proc-splitter::before {
  content: '';
  width: 3px;
  height: 40px;
  border-radius: 3px;
  background: var(--border);
  transition: background .2s, height .2s;
}
.proc-splitter:hover::before,
.proc-splitter.active::before {
  background: var(--accent);
  height: 60px;
}
.proc-splitter::after {
  content: '';
  position: absolute;
  inset: 0 -6px;
}

.proc-sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .7rem 1rem;
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--border);
}

.proc-sidebar-title {
  font-size: .85rem;
  font-weight: 700;
  color: #ffffff;
  display: flex;
  align-items: center;
  gap: .4rem;
}

.proc-add-btn {
  display: flex;
  align-items: center;
  gap: .3rem;
  padding: .3rem .7rem;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 6px;
  font-size: .75rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s;
}
.proc-add-btn:hover { filter: brightness(1.15); }

/* New procedure form */
.proc-new-form {
  padding: .75rem .85rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: .5rem;
  background: rgba(var(--accent-rgb),.04);
}

.proc-new-input {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font-size: .82rem;
  font-family: inherit;
  padding: .4rem .65rem;
  outline: none;
  text-align: start;
}
.proc-new-input:focus { border-color: var(--accent); }

.proc-file-label {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .35rem .75rem;
  border: 1px dashed var(--border);
  border-radius: 6px;
  font-size: .78rem;
  color: var(--muted);
  cursor: pointer;
  width: fit-content;
  transition: border-color .2s, color .2s;
}
.proc-file-label:hover { border-color: var(--accent); color: var(--accent-h); }

.proc-file-name {
  font-size: .72rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.proc-save-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: .4rem;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 6px;
  font-size: .8rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: filter .2s, opacity .2s;
}
.proc-save-btn:hover:not(:disabled) { filter: brightness(1.12); }
.proc-save-btn:disabled { opacity: .4; cursor: not-allowed; }

/* Procedure list */
.proc-list {
  flex: 1;
  overflow-y: auto;
  padding: .4rem;
  direction: ltr;
  scrollbar-width: thin;
  scrollbar-color: var(--accent) transparent;
}
html[dir="rtl"] .proc-list > * { direction: rtl; }
html[dir="ltr"] .proc-list > * { direction: ltr; }
.proc-list::-webkit-scrollbar {
  width: 6px;
}
.proc-list::-webkit-scrollbar-track {
  background: transparent;
}
.proc-list::-webkit-scrollbar-thumb {
  background: var(--accent);
  border-radius: 3px;
}
.proc-list::-webkit-scrollbar-thumb:hover {
  background: var(--accent-h);
}

/* Protocol groups (committees) */
.pr-group {
  margin-bottom: .35rem;
}
.pr-group-header {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .35rem .6rem;
  font-size: .72rem;
  font-weight: 700;
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.08);
  border-radius: 6px;
  margin-bottom: .2rem;
  position: sticky;
  top: 0;
  z-index: 1;
}
.pr-group-toggle {
  cursor: pointer;
  user-select: none;
  transition: background .15s;
}
.pr-group-toggle:hover {
  background: rgba(var(--accent-rgb),.16);
}
.pr-group-arrow {
  font-size: .55rem;
  transition: transform .2s;
}
.pr-group-arrow-collapsed {
  transform: rotate(-90deg);
}

.pr-toggle-all-wrap {
  margin-inline-start: auto;
  display: flex;
  gap: .25rem;
}
.pr-toggle-all-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
  font-size: .65rem;
  padding: 2px 6px;
  border-radius: 4px;
  transition: color .15s, background .15s, border-color .15s;
}
.proc-sidebar-header .pr-toggle-all-btn {
  color: #ffffff;
  border-color: rgba(255,255,255,.35);
}
.pr-toggle-all-btn:hover {
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.18);
  border-color: var(--accent);
}

.pr-group-end {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: .35rem;
}
.pr-group-nav {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  font-size: .7rem;
  padding: 2px 6px;
  border-radius: 4px;
  transition: color .15s, background .15s;
}
.pr-group-nav:hover {
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.18);
}

.proc-list-empty {
  padding: 1.5rem;
  text-align: center;
  font-size: .82rem;
  color: var(--muted);
}

.proc-item {
  display: flex;
  align-items: center;
  gap: .55rem;
  padding: .55rem .7rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s;
  margin-bottom: .25rem;
}
.proc-item:hover { background: rgba(var(--accent-rgb),.08); }
.proc-item-active { background: rgba(var(--accent-rgb),.18) !important; }
.proc-item-drag-over { border-top: 2px solid var(--accent) !important; }
.grp-row-drag-over { outline: 2px solid var(--accent); outline-offset: -2px; }

.proc-item-icon { color: var(--danger); font-size: .95rem; flex-shrink: 0; }

.proc-item-info {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

.proc-item-actions {
  display: flex;
  align-items: center;
  gap: .2rem;
  flex-shrink: 0;
  margin-inline-start: auto;
}

.proc-item-name {
  font-size: .82rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  white-space: nowrap;
}

.proc-item-date {
  font-size: .68rem;
  color: var(--text);
}

.proc-item-del {
  width: var(--act-btn); height: var(--act-btn);
  background: transparent;
  border: none;
  border-radius: 5px;
  /* colour comes from the grouped .um-btn-del rule above — one definition for every
     row-delete in the app. It used to be `color: var(--text)` here, which is why
     this looked like a neutral icon while the same action elsewhere was red. */
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--act-icon);
  opacity: 1;
  transition: opacity .15s, color .15s, background .15s;
  position: relative;   /* containing block for ::after's tap-target extension, see .um-btn-icon */
}
/* Same invisible tap-target extension as .um-btn-icon -- see its comment. */
.proc-item-del::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: max(44px, 100%);
  height: max(44px, 100%);
}
.proc-item:hover .proc-item-del,
.regs-tree-header:hover .proc-item-del { opacity: 1; }
.proc-item-del:hover { color: var(--danger); background: rgba(248,113,113,.12); }

/* Sidebar-list icons — brighter, always-visible edit/delete (chosen: option A,
   near-white), across the whole .proc-item family (info-pages, procedures, sysdocs,
   audits, protocols, committees, directory). Users/facilities keep their accent
   look (their .um-btn-edit is not inside .proc-item).
   The color MUST be set on the <i.app-icon> itself, not just the button: the
   duotone icon-style sets `[data-icon-style="duotone"] i.app-icon { color:
   var(--accent) }` DIRECTLY on the icon (specificity 0,2,1), which beats a color
   merely inherited from the button. These win at 0,3,x, so option A holds in fill,
   duotone AND flat. Theme-safe: var(--text) is dark on light, near-white on dark. */
.proc-item .um-btn-icon    .app-icon,
.proc-item .proc-item-topics .app-icon {
  color: var(--text);
  --ph-duotone-color: rgba(232,238,248,.30);
}
/* .proc-item-del is NOT in the group above any more. That rule is more specific
   than the .um-btn-del/.proc-item-del colour rule, so leaving it in forced the
   delete icon back to var(--text) inside a .proc-item and the unification would
   have applied everywhere EXCEPT the lists it was modelled on.
   .um-btn-del needs naming too: it rides .um-btn-icon, which IS still in the group
   above, so a migrated delete button sitting in a .proc-item would lose its red. */
.proc-item .proc-item-del .app-icon,
.proc-item .um-btn-del    .app-icon { color: var(--danger); }
/* .um-btn-icon (not just .um-btn-edit) so summary/aux action buttons in the list
   items — e.g. the protocols "summary" button with an inline color:var(--accent) —
   go white too. A rule on the <i> beats the inline color inherited from the button. */
.proc-item .um-btn-edit:hover   .app-icon { color: var(--accent-lt); }
.proc-item .proc-item-del:hover .app-icon { color: var(--danger); }

/* Regulations/documents tree — same option-A brightening, but this tree uses
   .regs-tree-* classes (not .proc-item), so it needs its own rules. Scoped by
   #content-regulations (id → 1,x,x) to beat the duotone `i.app-icon` rule.
   Option B: ALL tree icons — the caret arrow, the category/document icon, and the
   add / edit / delete actions — go var(--text). */
#content-regulations .regs-tree-header .app-icon,
#content-regulations .regs-tree-doc    .app-icon {
  color: var(--text);
  --ph-duotone-color: rgba(232,238,248,.30);
}
/* Same exception as .proc-item above: the rule immediately preceding this one is an
   id selector and beats the shared delete colour, so without this the documents
   tree would be the one place the delete icon is still not red. */
#content-regulations .regs-tree-header .proc-item-del .app-icon,
#content-regulations .regs-tree-doc    .proc-item-del .app-icon,
#content-regulations .regs-tree-header .um-btn-del    .app-icon,
#content-regulations .regs-tree-doc    .um-btn-del    .app-icon { color: var(--danger); }
#content-regulations .regs-tree-header .proc-item-del:hover .app-icon { color: var(--danger); }
#content-regulations .regs-tree-header .regs-tree-add:hover  .app-icon { color: var(--accent-lt); }
/* .regs-tree-add rests at opacity .6 (faded) — lift it so the edit/add icons read
   as crisp white like the delete, not a dim grey. */
#content-regulations .regs-tree-add { opacity: 1; }

/* ═══ round-11: unified action-icon system (colour · size · hover) ══════════
   _tagActionIcons() (app.js) marks every icon-ONLY row-action button with
   data-actico="del" (trash glyph) or "edit" (pencil glyph), so ONE place styles
   them all — whatever their own class is (um-btn-edit / proc-item-del / regs-
   tree-add / hh-action-btn / prof-edit-btn / bulletin-edit-btn / bare um-btn-
   icon …). Buttons that also carry text (the "edit-mode" toggles, the editing
   badge) are never tagged, so they keep their look.
   DEFAULT = COLOURED (del→red, edit→blue); <html data-act-color="white"> flips
   them neutral. Colour is written in THREE specificity tiers so it also beats
   the .proc-item "option-A white" (0,3,0) and the #content-regulations id (1,2,0);
   the html[attr] prefix then lifts each white-mode tier over its coloured twin. */

/* uniform glyph size + transitions on every tagged button */
[data-actico] .app-icon {
  font-size: var(--act-icon);
  transition: transform .2s cubic-bezier(.34,1.56,.64,1), filter .2s, color .15s;
}

/* — COLOURED (default) — three tiers: general / .proc-item / #content-regulations — */
[data-actico="del"]  .app-icon,
.proc-item           [data-actico="del"] .app-icon,
#content-regulations [data-actico="del"] .app-icon { color: var(--danger); }
[data-actico="edit"] .app-icon,
.proc-item           [data-actico="edit"] .app-icon,
#content-regulations [data-actico="edit"] .app-icon { color: var(--accent); }

/* — WHITE mode — every action icon neutral (html[attr] wins over the tier above) — */
html[data-act-color="white"] [data-actico] .app-icon,
html[data-act-color="white"] .proc-item           [data-actico] .app-icon,
html[data-act-color="white"] #content-regulations [data-actico] .app-icon { color: var(--text); }

/* — LIFT + SHADOW hover (no box/pill) — */
[data-actico]:hover { background: transparent; border-color: transparent; }
[data-actico]:hover .app-icon { transform: translateY(-3px); filter: drop-shadow(0 3px 4px rgba(0,0,0,.30)); }

/* — reduced-motion (OS query + the app's own toggle): keep the colour, drop the lift — */
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) [data-actico]:hover .app-icon { transform: none; filter: none; } }
html[data-motion="reduce"] [data-actico]:hover .app-icon { transform: none; filter: none; }

/* Year filter buttons */
.ip-year-filter {
  padding: .4rem .6rem;
  border-bottom: 1px solid var(--border);
}
.ip-year-btns {
  display: flex;
  gap: .3rem;
  flex-wrap: wrap;
}
.ip-year-btn {
  padding: .25rem .65rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  font-size: .75rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.ip-year-btn:hover { background: rgba(var(--accent-rgb),.1); color: var(--accent-h); }
.ip-year-active {
  background: rgba(var(--accent-rgb),.2) !important;
  color: var(--accent-h) !important;
  border-color: var(--accent) !important;
}

.proc-item-topics {
  font-size: .68rem;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: .25rem;
  cursor: default;
}

/* ── Topic Tooltip ── */
.topic-tooltip {
  position: fixed;
  z-index: 1500;
  display: none;
  pointer-events: none;
  background: linear-gradient(145deg, var(--surface), var(--bg));
  color: var(--text);
  border: 1px solid rgba(var(--accent-rgb),.35);
  border-radius: 14px;
  box-shadow:
    0 25px 70px rgba(0,0,0,.35),
    0 0 0 1px rgba(var(--accent-rgb),.1),
    inset 0 1px 0 rgba(255,255,255,.04);
  padding: .85rem 1rem;
  max-width: 320px;
  min-width: 180px;
  backdrop-filter: blur(12px);
  animation: tooltipIn .15s ease;
}
.topic-tooltip::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 14px;
  padding: 1px;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),.3), rgba(124,58,237,.2), transparent 60%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.topic-tooltip-title {
  font-size: .75rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: .55rem;
  padding-bottom: .4rem;
  border-bottom: 1px solid rgba(var(--accent-rgb),.2);
  display: flex;
  align-items: center;
  gap: .35rem;
}

.topic-tooltip-list {
  display: flex;
  flex-direction: column;
  gap: .3rem;
}

.topic-tooltip-item {
  font-size: .78rem;
  color: var(--text);
  line-height: 1.45;
  display: flex;
  align-items: flex-start;
  gap: .4rem;
}

.topic-tooltip-num {
  min-width: 18px;
  height: 18px;
  background: rgba(232,238,248,.12);
  color: var(--text);
  border-radius: 50%;
  font-size: .62rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}
/* the title's list icon — recolor on the <i> so it beats the duotone icon-style
   (i.app-icon → var(--accent)); the title text/numbers above are already var(--text). */
.topic-tooltip .topic-tooltip-title .app-icon {
  color: var(--text);
  --ph-duotone-color: rgba(232,238,248,.30);
}

/* Topics wrapper + toggle */
.ip-topics-wrap {
  flex-shrink: 0;
}

.ip-topics-header {
  display: flex;
  align-items: center;
  gap: .4rem;
}

.ip-topics-refresh {
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .8rem;
  transition: color .15s, background .15s, border-color .15s;
}
.ip-topics-refresh:hover {
  color: var(--accent-h);
  background: rgba(var(--accent-rgb),.12);
  border-color: var(--accent);
}
@keyframes ip-spin { to { transform: rotate(360deg); } }
.ip-topics-refresh.ip-loading {
  opacity: .7;
  pointer-events: none;
  cursor: default;
  width: auto !important;
  padding: 0 8px;
  gap: 3px;
}
.ip-topics-refresh.ip-loading .app-icon {
  animation: ip-spin .75s linear infinite;
  display: inline-block;
}
/* .ip-refresh-timer removed (09/10): styled the ticking elapsed-seconds badge
   that used to sit beside the spinning refresh icon -- removed app-wide, see
   .ai-think-timer's identical removal note above. */

.ip-topics-toggle {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .4rem .85rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--accent-h);
  font-size: .8rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s;
  width: 100%;
}
.ip-topics-toggle:hover { background: rgba(var(--accent-rgb),.08); }

.ip-toggle-arrow {
  font-size: .65rem;
  margin-inline-end: auto;
  transition: transform .2s;
}

/* Topics bar in viewer */
.ip-topics-bar {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .75rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 8px 8px;
  overflow-x: auto;
  flex-wrap: wrap;
  flex-shrink: 0;
  animation: fadeUp .2s ease;
}
.ip-topics-bar::-webkit-scrollbar { display: none; }

.ip-topic-tag {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: rgba(var(--accent-rgb),.1);
  color: var(--accent-h);
  border: 1px solid rgba(var(--accent-rgb),.25);
  border-radius: 20px;
  padding: .15rem .55rem;
  font-size: .72rem;
  white-space: nowrap;
}

.ip-topic-remove {
  background: none;
  border: none;
  color: var(--muted);
  font-size: .85rem;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color .15s, background .15s;
}
.ip-topic-remove:hover {
  color: var(--danger);
  background: rgba(248,113,113,.15);
}

/* Add topic inline */
.topic-add-wrap {
  gap: .2rem !important;
}
/* A11Y-0134 (quality-audit): .topic-add-input below sets outline:none with no
   replacement -- a keyboard user tabbing to it saw no focus indicator at all.
   It has no border of its own to recolor, but its .ip-topic-tag parent
   (.topic-add-wrap carries both classes) already does -- recolor that on
   :focus-within instead, same technique as .dap-chat-input-bar input:focus. */
.topic-add-wrap:focus-within { border-color: var(--accent); }
.topic-add-input {
  background: transparent;
  border: none;
  color: var(--text);
  font-size: .72rem;
  font-family: inherit;
  outline: none;
  width: 120px;
  text-align: start;
}
.topic-add-input::placeholder { color: var(--muted); }

/* Viewer area */
.proc-viewer-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: .75rem;
  min-width: 0;
  overflow-y: auto;
}

/* Groups — tab buttons */
.grp-tab-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: .35rem .8rem;
  font-size: .82rem;
  cursor: pointer;
  color: var(--muted);
  transition: color .15s, border-color .15s;
  margin-bottom: -1px;
}
.grp-tab-btn:hover { color: var(--text); }
.grp-tab-active { color: var(--accent) !important; border-bottom-color: var(--accent) !important; font-weight: 600; }

/* Groups — history timeline */
.grp-history-list { display: flex; flex-direction: column; gap: .5rem; }
.grp-history-row {
  display: flex;
  gap: .7rem;
  align-items: flex-start;
  padding: .5rem .4rem;
  border-radius: 6px;
  border-bottom: 1px solid var(--border-subtle, rgba(0,0,0,.06));
}
.grp-history-icon { width: 1.4rem; text-align: center; padding-top: .1rem; flex-shrink: 0; font-size: .9rem; }
.grp-history-body { flex: 1; min-width: 0; }
.grp-history-action { font-size: .82rem; font-weight: 400; margin-bottom: .1rem; }
.grp-history-meta { display: flex; gap: .6rem; align-items: center; font-size: .78rem; color: var(--muted); }
.grp-history-detail { font-size: .72rem; color: var(--muted); margin-top: .15rem; word-break: break-all; }

.proc-viewer-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  color: var(--muted);
  font-size: .9rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}

/* ═══════════════════════════════════════════
   OPEN TICKETS LIST
   ═══════════════════════════════════════════ */

.ot-list { display: flex; flex-direction: column; gap: 1.25rem; }

.ot-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}

.ds-card:hover { background: rgba(var(--accent-rgb),.06); }
.ds-card .ot-card-top { display: flex; justify-content: space-between; gap: .5rem; position: relative; }

.ds-topics {
  margin-top: .4rem;
  padding-top: .4rem;
  border-top: 1px solid var(--border);
}
.ds-topics-title {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-size: .75rem;
  color: var(--text-muted);
  margin-bottom: .35rem;
}
.ds-topics-list {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
}
.ds-topic-tag {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .72rem;
  background: rgba(var(--accent-rgb),.08);
  color: var(--text-muted);
  padding: .18rem .55rem;
  border-radius: 5px;
  border: 1px solid rgba(var(--accent-rgb),.15);
}
.ds-topic-match {
  background: rgba(250,204,21,.18);
  border-color: rgba(250,204,21,.45);
  color: var(--text-primary);
}
.ds-topic-num {
  font-weight: 700;
  color: var(--accent-h);
  font-size: .65rem;
  min-width: .9rem;
  text-align: center;
}
/* AI Search tabs */
.ai-search-tabs {
  display: flex;
  border-bottom: 2px solid var(--border);
  background: var(--surface);
}
.ai-search-tab {
  flex: 1;
  padding: .6rem 1rem;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  color: var(--muted);
  font-size: .85rem;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  transition: color .15s, border-color .15s;
}
.ai-search-tab:hover { color: var(--text); }
.ai-search-tab.active { color: var(--accent-h); border-bottom-color: var(--accent-h); }

/* AI Chat — fills available space, no outer scroll */
body.ai-chat-open .app-main {
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0;
}
body.ai-chat-open #panel-ai,
body.ai-chat-open #content-ai,
body.ai-chat-open .content-area,
body.ai-chat-open .um-wrap {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
body.ai-chat-open #aiChatContainer {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
.ai-chat-wrap {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  height: 100%;
}
body.ai-chat-open .ai-input-row {
  padding-inline-end: 90px; /* clear the fixed FAB rail (inset-inline-end:28px + width:52px ≈ 80px) */
}
.ai-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: .75rem;
}
.ai-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: .88rem;
  text-align: center;
  padding: 2rem;
}
.ai-empty-icon {
  width: 5rem;
  height: 5rem;
  border-radius: 50%;
  /* AI Visual Language (Stage 2b): was var(--bg-light, rgba(99,102,241,.08)) --
     --bg-light was never defined anywhere, so this always resolved to the
     fallback, a hardcoded indigo unrelated to the mascot's own purple. */
  background: rgba(var(--ai-accent-rgb),.08);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ai-empty-icon .ai-msg-icon { font-size: 2.5rem; margin: 0; }
.ai-empty-icon .ai-msg-logo { width: 2.8rem; height: 2.8rem; margin: 0; }
.ai-msg {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  max-width: 85%;
}
.ai-msg-user { align-self: flex-end; flex-direction: row-reverse; }
.ai-msg-bot  { align-self: flex-start; }
.ai-msg-icon {
  font-size: .85rem;
  color: var(--muted);
  margin-top: .35rem;
  flex-shrink: 0;
}
.ai-msg-logo {
  width: 1.5rem;
  height: 1.5rem;
  object-fit: contain;
  border-radius: 4px;
  flex-shrink: 0;
  margin-top: .2rem;
}
/* "Aria" — the assistant avatar (warm floating blob mascot). Sizes to its context:
   small beside a message, large in the empty-chat hero. */
.ai-aria {
  width: 1.7rem;
  height: 1.7rem;
  flex-shrink: 0;
  margin-top: .15rem;
  display: inline-block;
  line-height: 0;
  /* AI Visual Language (Stage 2b): was a hardcoded pink (255,107,157), unrelated
     to the mascot's own purple or the site's palette. */
  filter: drop-shadow(0 2px 5px rgba(var(--ai-accent-rgb), .4));
}
.ai-aria svg { width: 100%; height: 100%; overflow: visible; display: block; }
.ai-empty-icon .ai-aria { width: 2.9rem; height: 2.9rem; margin: 0; }
/* "Amit" — the user avatar (illustrated portrait) beside their own messages. */
.ai-user-av { width: 1.7rem; height: 1.7rem; flex-shrink: 0; margin-top: .15rem; display: inline-block; line-height: 0; }
.ai-user-av svg { width: 100%; height: 100%; display: block; }
.ai-aria-float { transform-box: fill-box; transform-origin: center; animation: aiAriaFloat 3.6s ease-in-out infinite; }
@keyframes aiAriaFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) .ai-aria * { animation: none !important; } }
.ai-msg-bubble {
  padding: .55rem .85rem;
  border-radius: 12px;
  font-size: .88rem;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}
.ai-msg-user .ai-msg-bubble {
  background: var(--accent-h);
  color: #fff;
  border-end-end-radius: 3px;
}
/* Quantum: navy user bubble; white text for legibility (was gold accent). */
:root:not([data-theme]) .ai-msg-user .ai-msg-bubble {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff;
}
.ai-msg-bot .ai-msg-bubble {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  border-end-start-radius: 3px;
}
.ai-thinking {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: .65rem .85rem !important;
}
.ai-thinking span {
  width: 7px; height: 7px;
  background: var(--muted);
  border-radius: 50%;
  animation: ai-bounce .9s infinite;
}
.ai-thinking span:nth-child(2) { animation-delay: .15s; }
.ai-thinking span:nth-child(3) { animation-delay: .3s; }
/* .ai-think-timer removed (09/10): styled the ticking elapsed-seconds counter
   that used to sit beside a loading spinner app-wide -- every call site that
   rendered one was migrated to spinner-only, leaving this class unused. */
@keyframes ai-bounce {
  0%,80%,100% { transform: translateY(0); opacity:.4; }
  40%          { transform: translateY(-5px); opacity:1; }
}
.ai-refs { margin-top: .6rem; padding-top: .5rem; border-top: 1px solid var(--border); }
.ai-refs-title { font-size: .73rem; font-weight: 700; color: var(--muted); margin-bottom: .4rem; }
.ai-ref-link {
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: .3rem .5rem;
  border-radius: 6px;
  background: var(--bg);
  color: var(--accent-h);
  text-decoration: none;
  font-size: .78rem;
  font-weight: 600;
  margin-bottom: .3rem;
  transition: background .15s;
}
.ai-ref-link:hover { background: var(--border); }
.ai-ref-type {
  margin-inline-start: auto;
  font-size: .68rem;
  color: var(--muted);
  font-weight: 400;
}
.ai-msg-feedback {
  display: flex;
  gap: .3rem;
  margin-top: .35rem;
  opacity: .55;
  transition: opacity .15s;
}
.ai-msg-feedback:hover { opacity: 1; }
.ai-fb-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1rem;
  padding: .1rem .25rem;
  border-radius: 6px;
  transition: background .15s;
}
.ai-fb-btn:hover { background: var(--border); }
.ai-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  margin-top: .6rem;
  padding-top: .5rem;
  border-top: 1px solid var(--border);
}
.ai-sugg-chip {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: .3rem .75rem;
  font-size: .78rem;
  cursor: pointer;
  color: var(--accent-h);
  transition: background .15s, border-color .15s;
}
.ai-sugg-chip:hover { background: var(--accent-h); color: #fff; border-color: var(--accent-h); }

/* F029 — agentic "open a ticket" confirmation card (rendered inline in the chat).
   AI Visual Language (Stage 2c, WOW-UX review Signature B): border/header
   recolored from the site's general --accent to --ai-accent -- every one of
   these 12 card types is an AI proposal, not a generic UI accent moment. */
.ai-action-card {
  margin: .6rem 0 .2rem;
  padding: .8rem .9rem;
  background: var(--surface);
  border: 1px solid var(--ai-accent);
  border-inline-start: 3px solid var(--ai-accent);
  border-radius: 10px;
  box-shadow: 0 1px 4px rgba(0,0,0,.06);
  max-width: 92%;
}
.ai-action-head {
  font-weight: 700;
  font-size: .92rem;
  /* --ai-accent, NOT --ai-accent-dark. That token is documented at its definition as
     the mascot's darker gradient stop -- an ILLUSTRATION colour -- and it was being
     borrowed here as text. On the default theme's dark --surface that lands at 2.09
     against a 4.5 requirement: the heading of every agentic card was unreadable, in
     the theme most people use. Measured, not guessed; --ai-accent gives 6.04 on the
     same surface and is the token that already marks AI-touched text everywhere else.
     The mascot keeps its own token, unchanged. */
  color: var(--ai-accent);
  display: flex;
  align-items: center;
  gap: .4rem;
  margin-bottom: .3rem;
}
/* The small sparkle that precedes each card's own domain icon (car, wrench,
   calendar...) -- signals "AI proposed this" without replacing the action's
   own identity icon. Scoped here, not baked into .ai-icon, since that class
   is also used at full size elsewhere (document summaries, stage 2a). */
.ai-action-head .ai-icon { font-size: .8em; }
.ai-action-intro { font-size: .8rem; color: var(--muted); margin-bottom: .6rem; }
/* The end of a completed agentic action: a link to the record it just created or
   changed. The UX review named this the missing half of the product's signature
   moment -- the flow used to finish on a checkmark and leave the user to go find the
   thing themselves.

   Uses --ai-accent, the one colour that marks anything AI-touched app-wide, so the
   ending belongs to the same language as the card it closes. Quiet by construction:
   text and a small out-arrow, no filled button -- the action is already done, this is
   an offer rather than the next step. */
.ai-action-open { margin-top: .5rem; }
.ai-open-record {
  display: inline-flex; align-items: center; gap: .35rem;
  background: none; border: 0; padding: .2rem 0; cursor: pointer;
  font-family: inherit; font-size: .82rem; font-weight: 600;
  color: var(--ai-accent);   /* same reason as .ai-action-head above */
  transition: color .18s;
}
.ai-open-record:hover { text-decoration: underline; filter: brightness(1.15); }
.ai-open-record:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.ai-action-lbl {
  display: block;
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted);
  margin: .5rem 0 .2rem;
}
.ai-action-card .um-input { width: 100%; }
.ai-action-foot { display: flex; gap: .5rem; margin-top: .8rem; }
.ai-action-foot .ai-act-cancel {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .4rem .9rem;
  font-size: .82rem;
  cursor: pointer;
  color: var(--text);
}
.ai-action-foot .ai-act-cancel:hover { background: var(--bg); }
.ai-action-done { border-color: var(--success, #2e7d32); border-inline-start-color: var(--success, #2e7d32); }
.ai-action-done .ai-action-head { color: var(--success, #2e7d32); }

.ai-new-chat-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: .78rem;
  padding: .3rem .7rem;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  align-self: flex-end;
  transition: background .15s, color .15s;
}
.ai-new-chat-btn:hover { background: var(--border); color: var(--text); }
.ai-msg-copy {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: .72rem;
  padding: .2rem .3rem;
  border-radius: 4px;
  opacity: 0;
  transition: opacity .15s, color .15s;
  align-self: flex-end;
  margin-bottom: .2rem;
  flex-shrink: 0;
}
.ai-msg:hover .ai-msg-copy { opacity: 1; }
.ai-msg-copy:hover { color: var(--accent-h); background: var(--border); }
.ai-input-row {
  display: flex;
  gap: .5rem;
  padding: .75rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--surface);
}
.ai-input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  padding: .55rem .75rem;
  font-size: .88rem;
  resize: none;
  font-family: inherit;
}
.ai-input:focus { outline: none; border-color: var(--accent-h); }

.ds-filters {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: .4rem 1rem;
  border-bottom: 1px solid var(--border);
}
.ds-filter-check {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .8rem;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
.ds-filter-check input[type="checkbox"] {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
  cursor: pointer;
}

/* .ds-timer removed (09/10): styled the ticking elapsed-seconds counter that
   used to sit next to the "Searching..." spinner -- removed app-wide, see
   .ai-think-timer's identical removal note above. */
.ds-results-header {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .5rem 1rem;
  font-size: .8rem;
  color: var(--text-muted);
}
.ds-time-badge {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .72rem;
  background: rgba(var(--accent-rgb),.08);
  color: var(--accent-h);
  padding: .2rem .55rem;
  border-radius: 5px;
  border: 1px solid rgba(var(--accent-rgb),.15);
}
.ds-results-count {
  font-size: .78rem;
  color: var(--text-muted);
}
.ds-hl {
  background: rgba(251,191,36,.25);
  color: var(--warn);
  border-radius: 2px;
  padding: 0 .1rem;
}
.ds-snippets {
  margin-top: .4rem;
  padding-top: .4rem;
  border-top: 1px solid var(--border);
}
.ds-snippet {
  font-size: .75rem;
  color: var(--text-muted);
  background: rgba(var(--accent-rgb),.04);
  border: 1px solid rgba(var(--accent-rgb),.1);
  border-radius: 5px;
  padding: .35rem .6rem;
  margin-top: .25rem;
  line-height: 1.5;
  direction: inherit;
}
.ds-help-group .ot-group-header {
  color: var(--notif-purple);
}
.ds-help-group .ot-count {
  background: rgba(var(--notif-purple-rgb),.15);
  color: var(--notif-purple);
}
.dap-result-highlight {
  outline: 2px solid var(--accent);
  border-radius: 6px;
  transition: outline .2s;
}

.ot-group-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .7rem 1.1rem;
  background: var(--accent);
  border-bottom: 1px solid var(--border);
  font-size: .85rem;
  font-weight: 700;
  color: #fff;
}

.ot-count {
  margin-inline-end: auto;
  background: rgba(255,255,255,.2);
  color: #fff;
  border-radius: 99px;
  padding: .1rem .55rem;
  font-size: .75rem;
  font-weight: 700;
}

.ot-group-arrow {
  font-size: .7rem;
  transition: transform .2s;
  opacity: .6;
}
.ot-group-header:hover .ot-group-arrow { opacity: 1; }

.ot-cards { display: flex; flex-direction: column; }

.ot-card {
  padding: .9rem 1.1rem;
  border-bottom: 1px solid var(--border);
  transition: background .15s, opacity .3s;
}
.ot-card:last-child { border-bottom: none; }
.ot-card:hover { background: rgba(var(--accent-rgb),.04); }

.ot-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .45rem;
}

.ot-subject {
  font-weight: 600;
  font-size: .9rem;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: .4rem;
}

.ot-date {
  font-size: .75rem;
  color: var(--text);
}

.ot-text {
  font-size: .85rem;
  color: var(--muted);
  line-height: 1.55;
  margin-bottom: .65rem;
  white-space: pre-wrap;
}

.ot-img {
  max-width: 180px;
  max-height: 130px;
  border-radius: 8px;
  border: 1px solid var(--border);
  object-fit: contain;
  display: block;
  margin-bottom: .65rem;
}

.ot-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .4rem;
}

.ot-footer-right {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
}

.ot-opener {
  font-size: .75rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: .3rem;
}

.ot-opener-line {
  font-size: .75rem;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: .35rem;
  margin-bottom: .45rem;
}

.ot-btn-handle {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .38rem .9rem;
  background: rgba(var(--accent-rgb),.15);
  color: var(--accent-h);
  border: 1px solid rgba(var(--accent-rgb),.35);
  border-radius: 8px;
  font-size: .8rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
.ot-btn-handle:hover { background: rgba(var(--accent-rgb),.28); border-color: var(--accent); }

/* בטיפול status badge */
.ot-badge-handling {
  background: rgba(251,191,36,.12);
  color: var(--warn);
  border-color: rgba(251,191,36,.35);
}

/* handling date/time inside badge */
.ot-handling-time {
  font-size: .7rem;
  font-weight: 400;
  opacity: .8;
  border-inline-end: 1px solid rgba(251,191,36,.4);
  padding-inline-end: .5rem;
  margin-inline-end: .25rem;
}

/* סמן כטופל button */
.ot-btn-done {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .38rem .9rem;
  background: rgba(52,211,153,.12);
  color: var(--success);
  border: 1px solid rgba(52,211,153,.35);
  border-radius: 8px;
  font-size: .8rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background .2s, border-color .2s;
}
.ot-btn-done:hover { background: rgba(52,211,153,.25); border-color: var(--success); }

.ot-btn-return {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .38rem .9rem;
  background: rgba(251,191,36,.10);
  color: var(--warn);
  border: 1px solid rgba(251,191,36,.30);
  border-radius: 8px;
  font-size: .78rem;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.ot-btn-return:hover { background: rgba(251,191,36,.22); border-color: var(--warn); }

.ot-footer-actions {
  display: flex;
  align-items: center;
  gap: .5rem;
}

/* טופל status badge */
.ot-badge-done {
  background: rgba(52,211,153,.12);
  color: var(--success);
  border-color: rgba(52,211,153,.35);
}

/* Ticket filter bar */
.tk-filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem .65rem;
  padding: .55rem 0 .6rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: .75rem;
  align-items: center;
}
.tk-filter-group {
  display: flex;
  align-items: center;
  gap: .25rem;
  flex-wrap: wrap;
}
.tk-filter-label {
  font-size: .74rem;
  color: var(--muted);
  font-weight: 600;
  white-space: nowrap;
  margin-inline-end: .15rem;
}
.tk-chip {
  padding: .18rem .55rem;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: .74rem;
  line-height: 1.4;
  transition: border-color .12s, color .12s, background .12s;
  white-space: nowrap;
}
.tk-chip:hover { border-color: var(--accent); color: var(--accent); }
.tk-chip.tk-chip-active { background: var(--accent); color: var(--accent-text); border-color: var(--accent); font-weight: 600; }
.tk-select {
  font-size: .78rem;
  padding: .18rem .45rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.tk-filter-count {
  font-size: .74rem;
  color: var(--muted);
  margin-inline-start: auto;
  padding-inline-start: .5rem;
  white-space: nowrap;
}

/* Ticket mini-dashboard stats row */
.tk-stats-row {
  display: flex;
  gap: .6rem;
  padding: .5rem 0 .7rem;
  flex-wrap: wrap;
}
.tk-stat-card {
  flex: 1;
  min-width: 88px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: .5rem .8rem;
  display: flex;
  flex-direction: column;
  gap: .1rem;
}
.tk-stat-num {
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--text);
}
.tk-stat-label {
  font-size: .7rem;
  color: var(--muted);
  font-weight: 500;
}
.tk-stat-card.tk-s-handling { border-color: rgba(243,156,18,.3); }
.tk-stat-card.tk-s-handling .tk-stat-num { color: var(--warn, #f39c12); }
.tk-stat-card.tk-s-done  { border-color: rgba(39,174,96,.3); }
.tk-stat-card.tk-s-done .tk-stat-num  { color: var(--success, #27ae60); }
.tk-stat-card.tk-s-urgent { border-color: rgba(231,76,60,.3); }
.tk-stat-card.tk-s-urgent .tk-stat-num { color: var(--danger, #e74c3c); }

/* Ticket comments thread */
.tk-comments {
  margin-top: .5rem;
  border-top: 1px solid var(--border);
  padding-top: .5rem;
}
.tk-comment-list { display: flex; flex-direction: column; gap: .5rem; margin-bottom: .6rem; }
.tk-comment {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .45rem .65rem;
}
.tk-comment-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: .2rem;
  gap: .5rem;
}
.tk-comment-author { font-size: .72rem; font-weight: 600; color: var(--text); }
.tk-comment-time   { font-size: .68rem; color: var(--muted); white-space: nowrap; }
.tk-comment-text   { font-size: .82rem; color: var(--text); white-space: pre-wrap; word-break: break-word; }
.tk-comment-empty  { font-size: .78rem; color: var(--muted); text-align: center; padding: .4rem 0; }
.tk-comment-compose {
  display: flex;
  flex-direction: column;
  gap: .4rem;
}
.tk-comment-input {
  width: 100%;
  resize: vertical;
  padding: .35rem .5rem;
  font-size: .82rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  box-sizing: border-box;
}
.tk-comment-send {
  padding: .3rem .7rem;
  font-size: .78rem;
  border-radius: 6px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: .3rem;
}
.tk-comment-send:hover { opacity: .88; }
.tk-cmt-btn {
  background: transparent;
  border: none;
  padding: .2rem .4rem;
  cursor: pointer;
  color: var(--muted);
  font-size: .8rem;
  display: flex;
  align-items: center;
  gap: .3rem;
  border-radius: 4px;
  transition: color .12s;
}
.tk-cmt-btn:hover { color: var(--accent); }
.tk-cmt-count {
  font-size: .7rem;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
}

/* Ticket friendly number badge */
.tk-ticket-id {
  font-size: .7rem;
  color: var(--muted);
  background: rgba(128,128,128,.12);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: .1rem .45rem;
  font-family: monospace;
  white-space: nowrap;
  letter-spacing: .03em;
}

/* Priority badges */
.ot-badge-priority-high {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .72rem;
  font-weight: 700;
  padding: .15rem .55rem;
  border-radius: 20px;
  background: rgba(239,68,68,.14);
  color: var(--danger);
  border: 1px solid rgba(239,68,68,.3);
}
.ot-badge-priority-low {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .72rem;
  font-weight: 600;
  padding: .15rem .55rem;
  border-radius: 20px;
  background: rgba(52,211,153,.1);
  color: var(--success);
  border: 1px solid rgba(52,211,153,.25);
}
.ot-badge-priority-normal {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .72rem;
  font-weight: 500;
  padding: .15rem .55rem;
  border-radius: 20px;
  background: rgba(148,163,184,.12);
  color: var(--text-muted, #94a3b8);
  border: 1px solid rgba(148,163,184,.25);
}

/* Resolution block */
.dt-resolution {
  background: rgba(52,211,153,.06);
  border: 1px solid rgba(52,211,153,.2);
  border-radius: 8px;
  padding: .65rem .85rem;
  margin-bottom: .65rem;
}
.dt-resolution-title {
  font-size: .75rem;
  font-weight: 600;
  color: var(--success);
  margin-bottom: .35rem;
  display: flex;
  align-items: center;
  gap: .35rem;
}
.dt-resolution-text {
  font-size: .84rem;
  color: var(--muted);
  line-height: 1.55;
  white-space: pre-wrap;
}

/* ── Zoomable thumbnail ── */
.ot-img-zoomable { cursor: zoom-in; }

/* ── Image hover preview (tooltip) ── */
.img-hover-preview {
  position: fixed;
  z-index: 1500;
  display: none;
  pointer-events: none;
  background: linear-gradient(145deg, var(--surface), var(--bg));
  border: 1px solid rgba(var(--accent-rgb),.35);
  border-radius: 14px;
  box-shadow:
    0 25px 70px rgba(0,0,0,.35),
    0 0 0 1px rgba(var(--accent-rgb),.1),
    inset 0 1px 0 rgba(255,255,255,.04);
  padding: 6px;
  max-width: 440px;
  backdrop-filter: blur(12px);
  animation: tooltipIn .15s ease;
}
@keyframes tooltipIn {
  from { opacity: 0; transform: scale(.92); }
  to   { opacity: 1; transform: scale(1); }
}
.img-hover-preview::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 14px;
  padding: 1px;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),.3), rgba(124,58,237,.2), transparent 60%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}
.img-hover-preview img {
  display: block;
  max-width: 428px;
  max-height: 340px;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,.3);
}

/* ── Image Lightbox ── */
/* ── Reusable PDF viewer modal (home feed doc cards, etc.) ── */
.pdf-modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.88); z-index: 2000;
  display: flex; align-items: center; justify-content: center; padding: 2vh 2vw;
}
.pdf-modal-box {
  position: relative; display: flex; flex-direction: column;
  width: 94vw; height: 94vh; max-width: 1100px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden; box-shadow: 0 12px 48px rgba(0,0,0,.45);
}
.pdf-modal-header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--topbar-bg);
}
.pdf-modal-title {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  font-weight: 600; color: var(--text); font-size: .95rem;
}
.pdf-modal-title i { color: var(--danger); font-size: 1.15rem; flex-shrink: 0; }
.pdf-modal-title > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pdf-modal-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.pdf-modal-close-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 8px; border: none; cursor: pointer;
  background: transparent; color: var(--muted); text-decoration: none; font-size: 1.1rem;
  transition: background .15s, color .15s;
}
.pdf-modal-close-btn:hover { background: rgba(var(--accent-rgb),.12); color: var(--text); }
/* ── Feed detail modal ── */
.feed-detail-body { padding: 1rem 1.25rem; overflow-y: auto; max-height: 70vh; }
.feed-detail-body .fd-image {
  width: 100%; max-height: 300px; object-fit: cover; border-radius: 10px;
  margin-bottom: .75rem; cursor: pointer;
}
.feed-detail-body .fd-carousel { position: relative; margin-bottom: .75rem; }
.feed-detail-body .fd-carousel img {
  width: 100%; max-height: 300px; object-fit: cover; border-radius: 10px; cursor: pointer;
}
.feed-detail-body .fd-carousel-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: rgba(0,0,0,.5); color: #fff; border: none; border-radius: 50%;
  width: 32px; height: 32px; font-size: 1rem; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.feed-detail-body .fd-carousel-nav.fd-prev { left: 8px; }
.feed-detail-body .fd-carousel-nav.fd-next { right: 8px; }
/* L10N-0005 (quality-audit): swap sides in RTL so "prev" stays on the
   reading-order-first side instead of hardcoding a left/right physical side. */
[dir="rtl"] .feed-detail-body .fd-carousel-nav.fd-prev { left: auto; right: 8px; }
[dir="rtl"] .feed-detail-body .fd-carousel-nav.fd-next { right: auto; left: 8px; }
.feed-detail-body .fd-carousel-counter {
  text-align: center; font-size: .75rem; color: var(--muted); margin-top: .3rem;
}
.feed-detail-body .fd-badge {
  display: inline-block; font-size: .72rem; padding: 2px 10px; border-radius: 8px;
  font-weight: 600; margin-bottom: .4rem;
  background: rgba(var(--accent-rgb),.12); color: var(--accent);
}
.feed-detail-body .fd-badge.fd-urgent { background: rgba(255,91,82,.12); color: var(--danger); }
.feed-detail-body .fd-badge.fd-event  { background: rgba(61,220,151,.12); color: var(--success); }
.feed-detail-body .fd-badge.fd-warn   { background: rgba(227,154,58,.12); color: var(--warn); }
.feed-detail-body .fd-badge.fd-new    { background: rgba(var(--accent-rgb),.12); color: var(--accent); }
.feed-detail-body .fd-badge.fd-handling { background: rgba(227,154,58,.12); color: var(--warn); }
.feed-detail-body .fd-badge.fd-done   { background: rgba(61,220,151,.12); color: var(--success); }
.feed-detail-body .fd-text {
  font-size: .88rem; line-height: 1.65; color: var(--text);
  white-space: pre-wrap; word-break: break-word; margin: .6rem 0;
}
.feed-detail-body .fd-meta {
  font-size: .78rem; color: var(--muted); display: flex; align-items: center;
  gap: 6px; flex-wrap: wrap; margin: .35rem 0;
}
.feed-detail-body .fd-meta i { font-size: .9rem; }
.feed-detail-body .fd-contact {
  font-size: .82rem; color: var(--text); margin: .5rem 0;
  display: flex; align-items: center; gap: 6px;
}
.feed-detail-body .fd-section-title {
  font-size: .8rem; font-weight: 600; color: var(--muted); margin: .8rem 0 .3rem;
  text-transform: uppercase; letter-spacing: .03em;
}
.feed-detail-body .fd-priority {
  display: inline-block; font-size: .7rem; padding: 1px 8px; border-radius: 6px;
  font-weight: 600; margin-inline-start: 6px;
}
.feed-detail-body .fd-priority.high { background: rgba(255,91,82,.12); color: var(--danger); }
.feed-detail-body .fd-priority.low  { background: rgba(var(--accent-rgb),.1); color: var(--muted); }
.feed-detail-body .fd-loading {
  text-align: center; padding: 2rem; color: var(--muted); font-size: .85rem;
}
.pdf-modal-topics {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  padding: .45rem .75rem; background: var(--surface);
  border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.pdf-modal-topics .ip-topic-tag { cursor: default; color: #fff; }
/* Collapsible topics bar — default collapsed to a "נושאים (N)" pill; the caret
   rotates and the tags reveal on expand. The list uses display:contents so its
   chips flow as flex items of the bar (keeping the gap) when shown. */
.pdf-topics-toggle {
  display: inline-flex; align-items: center; gap: .35rem; font-family: inherit;
  font-size: .8rem; font-weight: 600; color: #fff;
  background: rgba(var(--accent-rgb),.22); border: 1px solid rgba(var(--accent-rgb),.42);
  border-radius: 20px; padding: .2rem .7rem; cursor: pointer; transition: background .15s;
}
.pdf-topics-toggle:hover { background: rgba(var(--accent-rgb),.34); }
.pdf-topics-toggle i { font-size: .85rem; }
.pdf-topics-caret { transition: transform .18s ease; }
.pdf-modal-topics[data-collapsed="0"] .pdf-topics-caret { transform: rotate(180deg); }
.pdf-topics-list { display: contents; }
.pdf-topics-list[hidden] { display: none; }
.pdf-modal-body { flex: 1; min-height: 0; background: #525659; }
.pdf-modal-frame { width: 100%; height: 100%; border: 0; display: block; }
@media (max-width: 600px) {
  .pdf-modal-overlay { padding: 0; }
  .pdf-modal-box { width: 100vw; height: 100vh; border-radius: 0; }
}

.img-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.88);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
}

.img-modal-box {
  position: relative;
  display: flex;
  flex-direction: column;
  max-width: 90vw;
  max-height: 90vh;
  background: var(--topbar-bg);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 40px 100px rgba(0,0,0,.8);
  animation: fadeUp .2s ease;
}

.img-modal-toolbar {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem .75rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.img-modal-tool {
  width: 32px; height: 32px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: .85rem;
  transition: background .18s, color .18s;
}
.img-modal-tool:hover { background: rgba(var(--accent-rgb),.2); color: var(--accent-h); }

.img-modal-close-btn { margin-inline-end: auto; }
.img-modal-close-btn:hover { background: rgba(248,113,113,.15); color: var(--danger); border-color: var(--danger); }

.img-modal-viewport {
  overflow: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 400px;
  min-height: 300px;
  max-width: 88vw;
  max-height: 80vh;
  padding: 2rem;
}

.img-modal-img {
  max-width: 800px;
  max-height: 600px;
  width: auto;
  height: auto;
  display: block;
  transform-origin: center center;
  transition: transform .15s ease;
  border-radius: 6px;
}

/* ── Regulations Accordion ── */
.regs-group {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: .5rem;
  overflow: hidden;
  background: var(--surface);
}
.regs-group-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .75rem 1rem;
  cursor: pointer;
  user-select: none;
  font-weight: 600;
  font-size: .9rem;
  color: var(--text);
  background: rgba(var(--accent-rgb),.03);
  transition: background .15s;
}
.regs-group-header:hover {
  background: rgba(var(--accent-rgb),.08);
}
.regs-group-arrow {
  font-size: .7rem;
  transition: transform .25s;
  opacity: .6;
}
.regs-arrow-closed {
  transform: rotate(-90deg);
}
.regs-group-label {
  flex: 1;
}
.regs-group-body {
  border-top: 1px solid var(--border);
  padding: .5rem;
}

/* ── Regulations tree sidebar ── */
.regs-tree-group {
  margin-bottom: 2px;
}
.regs-tree-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .55rem .75rem;
  cursor: pointer;
  user-select: none;
  font-size: .85rem;
  font-weight: 600;
  color: var(--text);
  border-radius: 6px;
  transition: background .15s;
}
.regs-tree-header:hover {
  background: rgba(var(--accent-rgb),.1);
}
.regs-tree-header.proc-item-active {
  background: rgba(var(--accent-rgb),.18);
}
.regs-tree-arrow {
  font-size: .6rem;
  transition: transform .25s;
  opacity: .5;
}
/* was an inline style="color:var(--text-muted)" -- moved to a class so the
   default-theme override below can target it (an inline style always beats a
   stylesheet rule, so it couldn't be). */
.regs-tree-count {
  font-size: .7rem;
  color: var(--text-muted);
  margin-inline-start: 4px;
}
.regs-tree-add {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  font-size: .75rem;
  padding: 2px 4px;
  border-radius: 4px;
  opacity: .6;
  transition: opacity .15s, background .15s;
}
.regs-tree-add:hover {
  opacity: 1;
  background: rgba(var(--accent-rgb),.15);
}
.regs-tree-docs {
  padding: .15rem 0 .25rem 0;
  margin-inline-end: 1.5rem;
}
.regs-tree-doc {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .3rem .6rem;
  font-size: .8rem;
  color: var(--muted);
  cursor: pointer;
  border-radius: 4px;
  transition: background .12s, color .12s;
}
.regs-tree-doc:hover {
  background: rgba(var(--accent-rgb),.08);
  color: var(--text);
}
.regs-tree-doc.proc-item-active {
  background: rgba(var(--accent-rgb),.18);
  color: var(--text);
}
.regs-upload-progress {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem .6rem; font-size: .75rem; color: var(--accent);
}
.regs-upload-pct { font-weight: 600; }
/* ERR-0043 (quality-audit): shared cancel affordance for every in-progress XHR
   upload (docfamily.js/regulations.js) -- muted outline like .um-btn-cancel,
   scaled down to sit inline next to a progress bar/timer. */
.upload-cancel-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .25rem .6rem;
  margin-inline-start: .5rem;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: .75rem;
  font-family: inherit;
  cursor: pointer;
  transition: color .2s, border-color .2s;
}
.upload-cancel-btn:hover { color: var(--danger); border-color: var(--danger); }
.regs-tree-empty {
  padding: .3rem .6rem;
  font-size: .75rem;
  color: var(--muted);
  opacity: .6;
  font-style: italic;
}

/* ── Custom Tooltip ── */
.c-tooltip {
  position: fixed;
  z-index: 99999;
  pointer-events: none;
  padding: .4rem .7rem;
  font-size: .78rem;
  line-height: 1.4;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
  /* UI-0067 (quality-audit): a long title/data-tip string (long i18n strings,
     validation hints, etc.) rendered as one unbroken nowrap line that could
     run off both edges of the viewport -- tooltips.js's positioning only
     shifts the box to stay on-screen, it never shrinks the text. Capped
     width + wrapping keeps it readable at any string length/language. */
  max-width: 280px;
  white-space: normal;
  overflow-wrap: break-word;
  opacity: 0;
  transition: opacity .15s ease;
  direction: inherit;
}
.c-tooltip.visible {
  opacity: 1;
}
/* ── Quantum (brand · navy + gold, from logo-he.svg) ─────────────
   The KesherOS identity: near-black navy grounds, metallic gold as the
   accent (not a fill), high-contrast text, deep floating panels. Gold is
   light, so --accent-text must be dark navy or every primary button loses
   contrast. */
/* Quantum brand polish — applies to the DEFAULT state (:root without a
   data-theme = the Quantum brand identity). */
/* Floating panels: deep drop + hairline gold edge for the premium depth. */
:root:not([data-theme]) .card,
:root:not([data-theme]) .um-modal-box,
:root:not([data-theme]) .stg-section {
  border: 1px solid rgba(var(--accent-rgb),.14);
  box-shadow: 0 18px 44px rgba(0,0,0,.55), 0 4px 12px rgba(0,0,0,.4);
}
/* Primary actions: navy top-lit gradient with WHITE text (inverted from the gold
   fill). Vertical gradient — light navy top → dark navy bottom — plus a top
   highlight line for the lit-from-above 3D feel. Override the label to white
   (base rule sets it to --accent-text) for maximum contrast on the navy. */
:root:not([data-theme]) .um-btn-save,
:root:not([data-theme]) .um-btn-add,
:root:not([data-theme]) .ev-export-btn,
:root:not([data-theme]) .ev-rsvp-btn,
:root:not([data-theme]) .btn-primary,
:root:not([data-theme]) .prof-edit-btn,
:root:not([data-theme]) .mnh-btn-save,
:root:not([data-theme]) .ticket-btn-save,
:root:not([data-theme]) .reg-btn-upload,
:root:not([data-theme]) .reg-btn-download,
:root:not([data-theme]) .reg-btn-summary,
:root:not([data-theme]) .proc-add-btn,
:root:not([data-theme]) .proc-save-btn {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff !important;  /* beats .prof-edit-btn's base "color !important" */
  box-shadow: inset 0 1px 0 rgba(140,180,230,.35), 0 4px 12px rgba(0,0,0,.3);
  /* Include box-shadow so the hover halo below fades in smoothly instead of
     snapping — the base .btn transition only animates filter/transform. */
  transition: filter .22s, box-shadow .25s, transform .12s;
}
:root:not([data-theme]) .um-btn-save:hover,
:root:not([data-theme]) .um-btn-add:hover,
:root:not([data-theme]) .ev-export-btn:hover,
:root:not([data-theme]) .btn-primary:hover,
:root:not([data-theme]) .prof-edit-btn:hover,
:root:not([data-theme]) .mnh-btn-save:hover,
:root:not([data-theme]) .ticket-btn-save:hover,
:root:not([data-theme]) .reg-btn-upload:hover,
:root:not([data-theme]) .reg-btn-download:hover,
:root:not([data-theme]) .reg-btn-summary:hover,
:root:not([data-theme]) .proc-add-btn:hover,
:root:not([data-theme]) .proc-save-btn:hover {
  /* Gold halo: the lit-from-above lift plus a soft brand-gold glow ring, so the
     hovered action reads as "highlighted". Fades in via the transition above. */
  filter: brightness(1.1);
  box-shadow: inset 0 1px 0 rgba(140,180,230,.5),
              0 8px 22px rgba(0,0,0,.42),
              0 0 0 3px rgba(var(--accent-h-rgb),.28),
              0 0 18px rgba(var(--accent-h-rgb),.35);
}
/* Secondary buttons — filled navy+gold for a uniform look (was gold outline).
   No !important on colour, so inline danger overrides (e.g. delete) still win. */
:root:not([data-theme]) .um-btn-secondary,
:root:not([data-theme]) .um-btn-export {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff;
  border-color: rgba(var(--accent-h-rgb),.45);
  box-shadow: inset 0 1px 0 rgba(140,180,230,.3);
  transition: filter .22s, box-shadow .25s, transform .12s;
}
:root:not([data-theme]) .um-btn-secondary:hover,
:root:not([data-theme]) .um-btn-export:hover {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  /* A gentler gold halo than the primary buttons — secondary actions stay
     subordinate, so a thinner ring and softer glow. */
  filter: brightness(1.1);
  box-shadow: inset 0 1px 0 rgba(140,180,230,.4),
              0 6px 16px rgba(0,0,0,.35),
              0 0 0 2px rgba(var(--accent-h-rgb),.22),
              0 0 12px rgba(var(--accent-h-rgb),.25);
}
/* Group/category header bars (the gold bars) — same navy→gold inversion as the
   buttons, so the whole UI reads uniform. Recolor the inner count pill + text. */
:root:not([data-theme]) .ot-group-header,
:root:not([data-theme]) .regs-group-header,
:root:not([data-theme]) .stg-section-title {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(140,180,230,.3);
}
:root:not([data-theme]) .ot-group-header .ot-count {
  background: rgba(var(--accent-h-rgb),.18);
  color: #fff;
}
/* Segmented-control selected chip (icon-style / UI-style pickers) — navy+gold
   like the buttons, with a gold hairline so "selected" still reads clearly. */
:root:not([data-theme]) .tm-ss-chip.tm-ss-sel {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff;
  border-color: rgba(var(--accent-h-rgb),.55);
  box-shadow: inset 0 1px 0 rgba(140,180,230,.3);
}
/* Floating help button — navy+gold like the buttons, keep the round drop shadow. */
:root:not([data-theme]) .dap-fab {
  /* glossy navy dome + gold ring — sibling to the emergency red dome */
  background: radial-gradient(circle at 38% 30%, #3f6fa6, #1c3a63 52%, #0b1d38);
  /* was var(--accent-lt) -- see .feedback-fab's identical fix (style.css ~8057). */
  color: #fff;
  border: 1.5px solid rgba(var(--accent-h-rgb),.7);
  box-shadow: inset 0 2px 3px rgba(150,190,240,.45), inset 0 -4px 7px rgba(0,10,30,.5),
              0 0 0 1px rgba(var(--accent-h-rgb),.18), 0 6px 16px rgba(0,0,0,.5), 0 0 14px rgba(var(--accent-h-rgb),.14);
}
/* specular gloss across the top of the dome */
:root:not([data-theme]) .dap-fab::after {
  content: ""; position: absolute; top: 6px; left: 12px; right: 14px; height: 11px;
  border-radius: 50%; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,.45), transparent);
}
/* keep the navy dome on hover (base :hover would flip it to gold) */
:root:not([data-theme]) .dap-fab:hover {
  background: radial-gradient(circle at 38% 30%, #4778b0, #22406e 52%, #0e2444);
  box-shadow: inset 0 2px 3px rgba(150,190,240,.5), inset 0 -4px 7px rgba(0,10,30,.5),
              0 0 0 1px rgba(var(--accent-h-rgb),.22), 0 8px 22px rgba(0,0,0,.55), 0 0 18px rgba(var(--accent-h-rgb),.2);
}
/* the "?" glyph — crisp gold, above the gloss */
.dap-fab-q {
  position: relative; z-index: 1; line-height: 1;
  font-family: Georgia, 'Times New Roman', serif; font-weight: 700; font-size: 1.45rem;
  text-shadow: 0 1px 2px rgba(0,0,0,.5);
}
/* Selected recipient tags (alerts multi-select) — navy+gold with a gold hairline. */
:root:not([data-theme]) .alert-ms-tag {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: #fff;
  border: 1px solid rgba(var(--accent-h-rgb),.45);
}
/* Toggle switches — ON state = navy-gradient track + GOLD knob (like the buttons),
   with a gold inset ring so "on" reads clearly. Three variants: stg-toggle /
   alert-toggle use a ::before knob, ps-toggle uses ::after. OFF state untouched. */
:root:not([data-theme]) .stg-toggle input:checked + .stg-toggle-slider,
:root:not([data-theme]) .alert-toggle input:checked + .alert-toggle-slider,
:root:not([data-theme]) .ps-toggle-input:checked + .ps-toggle-slider {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-h-rgb),.4);
}
:root:not([data-theme]) .stg-toggle input:checked + .stg-toggle-slider::before,
:root:not([data-theme]) .alert-toggle input:checked + .alert-toggle-slider::before {
  background: var(--accent-h);
}
:root:not([data-theme]) .ps-toggle-input:checked + .ps-toggle-slider::after {
  background: var(--accent-h);
}
/* Display headings in the wordmark's own serif. */
:root:not([data-theme]) h1,
:root:not([data-theme]) h2,
:root:not([data-theme]) h3,
:root:not([data-theme]) .um-modal-header h3 { font-family: Georgia, 'Times New Roman', serif; }
/* Dashboard stat tiles — subtle 3D: whole-card tilt (JS-driven) + a gold light
   that tracks the pointer (--mx/--my), a metal accent rail, and depth. */
:root:not([data-theme]) .tk-stat-card {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg,#12274a,#0c1c37);
  box-shadow: 0 14px 34px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.05);
  transition: transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease;
  will-change: transform;
}
:root:not([data-theme]) .tk-stat-card::before {
  content: ""; position: absolute; inset-inline-start: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg,var(--accent-lt),var(--accent));
}
:root:not([data-theme]) .tk-stat-card::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(180px 180px at var(--mx,70%) var(--my,15%), rgba(var(--accent-lt-rgb),.16), transparent 60%);
  opacity: 0; transition: opacity .3s ease; mix-blend-mode: screen;
}
:root:not([data-theme]) .tk-stat-card:hover::after { opacity: 1; }
/* Tables — gold header underline (nav, focus & row-hover already inherit the
   gold accent via tokens), a touch stronger hover, rounded shell. User-reported
   low-contrast: the header text itself used to be a decorative dim blue
   (#b9c8e4) here, on top of the base rule's own var(--muted) -- switched to
   var(--text) (this theme's full-brightness ink) so every table's header
   reads clearly, not just this branded tint. */
:root:not([data-theme]) .um-table th {
  color: var(--text);
  border-bottom: 1px solid rgba(var(--accent-rgb),.35);
  text-transform: uppercase;
}
:root:not([data-theme]) .um-table tbody tr:hover { background: rgba(var(--accent-rgb),.08); }
:root:not([data-theme]) .um-table-wrap { box-shadow: 0 10px 28px rgba(0,0,0,.4); }
/* Inputs/selects — a slightly warmer gold focus glow to match the brand. */
:root:not([data-theme]) input:focus,
:root:not([data-theme]) .um-input:focus,
:root:not([data-theme]) select:focus,
:root:not([data-theme]) textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.22);
}
/* Document-module panels (the first screen after login is one of these, plus
   committees / protocols / regulations…): float with depth + a gold edge. */
:root:not([data-theme]) .proc-sidebar,
:root:not([data-theme]) .proc-viewer-wrap {
  border-color: rgba(var(--accent-rgb),.14);
  box-shadow: 0 14px 34px rgba(0,0,0,.4);
}
/* Feed panels — deep-navy panel on the dark page with a soft accent glow in the
   top corner ("A + B's glow"), so the dark "E" tiles float on a matching-dark
   surface instead of a jarring white one. Header text/count/see-all fall back to
   their light base rules (they were dark only for the old white panel). */
:root:not([data-theme]) .feed-section {
  background:
    radial-gradient(120% 90% at 88% -10%, rgba(var(--accent-rgb),.16), transparent 55%),
    #0a1526;
  border: 1px solid rgba(var(--accent-rgb),.22);
  box-shadow: 0 14px 34px rgba(0,0,0,.5);
  position: relative;
  overflow: hidden;
}
:root:not([data-theme]) .feed-section::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-lt), var(--accent));
  border-radius: var(--radius) var(--radius) 0 0;
}
/* Feed cards are the dark "E" tiles from the base .feed-card rule (they read
   as striking button/notice tiles on these white panels) — no light-card
   override here. Badges/status/notif-icon fall back to their dark-appropriate
   base rules, which suit the dark tile. */
:root:not([data-theme]) .feed-notif-icon.evacuation,
:root:not([data-theme]) .feed-notif-icon.emergency,
:root:not([data-theme]) .feed-notif-icon.evac_broadcast { background: rgba(200,50,40,.1); color: #c03020; }
:root:not([data-theme]) .feed-notif-icon.ticket_new,
:root:not([data-theme]) .feed-notif-icon.ticket_comment,
:root:not([data-theme]) .feed-notif-icon.ticket_status { background: rgba(180,110,20,.1); color: #9a6a10; }
:root:not([data-theme]) .feed-doc-btn { background: rgba(0,60,140,.08); color: #ffffff; border-color: rgba(0,60,140,.15); }
:root:not([data-theme]) .feed-doc-btn:hover { background: rgba(0,60,140,.18); }
:root:not([data-theme]) .feed-doc-btn-pdf { background: linear-gradient(180deg,#2a6fc0,#1a5bb5); color: #fff; }
:root:not([data-theme]) .feed-doc-topics { color: #ffffff; }
:root:not([data-theme]) .feed-date-block { color: #ffffff; }
/* Alerts / toasts float with soft depth. */
:root:not([data-theme]) .alert { box-shadow: 0 10px 28px rgba(0,0,0,.4); }
/* Info notices carry white text (not gold) for contrast on the dark navy —
   error/warning/success keep their semantic red/amber/green. */
:root:not([data-theme]) .alert-info { color: #fff; }
/* Auth-card accent text (2FA countdown value + footer "back to login" link):
   white on the dark navy card instead of low-contrast gold. */
:root:not([data-theme]) .countdown span,
:root:not([data-theme]) .card-footer a { color: #fff; }
/* Ribbon nav labels + icons: white on the navy top bar for readability, in every
   state (wins over the muted/active accent color). The "flat" icon style's
   per-panel colors are more specific and still win. */
:root:not([data-theme]) .ribbon-item span,
:root:not([data-theme]) .ribbon-item i { color: #fff; }
/* Sub-ribbon: same treatment — white label + icon. */
:root:not([data-theme]) .sub-item span,
:root:not([data-theme]) .sub-item i { color: #fff; }
/* Site (yishuv) name in the top bar: pure white on the navy. */
:root:not([data-theme]) .brand-name { color: #fff; }
/* Badges/chips that carried a WHITE label on the gold accent — low contrast,
   since the brand gold is light. Navy fill + white label instead, matching the
   buttons. Scoped to the default theme, so the light theme keeps its own accent
   (which is dark enough for white text). */
:root:not([data-theme]) .hh-badge,
:root:not([data-theme]) .hh-sel-chip,
:root:not([data-theme]) .theme-card-badge,
:root:not([data-theme]) .bulletin-sh-badge {
  background: #12294c;
  color: #fff;
}
/* The navy rule above (specificity 0,3,0) also beats the plain .hh-badge-dep
   (0,1,0), so the adults vs dependents badges would both go navy and lose their
   distinction in the default theme. Restore it at matching specificity: a lighter
   navy for dependents, still white-legible. */
:root:not([data-theme]) .hh-badge-dep { background: #274a7d; }
:root:not([data-theme]) .tk-comment-send,
:root:not([data-theme]) .ai-sugg-chip:hover {
  background: #12294c;
  color: #fff;
  border-color: #274a7d;
}
/* Owner request (08/09): var(--muted)/var(--text-muted) (a grayish-blue) read too
   low-contrast against this theme's navy background for: the daily-tip category
   pill, the home feed's "quick actions" section title, the recommendations
   sidebar's "categories" title, the regulations document tree's per-folder doc
   count and document names, the year-filter buttons shared by every "Documents"
   sub-tab (info pages/audit/protocols/assemblies/management/committees), the
   notification-preview popup's relative-time row (e.g. "לפני 6 ימים"), and (under
   the tickets/service module) the ticket-id badge, ticket description text, the
   filter-group labels (e.g. "קטגוריה:"), the stat-tile labels (e.g. "טופל"), and
   the handling-note/resolution text, (new-ticket/document form labels, e.g.
   "קטגוריה"/"תיאור"/"שם פותח הפניה") .ticket-field's own field labels, and the
   "(אופציונלי)" note next to the image field label. Scoped to the default theme
   only -- the light theme's --muted (#64748b) already reads fine on its pale
   backgrounds for these. */
:root:not([data-theme]) .daily-tip-cat-pill,
:root:not([data-theme]) .feed-qa-title,
:root:not([data-theme]) .rec-sidebar-title,
:root:not([data-theme]) .regs-tree-count,
:root:not([data-theme]) .regs-tree-doc,
:root:not([data-theme]) .notif-preview-time,
:root:not([data-theme]) .ip-year-btn,
:root:not([data-theme]) .tk-ticket-id,
:root:not([data-theme]) .ot-text,
:root:not([data-theme]) .tk-filter-label,
:root:not([data-theme]) .tk-stat-label,
:root:not([data-theme]) .dt-resolution-text,
:root:not([data-theme]) .ticket-field label,
:root:not([data-theme]) .ticket-optional-note,
:root:not([data-theme]) .ot-opener {
  color: #fff;
}
/* Same request: the readonly "opener name"/"date" values (.ticket-readonly)
   render dim because of the .6 opacity used to signal "not editable" -- that
   opacity dims the already-near-white var(--text) down to a muted-looking grey.
   Keep the background/cursor "disabled" cues, drop just the opacity in this
   theme so the value itself reads full-brightness. */
:root:not([data-theme]) .ticket-readonly {
  opacity: 1;
}
/* Was scoped to the committees table specifically, deliberately not a global
   change -- superseded by the base .um-table th rule above now covering every
   table's header the same way (#fff here vs. var(--text) there resolve to
   effectively the same near-white either way), so this is now redundant but
   harmless; left in place rather than touched for its own sake. */
:root:not([data-theme]) #content-committees .um-table th {
  color: #fff;
}
/* Same request (09/10), Personal Settings: the language/notification tab's card
   descriptions (e.g. "מכבה אנימציות ומעברים באפליקציה...", "בחר את שפת הממשק
   המועדפת עליך"), the display tab's section sub-labels (font/icon/style-set
   group headers), and the contact tab's descriptions + avatar upload hint all
   use .stg-hint / .tm-ss-label -- both shared app-wide with routes/settings.js's
   admin screens, so scoped to #content-personal specifically rather than a
   global change to either class. Same request again for the security tab's
   "TOTP not enabled" status text (.ps-totp-status-text, personal-only class). */
:root:not([data-theme]) #content-personal .stg-hint,
:root:not([data-theme]) #content-personal .tm-ss-label,
:root:not([data-theme]) #content-personal .ps-totp-status-text {
  color: #fff;
}
/* Search module: the "type text and press search" empty-state hint (search.js's
   ds-empty-hint) uses the shared .um-empty (--muted) app-wide, so this is its
   own class rather than a global change -- .um-empty's other call sites (list
   empty-states, error states) keep the muted look on purpose.
   --text (not a hardcoded white) is the theme's own full-brightness ink colour
   -- already correct in every theme on its own (near-white in default/dark,
   dark in light, white in both high-contrast variants), so no per-theme
   override is needed here at all. Doubled with .um-empty for specificity, so
   source order can't flip it either way. */
.um-empty.ds-empty-hint { color: var(--text); }
.ds-empty-hint .app-icon { opacity: .6; }
@media (prefers-reduced-motion: reduce){
  html:not([data-motion="full"]) :root:not([data-theme]) .tk-stat-card { transition: none; }
}
/* ── Light ──────────────────────────────────────────────────── */
[data-theme="light"] {
  --bg:       #f5f7fa;
  --surface:  #ffffff;
  --border:   #dde2ea;
  --accent:   #4f46e5;
  --accent-rgb: 79,70,229;
  /* MUST be re-declared here. :root's --accent-text (#08192e, near-black) was chosen
     for the DEFAULT theme's pale #4C9AFF, where it measures 6.20:1. On this theme's
     indigo it is 2.81:1 -- so every primary action button, FAB and active chip
     shipped as near-black text on indigo, unreadable, and invisible to anyone
     developing in the default theme. #fff measures 7.35:1 here. One token; 32 rules
     already read it. Guarded by tests/test_theme_contrast_ratios.py. */
  --accent-text: #fff;
  --accent-h: #6366f1;
  /* Deeper violet than the default theme's --ai-accent -- this theme's own
     --accent is already indigo, so a lighter violet would blend into it. */
  --ai-accent: #7c3aed;
  --ai-accent-rgb: 124,58,237;
  --ai-accent-dark: #5b21b6;
  --text:     #1e293b;
  --muted:    #64748b;
  --danger:   #dc2626;
  --success:  #16a34a;
  --success-rgb: 22,163,74;
  --warn:     #d97706;
  --warn-rgb: 217,119,6;
  --warning:     var(--warn);
  --warning-rgb: var(--warn-rgb);
  --info:        var(--accent);
  --notif-purple: #7c3aed;
  --notif-purple-rgb: 124,58,237;
  --notif-blue: #2563eb;
  --notif-blue-rgb: 37,99,235;
  /* UI-0042 (quality-audit): see :root's own comment above. */
  --search-pink: #db2777;
  --search-pink-rgb: 219,39,119;
  --search-indigo: #4f46e5;
  --search-indigo-rgb: 79,70,229;
  /* UI-0039 (quality-audit): same 8 evacuation-status swatches as :root's own
     comment above. */
  --evac-evacuated-self:     #43a047;
  --evac-evacuated-org:      #66bb6a;
  --evac-at-home:            #f57c00;
  --evac-not-evacuating:     #e53935;
  --evac-unknown-location:   #b71c1c;
  --evac-not-in-settlement:  #607d8b;
  --evac-no-contact:         #6a1b9a;
  --evac-not-reported:       #78909c;
  --radius:   12px;
  --shadow:   0 12px 40px rgba(0,0,0,.08);
  --font:     'Segoe UI', system-ui, sans-serif;
  --text-primary: #1e293b;
  --text-muted:   #64748b;
  --toggle-bg:    #94a3b8;
  --topbar-bg:    #ffffff;
  --subribbon-bg: #f1f5f9;
}

/* ── High-Contrast theme (WCAG AAA, a11y) ───────────────────────────────
   Every colour token satisfies 7:1+ contrast against its opposite:
     text     #fafafa on bg #0a0a0a = 19:1
     muted    #bcbcbc on bg #0a0a0a = 10.4:1
     accent   #4dd0e1 on bg #0a0a0a = 10.9:1
     danger   #ff8a80 on bg #0a0a0a = 7.6:1
     success  #80e27e on bg #0a0a0a = 12:1
   Also carries the two structural high-contrast rules that palette alone
   can't fix: THICKER default focus ring (WCAG 2.4.11 focus-not-obscured)
   and BOLDER borders so shapes read at reduced acuity. */
[data-theme="high-contrast"] {
  --bg:       #0a0a0a;
  --surface:  #141414;
  --border:   #fafafa;
  --accent:   #4dd0e1;
  --accent-rgb: 77,208,225;
  --accent-h: #26c6da;
  /* No separate AI hue here on purpose -- this theme leans on a small, curated
     palette; the sparkle icon + "AI" badge carry the signal instead. */
  --ai-accent: #4dd0e1;
  --ai-accent-rgb: 77,208,225;
  --ai-accent-dark: #26c6da;
  --text:     #fafafa;
  --muted:    #bcbcbc;
  --danger:   #ff8a80;
  --success:  #80e27e;
  --success-rgb: 128,226,126;
  --warn:     #ffd54f;
  --warn-rgb: 255,213,79;
  --warning:     var(--warn);
  --warning-rgb: var(--warn-rgb);
  /* High-contrast keeps a deliberately small palette -- fold the two
     notif-icon colors with no dedicated token into the theme's own accent
     rather than adding new low-contrast hues. --info (no dedicated token in
     any theme) folds into accent for the same reason. */
  --info: var(--accent);
  --notif-purple: var(--accent);
  --notif-purple-rgb: var(--accent-rgb);
  --notif-blue: var(--accent);
  --notif-blue-rgb: var(--accent-rgb);
  /* UI-0042 (quality-audit): same reasoning as notif-purple/notif-blue above. */
  --search-pink: var(--accent);
  --search-pink-rgb: var(--accent-rgb);
  --search-indigo: var(--accent);
  --search-indigo-rgb: var(--accent-rgb);
  /* UI-0039 (quality-audit): same reasoning as notif-purple/notif-blue above --
     fold the 8 evacuation-status colors into the theme's own accent. Every
     swatch is always paired with its status label text right next to it, so
     no information is color-only here. */
  --evac-evacuated-self:     var(--accent);
  --evac-evacuated-org:      var(--accent);
  --evac-at-home:            var(--accent);
  --evac-not-evacuating:     var(--accent);
  --evac-unknown-location:   var(--accent);
  --evac-not-in-settlement:  var(--accent);
  --evac-no-contact:         var(--accent);
  --evac-not-reported:       var(--accent);
  --radius:   10px;
  --shadow:   0 0 0 1px #fafafa, 0 8px 24px rgba(0,0,0,.7);
  --font:     'Segoe UI', system-ui, sans-serif;
  --text-primary: #fafafa;
  --text-muted:   #bcbcbc;
  --toggle-bg:    #4dd0e1;
  --topbar-bg:    #141414;
  --subribbon-bg: #0f0f0f;
}
[data-theme="high-contrast"] body { font-family: var(--font); }
/* Bolder focus everywhere — 3px cyan ring instead of the default 1-2px,
   so keyboard users can spot it without straining. */
[data-theme="high-contrast"] *:focus-visible {
  outline: 3px solid #4dd0e1 !important;
  outline-offset: 2px !important;
}
/* Bolder borders on the boxes that define shape (cards, inputs, buttons),
   so structure reads at reduced acuity without changing behaviour. */
[data-theme="high-contrast"] input,
[data-theme="high-contrast"] select,
[data-theme="high-contrast"] textarea,
[data-theme="high-contrast"] .mnh-input,
[data-theme="high-contrast"] .um-input,
[data-theme="high-contrast"] .stg-input {
  border-width: 2px;
  border-color: #fafafa;
  background: #0a0a0a;
  color: #fafafa;
}
[data-theme="high-contrast"] .um-btn-add,
[data-theme="high-contrast"] .um-btn-save,
[data-theme="high-contrast"] .prof-edit-btn {
  border: 2px solid #4dd0e1;
  color: #0a0a0a;
  background: #4dd0e1;
  font-weight: 700;
}
[data-theme="high-contrast"] .um-btn-cancel,
[data-theme="high-contrast"] .um-btn-secondary {
  border: 2px solid #fafafa;
  background: transparent;
  color: #fafafa;
}
[data-theme="high-contrast"] .um-btn-danger,
[data-theme="high-contrast"] .proc-item-del {
  border: 2px solid #ff8a80;
  color: #ff8a80;
}
/* Cards and modal shells — a 1px border can vanish at high magnification;
   2px is the reliable minimum. */
[data-theme="high-contrast"] .stg-section,
[data-theme="high-contrast"] .um-modal-box,
[data-theme="high-contrast"] .um-wrap,
[data-theme="high-contrast"] .proc-wrap {
  border: 2px solid #fafafa;
}
/* The selected/active item must be UNMISTAKABLE — the standard 1px accent
   ring is easy to miss at low vision. */
[data-theme="high-contrast"] .proc-item.proc-item-active,
[data-theme="high-contrast"] .sub-item.active,
[data-theme="high-contrast"] .ribbon-item.active {
  outline: 2px solid #4dd0e1;
  outline-offset: -2px;
  background: color-mix(in srgb, #4dd0e1 20%, transparent);
  font-weight: 700;
}

/* ── High-Contrast Maximum theme (WCAG AAA, classic Windows-style) ──────
   Pure black + pure white + yellow accent + orange danger. Every token pair
   is 15:1+ contrast — the strictest end of AAA. Same three structural rules
   as the softer variant (thick focus ring, bold borders, unmistakable active
   state), just applied on the classic palette. */
[data-theme="high-contrast-max"] {
  --bg:       #000000;
  --surface:  #000000;
  --border:   #ffffff;
  --accent:   #ffff00;
  --accent-rgb: 255,255,0;
  --accent-h: #ffff00;
  /* Same reasoning as high-contrast above -- no separate AI hue. */
  --ai-accent: #ffff00;
  --ai-accent-rgb: 255,255,0;
  --ai-accent-dark: #ffff00;
  --text:     #ffffff;
  --muted:    #ffffff;
  --danger:   #ff8000;
  --success:  #00ff00;
  --success-rgb: 0,255,0;
  --warn:     #ffff00;
  --warn-rgb: 255,255,0;
  --warning:     var(--warn);
  --warning-rgb: var(--warn-rgb);
  /* Same reasoning as high-contrast: the strict AAA palette has no room for
     two more hues, fold into the theme's own accent. */
  --info: var(--accent);
  --notif-purple: var(--accent);
  --notif-purple-rgb: var(--accent-rgb);
  --notif-blue: var(--accent);
  --notif-blue-rgb: var(--accent-rgb);
  /* UI-0042 (quality-audit): same reasoning as notif-purple/notif-blue above. */
  --search-pink: var(--accent);
  --search-pink-rgb: var(--accent-rgb);
  --search-indigo: var(--accent);
  --search-indigo-rgb: var(--accent-rgb);
  /* UI-0039 (quality-audit): same reasoning as notif-purple/notif-blue above. */
  --evac-evacuated-self:     var(--accent);
  --evac-evacuated-org:      var(--accent);
  --evac-at-home:            var(--accent);
  --evac-not-evacuating:     var(--accent);
  --evac-unknown-location:   var(--accent);
  --evac-not-in-settlement:  var(--accent);
  --evac-no-contact:         var(--accent);
  --evac-not-reported:       var(--accent);
  --radius:   8px;
  --shadow:   0 0 0 1px #ffffff, 0 8px 24px rgba(0,0,0,.8);
  --font:     'Segoe UI', system-ui, sans-serif;
  --text-primary: #ffffff;
  --text-muted:   #ffffff;
  --toggle-bg:    #ffff00;
  --topbar-bg:    #000000;
  --subribbon-bg: #000000;
}
[data-theme="high-contrast-max"] body { font-family: var(--font); }
[data-theme="high-contrast-max"] *:focus-visible {
  outline: 3px solid #ffff00 !important;
  outline-offset: 2px !important;
}
[data-theme="high-contrast-max"] input,
[data-theme="high-contrast-max"] select,
[data-theme="high-contrast-max"] textarea,
[data-theme="high-contrast-max"] .mnh-input,
[data-theme="high-contrast-max"] .um-input,
[data-theme="high-contrast-max"] .stg-input {
  border-width: 2px;
  border-color: #ffffff;
  background: #000000;
  color: #ffffff;
}
[data-theme="high-contrast-max"] .um-btn-add,
[data-theme="high-contrast-max"] .um-btn-save,
[data-theme="high-contrast-max"] .prof-edit-btn {
  border: 2px solid #ffff00;
  color: #000000;
  background: #ffff00;
  font-weight: 700;
}
[data-theme="high-contrast-max"] .um-btn-cancel,
[data-theme="high-contrast-max"] .um-btn-secondary {
  border: 2px solid #ffffff;
  background: transparent;
  color: #ffffff;
}
[data-theme="high-contrast-max"] .um-btn-danger,
[data-theme="high-contrast-max"] .proc-item-del {
  border: 2px solid #ff8000;
  color: #ff8000;
}
[data-theme="high-contrast-max"] .stg-section,
[data-theme="high-contrast-max"] .um-modal-box,
[data-theme="high-contrast-max"] .um-wrap,
[data-theme="high-contrast-max"] .proc-wrap {
  border: 2px solid #ffffff;
}
[data-theme="high-contrast-max"] .proc-item.proc-item-active,
[data-theme="high-contrast-max"] .sub-item.active,
[data-theme="high-contrast-max"] .ribbon-item.active {
  outline: 2px solid #ffff00;
  outline-offset: -2px;
  background: color-mix(in srgb, #ffff00 25%, transparent);
  font-weight: 700;
}
[data-theme="light"] body { font-family: var(--font); }
[data-theme="light"] .top-bar {
  background: var(--topbar-bg);
  border-bottom: 1px solid var(--border);
  color: var(--text);
}
[data-theme="light"] input,
[data-theme="light"] select,
[data-theme="light"] textarea,
[data-theme="light"] .mnh-input {
  background: #f8fafc;
  border-color: #cbd5e1;
  color: #1e293b;
}
[data-theme="light"] input:focus,
[data-theme="light"] select:focus,
[data-theme="light"] textarea:focus {
  border-color: var(--accent);
  background: #fff;
}
[data-theme="light"] .um-modal-box {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  box-shadow: 0 20px 60px rgba(0,0,0,.15);
}
[data-theme="light"] .um-modal-header {
  border-bottom-color: #e2e8f0;
}
[data-theme="light"] .um-table td,
[data-theme="light"] .um-table th {
  border-bottom-color: #e2e8f0;
}
[data-theme="light"] .um-table th {
  background: #f1f5f9;
  color: #334155;
}
[data-theme="light"] .um-table tr:hover td {
  background: rgba(79,70,229,.03);
}
[data-theme="light"] .proc-sidebar {
  background: #f8fafc;
  border-color: #e2e8f0;
}
[data-theme="light"] .proc-item:hover,
[data-theme="light"] .proc-item-active {
  background: rgba(79,70,229,.06);
}
[data-theme="light"] .stg-section {
  background: #ffffff;
  border: 1px solid #e2e8f0;
}
[data-theme="light"] .um-btn-cancel {
  color: #475569;
  border-color: #cbd5e1;
}
[data-theme="light"] .um-btn-cancel:hover {
  color: #1e293b;
  border-color: #94a3b8;
}
[data-theme="light"] .alert-success { background: rgba(22,163,74,.08); border-color: rgba(22,163,74,.25); }
[data-theme="light"] .alert-error   { background: rgba(220,38,38,.08); border-color: rgba(220,38,38,.25); }
[data-theme="light"] .alert-info    { background: rgba(79,70,229,.08); border-color: rgba(79,70,229,.25); }
[data-theme="light"] .alert-warning { background: rgba(217,119,6,.08); border-color: rgba(217,119,6,.25); }
[data-theme="light"] .um-modal-overlay {
  background: rgba(0,0,0,.3);
}
[data-theme="light"] ::-webkit-scrollbar-track { background: #f1f5f9; }
[data-theme="light"] ::-webkit-scrollbar-thumb { background: #cbd5e1; }
[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
[data-theme="light"] .ds-card {
  background: #ffffff;
  border: 1px solid #e2e8f0;
}
[data-theme="light"] .ds-card:hover {
  border-color: var(--accent);
}
[data-theme="light"] .reg-toolbar {
  background: #f1f5f9;
  border-bottom: 1px solid #e2e8f0;
}
[data-theme="light"] .status-bar-theme:hover,
[data-theme="light"] .status-bar-lang:hover { background: rgba(0,0,0,.06); }
[data-theme="light"] .user-chip-profile { background: rgba(0,0,0,.07); }
/* ── Shared overrides for all light-based themes ───────────── */
[data-theme="light"] .ot-group-header{
  background: var(--accent);
  color: #ffffff;
}
[data-theme="light"] .ot-group-header .ot-count{
  color: rgba(255,255,255,.75);
}
[data-theme="light"] .ot-group-header .ot-group-arrow{
  color: #ffffff;
}
[data-theme="light"] .ot-group{
  background: #ffffff;
  border: 1px solid var(--border);
}
[data-theme="light"] .ot-card{
  border-bottom-color: var(--border);
}
[data-theme="light"] .ot-card:hover{
  background: rgba(0,0,0,.02);
}
[data-theme="light"] .img-modal-box{
  background: #ffffff;
  border-color: var(--border);
}
[data-theme="light"] .proc-sidebar-header,
[data-theme="light"] .proc-sidebar-header *,
[data-theme="light"] .proc-sidebar-title {
  background: var(--accent);
  color: #ffffff;
}
[data-theme="light"] .stg-section-title {
  background: var(--accent);
  color: #ffffff;
  border-bottom-color: var(--border);
}
[data-theme="light"] .stg-section-title i {
  color: #ffffff;
}
[data-theme="light"] .sub-ribbon {
  background: #f1f5f9;
  border-bottom: 1px solid #e2e8f0;
}

/* ── Theme selector card previews ───────────────────────────── */
.theme-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: .8rem;
}
.theme-grid .theme-card {
  flex: 0 1 calc(20% - 1rem);
  min-width: 140px;
}
.theme-card {
  border: 2px solid var(--border);
  border-radius: var(--radius);
  padding: .75rem;
  cursor: pointer;
  transition: border-color .2s, box-shadow .2s, transform .15s;
  position: relative;
}
.theme-card:hover {
  border-color: var(--accent-h);
  transform: translateY(-2px);
}
.theme-card.theme-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.25);
}
.theme-card-preview {
  border-radius: 6px;
  height: 90px;
  margin-bottom: .6rem;
  overflow: hidden;
  position: relative;
}
.theme-card-preview-header {
  height: 22px;
  display: flex;
  align-items: center;
  padding: 0 8px;
  gap: 4px;
}
.theme-card-preview-header span {
  width: 6px; height: 6px; border-radius: 50%;
}
.theme-card-preview-body {
  display: flex;
  height: calc(100% - 22px);
}
.theme-card-preview-sidebar {
  width: 35px;
  padding: 4px 3px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.theme-card-preview-sidebar span {
  height: 4px;
  border-radius: 2px;
  opacity: .6;
}
.theme-card-preview-content {
  flex: 1;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.theme-card-preview-content span {
  height: 4px;
  border-radius: 2px;
  opacity: .5;
}
.theme-card-preview-content span:first-child {
  width: 60%;
  height: 6px;
  opacity: .8;
}
.theme-card-name {
  font-size: .88rem;
  font-weight: 600;
  margin-bottom: .15rem;
}
.theme-card-desc {
  font-size: .75rem;
  color: var(--muted);
  line-height: 1.3;
}
.theme-card-badge {
  position: absolute;
  top: 8px;
  inset-inline-start: 8px;
  font-size: .65rem;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}

/* ── Theme Manager ─────────────────────────────────────────── */
.tm-search-wrap {
  position: relative;
  margin-bottom: 1rem;
}
.tm-search-wrap i {
  position: absolute;
  inset-inline-end: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  font-size: .85rem;
  pointer-events: none;
}
.tm-search-wrap input {
  width: 100%;
  padding: .55rem 2.2rem .55rem .8rem;
  box-sizing: border-box;
}
.tm-default-row {
  margin-bottom: 1rem;
}
.tm-default-row .theme-card {
  max-width: 200px;
}
.tm-group {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: .6rem;
  overflow: hidden;
  transition: border-color .2s;
}
.tm-group:hover {
  border-color: var(--accent-h, var(--accent));
}
.tm-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .7rem 1rem;
  cursor: pointer;
  background: var(--surface);
  user-select: none;
  transition: background .2s;
}
.tm-group-header:hover {
  background: color-mix(in srgb, var(--surface) 85%, var(--accent) 15%);
}
.tm-group-header-right {
  display: flex;
  align-items: center;
  gap: .5rem;
}
.tm-group-header-right > i {
  color: var(--accent);
  font-size: .95rem;
}
.tm-group-name {
  font-weight: 600;
  font-size: .92rem;
  color: var(--text);
}
.tm-group-count {
  font-size: .72rem;
  color: var(--muted);
  background: var(--border);
  padding: 1px 7px;
  border-radius: 8px;
  font-weight: 500;
}
.tm-group-active-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  box-shadow: 0 0 6px var(--accent);
}
.tm-group-arrow {
  color: var(--muted);
  font-size: .75rem;
  transition: transform .3s ease;
}
.tm-group-header.tm-open .tm-group-arrow {
  transform: rotate(180deg);
}
.tm-group-body {
  max-height: 0;
  overflow: hidden;
  transition: max-height .35s ease, padding .25s ease;
  padding: 0 1rem;
}
.tm-group-body.tm-body-open {
  max-height: 800px;
  padding: .8rem 1rem 1rem;
}

/* CSP phase 2: voting.js's closed-ballot card header had onmouseenter/onmouseleave
   inline (dead under CSP) that set background to the SAME value on enter and leave —
   a no-op even before CSP broke it. Given a real hover highlight instead, matching
   the var(--hover) convention used elsewhere for this exact pattern. */
.vote-closed-card-header { display: flex; justify-content: space-between; align-items: center; padding: .75rem 1rem; cursor: pointer; user-select: none; background: var(--surface); transition: background .15s; }
.vote-closed-card-header:hover { background: var(--hover); }

/* ══════════════════════════════════════
   Fan-Out (מניפה) Module
   ══════════════════════════════════════ */
/* CSP phase 2: was onmouseenter/onmouseleave inline (dead under CSP) toggling
   text-decoration-color / a child tooltip's display. */
.fan-hh-name-cell { padding: .4rem .8rem; font-size: .88rem; color: var(--accent); text-decoration: underline; text-decoration-color: transparent; transition: text-decoration-color .15s; }
.fan-hh-name-cell:hover { text-decoration-color: currentColor; }
.fan-gt { display: none; }
.fan-hh-chip:hover .fan-gt, .fan-hh-chip:focus-within .fan-gt { display: block; }
.fan-wrap { padding: 1.5rem; position: relative; }

.fan-roles-panel { position: absolute; top: 0; inset-inline-start: 0; width: 210px; background: var(--surface); border: 1px solid var(--border); border-radius: .6rem; padding: .7rem; z-index: 2; box-shadow: 0 2px 8px rgba(0,0,0,.08); transition: width .2s ease, padding .2s ease; overflow: hidden; }
.fan-wrap:has(.fan-roles-panel) { padding-inline-start: 230px; transition: padding .2s ease; }
.fan-wrap:has(.fan-roles-panel--collapsed) { padding-inline-start: 46px; }
.fan-roles-header { font-size: .85rem; font-weight: 700; color: var(--accent); margin-bottom: .6rem; display: flex; align-items: center; gap: .4rem; border-bottom: 1px solid var(--border); padding-bottom: .5rem; white-space: nowrap; }
.fan-roles-panel--collapsed { width: 32px; padding: .5rem .4rem; }
.fan-roles-body { max-height: calc(100vh - 180px); overflow-y: auto; }
.fan-roles-panel--collapsed .fan-roles-body { display: none; }
.fan-roles-panel--collapsed .fan-roles-header { flex-direction: column; border-bottom: none; margin-bottom: 0; padding-bottom: 0; gap: .5rem; }
.fan-roles-panel--collapsed .fan-roles-header > span { display: none; }
.fan-roles-panel--collapsed .fan-roles-toggle-icon { transform: rotate(90deg); }
/* CSP phase 2: was onmouseover/onmouseout inline (dead under CSP) toggling background. */
.evac-export-item { display: block; padding: .4rem .8rem; color: var(--text); text-decoration: none; font-size: .8rem; }
.evac-export-item:hover { background: var(--bg); }
.evac-wrap { padding: 1rem; position: relative; }
.evac-roles-panel { position: absolute; top: 0; inset-inline-start: 0; width: 200px; background: var(--surface); border: 1px solid var(--border); border-radius: .6rem; padding: .7rem; z-index: 2; box-shadow: 0 2px 8px rgba(0,0,0,.08); transition: width .2s ease, padding .2s ease; overflow: hidden; }
.evac-wrap:has(.evac-roles-panel) { padding-inline-start: 218px; transition: padding .2s ease; }
.evac-wrap:has(.evac-roles-panel--collapsed) { padding-inline-start: 46px; }
.evac-roles-header { font-size: .85rem; font-weight: 700; color: var(--accent); margin-bottom: .6rem; display: flex; align-items: center; gap: .4rem; border-bottom: 1px solid var(--border); padding-bottom: .5rem; white-space: nowrap; }
.evac-roles-panel--collapsed { width: 32px; padding: .5rem .4rem; }
.evac-roles-body { max-height: calc(100vh - 180px); overflow-y: auto; }
.evac-roles-panel--collapsed .evac-roles-body { display: none; }
.evac-roles-panel--collapsed .evac-roles-header { flex-direction: column; border-bottom: none; margin-bottom: 0; padding-bottom: 0; gap: .5rem; }
.evac-roles-panel--collapsed .evac-roles-header > span { display: none; }
.evac-roles-panel--collapsed .evac-roles-toggle-icon { transform: rotate(90deg); }
@media (max-width: 900px) { .evac-roles-panel { position: static; width: 100%; margin-bottom: 1rem; } .evac-wrap:has(.evac-roles-panel) { padding-inline-start: 1rem; } .evac-wrap:has(.evac-roles-panel--collapsed) { padding-inline-start: 1rem; } }
.fan-role-row { display: flex; gap: .5rem; align-items: flex-start; padding: .45rem 0; border-bottom: 1px solid var(--border); }
.fan-row-pending { background: rgba(var(--accent-rgb),.08); }
.fan-row-pending .fan-inline-sel { border-color: var(--accent); }
.fan-role-row:last-child { border-bottom: none; }
.fan-role-icon { width: 26px; height: 26px; border-radius: 50%; background: var(--accent); color: var(--accent-text); display: flex; align-items: center; justify-content: center; font-size: .7rem; flex-shrink: 0; margin-top: 2px; }
.fan-role-info { min-width: 0; }
.fan-role-title { font-size: .75rem; color: var(--muted); font-weight: 600; }
.fan-role-name { font-size: .85rem; font-weight: 500; color: var(--text); }
.fan-role-phone { font-size: .75rem; color: var(--text); display: flex; align-items: center; gap: .3rem; }   /* was var(--muted) */

@media (max-width: 900px) {
  .fan-roles-panel { position: static; width: 100%; margin-bottom: 1rem; }
  .fan-toast-container { inset-inline-end: .5rem; inset-inline-start: .5rem; max-width: none; }
}
.fan-section-title {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-size: 1.1rem; font-weight: 600; color: var(--text);
  margin-bottom: 1.2rem; padding-bottom: .6rem;
  border-bottom: 1px solid var(--border);
}
.fan-req-title { font-size: 1rem; font-weight: 600; color: var(--text); margin: 0 0 .3rem; }
.fan-req-msg { color: var(--muted); font-size: .85rem; margin: 0 0 1.2rem; }
.fan-empty { text-align: center; color: var(--muted); padding: 2rem; }

.fan-table {
  width: 100%; border-collapse: collapse; font-size: .85rem;
}
.fan-table th {
  background: var(--surface); color: var(--muted); font-weight: 600;
  padding: .55rem .7rem; text-align: start; border-bottom: 2px solid var(--border);
  position: sticky; top: 0; z-index: 1;
}
/* UI-0099: the .fan-table family is wide -- the manage view is eight columns
   ending in Actions -- and `width:100%` with the default `table-layout:auto`
   does NOT fit a 360px phone: auto lets content force minimum column widths past
   100%. So the Actions column left the screen with no way to reach it.

   The obvious fix, wrapping in .um-table-wrap, is wrong HERE and
   tests/test_fan_table_scroll_wrap.py pins why: `overflow-x:auto` forces
   `overflow-y` to compute to auto as well, which makes the wrapper the sticky
   containing block. The header would then stick inside a box with no height
   constraint, i.e. never stick at all. That is why five of these tables are
   deliberately unwrapped, and it is a real constraint, not an oversight.

   But the two concerns live on different screens. The overflow is a PHONE
   problem; the sticky header earns its keep on a WIDE one, where enough rows
   scroll beneath it to matter. On a phone you see a handful of rows and the
   header barely leaves the viewport. So the trade is only made below 600px:
   there the header stops sticking and the table gets its scroller. Nothing about
   the desktop rendering changes. */
@media (max-width: 600px) {
  .fan-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* Dropped together with the wrapper, not incidentally: a sticky header inside
     an overflow container is the exact combination that silently stops working. */
  .fan-table th { position: static; }
}

.fan-table td {
  padding: .5rem .7rem; border-bottom: 1px solid var(--border); color: var(--text);
}
.fan-table tbody tr:hover { background: rgba(var(--accent-rgb),.04); }
.fan-table-sm { font-size: .82rem; }
.fan-table-sm th, .fan-table-sm td { padding: .4rem .5rem; }

.fan-badge {
  display: inline-block; padding: .15rem .6rem; border-radius: 10px;
  font-size: .75rem; font-weight: 600;
}
.fan-badge-active { background: rgba(34,197,94,.15); color: var(--success); }
.fan-badge-expired { background: rgba(239,68,68,.15); color: var(--danger); }
.fan-badge-closed { background: rgba(148,163,184,.15); color: var(--muted); }
.fan-badge-draft  { background: rgba(245,158,11,.15); color: var(--warn); }
/* UI-0100: these two were the only badges in the family hardcoding their TEXT
   colour as well as their background -- and both hardcoded #16a34a / #0d9488,
   which are the LIGHT theme's greens, so on the default dark theme they painted
   dark green on a dark surface. The pair still reads as two states: the
   correction itself is the success green, while the retracted original takes
   --info (an alias of --accent), which stays distinct on every theme. */
.fan-badge-corrected  { background: rgba(var(--accent-rgb),.18);  color: var(--info); }     /* original was retracted */
.fan-badge-correction { background: rgba(var(--success-rgb),.18); color: var(--success); }  /* the all-clear row itself */
/* "Send all-clear" action — green, distinct from the navy+gold primary + red delete.
   The white-on-#16a34a it used to carry measured 3.30:1, under WCAG AA, and simply
   tokenising the background while keeping white would have made it 1.77:1 on the
   default theme's lighter mint. --success-text is the ink that clears AA on all
   four themes. */
.fan-actions .prof-edit-btn.fan-action-correct { background: var(--success); color: var(--success-text) !important; }
.fan-actions .prof-edit-btn.fan-action-correct:hover { filter: brightness(.88); }

.fan-actions { display: flex; flex-wrap: wrap; gap: .3rem; }
.fan-actions .prof-edit-btn { padding: .3rem .6rem; font-size: .78rem; white-space: nowrap; }
/* Delete stays the odd one out — a full danger button, not an accent one, so the
   destructive action reads as destructive now that it carries a label. */
.fan-actions .prof-edit-btn.fan-action-delete { background: var(--danger); color: #fff !important; }
.fan-actions .prof-edit-btn.fan-action-delete:hover { background: var(--danger); filter: brightness(.92); }
/* Any accent button given a solid danger (coral) fill via inline background must
   carry a white label — otherwise the per-theme gold/navy text is unreadable on it.
   :root scoping reaches (0,3,0) and, placed after the theme blocks, wins the cascade. */
:root .prof-edit-btn[style*="background:var(--danger)"],
:root .um-btn-add[style*="background:var(--danger)"] { color: #fff !important; }

.fan-stats-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.5rem;
}
.fan-stat-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 1.2rem; text-align: center;
}
.fan-stat-wide { grid-column: 1 / -1; }
.fan-stat-num { font-size: 2rem; font-weight: 700; color: var(--text); }
.fan-stat-lbl { font-size: .8rem; color: var(--muted); margin-top: .2rem; }

.fan-progress-bar {
  height: 10px; background: var(--border); border-radius: 5px; overflow: hidden; margin-bottom: .4rem;
}
.fan-progress-fill {
  height: 100%; background: linear-gradient(90deg, var(--accent), var(--success));
  border-radius: 5px; transition: width .6s ease;
}

.fan-status-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem;
}
.fan-status-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 1rem; text-align: center; border-top: 3px solid;
}
.fan-status-num { font-size: 1.6rem; font-weight: 700; color: var(--text); margin: .4rem 0 .1rem; }
.fan-status-lbl { font-size: .78rem; color: var(--muted); }
.fan-status-pct { font-size: .9rem; font-weight: 600; color: var(--text); margin-top: .3rem; }

/* ── Bounce spinner ──────────────────────────────────── */
@keyframes sp-bounce {
  0%, 80%, 100% { transform: translateY(0); opacity: .55; }
  40% { transform: translateY(-7px); opacity: 1; }
}

/* Reduced-motion counterpart of sp-bounce. Same rhythm, opacity only: the 7px
   translateY is the part a vestibular user cannot tolerate, the "something is
   happening" signal is not. Used by the two reduced-motion blocks at the end of
   this file -- see the note there for why the loader is exempt at all. */
@keyframes sp-fade {
  0%, 80%, 100% { opacity: .3; }
  40% { opacity: 1; }
}
.sp-bounce { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; }
.sp-bounce i { border-radius: 50%; background: currentColor; animation: sp-bounce .9s ease infinite; }
.sp-bounce.xl i { width: 12px; height: 12px; }
.sp-bounce.lg i { width: 8px; height: 8px; }
.sp-bounce.md i { width: 6px; height: 6px; }
.sp-bounce.sm i { width: 4px; height: 4px; }
.sp-bounce i:nth-child(2) { animation-delay: .15s; }
.sp-bounce i:nth-child(3) { animation-delay: .3s; }

/* ── Broadcast message stats ──────────────────────────── */
.msg-stats-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; padding: .5rem 1.2rem 1rem;
}
.msg-stat-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 1.2rem .8rem; text-align: center;
  border-top: 3px solid var(--border);
  transition: border-color .2s;
}
.msg-stat-card.s-recipients { border-top-color: var(--accent, #2563eb); }
.msg-stat-card.s-delivered  { border-top-color: var(--success, #27ae60); }
.msg-stat-card.s-opened     { border-top-color: var(--warn, #d97706); }
.msg-stat-icon { font-size: 1.3rem; margin-bottom: .5rem; }
.msg-stat-card.s-recipients .msg-stat-icon { color: var(--accent, #2563eb); }
.msg-stat-card.s-delivered  .msg-stat-icon { color: var(--success, #27ae60); }
.msg-stat-card.s-opened     .msg-stat-icon { color: var(--warn, #d97706); }
.msg-stat-num { font-size: 1.8rem; font-weight: 700; color: var(--text); line-height: 1; }
.msg-stat-lbl { font-size: .78rem; color: var(--muted); margin-top: .35rem; }
.msg-stat-pct { font-size: .82rem; color: var(--muted); margin-top: .2rem; }
.msg-stat-bar-wrap { height: 4px; background: var(--border); border-radius: 2px; margin-top: .7rem; overflow: hidden; }
.msg-stat-bar-fill { height: 100%; border-radius: 2px; transition: width .6s ease; }
.msg-stat-card.s-recipients .msg-stat-bar-fill { background: var(--accent, #2563eb); }
.msg-stat-card.s-delivered  .msg-stat-bar-fill { background: var(--success, #27ae60); }
.msg-stat-card.s-opened     .msg-stat-bar-fill { background: var(--warn, #d97706); }

.fan-result-group { margin-bottom: .6rem; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.fan-result-group-hdr {
  display: flex; align-items: center; gap: .6rem; padding: .7rem 1rem;
  background: var(--surface); cursor: pointer; font-weight: 600; font-size: .88rem; color: var(--text);
}
.fan-result-group-hdr:hover { background: rgba(var(--accent-rgb),.06); }
.fan-chevron { margin-inline-start: auto; transition: transform .2s; font-size: .7rem; color: var(--muted); }
.fan-result-group.collapsed .fan-chevron { transform: rotate(-90deg); }
html[dir="ltr"] .fan-result-group.collapsed .fan-chevron { transform: rotate(90deg); }
.fan-result-group.collapsed .fan-result-group-body { display: none; }
.fan-result-group-body { padding: 0; }
.fan-mg-stats { font-weight: 400; font-size: .78rem; color: var(--muted); margin-inline-start: .5rem; }

.fan-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-inline-end: .3rem; }

.fan-form { display: flex; flex-direction: column; gap: 1rem; }
.fan-field label { display: block; font-size: .82rem; font-weight: 600; color: var(--muted); margin-bottom: .3rem; }
.fan-input {
  width: 100%; padding: .5rem .7rem; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text); font-size: .88rem; font-family: inherit;
  box-sizing: border-box;
}
.fan-input:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 2px rgba(var(--accent-rgb),.15); }
.fan-textarea { min-height: 80px; resize: vertical; }

.fan-recip-scroll { max-height: 350px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; }

.fan-submit-btn { padding: .55rem 1.5rem !important; font-size: .9rem !important; }

/* Standard save button, rendered via saveButtonHtml() and driven by
   runSaveAction() — one consistent size/layout for every "שמור" it produces. */
.save-action { display: flex; align-items: center; gap: .6rem; }
.save-action .js-save-btn { padding: .55rem 1.5rem; font-size: .9rem; }

.fan-select {
  padding: .3rem .6rem; border: 1px solid var(--border); border-radius: 6px;
  background: var(--surface); color: var(--text); font-size: .82rem; font-family: inherit;
}
.fan-inline-sel {
  padding: .2rem .4rem; border: 1px solid var(--border); border-radius: 5px;
  background: var(--surface); color: var(--text); font-size: .78rem; font-family: inherit;
}

.fan-group-btn.active { background: var(--accent) !important; color: var(--accent-text) !important; }

.fan-grp-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  margin-bottom: .75rem; overflow: hidden;
}
.fan-grp-card--system {
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
  background: color-mix(in srgb, var(--accent) 4%, var(--surface));
}
.fan-sys-name { font-weight: 600; font-size: .95rem; }
.fan-sys-lock { color: var(--muted); font-size: .7rem; margin-inline-start: auto; }
.fan-grp-card-hdr {
  display: flex; align-items: center; gap: .5rem; padding: .6rem .8rem;
  cursor: pointer; flex-wrap: wrap;
}
.fan-grp-card-hdr:hover { background: rgba(var(--accent-rgb),.04); }
.fan-grp-chevron { transition: transform .2s; font-size: .7rem; color: var(--muted); }
html[dir="rtl"] .fan-grp-chevron { transform: rotate(180deg); }
html[dir="rtl"] .fan-grp-chevron-open { transform: rotate(270deg); }
html[dir="ltr"] .fan-grp-chevron { transform: rotate(0deg); }
html[dir="ltr"] .fan-grp-chevron-open { transform: rotate(90deg); }
.fan-grp-card-hdr .fan-grp-name { flex: 1; min-width: 100px; max-width: 180px; }
.fan-grp-count {
  font-size: .78rem; color: var(--accent); font-weight: 600;
  white-space: nowrap; min-width: 70px;
}
.fan-grp-hdr-actions { display: flex; align-items: center; gap: .4rem; margin-inline-start: auto; }
.fan-grp-hdr-actions .fan-grp-mgr { max-width: 180px; }
.fan-grp-card-body { padding: .5rem .8rem .8rem; border-top: 1px solid var(--border); }
.fan-grp-body-split { display: flex; gap: .8rem; }
.fan-grp-in-section { flex: 1; min-width: 0; }
.fan-grp-out-section { flex: 1; min-width: 0; }
.fan-grp-section-hdr {
  font-size: .82rem; font-weight: 600; color: var(--accent);
  padding: .4rem 0; margin-bottom: .3rem;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: .4rem;
}
.fan-grp-section-hdr i { font-size: .75rem; }
.fan-grp-count-in { color: var(--muted); font-weight: 400; }
.fan-grp-members-toolbar { display: flex; gap: .4rem; margin-bottom: .4rem; flex-wrap: wrap; }
.fan-grp-members-scroll { max-height: 240px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; }
.fan-grp-members-tbl { font-size: .8rem; }
.fan-grp-members-tbl td, .fan-grp-members-tbl th { padding: .25rem .4rem; }
.fan-grp-taken { font-size: .7rem; color: var(--muted); margin-inline-start: .3rem; }
.fan-grp-add-btn { color: var(--success) !important; }
.fan-grp-remove-btn { color: var(--danger, #f87171) !important; }
.fan-grp-empty-row td { font-style: italic; }
@media (max-width: 640px) {
  .fan-grp-body-split { flex-direction: column; }
}
.fan-grp-status-filter {
  font-size: .78rem; padding: .25rem .4rem;
  background: var(--surface); color: var(--muted); border: 1px solid var(--border);
  border-radius: 6px; cursor: pointer;
}
.fan-grp-nogrp-label {
  font-size: .78rem; color: var(--muted); display: flex; align-items: center; gap: .3rem;
  white-space: nowrap; cursor: pointer; user-select: none;
}
.fan-grp-nogrp-label input { accent-color: var(--accent); cursor: pointer; }

.fan-pop-toolbar {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  margin-bottom: 1rem; padding: .5rem 0;
}
.fan-pop-counter {
  font-size: .85rem; color: var(--muted); white-space: nowrap;
  margin-inline-start: auto;
}
.fan-pop-table-wrap { overflow-x: auto; }
.fan-pop-table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.fan-pop-table th {
  background: var(--surface); color: var(--muted); font-weight: 600;
  padding: .5rem .6rem; border-bottom: 2px solid var(--border); text-align: start;
}
.fan-pop-table td { padding: .45rem .6rem; border-bottom: 1px solid var(--border); }
.fan-pop-table tr:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.fan-pop-cb { accent-color: var(--accent); cursor: pointer; width: 1.1rem; height: 1.1rem; }
.fan-pop-contact-sel {
  background: var(--surface); color: var(--text); border: 1px solid var(--border);
  border-radius: .3rem; padding: .25rem .4rem; font-size: .82rem; max-width: 12rem; width: 100%;
}
.fan-pop-contact-cell { min-width: 8rem; }
.fan-pop-search-wrap { position: relative; flex: 1; min-width: 8rem; }
.fan-pop-search-wrap .fan-filter-input { width: 100%; padding-inline-start: 2rem; }
.fan-pop-search-clear {
  position: absolute; inset-inline-start: .5rem; top: 50%; transform: translateY(-50%);
  cursor: pointer; color: var(--muted); font-size: .85rem; line-height: 1;
}
.fan-pop-search-clear:hover { color: var(--danger); }

@media (max-width: 767.98px) {
  .fan-stats-grid { grid-template-columns: 1fr 1fr; }
  .fan-status-grid { grid-template-columns: 1fr 1fr; }
  .fan-wrap { padding: 1rem; }
}

/* ── Fan Checks (בדיקות מניפה) ── */
.fan-checks-pick { display: flex; align-items: center; gap: .7rem; margin-bottom: 1.2rem; }
.fan-checks-pick label { font-weight: 600; font-size: .9rem; white-space: nowrap; }
.fan-checks-detail { margin-top: .5rem; }
.fan-checks-info { margin-bottom: .5rem; }
.fan-checks-sim { margin: 1rem 0; padding: .8rem 1rem; background: var(--surface); border: 1px solid var(--border); border-radius: .5rem; }
.fan-checks-sim-row { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.fan-checks-sim-row label { font-weight: 600; font-size: .9rem; white-space: nowrap; }
.fan-checks-sim-row input[type="number"] { background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: .3rem; padding: .3rem .5rem; font-size: .9rem; text-align: center; }
.fan-checks-timer { font-size: 1.4rem; font-weight: 700; font-family: monospace; color: var(--accent); min-width: 5rem; }
.fan-checks-sent-count { font-size: .95rem; color: var(--text); white-space: nowrap; }
.fan-filter-chip { display: inline-flex; align-items: center; gap: .3rem; padding: .3rem .7rem; border-radius: 1rem; border: 1.5px solid var(--chip-color, var(--border)); background: var(--surface); color: var(--text); font-size: .82rem; cursor: pointer; transition: all .15s; }
.fan-filter-chip:hover { opacity: .85; }
.fan-filter-chip.active { background: var(--chip-color, var(--accent)); color: #fff; border-color: var(--chip-color, var(--accent)); }
.fan-filter-chip i { font-size: .75rem; }
/* A11Y-0134 (quality-audit): #fanResSearchBox's inline style suppressed the focus
   outline with nothing standing in for it -- unlike every other :focus-visible
   ring in this file, it has its own border to work with, so a direct outline
   (not the wrapper-recolor trick used for .topic-add-input/.dap-search-bar,
   which have none) is simplest here. */
#fanResSearchBox:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fan-toast-container { position: fixed; bottom: 1.5rem; inset-inline-end: 1.5rem; z-index: 9999; display: flex; flex-direction: column-reverse; gap: .5rem; pointer-events: none; max-width: min(400px, 90vw); }
.fan-toast { pointer-events: auto; display: flex; align-items: center; gap: .7rem; padding: .7rem 1rem; background: var(--surface); border: 2px solid var(--danger); border-radius: .7rem; box-shadow: 0 4px 20px rgba(0,0,0,.18); min-width: 280px; transition: opacity .4s, transform .4s; }
.fan-toast-enter { opacity: 0; transform: translateY(1rem); }
.fan-toast-exit { opacity: 0; transform: translateY(1rem); }
.fan-toast-icon { font-size: 1.4rem; color: var(--danger); flex-shrink: 0; }
.fan-toast-body { flex: 1; }
.fan-toast-title { font-weight: 700; font-size: .85rem; color: var(--danger); margin-bottom: .15rem; }
.fan-toast-name { font-size: .95rem; font-weight: 600; color: var(--text); }
.fan-toast-phone { font-size: .85rem; color: var(--text); }   /* was var(--muted) */
.fan-toast-close { background: none; border: none; font-size: 1.2rem; color: var(--muted); cursor: pointer; padding: 0 .3rem; flex-shrink: 0; }
.fan-toast-close:hover { color: var(--danger); }
.fan-toast-contacts { margin-top: .4rem; padding-top: .4rem; border-top: 1px solid var(--border); }
.fan-toast-contacts-title { font-size: .78rem; color: var(--muted); font-weight: 600; margin-bottom: .2rem; }
.fan-toast-contacts-title i { margin-inline-end: .3rem; }
.fan-toast-contact-row { display: flex; justify-content: space-between; gap: .5rem; font-size: .82rem; color: var(--text); }
.fan-toast-header { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.fan-toast-header .fan-toast-title { margin-bottom: 0; }
.fan-toast-chevron { font-size: .6rem; color: var(--muted); transition: transform .2s; margin-inline-start: auto; }
.fan-toast--collapsed .fan-toast-chevron { transform: rotate(180deg); }
.fan-toast-detail { max-height: 300px; overflow: hidden; transition: max-height .3s ease, opacity .25s ease; opacity: 1; }
.fan-toast--collapsed .fan-toast-detail { max-height: 0; opacity: 0; }

/* ── Personal Settings ── */
.ps-panel { padding: 1.5rem; margin-inline-end: auto; margin-inline-start: 0; }
[dir="ltr"] .ps-panel, :root:not([dir="rtl"]) .ps-panel { margin-inline-start: 0; margin-inline-end: auto; }

.ps-lang-grid { display: flex; flex-wrap: wrap; gap: .6rem; }
.ps-lang-card { display: inline-flex; align-items: center; gap: .5rem; padding: .7rem .9rem; border-radius: .6rem; border: 2px solid var(--border); background: var(--surface); cursor: pointer; transition: all .15s; flex: 0 0 auto; }
.ps-lang-card:hover { border-color: var(--accent); }
.ps-lang-card.ps-lang-active { border-color: var(--accent); background: var(--accent); color: var(--accent-text); }
.ps-lang-flag img { width: 24px; height: 18px; border-radius: 2px; }
.ps-lang-label { font-size: .9rem; font-weight: 500; }

.ps-theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: .7rem; }
.ps-theme-card { border-radius: .6rem; border: 2px solid var(--border); overflow: hidden; cursor: pointer; transition: all .15s; background: var(--surface); }
.ps-theme-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.ps-theme-card.ps-theme-active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.ps-theme-preview { height: 60px; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ps-theme-name { padding: .4rem .5rem; font-size: .8rem; font-weight: 500; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ps-form { display: flex; flex-direction: column; gap: .8rem; }
.ps-form input[type="email"],
.ps-form input[type="tel"],
.ps-form input[type="text"] { width: 100%; padding: .55rem .75rem; font-size: .95rem; border: 1px solid var(--border); border-radius: .45rem; background: var(--surface); color: var(--text); box-sizing: border-box; }
.ps-label { display: flex; flex-direction: column; gap: .3rem; font-size: .88rem; font-weight: 500; color: var(--text); }

.ps-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; padding: .7rem 0; border-bottom: 1px solid var(--border); cursor: pointer; font-size: .9rem; }
.ps-toggle-input { display: none; }
.ps-toggle-slider { position: relative; width: 44px; height: 24px; background: var(--toggle-bg); border-radius: 12px; transition: background .2s; flex-shrink: 0; }
.ps-toggle-slider::after { content: ''; position: absolute; top: 2px; inset-inline-start: 2px; width: 20px; height: 20px; background: #fff; border-radius: 50%; transition: transform .2s; }
.ps-toggle-input:checked + .ps-toggle-slider { background: var(--accent); }
.ps-toggle-input:checked + .ps-toggle-slider::after { transform: translateX(20px); }
[dir="rtl"] .ps-toggle-input:checked + .ps-toggle-slider::after { transform: translateX(-20px); }

/* Auto-save note — a tinted chip telling the user toggles persist without a
   save button. Success/error feedback now goes through showAlert toasts. */
.ps-autosave-note {
  display: inline-flex; align-items: center; gap: .4rem;
  margin-top: .9rem; padding: .4rem .7rem;
  font-size: .84rem; font-weight: 600; line-height: 1.3;
  color: var(--success);
  background: color-mix(in srgb, var(--success) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--success) 30%, transparent);
  border-radius: 999px;
}
.ps-autosave-note .app-icon { font-size: 1rem; flex-shrink: 0; color: var(--warn); }

/* ── Reports ── */
.rpt-wrap { padding: 1.5rem; }
.rpt-header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: .8rem; margin-bottom: 1.2rem; }
.rpt-title { font-size: 1.2rem; font-weight: 700; color: var(--text); margin: 0; display: flex; align-items: center; gap: .5rem; }
.rpt-title i { color: var(--accent); }
.rpt-export { display: flex; gap: .4rem; }
.rpt-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .8rem; margin-bottom: 1.2rem; }
.rpt-summary-card { background: var(--surface); border: 1px solid var(--border); border-radius: .6rem; padding: .8rem; text-align: center; }
.rpt-summary-num { font-size: 1.3rem; font-weight: 700; color: var(--accent); }
.rpt-summary-label { font-size: .78rem; color: var(--muted); margin-top: .2rem; }
/* ── Dashboard Charts ── */
.dash-charts-loading { padding: 3rem; text-align: center; color: var(--muted); font-size: .9rem; }
.dash-charts-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.2rem;
  padding: 1.2rem;
}
.dash-chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: .8rem;
}
.dash-chart-header { display: flex; flex-direction: column; gap: .15rem; }
.dash-chart-title  { font-size: .92rem; font-weight: 700; color: var(--text); }
.dash-chart-sub    { font-size: .75rem; color: var(--muted); }
.dash-chart-wrap   { position: relative; }
.dash-chart-wrap svg { display: block; overflow: visible; }
.dash-chart-legend { display: flex; flex-wrap: wrap; gap: .4rem .9rem; margin-top: .6rem; font-size: .74rem; color: var(--muted); }
.dash-chart-legend span { display: flex; align-items: center; gap: .3rem; }
/* Chart reveal (style C) layered on the depth gradients: bars grow from their
   baseline, the donut scales in, each staggered on render. Off under reduced-motion. */
@keyframes rptBarGrowX { from { transform: scaleX(0); } }
@keyframes rptBarGrowY { from { transform: scaleY(0); } }
@keyframes rptDonutIn  { from { transform: scale(.55); opacity: 0; } }
.dash-chart-wrap .rpt-bar-h   { transform-box: fill-box; transform-origin: left center;   animation: rptBarGrowX .8s cubic-bezier(.22,1,.36,1) both; }
.dash-chart-wrap .rpt-bar-v   { transform-box: fill-box; transform-origin: center bottom; animation: rptBarGrowY .8s cubic-bezier(.22,1,.36,1) both; }
.dash-chart-wrap .rpt-donut-g { transform-box: view-box; transform-origin: center;        animation: rptDonutIn  .7s cubic-bezier(.22,1,.36,1) both; }
@media (prefers-reduced-motion: reduce) {
  html:not([data-motion="full"]) .dash-chart-wrap .rpt-bar-h, html:not([data-motion="full"]) .dash-chart-wrap .rpt-bar-v, html:not([data-motion="full"]) .dash-chart-wrap .rpt-donut-g { animation: none; }
}
.dash-chart-legend i  { display: inline-block; width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.dash-chart-legend b  { color: var(--text); }
.dash-chart-full { grid-column: 1 / -1; }

/* ── Dashboard Preferences Panel ── */
.dash-pref-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 1050; }
.dash-pref-drawer  { position: fixed; top: 0; inset-inline-end: 0; bottom: 0; width: 300px; background: var(--surface); border-inline-start: 1px solid var(--border); z-index: 1051; display: flex; flex-direction: column; box-shadow: 0 0 20px rgba(0,0,0,.12); }
/* L10N-0052 (quality-audit): was hardcoded `right`/`border-left` with no RTL handling
   -- same bug class as the already-fixed L10N-0050. inset-inline-end/border-inline-start
   correctly pin the drawer to the trailing edge in both directions; the shadow is now
   symmetric (no horizontal offset) so it doesn't need its own [dir] override either. */
.dash-pref-header  { display: flex; align-items: center; justify-content: space-between; padding: .9rem 1rem; border-bottom: 1px solid var(--border); }
.dash-pref-list    { flex: 1; overflow-y: auto; padding: .5rem; }
.dash-pref-item    { display: flex; align-items: center; gap: .6rem; padding: .55rem .6rem; border-radius: 8px; cursor: grab; user-select: none; transition: background .12s; }
.dash-pref-item:hover { background: var(--bg); }
.dash-pref-item.dash-pref-hidden { opacity: .4; }
.dash-pref-item.dash-pref-drag-over { background: rgba(var(--accent-rgb),.1); outline: 1.5px dashed var(--accent); }
.dash-pref-grip    { color: var(--muted); font-size: .85rem; flex-shrink: 0; }
.dash-pref-label   { flex: 1; font-size: .87rem; }
.dash-pref-eye     { background: none; border: none; cursor: pointer; color: var(--muted); padding: .2rem .35rem; border-radius: 4px; line-height: 1; }
.dash-pref-eye:hover { color: var(--accent); background: var(--bg); }
/* A11Y-0094 (quality-audit): the move-up/move-down buttons reuse .dash-pref-eye
   and sit disabled at the list boundaries -- same convention as .feed-tr-btn[disabled]. */
.dash-pref-eye:disabled { opacity: .35; cursor: default; }
.dash-pref-eye:disabled:hover { color: var(--muted); background: none; }
.dash-pref-footer  { display: flex; flex-direction: column; gap: .5rem; padding: .9rem 1rem; border-top: 1px solid var(--border); }

/* Quick-action toggles share the panel drawer (phase 1.2 -- the brief says not to
   duplicate an existing favourites mechanism, and this is it). Two differences from
   the panel list above, both of which look wrong if left inherited:
   `flex: 1` on two sibling lists splits the drawer's height between them, and
   `cursor: grab` on rows with no drag handle promises a reorder that does nothing. */
.dash-pref-section {
  padding: .75rem 1rem .25rem; font-size: .78rem; font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
  border-top: 1px solid var(--border);
}
.dash-pref-list-static { flex: 0 1 auto; max-block-size: 40vh; }
.dash-pref-list-static .dash-pref-item { cursor: default; }
.dash-pref-empty { padding: .75rem .6rem; color: var(--muted); font-size: .85rem; text-align: center; }


.rpt-toolbar { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: .7rem; margin-bottom: 1rem; }
.rpt-filters { display: flex; gap: .5rem; flex-wrap: wrap; flex: 1; }
.rpt-toolbar .mnh-input, .rpt-filters .mnh-input {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .42rem .7rem;
  font-size: .85rem;
  color: var(--text);
  transition: border-color .2s, box-shadow .2s;
}
.rpt-toolbar .mnh-input:focus, .rpt-filters .mnh-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.2);
  outline: none;
}
.rpt-group-btns { display: flex; gap: 0; border: 1px solid var(--border); border-radius: .4rem; overflow: hidden; }
.rpt-group-btns button { background: var(--surface); border: none; padding: .4rem .8rem; font-size: .82rem; color: var(--text); cursor: pointer; border-inline-end: 1px solid var(--border); }
.rpt-group-btns button:last-child { border-inline-end: none; }
.rpt-group-btns button.active { background: var(--accent); color: var(--accent-text); }
.rpt-table { width: 100%; }
.rpt-table th { white-space: nowrap; user-select: none; text-align: start; }
.rpt-term-table { width: 100%; border-collapse: collapse; }
.rpt-term-table th { text-align: start; white-space: nowrap; padding: .45rem .7rem; border-bottom: 2px solid var(--border); color: var(--muted); font-size: .82rem; }
.rpt-term-table td { padding: .4rem .7rem; border-bottom: 1px solid var(--border); font-size: .87rem; vertical-align: middle; }
.rpt-days-badge span { display: inline-block; padding: .15rem .5rem; border-radius: .3rem; font-size: .8rem; font-weight: 600; }
.rpt-days-badge .rpt-danger { background: rgba(var(--accent-rgb),.08); color: var(--danger); }
.rpt-days-badge .rpt-warn { background: rgba(var(--accent-rgb),.08); color: var(--warn); }
.rpt-days-badge .rpt-ok { background: rgba(var(--accent-rgb),.08); color: var(--success); }
.rpt-group { border: 1px solid var(--border); border-radius: .5rem; margin-bottom: .5rem; overflow: hidden; }
.rpt-group-header { display: flex; align-items: center; gap: .5rem; padding: .7rem 1rem; background: var(--surface); cursor: pointer; font-size: .9rem; color: var(--text); }
.rpt-group-header:hover { background: rgba(var(--accent-rgb),.08); }
.rpt-chevron { font-size: .7rem; transition: transform .2s; color: var(--muted); }
[dir="ltr"] .rpt-chevron { transform: rotate(0deg); }
.rpt-group-open > .rpt-group-header .rpt-chevron { transform: rotate(-90deg); }
html[dir="rtl"] .vclosed-arrow { transform: rotate(180deg); }
html[dir="rtl"] .rpt-chevron { transform: rotate(180deg); }
html[dir="rtl"] .rpt-group-open > .rpt-group-header .rpt-chevron { transform: rotate(90deg); }
.rpt-group-count { margin-inline-start: auto; font-size: .78rem; color: var(--muted); font-weight: 400; }
.rpt-group-body { display: none; }
.rpt-group-open > .rpt-group-body { display: block; }
.rpt-pagination { display: flex; justify-content: center; gap: .3rem; margin-top: 1rem; }
.rpt-pagination button { background: var(--surface); border: 1px solid var(--border); border-radius: .3rem; padding: .3rem .6rem; font-size: .82rem; cursor: pointer; color: var(--text); }
.rpt-pagination button.active { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
@media (max-width: 767.98px) {
  .rpt-summary { grid-template-columns: repeat(2, 1fr); }
  .rpt-toolbar { flex-direction: column; align-items: stretch; }
  .rpt-table { font-size: .82rem; }
}

/* ── Events Module ── */
.ev-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 300px; }

/* Upcoming Events — horizontal layout */
.ev-upcoming-row { display: flex; gap: 1.5rem; max-width: 1100px; margin: 1rem auto; flex-wrap: wrap; justify-content: center; }
.ev-upcoming-card { flex: 1 1 0; min-width: 280px; max-width: 520px; background: var(--surface); border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,.08); overflow: hidden; }
.ev-upcoming-img { width: 100%; max-height: 220px; overflow: hidden; }
.ev-upcoming-img img { width: 100%; height: 100%; object-fit: cover; }
/* A11Y-0121 (quality-audit): the thumbnail is now keyboard-focusable
   (role="button" tabindex="0"). */
.ev-upcoming-img img:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ev-upcoming-body { padding: 1.2rem; }
.ev-upcoming-title { font-size: 1.4rem; font-weight: 800; color: var(--text); margin-bottom: .6rem; }
.ev-upcoming-meta { display: flex; flex-wrap: wrap; gap: .8rem; color: var(--muted); font-size: .9rem; margin-bottom: .8rem; }
.ev-upcoming-meta i { color: var(--accent); margin-inline-end: .3rem; }
.ev-upcoming-desc { color: var(--text); line-height: 1.6; white-space: pre-wrap; font-size: .9rem; }
.ev-upcoming-footer { padding: 0 1.2rem 1.2rem; }

/* ── Resident "confirm attendance" (RSVP) — button + modal form. Shared by the
   events-list cards (events.js), the events day-detail card, and the home feed
   (feed.js — card footer + detail modal). ── */
.ev-rsvp-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  background: var(--accent); color: #fff; border: none;
  border-radius: var(--radius, 8px); padding: .5rem .9rem;
  font-size: .85rem; font-weight: 600; cursor: pointer;
  transition: background .15s, opacity .15s;
}
.ev-rsvp-btn:hover { background: var(--accent-lt, var(--accent)); }
.ev-rsvp-btn.ev-rsvp-answered { background: var(--surface); color: var(--text); border: 1.5px solid var(--border); }
.ev-rsvp-btn.ev-rsvp-answered.ev-rsvp-yes { border-color: var(--accent); color: var(--accent); }
.ev-rsvp-btn.ev-rsvp-answered.ev-rsvp-no { border-color: var(--danger); color: var(--danger); }
/* .ev-day-actions' icon-only variant (prof-edit-btn base already sizes/rounds it) */
.ev-day-actions .ev-rsvp-btn { padding: 0; width: 32px; height: 32px; justify-content: center; }
.ev-day-actions .ev-rsvp-btn span { display: none; }

.rsvp-already-badge {
  display: inline-flex; align-items: center; gap: .4rem;
  background: rgba(var(--accent-rgb), .12); color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), .3); border-radius: 20px;
  padding: .3rem .8rem; font-size: .82rem; font-weight: 600; margin-bottom: .8rem;
}
.rsvp-choices { display: flex; gap: .75rem; margin-bottom: 1rem; }
.rsvp-choice-btn {
  flex: 1; padding: .85rem; border-radius: var(--radius, 8px); font-size: .95rem;
  font-weight: 700; cursor: pointer; border: 2px solid var(--border);
  background: var(--surface); color: var(--text);
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  transition: border-color .15s, background .15s, color .15s;
}
.rsvp-choice-btn:hover { border-color: var(--accent); }
.rsvp-choice-btn.selected-yes { border-color: var(--accent); background: rgba(var(--accent-rgb), .1); color: var(--accent); }
.rsvp-choice-btn.selected-no { border-color: var(--danger); background: rgba(255,91,82,.08); color: var(--danger); }
.rsvp-attendees-wrap { margin-bottom: 1rem; }
.rsvp-attendees-row { display: flex; gap: 1.2rem; flex-wrap: wrap; margin-bottom: .4rem; }
.rsvp-attendees-group { flex: 1; min-width: 120px; }
.rsvp-attendees-group label { font-size: .8rem; color: var(--muted); margin-bottom: .3rem; display: block; }
.rsvp-attendees-input { display: flex; align-items: center; gap: .6rem; }
.rsvp-attendees-input button {
  width: 30px; height: 30px; border-radius: 50%; border: 1px solid var(--border);
  background: var(--bg); font-size: 1rem; cursor: pointer; color: var(--text);
}
.rsvp-attendees-input button:hover { background: var(--border); }
.rsvp-attendees-input span { font-size: 1rem; font-weight: 700; min-width: 24px; text-align: center; }

/* Calendar */
/* Split layout: calendar + detail side by side */
.ev-cal-split { display: flex; gap: 1.5rem; max-width: 1100px; margin: 1rem auto; }
[dir="rtl"] .ev-cal-split { flex-direction: row; }
[dir="ltr"] .ev-cal-split { flex-direction: row-reverse; }
.ev-cal-side { flex: 0 0 auto; width: 340px; }
.ev-cal-detail-side { flex: 1; min-width: 0; min-height: 300px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 1rem; overflow-y: auto; max-height: 500px; }
.ev-day-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; gap: .6rem; color: var(--muted); font-size: .95rem; }
.ev-day-placeholder i { font-size: 2.5rem; opacity: .4; }

.ev-cal-wrap { margin: 0; }
.ev-cal-header { display: flex; align-items: center; justify-content: center; gap: 1rem; margin-bottom: .8rem; }
.ev-cal-month { font-size: 1.1rem; font-weight: 600; color: var(--text); min-width: 140px; text-align: center; }
.ev-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.ev-cal-day-name { text-align: center; font-weight: 600; font-size: .75rem; color: var(--muted); padding: .3rem 0; }
.ev-cal-cell { position: relative; min-height: 44px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: .2rem; cursor: pointer; transition: background .15s, box-shadow .15s; display: flex; flex-direction: column; align-items: center; }
.ev-cal-cell:hover { background: rgba(var(--accent-rgb),.06); box-shadow: 0 1px 4px rgba(0,0,0,.1); }
.ev-cal-empty { background: transparent; border-color: transparent; cursor: default; }
.ev-cal-empty:hover { background: transparent; box-shadow: none; }
.ev-cal-num { font-size: .85rem; font-weight: 500; color: var(--text); }
.ev-cal-today { background: rgba(var(--accent-rgb),.15); border-color: var(--accent); }
.ev-cal-today .ev-cal-num { color: var(--accent); font-weight: 700; }
.ev-cal-has-event { border-color: var(--accent); }
.ev-cal-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); margin-top: 2px; }
.ev-cal-badge { background: var(--accent); color: var(--accent-text); font-size: .6rem; font-weight: 700; border-radius: 8px; padding: 0 4px; margin-top: 2px; min-width: 14px; text-align: center; }
.ev-cal-cell.ev-cal-selected { background: var(--accent); border-color: var(--accent); }
.ev-cal-cell.ev-cal-selected .ev-cal-num { color: var(--accent-text); font-weight: 700; }
.ev-cal-cell.ev-cal-selected .ev-cal-dot { background: #fff; }
.ev-cal-cell.ev-cal-selected .ev-cal-badge { background: #fff; color: var(--accent); }

/* Day Detail */
.ev-day-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: .8rem; padding-bottom: .5rem; border-bottom: 1px solid var(--border); }
.ev-day-header h4 { margin: 0; font-size: 1rem; font-weight: 600; color: var(--text); }
.ev-day-count { background: var(--accent); color: var(--accent-text); font-size: .75rem; font-weight: 700; border-radius: 10px; padding: .1rem .5rem; min-width: 20px; text-align: center; }
.ev-day-card { display: flex; gap: 1rem; align-items: flex-start; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 1rem; margin-bottom: .6rem; }
.ev-day-img { width: 90px; height: 65px; object-fit: cover; border-radius: 8px; flex-shrink: 0; }
.ev-day-info { flex: 1; min-width: 0; }
.ev-day-title { font-weight: 800; font-size: 1.15rem; color: var(--text); margin-bottom: .3rem; }
.ev-day-meta { display: flex; flex-wrap: wrap; gap: .8rem; font-size: .85rem; color: var(--muted); margin-bottom: .3rem; }
.ev-day-meta i { color: var(--accent); margin-inline-end: .2rem; }
.ev-day-desc { font-size: .88rem; color: var(--text); line-height: 1.5; white-space: pre-wrap; }
.ev-day-actions { display: flex; gap: .3rem; flex-shrink: 0; }

/* Form */
.ev-form-wrap { max-width: 650px; margin: 1rem auto; }
.ev-form-title { font-size: 1.2rem; font-weight: 600; color: var(--text); margin-bottom: 1rem; }
.ev-form-title i { color: var(--accent); margin-inline-end: .4rem; }
.ev-form { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 1.5rem; }
.ev-form-row { margin-bottom: 1rem; }
.ev-form-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.ev-form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }
.ev-form-field label { display: block; font-weight: 500; font-size: .88rem; color: var(--text); margin-bottom: .3rem; }
.ev-form-field input[type="text"],
.ev-form-field input[type="date"],
.ev-form-field input[type="time"],
.ev-form-field textarea { width: 100%; padding: .5rem .7rem; border: 1px solid var(--border); border-radius: 6px; font-size: .95rem; background: var(--bg); color: var(--text); }
.ev-form-field textarea { resize: vertical; }
.ev-form-img-preview { margin-top: .5rem; display: flex; align-items: center; gap: .8rem; }
.ev-form-img-preview img { width: 80px; height: 60px; object-fit: cover; border-radius: 6px; }
.ev-form-img-preview label { font-size: .85rem; color: var(--muted); cursor: pointer; }
.ev-form-actions { display: flex; gap: .6rem; margin-top: .5rem; }

@media (max-width: 767.98px) {
  .ev-cal-split { flex-direction: column !important; }
  .ev-cal-side { width: 100%; }
  .ev-cal-detail-side { max-height: none; }
  .ev-day-actions { display: none !important; }
  /* tables: cancel fixed layout so columns auto-size and the wrapper scrolls */
  .um-table-wrap { -webkit-overflow-scrolling: touch; }
  .um-table { table-layout: auto !important; min-width: 480px; }
}
@media (max-width: 600px) {
  .ev-form-row-2 { grid-template-columns: 1fr; }
  .ev-form-row-3 { grid-template-columns: 1fr; }
  .ev-cal-cell { min-height: 38px; }
  .ev-day-card { flex-direction: column; }
  .ev-day-img { width: 100%; height: 140px; }
  .ev-upcoming-row { flex-direction: column; align-items: center; }
  .ev-upcoming-card { max-width: 100%; }
  .ev-upcoming-meta { flex-direction: column; gap: .4rem; }
  .ev-sub-url-row { flex-direction: column; }
}

/* Export panel */
.ev-export-panel { max-width: 700px; margin: 1.5rem auto; padding: 0 1rem; display: flex; flex-direction: column; gap: 1.2rem; }
.ev-export-title { font-size: 1.2rem; font-weight: 700; color: var(--accent-h); margin-bottom: .2rem; }
.ev-export-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 1.2rem 1.4rem; display: flex; flex-direction: column; gap: .7rem; }
.ev-export-card h3 { font-size: 1rem; font-weight: 700; color: var(--text); margin: 0; }
.ev-export-card p { color: var(--muted); font-size: .9rem; margin: 0; }
.ev-export-btn { display: inline-flex; align-items: center; gap: .4rem; background: var(--accent); color: var(--accent-text); border: none; border-radius: 6px; padding: .45rem .9rem; font-size: .88rem; font-weight: 600; cursor: pointer; text-decoration: none; transition: opacity .15s; align-self: flex-start; }
.ev-export-btn:hover { opacity: .85; }
.ev-sub-url-row { display: flex; gap: .5rem; align-items: center; margin-top: .3rem; }
.ev-sub-url-input { flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: .4rem .6rem; font-size: .82rem; color: var(--text); direction: ltr; min-width: 0; }
.ev-sub-copy-btn { flex-shrink: 0; }
.ev-sub-hint { font-size: .8rem; color: var(--muted); margin: 0; }
.ev-action-status { min-height: 1.4rem; font-size: .85rem; color: var(--muted); display: flex; align-items: center; gap: .4rem; margin-top: .3rem; }

/* ── Mobile nav-back FAB ── */
.mob-nav-back-fab {
  display: none;
}
body.is-mobile .mob-nav-back-fab {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  bottom: 130px;
  inset-inline-start: 16px;
  z-index: 9998;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent, #2563eb);
  color: #fff;
  border: none;
  cursor: pointer;
  font-size: 1.1rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
  transition: transform .2s, box-shadow .2s, background .15s;
}
body.is-mobile .mob-nav-back-fab:hover { transform: scale(1.1); }
body.is-mobile .mob-nav-back-fab.no-history { display: none; }
[dir="rtl"] .mob-nav-back-fab .app-icon { transform: scaleX(-1); }
/* #ribbon now opens on the same inline-start edge this FAB is pinned to (16px in,
   z-index 9998 -- above the drawer's 999), so an open drawer would otherwise sit
   the back button on top of whatever nav item is underneath it. :has() is already
   load-bearing elsewhere in this file (see .status-bar-item:has(...) above). */
body.is-mobile:has(#ribbon.mob-open) .mob-nav-back-fab { display: none; }

/* ── Mobile: full-width layout ── */
body.is-mobile .app-main { padding: 0 !important; }
/* Two rules for .proc-sidebar and .proc-wrap used to sit here. Every declaration in
   them was overridden by the block further down the file -- border-radius and the
   border shorthand on the sidebar, and gap/height/overflow on the wrap -- so they
   contributed nothing. Verified by deleting them live in the browser and diffing the
   computed styles: identical. The surviving definitions are the ones below. */
body.is-mobile .fac-cal-grid { grid-template-columns: 1fr !important; }

/* ── Mobile: directory tables ── */
body.is-mobile .win-controls { display: none !important; }
body.is-mobile #content-directory .um-btn-export,
body.is-mobile #content-directory .um-btn-add,
body.is-mobile #content-directory .dir-edit-btn { display: none !important; }
/* population: hide # (col 2), סטטוס (col 5), מייל (col 7) */
body.is-mobile #content-directory .um-table:has(#popTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#popTbody) thead tr th:nth-child(2),
body.is-mobile #content-directory .um-table:has(#popTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#popTbody) thead tr th:nth-child(7),
body.is-mobile #content-directory .um-table:has(#popTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#popTbody) tbody tr td:nth-child(2),
body.is-mobile #content-directory .um-table:has(#popTbody) tbody tr td:nth-child(5),
body.is-mobile #content-directory .um-table:has(#popTbody) tbody tr td:nth-child(7) { display: none; }
/* give phone column fixed width so it doesn't get squeezed */
body.is-mobile #content-directory .um-table:has(#popTbody) thead tr th:nth-child(6),
body.is-mobile #content-directory .um-table:has(#popTbody) tbody tr td:nth-child(6) { width: 110px; min-width: 110px; }
/* roles: hide # (col 1) and מייל (col 5) */
body.is-mobile #content-directory .um-table:has(#rolesTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#rolesTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#rolesTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#rolesTbody) tbody tr td:nth-child(5) { display: none; }
/* branches: hide # (col 1) and מייל (col 5) */
body.is-mobile #content-directory .um-table:has(#brTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#brTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#brTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#brTbody) tbody tr td:nth-child(5) { display: none; }
/* services/education/emergency: hide # (col 1) and מייל (col 5) */
body.is-mobile #content-directory .um-table:has(#svcTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#svcTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#svcTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#svcTbody) tbody tr td:nth-child(5),
body.is-mobile #content-directory .um-table:has(#eduTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#eduTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#eduTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#eduTbody) tbody tr td:nth-child(5),
body.is-mobile #content-directory .um-table:has(#emgTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#emgTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#emgTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#emgTbody) tbody tr td:nth-child(5) { display: none; }
/* council: hide # (col 1) and מייל (col 5) */
body.is-mobile #content-directory .um-table:has(#councilTbody) thead tr th:nth-child(1),
body.is-mobile #content-directory .um-table:has(#councilTbody) thead tr th:nth-child(5),
body.is-mobile #content-directory .um-table:has(#councilTbody) tbody tr td:nth-child(1),
body.is-mobile #content-directory .um-table:has(#councilTbody) tbody tr td:nth-child(5) { display: none; }
/* mobile: directory — switch to auto layout so the table can scroll horizontally */
body.is-mobile #content-directory .um-table { table-layout: auto !important; }
/* mobile: population — read-only (no add / edit / delete / export) */
body.is-mobile #content-population .um-btn-add,
body.is-mobile #content-population .um-btn-export,
body.is-mobile #content-population .dir-edit-btn,
body.is-mobile #content-population .hh-action-btn,
body.is-mobile #content-population .um-actions { display: none !important; }
/* mobile: settings module — not accessible on mobile */
body.is-mobile .ribbon-item[data-panel="settings"] { display: none !important; }
/* mobile: committees — hide create/edit/delete (read-only on mobile) */
body.is-mobile #content-committees .prof-edit-btn,
body.is-mobile #content-committees .proc-item-del { display: none !important; }
/* mobile: PDF iframes don't render — hide viewer area entirely */
body.is-mobile .reg-viewer { display: none !important; }
/* mobile: hide "select document" empty-state hint */
body.is-mobile .proc-viewer-empty { display: none !important; }
/* mobile: hide download buttons (keep open-in-window) */
body.is-mobile a.reg-btn-download[href*="/download"] { display: none !important; }
/* info pages sidebar toggle — desktop only hides it */
.ip-mobile-list-toggle { display: none; }
body.is-mobile .ip-mobile-list-toggle { display: inline-flex !important; }
/* mobile: hide all edit/delete/add/replace actions in regulations and info panels */
body.is-mobile .reg-btn-upload { display: none !important; }
body.is-mobile .sub-item[data-sub-key="sub.info.new_page"],
body.is-mobile .sub-item[data-i18n="sub.info.new_page"] { display: none !important; }
body.is-mobile .sub-item[data-sub-key="sub.protocols.new"],
body.is-mobile .sub-item[data-i18n="sub.protocols.new"] { display: none !important; }
body.is-mobile .sub-item[data-sub-key="sub.audit.new"],
body.is-mobile .sub-item[data-i18n="sub.audit.new"] { display: none !important; }
body.is-mobile #content-audit .proc-item-del,
body.is-mobile #content-audit .um-btn-edit,
body.is-mobile #content-audit .reg-btn-upload,
body.is-mobile #content-audit .ip-topics-refresh,
body.is-mobile #content-audit .ip-topic-remove { display: none !important; }
body.is-mobile #content-protocols .proc-item-del,
body.is-mobile #content-protocols .um-btn-edit,
body.is-mobile #content-protocols .reg-btn-upload,
body.is-mobile #content-protocols .ip-topics-refresh,
body.is-mobile #content-protocols .ip-topic-remove { display: none !important; }
body.is-mobile #content-regulations .regs-tree-add,
body.is-mobile #content-regulations .proc-item-del,
body.is-mobile #content-regulations .reg-toolbar .um-btn-icon,
body.is-mobile #content-regulations .reg-toolbar .um-btn-del,
body.is-mobile #content-regulations .proc-sidebar-header .prof-edit-btn { display: none !important; }
body.is-mobile #content-info .um-btn-edit,
body.is-mobile #content-info .proc-item-del,
body.is-mobile #content-info .ip-topics-refresh,
body.is-mobile #content-info .ip-topic-remove { display: none !important; }



/* ═══════════════════════════════════════════════════════════
   DAP — Digital Adoption Platform (Phase 0)
   ═══════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════
   Emoji Picker — shared singleton panel (#emoji-picker)
   ═══════════════════════════════════════════════════════════ */

#emoji-picker {
  position: fixed;
  z-index: 9000;
  width: 400px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0,0,0,.25);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#emoji-picker[hidden] { display: none !important; }

.ep-search-row {
  padding: 8px;
  border-bottom: 1px solid var(--border);
}
.ep-search-row input {
  width: 100%;
  box-sizing: border-box;
}

.ep-cats {
  display: flex;
  gap: 2px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;  /* hide thin scrollbar on category row */
}
.ep-cats::-webkit-scrollbar { display: none; }

.ep-cat {
  background: none;
  border: none;
  font-size: 18px;
  padding: 4px 6px;
  border-radius: 6px;
  cursor: pointer;
  opacity: .55;
  transition: opacity .15s, background .15s;
  flex-shrink: 0;
}
.ep-cat:hover { opacity: .85; background: var(--hover); }
.ep-cat.active { opacity: 1; background: var(--hover); }

.ep-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 8px;
  max-height: 260px;
  overflow-y: auto;
}

.ep-btn {
  font-size: 22px;
  width: 38px;
  height: 38px;
  border: none;
  background: none;
  border-radius: 6px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .1s;
  line-height: 1;
}
.ep-btn:hover { background: var(--hover); }

.ep-empty {
  width: 100%;
  text-align: center;
  color: var(--muted);
  padding: 24px 0;
  font-size: .9rem;
}

/* ── Emoji trigger button (inside composers) ────────────────── */
/* ep-host: wrapper gets position:relative when the parent was static */
.ep-host { position: relative; }

.emoji-trigger {
  position: absolute;
  inset-inline-end: 8px;
  bottom: 8px;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  transition: color .15s, background .15s;
  z-index: 1;
}
.emoji-trigger:hover { color: var(--primary); background: var(--hover); }

/* ── Mobile: full-width bottom sheet ───────────────────────── */
@media (max-width: 480px) {
  #emoji-picker {
    position: fixed !important;
    top: auto !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: 100% !important;
    border-radius: 16px 16px 0 0;
    max-height: 60vh;
  }
  .ep-grid { max-height: calc(60vh - 110px); }
}

/* ── Help FAB ─────────────────────────────────────────────── */
.dap-fab {
  position: fixed;
  bottom: var(--fab-slot-1);   /* rail slot 1 (bottom-most) */
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px));
  z-index: 9990;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-text, #fff);
  border: none;
  cursor: pointer;
  font-size: 1.2rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .2s, box-shadow .2s, background .15s;
}
.dap-fab:hover {
  transform: scale(1.1);
  box-shadow: 0 6px 22px rgba(0,0,0,.5);
  background: var(--accent-h, var(--accent));
}
.dap-fab:focus-visible {
  outline: 2px solid var(--accent-h, var(--accent));
  outline-offset: 3px;
}

/* ═══════════════════════════════════════════════════════════════
   Floating accessibility button + quick panel.
   The FAB is a sibling of .dap-fab (same navy dome / gold rim / gloss),
   pinned mid-edge (inline-end → left in Hebrew, right in LTR).
   ═══════════════════════════════════════════════════════════════ */
/* Pilot-feedback FAB — sits above the help "?" FAB (bottom-corner), sibling of
   the .dap-fab / .a11y-fab family. */
.feedback-fab {
  position: fixed;
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px));
  bottom: var(--fab-slot-2);   /* rail slot 2 — same 100px it already resolved to */
  z-index: 9990;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-text, #fff);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.35rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
  transition: transform .2s, box-shadow .2s, background .15s;
}
.feedback-fab .app-icon { filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.feedback-fab:hover { transform: scale(1.1); box-shadow: 0 6px 22px rgba(0,0,0,.5); }
.feedback-fab:focus-visible { outline: 2px solid var(--accent-h, var(--accent)); outline-offset: 3px; }
:root:not([data-theme]) .feedback-fab {
  background: radial-gradient(circle at 38% 30%, #3f6fa6, #1c3a63 52%, #0b1d38);
  /* was var(--accent-lt) (#A9CCFF) -- against this gradient's lightest patch
     (#3f6fa6, right where the icon sits) that only computed to ~3.2:1 contrast,
     reading as a dim/washed-out glyph. Plain white clears ~6:1 there. */
  color: #fff;
  border: 1.5px solid rgba(var(--accent-h-rgb),.7);
  box-shadow: inset 0 2px 3px rgba(150,190,240,.45), inset 0 -4px 7px rgba(0,10,30,.5),
              0 6px 16px rgba(0,0,0,.5);
}
.feedback-shots { display: flex; gap: .5rem; flex-wrap: wrap; margin: .3rem 0 .6rem; }
.feedback-tech { margin: .5rem 0; font-size: .82rem; }
.feedback-tech summary { cursor: pointer; color: var(--text); }   /* was var(--muted) -- match .um-label's fix */
.feedback-tech pre { max-height: 160px; overflow: auto; background: var(--bg-soft, #f5f3ee);
  border: 1px solid var(--line, #e2ddd2); border-radius: 6px; padding: .5rem;
  font-size: 11px; white-space: pre-wrap; }
.feedback-tech-summary { background: var(--bg-soft, #f5f3ee); border: 1px solid var(--line, #e2ddd2);
  border-radius: 6px; padding: .4rem .6rem; margin-top: .35rem; }
.feedback-tech-summary .fb-tech-row { display: flex; justify-content: space-between; gap: 1rem;
  padding: .15rem 0; }
.feedback-tech-summary .fb-tech-row + .fb-tech-row { border-top: 1px solid var(--line, #e2ddd2); }
.feedback-tech-summary .fb-tech-k { color: var(--muted); }
.feedback-tech-summary .fb-tech-v { text-align: end; word-break: break-word; }

.a11y-fab {
  position: fixed;
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px));
  bottom: var(--fab-slot-3);   /* rail slot 3 — was 100px, colliding with .feedback-fab */
  z-index: 9990;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-text, #fff);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  box-shadow: 0 4px 16px rgba(0,0,0,.4);
  transition: transform .2s, box-shadow .2s, background .15s;
}
.a11y-fab .app-icon { position: relative; z-index: 1; filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
.a11y-fab:hover {
  transform: scale(1.1);
  box-shadow: 0 6px 22px rgba(0,0,0,.5);
}
.a11y-fab:focus-visible {
  outline: 2px solid var(--accent-h, var(--accent));
  outline-offset: 3px;
}
/* default-theme glossy navy dome + gold ring (mirrors .dap-fab) */
:root:not([data-theme]) .a11y-fab {
  background: radial-gradient(circle at 38% 30%, #3f6fa6, #1c3a63 52%, #0b1d38);
  /* was var(--accent-lt) -- see .feedback-fab's identical fix above for why. */
  color: #fff;
  border: 1.5px solid rgba(var(--accent-h-rgb),.7);
  box-shadow: inset 0 2px 3px rgba(150,190,240,.45), inset 0 -4px 7px rgba(0,10,30,.5),
              0 0 0 1px rgba(var(--accent-h-rgb),.18), 0 6px 16px rgba(0,0,0,.5), 0 0 14px rgba(var(--accent-h-rgb),.14);
}
:root:not([data-theme]) .a11y-fab::after {
  content: ""; position: absolute; top: 6px; left: 11px; right: 13px; height: 10px;
  border-radius: 50%; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,.45), transparent);
}
:root:not([data-theme]) .a11y-fab:hover {
  background: radial-gradient(circle at 38% 30%, #4778b0, #22406e 52%, #0e2444);
  box-shadow: inset 0 2px 3px rgba(150,190,240,.5), inset 0 -4px 7px rgba(0,10,30,.5),
              0 0 0 1px rgba(var(--accent-h-rgb),.22), 0 8px 22px rgba(0,0,0,.55), 0 0 18px rgba(var(--accent-h-rgb),.2);
}

/* ── backdrop + panel drawer ── */
.a11y-backdrop {
  position: fixed; inset: 0; z-index: 9991;
  background: rgba(0,0,0,.42); backdrop-filter: blur(2px);
}
.a11y-panel {
  position: fixed; inset-inline-end: 78px; top: 50%; transform: translateY(-50%);
  z-index: 9992; width: 300px; max-width: calc(100vw - 100px);
  max-height: calc(100vh - 32px); overflow-y: auto;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 16px; padding: 16px;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
  animation: a11yPanelIn .18s cubic-bezier(.4,0,.2,1);
}
@keyframes a11yPanelIn {
  from { opacity: 0; transform: translateY(-50%) scale(.97); }
  to   { opacity: 1; transform: translateY(-50%) scale(1); }
}
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) .a11y-panel { animation: none; } }
.a11y-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.a11y-head .app-icon { color: var(--accent-lt, var(--accent)); font-size: 1.3rem; }
.a11y-title { margin: 0; font-size: 1.1rem; font-weight: 700; color: var(--text); }
.a11y-x {
  margin-inline-start: auto; background: none; border: none; color: var(--muted);
  cursor: pointer; font-size: 1.2rem; line-height: 1; padding: 4px 6px; border-radius: 8px;
}
.a11y-x:hover { background: var(--border); color: var(--text); }
.a11y-block { padding: 10px 2px; border-top: 1px solid var(--border); }
.a11y-block:first-of-type { border-top: none; }
.a11y-lab { display: block; font-size: .82rem; color: var(--muted); margin-bottom: 8px; }
.a11y-seg { display: flex; gap: 6px; }
.a11y-sbtn {
  flex: 1; min-height: 42px; min-width: 42px; padding: 0 6px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  border-radius: 10px; cursor: pointer; font: inherit; font-weight: 600; transition: .13s;
}
.a11y-sbtn:hover { background: var(--surface); border-color: var(--accent); }
.a11y-sbtn:focus-visible { outline: 2px solid var(--accent-h, var(--accent)); outline-offset: 2px; }
.a11y-sbtn.on { background: var(--accent); border-color: transparent; color: var(--accent-text, #fff); }
.a11y-fs { font-size: .82rem; } .a11y-fm { font-size: 1rem; } .a11y-fl { font-size: 1.28rem; }
.a11y-tgl-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.a11y-tgl-row .a11y-lab { margin: 0; }
.a11y-switch {
  width: 50px; height: 28px; border-radius: 99px; padding: 0; flex: none; cursor: pointer;
  background: var(--bg); border: 1px solid var(--border); position: relative; transition: .15s;
}
.a11y-switch::after {
  content: ""; position: absolute; top: 2px; inset-inline-start: 2px; width: 22px; height: 22px;
  border-radius: 50%; background: var(--muted); transition: .18s;
}
.a11y-switch[aria-checked="true"] { background: var(--accent); border-color: transparent; }
.a11y-switch[aria-checked="true"]::after { inset-inline-start: 24px; background: #fff; }
.a11y-switch:focus-visible { outline: 2px solid var(--accent-h, var(--accent)); outline-offset: 2px; }
.a11y-foot { margin-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.a11y-more {
  background: none; border: 1px solid var(--border); color: var(--text);
  padding: 11px; border-radius: 10px; cursor: pointer; font: inherit;
}
.a11y-more:hover { background: var(--bg); border-color: var(--accent); }
.a11y-hide {
  background: none; border: none; color: var(--danger, #f87171); cursor: pointer;
  font: inherit; font-size: .85rem; padding: 6px; border-radius: 8px;
}
.a11y-hide:hover { text-decoration: underline; }

/* ── Backdrop ─────────────────────────────────────────────── */
.dap-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.42);
  z-index: 9991;
  backdrop-filter: blur(2px);
}

/* ── Panel Drawer ─────────────────────────────────────────── */
/* L10N-0014 (quality-audit): this used to anchor with a physical right:0
   while its own separator (border-inline-start) and trigger (.dap-fab, which
   uses inset-inline-end) were logical -- in RTL the panel stayed pinned to
   the physical right while its trigger moved to the left, so the drawer
   opened on the opposite side of the screen from the button that opened it,
   with the border landing on the wrong edge too. Mirrors #ribbon's
   logical-inset + inset-transition TECHNIQUE instead of transform, since
   translateX doesn't flip with direction the way inset-inline-end does --
   #ribbon itself was later flipped from -end to -start (see its own rule)
   once its SIDE, not just its technique, turned out to be the wrong one. */
.dap-panel {
  position: fixed;
  top: 0;
  bottom: 0;
  inset-inline-end: -410px;   /* width 380px + 30px margin, same convention as #ribbon */
  width: 380px;
  max-width: 100vw;
  background: var(--surface);
  border-inline-start: 1px solid var(--border);
  z-index: 9992;
  display: flex;
  flex-direction: column;
  transition: inset-inline-end .28s cubic-bezier(.4,0,.2,1);
  box-shadow: -6px 0 40px rgba(0,0,0,.35);
}
.dap-panel.dap-panel-open {
  inset-inline-end: 0;
}

/* ── Header ───────────────────────────────────────────────── */
.dap-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .9rem 1.1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex-shrink: 0;
}
.dap-header-icon {
  color: var(--accent);
  font-size: 1.15rem;
}
.dap-header-title {
  flex: 1;
  font-size: .95rem;
  font-weight: 700;
  color: var(--text);
  margin: 0;
}
.dap-home-btn {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: .3rem .4rem;
  border-radius: 6px;
  font-size: .95rem;
  line-height: 1;
  transition: color .15s, background .15s;
  flex-shrink: 0;
}
.dap-home-btn:hover {
  color: var(--accent);
  background: rgba(255,255,255,.07);
}
.dap-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: .3rem .4rem;
  border-radius: 6px;
  font-size: .95rem;
  line-height: 1;
  transition: color .15s, background .15s;
}
.dap-close:hover {
  color: var(--text);
  background: rgba(255,255,255,.07);
}

/* ── Tabs ─────────────────────────────────────────────────── */
.dap-tabs {
  display: flex;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg);
}
.dap-tab {
  flex: 1;
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: .55rem .3rem;
  font-size: .75rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .18rem;
  border-bottom: 2px solid transparent;
  transition: color .15s, border-color .15s;
  font-family: var(--font);
}
.dap-tab:hover { color: var(--text); }
.dap-tab.dap-tab-active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.dap-tab i { font-size: .88rem; }

/* ── Search bar ───────────────────────────────────────────── */
.dap-search-bar {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .55rem 1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  flex-shrink: 0;
}
/* A11Y-0134 (quality-audit): the input below sets outline:none with no
   replacement -- a keyboard user tabbing into the search field saw no focus
   indicator at all. It has no border of its own; recolor the bar's existing
   border-bottom on :focus-within instead, same technique as
   .dap-chat-input-bar input:focus. */
.dap-search-bar:focus-within { border-bottom-color: var(--accent); }
.dap-search-bar i { color: var(--muted); font-size: .82rem; flex-shrink: 0; }
.dap-search-bar input {
  flex: 1;
  background: none;
  border: none;
  color: var(--text);
  font-size: .88rem;
  outline: none;
  font-family: var(--font);
  min-width: 0;
}
.dap-search-bar input::placeholder { color: var(--muted); }

/* ── Body ─────────────────────────────────────────────────── */
.dap-body {
  flex: 1;
  overflow-y: auto;
  padding: .8rem;
}
.dap-body::-webkit-scrollbar { width: 4px; }
.dap-body::-webkit-scrollbar-track { background: transparent; }
.dap-body::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }

/* ── Empty state ──────────────────────────────────────────── */
.dap-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .75rem;
  padding: 3rem 1.5rem;
  color: var(--muted);
  text-align: center;
}
.dap-empty i { font-size: 2.4rem; opacity: .4; }
.dap-empty p  { font-size: .85rem; line-height: 1.5; }

/* ── Article cards ────────────────────────────────────────── */
.dap-article {
  background: rgba(255,255,255,.04);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .85rem 1rem;
  margin-bottom: .55rem;
  transition: border-color .15s;
  outline: none;
}
.dap-article:hover,
.dap-article:focus-visible { border-color: var(--accent); }
.dap-article-title {
  font-weight: 600;
  font-size: .88rem;
  color: var(--text);
  margin-bottom: .38rem;
}
.dap-article-body {
  font-size: .8rem;
  color: var(--muted);
  line-height: 1.65;
}

/* ── FAQ accordion ────────────────────────────────────────── */
.dap-faq {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: .45rem;
  cursor: pointer;
  overflow: hidden;
  transition: border-color .15s;
  outline: none;
}
.dap-faq:hover,
.dap-faq:focus-visible { border-color: var(--accent); }
.dap-faq-q {
  padding: .7rem 1rem;
  font-size: .86rem;
  color: var(--text);
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: .5rem;
  user-select: none;
}
.dap-faq-chevron {
  color: var(--muted);
  font-size: .68rem;
  margin-inline-start: auto;
  flex-shrink: 0;
  transition: transform .2s;
}
.dap-faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height .28s ease, padding .28s ease;
  font-size: .8rem;
  color: var(--muted);
  line-height: 1.65;
  padding: 0 1rem;
}
.dap-faq.dap-faq-open .dap-faq-a {
  max-height: 600px;
  padding: .4rem 1rem .8rem;
}
.dap-faq.dap-faq-open .dap-faq-chevron {
  transform: rotate(-90deg);
}
[dir="rtl"] .dap-faq.dap-faq-open .dap-faq-chevron {
  transform: rotate(90deg);
}

/* ── Search results ───────────────────────────────────────── */
.dap-search-results { display: flex; flex-direction: column; gap: .45rem; }
.dap-search-result {
  display: flex;
  gap: .65rem;
  padding: .65rem .8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.dap-search-result:hover {
  border-color: var(--accent);
  background: rgba(var(--accent-rgb), .07);
}
.dap-search-result-icon {
  color: var(--accent);
  font-size: .85rem;
  flex-shrink: 0;
  padding-top: .1rem;
}
.dap-search-result-content { flex: 1; min-width: 0; }
.dap-search-result-title {
  font-size: .84rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: .18rem;
}
.dap-search-result-excerpt {
  font-size: .76rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 500px) {
  /* L10N-0014: the closed-state offset above is fixed to the 380px desktop
     width, which doesn't scale with this override -- without a matching
     closed offset here, up to ~90px of the "closed" drawer would poke onto
     screen at this width. */
  .dap-panel { width: 100vw; inset-inline-end: -100vw; }
  .dap-fab   { bottom: var(--fab-slot-1); }
}

/* ── Light-theme adjustments ──────────────────────────────── */
[data-theme="light"]   .dap-article { background: rgba(0,0,0,.03); }

/* ── DAP Phase 1: Article Actions + Feedback ─────────────── */
.dap-article-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border, rgba(255,255,255,.1));
}

.dap-action-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 12px;
  border: 1px solid var(--accent, #0af);
  border-radius: 20px;
  background: transparent;
  color: var(--accent, #0af);
  font-size: .78rem;
  cursor: pointer;
  transition: background .15s, color .15s;
  white-space: nowrap;
}

.dap-action-chip:hover {
  background: var(--accent, #0af);
  color: var(--accent-text);
}

.dap-action-chip i { font-size: .7rem; }

.dap-feedback {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border, rgba(255,255,255,.08));
}

.dap-feedback-label {
  font-size: .75rem;
  color: var(--muted, #999);
  flex: 1;
}

.dap-fb-btn {
  background: none;
  border: 1px solid var(--border, rgba(255,255,255,.15));
  border-radius: 6px;
  padding: 3px 8px;
  color: var(--muted, #999);
  cursor: pointer;
  font-size: .8rem;
  transition: border-color .15s, color .15s, background .15s;
}

.dap-fb-btn:hover {
  border-color: var(--accent, #0af);
  color: var(--accent, #0af);
}

.dap-fb-btn.dap-fb-active {
  background: var(--accent, #0af);
  border-color: var(--accent, #0af);
  color: var(--accent-text);
}

/* Light-theme overrides for action chips + feedback */
[data-theme=light]   .dap-action-chip { color: var(--accent, #005f9e); }

[data-theme=light]   .dap-fb-btn { color: var(--muted, #666); }

[data-theme=light]   .dap-fb-btn.dap-fb-active { color: #fff; }

/* ── DAP Phase 2: Guided Tours ───────────────────────────── */

/* Start-tour button in guides panel */
.dap-start-tour {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%%;
  margin-bottom: 12px;
  padding: 10px 14px;
  border: 1.5px dashed var(--accent, #0af);
  border-radius: 10px;
  background: transparent;
  color: var(--accent, #0af);
  font-size: .85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.dap-start-tour:hover {
  background: var(--accent, #0af);
  color: var(--accent-text);
}
.dap-start-tour i { font-size: .85rem; }

/* Tour overlay — dark backdrop */
#dap-tour-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  pointer-events: none;
}

/* Spotlight — creates the "hole" via box-shadow */
#dap-tour-spotlight {
  position: fixed;
  display: none;
  border-radius: 8px;
  box-shadow: 0 0 0 9999px rgba(0,0,0,.68);
  z-index: 10001;
  pointer-events: none;
  transition: top .22s ease, left .22s ease, width .22s ease, height .22s ease;
}

/* Tour tooltip */
#dap-tour-tooltip {
  position: fixed;
  z-index: 10002;
  min-width: 260px;
  max-width: 340px;
  background: var(--surface, #1e2535);
  border: 1px solid var(--border, rgba(255,255,255,.12));
  border-radius: 12px;
  padding: 16px 18px 14px;
  box-shadow: 0 8px 36px rgba(0,0,0,.45);
  display: none;
  animation: dap-tour-in .2s ease;
}
@keyframes dap-tour-in {
  from { opacity: 0; transform: translateY(-6px) scale(.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1);   }
}

.dap-tour-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.dap-tour-counter {
  font-size: .72rem;
  color: var(--muted, #888);
  font-variant-numeric: tabular-nums;
}
.dap-tour-close {
  background: none;
  border: none;
  color: var(--muted, #888);
  cursor: pointer;
  font-size: .85rem;
  padding: 2px 4px;
  border-radius: 4px;
  line-height: 1;
  transition: color .15s;
}
.dap-tour-close:hover { color: var(--text, #fff); }

.dap-tour-title {
  font-weight: 700;
  font-size: .95rem;
  color: var(--text, #fff);
  margin-bottom: 7px;
}
.dap-tour-body {
  font-size: .82rem;
  color: rgba(255,255,255,.82);
  line-height: 1.55;
  margin-bottom: 14px;
}

.dap-tour-nav {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.dap-tour-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 14px;
  border-radius: 8px;
  font-size: .8rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
  border: 1px solid var(--border, rgba(255,255,255,.15));
  background: transparent;
  color: var(--text, #eee);
}
.dap-tour-btn:hover { border-color: var(--accent, #0af); color: var(--accent, #0af); }

.dap-tour-next,
.dap-tour-finish {
  background: var(--accent, #0af);
  border-color: var(--accent, #0af);
  color: var(--accent-text);
}
.dap-tour-next:hover,
.dap-tour-finish:hover {
  filter: brightness(1.15);
  color: var(--accent-text);
}

/* Light-theme overrides */
[data-theme=light] #dap-tour-tooltip {
  background: #fff;
  border-color: rgba(0,0,0,.12);
  box-shadow: 0 8px 36px rgba(0,0,0,.18);
}
[data-theme=light] .dap-tour-title { color: #1a1a2e; }
[data-theme=light] .dap-tour-body { color: #444; }

[data-theme=light] .dap-start-tour { color: var(--accent, #005f9e); border-color: var(--accent, #005f9e); }

/* ── DAP Phase 3: Contextual Tooltip ─────────────────────── */
#dap-ctip {
  position: fixed;
  z-index: 9500;
  max-width: 260px;
  padding: 6px 10px;
  border-radius: 7px;
  background: var(--surface, #1e2535);
  border: 1px solid var(--border, rgba(255,255,255,.13));
  box-shadow: 0 4px 18px rgba(0,0,0,.35);
  font-size: .78rem;
  line-height: 1.45;
  color: var(--text, #e8eaf6);
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  animation: dap-ctip-in .12s ease;
}
@keyframes dap-ctip-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.dap-ctip-text { flex: 1; }

.dap-ctip-more {
  pointer-events: all;
  flex-shrink: 0;
  padding: 2px 7px;
  border: 1px solid var(--accent, #0af);
  border-radius: 5px;
  background: transparent;
  color: var(--accent, #0af);
  font-size: .72rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s;
}
.dap-ctip-more:hover { background: var(--accent, #0af); color: var(--accent-text); }

/* Light-theme overrides */
[data-theme=light]   #dap-ctip {
  background: #fff;
  border-color: rgba(0,0,0,.13);
  color: #1a1a2e;
  box-shadow: 0 4px 14px rgba(0,0,0,.14);
}

/* ── DAP Phase 4 — Chat / AI Copilot ────────────────────────── */

/* Input bar */
.dap-chat-input-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.1));
  background: var(--surface, #1e1e2e);
}
.dap-chat-input-bar input {
  flex: 1;
  background: var(--bg, #12121f);
  color: var(--text, #eee);
  border: 1px solid var(--border, rgba(255,255,255,.15));
  border-radius: 18px;
  padding: 7px 14px;
  font-size: .87rem;
  outline: none;
  direction: inherit;
}
.dap-chat-input-bar input:focus {
  border-color: var(--accent, #0af);
}
.dap-chat-send {
  background: var(--accent, #0af);
  color: var(--accent-text);
  border: none;
  border-radius: 50%;
  width: 34px;
  height: 34px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: .85rem;
  transition: opacity .15s;
}
.dap-chat-send:hover { opacity: .82; }

/* Chat body */
.dap-chat-msgs {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dap-chat-welcome {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 40px 20px;
  color: var(--muted, #888);
  text-align: center;
}
.dap-chat-welcome i {
  font-size: 2.2rem;
  opacity: .45;
}
.dap-chat-welcome p {
  font-size: .88rem;
  max-width: 220px;
  line-height: 1.5;
}

/* Message bubbles */
.dap-chat-msg {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dap-chat-user {
  align-items: flex-end;
}
.dap-chat-user span {
  background: var(--accent, #0af);
  color: #fff;
  border-radius: 16px 16px 4px 16px;
  padding: 8px 13px;
  font-size: .86rem;
  max-width: 82%;
  word-break: break-word;
  line-height: 1.45;
}
/* Quantum: navy+gold user bubble, matching the buttons (was gold fill + white). */
:root:not([data-theme]) .dap-chat-user span {
  background: linear-gradient(180deg,#274a7d,#12294c 55%,#0c1f3c);
  color: var(--accent-h);
}
.dap-chat-bot {
  align-items: flex-start;
}
.dap-chat-bot-text {
  background: var(--surface, #1e1e2e);
  color: var(--text, #eee);
  border: 1px solid var(--border, rgba(255,255,255,.1));
  border-radius: 4px 16px 16px 16px;
  padding: 8px 13px;
  font-size: .86rem;
  max-width: 90%;
  line-height: 1.55;
}
.dap-chat-bot-text p { margin: 0 0 6px; }
.dap-chat-bot-text p:last-child { margin-bottom: 0; }
.dap-chat-bot-text strong { color: var(--accent, #0af); }

/* Source chips under bot messages */
.dap-chat-sources {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  padding-top: 2px;
  max-width: 90%;
}
.dap-chat-chip {
  background: transparent;
  border: 1px solid var(--accent, #0af);
  color: var(--accent, #0af);
  border-radius: 12px;
  padding: 3px 9px;
  font-size: .76rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 4px;
  transition: background .12s, color .12s;
}
.dap-chat-chip:hover { background: var(--accent, #0af); color: var(--accent-text); }

.dap-chat-suggestions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  max-width: 240px;
  margin-top: 4px;
}
.dap-chat-suggestions .dap-chat-chip {
  justify-content: flex-start;
  text-align: start;
  border-radius: 10px;
  padding: 6px 11px;
  font-size: .81rem;
  white-space: normal;
  line-height: 1.35;
  /* override base .dap-chat-chip accent colors — must work on all 22 themes */
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
}
.dap-chat-suggestions .dap-chat-chip:hover,
.dap-chat-suggestions .dap-chat-chip:focus-visible {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
  outline: none;
}

/* Light-theme overrides */
[data-theme=light]   .dap-chat-input-bar {
  background: #f5f5fa;
  border-bottom-color: rgba(0,0,0,.1);
}
[data-theme=light]   .dap-chat-input-bar input {
  background: #fff;
  color: #1a1a2e;
  border-color: rgba(0,0,0,.18);
}
[data-theme=light]   .dap-chat-bot-text {
  background: #fff;
  color: #1a1a2e;
  border-color: rgba(0,0,0,.12);
}

/* ── DAP Phase 5 — Onboarding wizard ────────────────────────── */

#dap-onboard-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .72);
  z-index: 10200;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: dap-fade-in .22s ease;
}
#dap-onboard-overlay.dap-ob-out {
  animation: dap-fade-in .28s ease reverse forwards;
}
#dap-onboard-card {
  background: var(--surface, #1e1e2e);
  color: var(--text, #eee);
  border: 1px solid var(--border, rgba(255,255,255,.12));
  border-radius: 20px;
  padding: 40px 32px 30px;
  max-width: 360px;
  width: 88%;
  text-align: center;
  box-shadow: 0 24px 64px rgba(0, 0, 0, .55);
  animation: dap-slide-up .3s ease;
}
.dap-onboard-icon {
  font-size: 2.6rem;
  color: var(--accent, #7c6af7);
  margin-bottom: 18px;
}
.dap-onboard-title {
  font-size: 1.15rem;
  font-weight: 700;
  margin: 0 0 12px;
  color: var(--text, #eee);
}
.dap-onboard-body {
  font-size: .88rem;
  line-height: 1.65;
  color: var(--muted, #aaa);
  margin: 0 0 24px;
}
.dap-onboard-dots {
  display: flex;
  justify-content: center;
  gap: 7px;
  margin-bottom: 26px;
}
.dap-ob-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border, rgba(255,255,255,.2));
  transition: background .2s, transform .2s;
}
.dap-ob-dot-on {
  background: var(--accent, #7c6af7);
  transform: scale(1.35);
}
.dap-onboard-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.dap-onboard-skip {
  background: none;
  border: none;
  color: var(--muted, #888);
  font-size: .84rem;
  cursor: pointer;
  padding: 6px 4px;
  transition: color .15s;
}
.dap-onboard-skip:hover { color: var(--text, #eee); }
.dap-onboard-next {
  background: var(--accent, #7c6af7);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 10px 28px;
  font-size: .9rem;
  font-weight: 600;
  cursor: pointer;
  flex: 1;
  transition: opacity .15s;
}
.dap-onboard-next:hover { opacity: .85; }

/* Light-theme overrides */
[data-theme=light]      #dap-onboard-card {
  background: #fff;
  color: #1a1a2e;
  border-color: rgba(0,0,0,.1);
  box-shadow: 0 24px 64px rgba(0,0,0,.18);
}
[data-theme=light]      .dap-onboard-title { color: #1a1a2e; }
[data-theme=light]      .dap-onboard-body { color: #555; }

/* ── DAP Phase 6 — Analytics card ───────────────────────────── */

.dap-analytics-card {
  margin-top: 18px;
  border: 1px solid var(--border, rgba(255,255,255,.1));
  border-radius: 10px;
  overflow: hidden;
  font-size: .83rem;
}
.dap-analytics-card summary {
  padding: 9px 13px;
  cursor: pointer;
  user-select: none;
  color: var(--muted, #888);
  display: flex;
  align-items: center;
  gap: 7px;
  list-style: none;
  transition: color .15s;
}
.dap-analytics-card summary::-webkit-details-marker { display: none; }
.dap-analytics-card[open] summary { color: var(--accent, #7c6af7); }
.dap-analytics-card summary:hover { color: var(--text, #eee); }
.dap-an-total { opacity: .6; font-size: .78rem; margin-inline-start: auto; }
.dap-an-body {
  padding: 4px 13px 12px;
  border-top: 1px solid var(--border, rgba(255,255,255,.08));
}
.dap-an-head {
  margin: 10px 0 4px;
  font-size: .78rem;
  color: var(--muted, #888);
  display: flex;
  align-items: center;
  gap: 5px;
}
.dap-an-body ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.dap-an-body ul li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.05));
  color: var(--text, #eee);
}
.dap-an-body ul li:last-child { border-bottom: none; }
.dap-an-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dap-an-count {
  background: var(--accent, #7c6af7);
  color: #fff;
  border-radius: 10px;
  padding: 1px 7px;
  font-size: .75rem;
  font-weight: 600;
  flex-shrink: 0;
}
.dap-an-rating { color: var(--text, #eee); margin: 4px 0 8px; }
.dap-an-clear {
  background: none;
  border: 1px solid var(--border, rgba(255,255,255,.15));
  color: var(--muted, #888);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: .78rem;
  cursor: pointer;
  margin-top: 8px;
  transition: border-color .15s, color .15s;
}
.dap-an-clear:hover { border-color: var(--danger, #e55); color: var(--danger, #e55); }

/* Light-theme overrides */
[data-theme=light]   .dap-analytics-card {
  border-color: rgba(0,0,0,.12);
}
[data-theme=light]   .dap-an-body ul li { color: #1a1a2e; }

/* ── DAP Phase 7 — CMS edit mode ────────────────────────────── */

/* Edit toggle button in header */
.dap-edit-toggle {
  background: none;
  border: 1px solid var(--accent, #7c6af7);
  color: var(--accent, #7c6af7);
  border-radius: 7px;
  width: 30px;
  height: 30px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .85rem;
  transition: color .15s, border-color .15s, background .15s;
  margin-inline-end: 4px;
  opacity: .75;
}
.dap-edit-toggle:hover { opacity: 1; }
.dap-edit-toggle.dap-edit-active {
  color: #fff;
  background: var(--accent, #7c6af7);
  border-color: var(--accent, #7c6af7);
}

/* Article header row (title + CMS controls) */
.dap-article-header {
  display: flex;
  align-items: center;
  gap: 6px;
}
.dap-article-header .dap-article-title { flex: 1; }

/* CMS controls (edit + delete icons on each item) */
.dap-cms-controls {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
.dap-cms-btn {
  background: none;
  border: 1px solid var(--border, rgba(255,255,255,.15));
  color: var(--muted, #888);
  border-radius: 6px;
  width: 26px;
  height: 26px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .75rem;
  transition: color .12s, border-color .12s, background .12s;
}
.dap-cms-btn:hover { color: var(--accent, #7c6af7); border-color: var(--accent, #7c6af7); }
.dap-cms-del:hover { color: var(--danger, #e55); border-color: var(--danger, #e55); }

/* Inline edit form */
.dap-cms-form {
  background: var(--bg, #12121f);
  border: 1px solid var(--accent, #7c6af7);
  border-radius: 10px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}
.dap-cms-inp,
.dap-cms-area {
  background: var(--surface, #1e1e2e);
  color: var(--text, #eee);
  border: 1px solid var(--border, rgba(255,255,255,.15));
  border-radius: 7px;
  padding: 7px 10px;
  font-size: .84rem;
  font-family: inherit;
  direction: inherit;
  resize: vertical;
  outline: none;
  width: 100%;
  box-sizing: border-box;
}
.dap-cms-inp:focus,
.dap-cms-area:focus { border-color: var(--accent, #7c6af7); }
.dap-cms-form-nav {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.dap-cms-save {
  background: var(--accent, #7c6af7);
  color: #fff;
  border: none;
  border-radius: 7px;
  padding: 6px 18px;
  font-size: .83rem;
  cursor: pointer;
  font-weight: 600;
}
.dap-cms-save:hover { opacity: .85; }
.dap-cms-cancel {
  background: none;
  border: 1px solid var(--border, rgba(255,255,255,.2));
  color: var(--muted, #888);
  border-radius: 7px;
  padding: 6px 14px;
  font-size: .83rem;
  cursor: pointer;
}
.dap-cms-cancel:hover { color: var(--text, #eee); }

/* Add item button */
.dap-cms-add-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  background: none;
  border: 1px dashed var(--accent, #7c6af7);
  color: var(--accent, #7c6af7);
  border-radius: 8px;
  padding: 8px 14px;
  font-size: .84rem;
  cursor: pointer;
  width: 100%;
  margin-top: 8px;
  justify-content: center;
  transition: background .12s;
}
.dap-cms-add-btn:hover { background: rgba(124,106,247,.1); }

/* FAQ edit controls inside question row */
.dap-faq-q { display: flex; align-items: center; }
.dap-faq-q .dap-cms-controls { margin-inline-start: auto; }

/* Light-theme overrides */
[data-theme=light]   .dap-cms-form { background: #f5f5fa; border-color: var(--accent, #4a5af7); }
[data-theme=light]   .dap-cms-inp,
[data-theme=light]   .dap-cms-area { background: #fff; color: #1a1a2e; border-color: rgba(0,0,0,.18); }

/* ── DAP Phase 7 — CMS export/import toolbar ─────────────── */
.dap-cms-toolbar {
  display: flex;
  gap: .5rem;
  padding: .45rem .75rem;
  border-bottom: 1px solid var(--border, rgba(255,255,255,.08));
  background: var(--surface, #252540);
  flex-shrink: 0;
}
.dap-cms-tool-btn {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .76rem;
  padding: .28rem .6rem;
  border-radius: 6px;
  border: 1px solid var(--border, rgba(255,255,255,.18));
  color: var(--muted, #aaa);
  background: none;
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.dap-cms-tool-btn:hover { color: var(--accent, #7c6af7); border-color: var(--accent, #7c6af7); }

[data-theme=light]   .dap-cms-toolbar { background: #f0f0f8; border-bottom-color: rgba(0,0,0,.1); }

[data-theme=light]   .dap-cms-tool-btn { color: #555; border-color: rgba(0,0,0,.18); }

/* ══════════════════════════════════════════════════════════════
   FONT SIZE & FAMILY  (data-fontsize / data-font on <html>, resolved
   server-side from the general/user settings). The app is ~99% rem, so the
   root px scales the whole UI. normal = the 16px browser default (no rule).
   ══════════════════════════════════════════════════════════════ */
html[data-fontsize="small"] { font-size: 14px; }
html[data-fontsize="large"] { font-size: 18px; }
html[data-fontsize="huge"]  { font-size: 20px; }
/* Font family — system fonts only. default = the :root --font (Segoe UI). Each
   stack ends in a Hebrew-capable fallback so the RTL UI never loses its glyphs
   when the primary face has no Hebrew (or isn't installed on the OS). */
html[data-font="arial"]   { --font: Arial, "Helvetica Neue", sans-serif; }
html[data-font="tahoma"]  { --font: Tahoma, "Segoe UI", Arial, sans-serif; }
html[data-font="verdana"] { --font: Verdana, Geneva, "Segoe UI", Arial, sans-serif; }
html[data-font="serif"]   { --font: "Frank Ruehl CLM", "David", "Times New Roman", serif; }
html[data-font="times"]   { --font: "Times New Roman", "David", "Frank Ruehl CLM", serif; }
html[data-font="mono"]    { --font: Consolas, "Courier New", "Miriam Mono CLM", monospace; }

/* ══════════════════════════════════════════════════════════════
   STYLE SETS
   Compact / Airy / Sharp / Warm — override radius, shadow, font
   ══════════════════════════════════════════════════════════════ */
[data-style-set="compact"] {
  --radius: 4px;
  --shadow: 0 2px 8px rgba(0,0,0,.28);
}
[data-style-set="airy"] {
  --radius: 14px;
  --shadow: 0 12px 40px rgba(0,0,0,.36);
}
[data-style-set="sharp"] {
  --radius: 0px;
  --shadow: none;
}
[data-style-set="warm"] {
  --radius: 18px;
  --shadow: 0 6px 24px rgba(220,100,40,.15);
  --font: Georgia, 'Times New Roman', serif;
}

/* Style-set density tweaks */
[data-style-set="compact"] .card,
[data-style-set="compact"] .stg-section { padding: .6rem .8rem; }
[data-style-set="compact"] .um-table th,
[data-style-set="compact"] .um-table td { padding: .3rem .55rem; }
[data-style-set="compact"] .mnh-input,
[data-style-set="compact"] input,
[data-style-set="compact"] select { padding-top: .35rem; padding-bottom: .35rem; }

[data-style-set="airy"] .card,
[data-style-set="airy"] .stg-section { padding: 1.4rem 1.6rem; }
[data-style-set="airy"] .um-table th,
[data-style-set="airy"] .um-table td { padding: .7rem 1rem; }

/* ══════════════════════════════════════════════════════════════
   ICON STYLES  (data-icon-style on <html>)
   ══════════════════════════════════════════════════════════════ */
.app-icon { display: inline-block; }

[data-icon-style="duotone"] i.app-icon {
  color: var(--accent);
  --ph-duotone-color: rgba(var(--accent-rgb), .25);
}

/* Keep the a11y/feedback glyphs matching the help "?" glyph's plain white --
   the duotone rule above recolors every real <i class="app-icon"> to
   var(--accent), and these two ARE real icons (unlike .dap-fab-q, which is
   plain text and was never touched by it). Same specificity as that rule
   (attribute + type + class), placed after it, so this wins on source order. */
.a11y-fab i.app-icon,
.feedback-fab i.app-icon {
  color: inherit;
}

/* Flat: per-module accent color on the ribbon icon */
/* ── Feed (F079) ── */
.feed-configure-btn {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .78rem; font-weight: 600; color: var(--accent-h);
  background: rgba(var(--accent-rgb),.08); border: 1px solid rgba(var(--accent-rgb),.18);
  border-radius: 8px; padding: 5px 12px; cursor: pointer; font-family: inherit;
  margin: 12px 16px 0; transition: background .15s, border-color .15s;
}
.feed-configure-btn:hover { background: rgba(var(--accent-rgb),.16); border-color: rgba(var(--accent-rgb),.3); }
.feed-configure-btn i { font-size: .9rem; }
.feed-grid {
  padding: 20px 16px 48px;
  /* Home phase 1.2: ONE panel per row. Was repeat(2, ...) -- two half-width panels
     side by side, which capped every panel's content at whatever fits in half a
     screen and made the page read as a wall of equal tiles with no hierarchy. */
  display: grid; grid-template-columns: 1fr;
  gap: 16px; align-items: stretch;
}
.feed-section {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 15px 16px 16px;
  display: flex; flex-direction: column;
}
/* ── Personal command centre (home phase 2b) ─────────────────────────────────
   Restraint on purpose: the centre earns its weight from POSITION (always first)
   and from one accent edge, not from a colour per module. Colour here carries
   exactly one meaning -- urgency -- and never carries it alone: every priority
   badge pairs the tint with a word and an icon, so it survives a colourblind
   reader, high-contrast themes, and a greyscale print. */
.hc-section { border-inline-start: 3px solid var(--accent); }
/* Same leading accent stripe as the personal centre -- the two are the panels
   the home screen is built around, and they should read as a pair. */
.cs-section { border-inline-start: 3px solid var(--accent); }
/* .feed-cards.hc-body, not .hc-body: both classes sit on the same element and
   `.feed-cards { display: grid }` is defined LATER in this file, so a bare .hc-body
   ties on specificity and loses on order -- the two groups then lay out as grid
   items side by side instead of stacking. Caught by rendering it; the third time
   this exact tie has bitten in this file's neighbourhood. */
.feed-cards.hc-body { display: block; }   /* groups stack; the cards inside them grid */
/* Same specificity-tie trap as .hc-body above, same fix: .feed-cards' own
   `display: grid; grid-template-columns: repeat(auto-fill, minmax(260px,1fr))`
   (defined later in this file) is for panels with several small tiles side by
   side. The daily tip has exactly ONE child filling the whole panel -- as a
   grid item it only got the first ~260-1fr column's width, so its title/body
   text wrapped narrow with the rest of the wide panel sitting empty beside it. */
.feed-cards.daily-tip-body-wrap { display: block; }
.hc-group + .hc-group { margin-top: 1rem; }
.hc-group-title {
  font-size: .82rem; font-weight: 600; color: var(--muted);
  margin-bottom: .5rem; display: flex; align-items: center; gap: .4rem;
}
.hc-group-cards, .hc-rest {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px;
}
.hc-rest { margin-top: 10px; }
/* The skeleton renders more cards than any viewport shows; this clips them to ONE row.
   Doing it in CSS rather than counting columns in JS means the row stays exactly full
   through a window resize, with nothing to recompute and nothing to get wrong. */
.hc-skel-row { grid-auto-rows: 128px; max-block-size: 128px; overflow: hidden; }
.hc-day { font-size: .8rem; color: var(--muted); }

.hc-action-top { display: flex; align-items: center; gap: .4rem; margin-bottom: .35rem; }
.hc-kind { color: var(--accent); }
.hc-prio {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .72rem; font-weight: 600; border-radius: 999px;
  padding: .12rem .5rem; border: 1px solid currentColor;
}
.hc-prio-urgent { color: var(--danger); }
.hc-prio-today  { color: var(--warning); }
.hc-prio-soon   { color: var(--muted); }
/* The left edge repeats what the badge says, for scanning a long list. It is a
   SECOND channel, never the only one. */
.hc-action.hc-p-urgent { border-inline-start: 3px solid var(--danger); }
.hc-action.hc-p-today  { border-inline-start: 3px solid var(--warning); }

.hc-when { display: inline-flex; align-items: center; gap: .3rem; }
.hc-cta {
  display: inline-flex; align-items: center; gap: .35rem; margin-top: .5rem;
  font-size: .82rem; font-weight: 600; color: var(--accent);
}
/* Unread updates get a dot, not a different background -- a wall of tinted cards
   stops meaning anything once more than a couple are unread. */
.hc-update.hc-unread .feed-card-title::before {
  content: ""; display: inline-block; inline-size: 6px; block-size: 6px;
  border-radius: 50%; background: var(--accent); margin-inline-end: .4rem;
  vertical-align: middle;
}
/* "Why am I seeing this?" -- deliberately quiet. It is an answer for the person who
   stops to ask, not a third line of copy on every card, so it reads as a link and
   only takes space once opened. */
.hc-why { margin-top: .45rem; font-size: .78rem; color: var(--muted); }
.hc-why > summary {
  cursor: pointer; color: var(--muted); list-style: none;
  text-decoration: underline dotted; text-underline-offset: 2px;
  transition: color .18s;
}
.hc-why > summary::-webkit-details-marker { display: none; }
.hc-why > summary:hover { color: var(--accent); }
.hc-why[open] > summary { margin-bottom: .25rem; }

/* .hc-main is the card's activation target, and the reason it exists is in
   feed.js: role="button" flattens its descendants in the accessibility tree, so the
   dismiss button and the why-disclosure have to be OUTSIDE it. It fills the card so
   the clickable area is unchanged from when the wrapper itself was the button. */
/* text-decoration:none because .hc-main is an <a href> whenever the item has a URL
   (a survey / ballot / roll-call answer page) and a div-as-button otherwise. Those
   two sit side by side in the same group, and the browser's default underline made
   the anchor card visibly different from its neighbour -- measured, not assumed. The
   card's affordance is .hc-cta; underlining the whole thing is noise. */
.hc-main { display: block; cursor: pointer; text-decoration: none; color: inherit; }
.hc-main:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* Dismiss sits in the card's top corner. Logical inset, so it lands on the left in
   the Hebrew RTL default and on the right in an LTR locale without a second rule. */
.hc-dismiss {
  position: absolute; inset-block-start: 6px; inset-inline-end: 6px;
  inline-size: 24px; block-size: 24px; padding: 0; z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: 6px;
  color: var(--muted); font-size: .82rem; cursor: pointer; opacity: .55;
  /* Measured, not decorative: these controls changed colour/opacity on hover with
     transition-duration 0s while the .feed-card they sit on eases at .18s, so the
     card settled and its buttons snapped. Same duration as the card, so the whole
     surface moves as one. The global prefers-reduced-motion catch-all already
     collapses every transition-duration, so none of this needs its own guard. */
  transition: opacity .18s, color .18s;
}
.hc-dismiss:hover, .hc-dismiss:focus-visible { opacity: 1; color: var(--danger); }
.hc-dismiss:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Same invisible tap-target extension .um-btn-icon uses: the visible box stays 24px
   so it cannot crowd the card title, while the touchable area reaches the WCAG 44px. */
.hc-dismiss::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: max(44px, 100%); height: max(44px, 100%);
}
/* Keep the title clear of the button in both directions. */
.hc-update .feed-card-title { padding-inline-end: 26px; }

/* The undo strip replaces the card IN PLACE for the few seconds the request is held
   back. Not a toast: showToast takes only (msg, type), self-destructs after 3s --
   shorter than the undo window -- and its own comment says a toast needing markup
   should be a modal instead. In place also puts the undo exactly where the card was. */
.hc-undo {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .6rem .75rem; font-size: .85rem; color: var(--muted);
  background: var(--surface); border: 1px dashed var(--border);
}
.hc-undo-btn {
  background: none; border: 0; padding: .25rem .5rem; border-radius: 6px;
  color: var(--accent); font-weight: 600; font-size: .85rem; cursor: pointer;
  font-family: inherit;
  /* No transition here on purpose: measuring showed the only thing this changes on
     hover is text-decoration-line, which is not animatable. A `transition: color`
     would look like polish and do nothing. The underline stays -- it is the clearest
     affordance for a text button, and it is instant by nature. */
}
.hc-undo-btn:hover { text-decoration: underline; }
.hc-undo-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Skeleton, not a spinner: the centre is the first panel on the page, so it is the
   one the user is looking at while it loads. A fixed-height placeholder means the
   real cards land without shifting anything below them. */
.hc-skel-card {
  /* Measured, not picked: the real cards render 128px (update) and 144px (action)
     at every width tested. 92px was a guess and left a 36px jump per card -- the
     exact thing a skeleton exists to avoid. */
  block-size: 128px; border-radius: var(--radius);
  background: linear-gradient(90deg,
    rgba(var(--accent-rgb), .06) 25%,
    rgba(var(--accent-rgb), .13) 37%,
    rgba(var(--accent-rgb), .06) 63%);
  background-size: 400% 100%;
  animation: hc-shimmer 1.4s ease-in-out infinite;
}
@keyframes hc-shimmer {
  from { background-position: 100% 50%; }
  to   { background-position: 0 50%; }
}
/* Both halves, per the app's convention (test_reduce_motion_override guards it):
   the media query is gated on :not([data-motion="full"]) so the in-app "full motion"
   setting can override the OS preference, and the explicit [data-motion="reduce"]
   rule makes the in-app "reduce" setting work on a machine whose OS asks for none.
   I wrote the media query alone and the comment above claimed to follow a convention
   I had only half-applied. */
/* A skeleton is a PROGRESS INDICATOR, so it has to keep signalling under reduced motion:
   frozen grey boxes read as a broken screen, which is the same "a static ring reads as
   broken" failure .sp-bounce had (bb9c583d). That pass fixed the app's main loader and
   checked that two DECORATIVE animations still stop -- it never asked whether any other
   progress indicator had been caught by the catch-all. This one had.
   It does NOT get its shimmer back: hc-shimmer slides a gradient across the element, and
   travel is the vestibular trigger. hc-skel-fade pulses opacity in place -- same rhythm,
   nothing moves. */
@keyframes hc-skel-fade {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  html:not([data-motion="full"]) .hc-skel-card {
    /* !important, like .sp-bounce's exemption: the catch-all above sets
       animation-duration and animation-iteration-count with !important, so a plain
       declaration here is crushed to 0.01ms and one iteration -- the fade would be
       named but never run, which looks identical to the frozen box it replaced. */
    animation-name: hc-skel-fade !important;
    animation-duration: 1.8s !important;
    animation-iteration-count: infinite !important;
    animation-timing-function: ease-in-out !important;
    background-position: 0 50%;
  }
}
html[data-motion="reduce"] .hc-skel-card {
  animation-name: hc-skel-fade !important;          /* see the note above */
  animation-duration: 1.8s !important;
  animation-iteration-count: infinite !important;
  animation-timing-function: ease-in-out !important;
  background-position: 0 50%;
}

/* Recently used screens (phase 3). Deliberately the quietest thing on the page: a
   label and a row of chips, no card chrome, no border, no background -- the brief
   says not to give it excessive visual weight, and it sits between the personal
   centre and the module panels where anything heavier would compete with both.
   The row scrolls sideways rather than wrapping, so five chips can never push the
   panels below the fold on a phone. */
.feed-recent {
  display: flex; align-items: center; gap: .6rem;
  padding: .1rem .1rem .35rem;
}
.feed-recent-title {
  display: inline-flex; align-items: center; gap: .35rem; flex-shrink: 0;
  font-size: .78rem; font-weight: 600; color: var(--muted);
}
.feed-recent-chips {
  display: flex; gap: .4rem; overflow-x: auto; padding-block-end: 2px;
  scrollbar-width: thin;
}
.feed-recent-chip {
  display: inline-flex; align-items: baseline; gap: .3rem; flex-shrink: 0;
  padding: .28rem .6rem; border-radius: 999px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  color: var(--text); font-size: .8rem; font-family: inherit;
  white-space: nowrap; transition: border-color .18s, color .18s;
}
.feed-recent-chip:hover { border-color: var(--accent); color: var(--accent); }
.feed-recent-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.feed-recent-sub { color: var(--muted); font-size: .74rem; }
.feed-recent-chip:hover .feed-recent-sub { color: inherit; }

.hc-empty {
  display: flex; align-items: center; gap: .5rem; justify-content: center;
  padding: 1.25rem; color: var(--text); font-size: .88rem;   /* was var(--muted) */
}
.hc-empty i { color: var(--success, #22c55e); font-size: 1.15rem; }
.hc-more {
  margin-top: .6rem; background: none; border: 1px solid var(--border);
  color: var(--text); font-family: inherit; font-size: .82rem;
  border-radius: 999px; padding: .35rem .9rem; cursor: pointer;
  transition: border-color .18s, color .18s;
}
.hc-more:hover { border-color: var(--accent); color: var(--accent); }

/* Feed grid drag-and-drop */
.feed-section[draggable="true"] { cursor: grab; }
.feed-section[draggable="true"]:active { cursor: grabbing; }
.feed-section.fs-dragging { opacity: .3; }
.feed-section.fs-over-before { box-shadow: inset 3px 0 0 var(--accent); }
.feed-section.fs-over-after  { box-shadow: inset -3px 0 0 var(--accent); }
.fs-drag-ghost {
  position: fixed; z-index: 9999; opacity: .8; pointer-events: none;
  border-radius: 8px; background: var(--surface); color: var(--text);
  box-shadow: 0 4px 12px rgba(0,0,0,.25); padding: 10px 16px;
  font-size: .85rem; font-weight: 600; max-width: 200px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Feed panel collapse / expand */
.feed-header-actions {
  display: flex; align-items: center; gap: 6px;
}
.feed-collapse-btn {
  background: none; border: none; cursor: pointer; padding: 2px 4px;
  color: var(--muted); font-size: 1rem; line-height: 1;
  transition: transform .2s, color .15s;
}
.feed-collapse-btn:hover { color: var(--text); }
.feed-collapse-btn i { pointer-events: none; }
.fs-collapsed .feed-collapse-btn i { transform: rotate(180deg); }
.fs-collapsed .feed-cards { display: none; }
.fs-collapsed .feed-section-header { margin-bottom: 0; }
.feed-section-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.feed-section-title {
  font-size: .9rem; font-weight: 600; color: var(--text);
  display: flex; align-items: center; gap: 7px;
}
.feed-section-title i { color: #ffffff; font-size: 1.1rem; }
.feed-count {
  font-size: .72rem; color: #ffffff;
  background: rgba(var(--accent-rgb),.1);
  padding: 1px 8px; border-radius: 10px;
}
.feed-see-all {
  font-size: .78rem; color: #ffffff; background: none;
  border: none; cursor: pointer; font-family: inherit;
}
.feed-see-all:hover { text-decoration: underline; }
.feed-cards {
  /* The panel is full-width now, so a fixed 2 columns would just stretch two cards
     across the screen. auto-fill lets each panel use the width it actually has --
     more cards per row on a wide screen, fewer on a narrow one -- without a
     breakpoint per size. This is the half that makes 1.2 a redesign rather than a
     stretch. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px;
}

/* The 8-row rule. max-height is set by _feedCapToRows from the rendered geometry --
   this grid's column count decides how many cards make a row, so the number cannot
   live in CSS. Without the JS the panel simply grows, which is the old behaviour.
   overscroll-behavior stops a flick inside the panel from carrying on into the page
   once it hits the end, which on a phone is what makes a nested scroller usable. */
.feed-cards-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Keeps a card scrolled to by keyboard focus clear of both edges. */
  scroll-padding-block: 10px;
}

/* ── "What's new" as a list, not a mosaic ────────────────────────────────────
   .feed-cards is a `repeat(auto-fill, minmax(260px, 1fr))` grid, so six updates sat
   across a desktop and "8 rows" meant 48 notifications before anything scrolled. One
   column makes a row a row, which is what _feedCapToRows measures and what the 8-row
   rule was always about.

   Only this one section opts in (via _feedSection's cardsClass, which nothing else
   passes), so every other panel keeps its tiles. */
.feed-cards-rows { grid-template-columns: 1fr; gap: 0; }

/* The row itself is the bell's .notif-item, reused wholesale. These are the only
   differences: the bell stacks title/body/time so it aligns to the top, this is a
   single line so it centres; and the bell sits in a dropdown with its own padding. */
.feed-cards-rows .notif-item { align-items: center; padding: .5rem .6rem; border-radius: 8px; }
.feed-cards-rows .notif-item:last-child { border-bottom: 1px solid var(--border); }
/* The activatable element now holds the icon, the title and the time, so it has to
   lay them out itself -- and it must fill the row, or the inert strip that made the
   click feel dead comes straight back. */
.wn-main {
  display: flex; align-items: center; gap: .65rem;
  flex: 1; min-width: 0;
}
.wn-row .notif-item-title { margin: 0; flex: 1; min-width: 0; }
/* Overrides .feed-card-title's 2-line clamp, which is kept on the element so the
   emergency-title colour rules below still have something to key on. */
.wn-row .feed-card-title {
  display: block; -webkit-line-clamp: none; padding-inline-end: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.wn-time {
  flex-shrink: 0; font-size: .72rem; color: var(--text);   /* was var(--muted) */
  font-variant-numeric: tabular-nums;   /* times line up down the column */
}
/* The dismiss is absolutely positioned on a card; in a row it is just the last item.
   RELATIVE, not static, and that distinction is the whole bug this row shipped with:
   .hc-dismiss::after is an absolutely-positioned WCAG touch-target extension sized
   `max(44px, 100%)`. With `position: static` it stops resolving against the button and
   anchors to whatever ancestor is positioned instead, so 100% becomes 100% OF THE
   PANEL -- an invisible rectangle covering every row, swallowing every click and every
   wheel event, and painting its own `cursor: pointer` over the lot.
   elementFromPoint on any part of any row returned this button. */
.wn-dismiss { position: relative; opacity: 0; }
.wn-row:hover .wn-dismiss,
.wn-row:focus-within .wn-dismiss { opacity: 1; }

/* Danger rows: emergency / evacuation keep the red treatment they had as cards.
   The card version was `.feed-card:has(.feed-notif-icon.emergency)` recolouring the
   whole tile; a row has no tile, so it takes a red edge and a red title instead. The
   icon still carries the type class, which is what both versions key on. */
.wn-row:has(.feed-notif-icon.emergency),
.wn-row:has(.feed-notif-icon.emergency_broadcast),
.wn-row:has(.feed-notif-icon.evacuation),
.wn-row:has(.feed-notif-icon.evac_broadcast) {
  border-inline-start: 3px solid var(--danger);
  background: rgba(239, 68, 68, .06);
}
.wn-row:has(.feed-notif-icon.emergency)           .feed-card-title,
.wn-row:has(.feed-notif-icon.emergency_broadcast) .feed-card-title,
.wn-row:has(.feed-notif-icon.evacuation)          .feed-card-title,
.wn-row:has(.feed-notif-icon.evac_broadcast)      .feed-card-title { color: var(--danger); font-weight: 600; }

.feed-card {
  /* ── "E" vivid accent-tint — a committed DARK branded tile in EVERY theme
     (approved 2026-08): accent-gradient ground + accent border + accent-light
     title + a bottom accent underline, so each tile reads like a button/notice.
     Fixed brand colours (not theme tokens) so it matches the mockup identically
     in every theme; the danger variant below swaps --fc to red for
     emergencies/urgent. High-contrast themes reset to flat a11y cards below. */
  --fc: 76,154,255;                 /* tile hue: accent blue (danger red below) */
  position: relative;
  background:
    linear-gradient(135deg, rgba(var(--fc),.18), rgba(var(--fc),.02) 55%),
    #0e2144;
  border: 1px solid rgba(var(--fc),.32);
  border-radius: 11px; padding: 12px 13px; cursor: pointer;
  /* F: uniform card height across ALL feed cards — sized to the tallest type
     (doc card: badge + 2-line title + date + summary/topics). Shorter cards pad
     to match; long titles already clamp to 2 lines. One tunable value. */
  min-height: var(--feed-card-h, 128px);
  display: flex; flex-direction: column; gap: 7px;
  transition: transform .18s, box-shadow .18s, border-color .18s, background .18s;
}
/* Bottom accent underline — the "E" signature, rounded to the card corners. */
.feed-card::after {
  content: ''; position: absolute; inset-inline: 0; bottom: 0; height: 3px;
  background: linear-gradient(90deg, rgb(var(--fc)), transparent);
  border-radius: 0 0 10px 10px; pointer-events: none;
}
/* Danger tile: emergency/evacuation notifications + urgent bulletins → red hue. */
.feed-card:has(.feed-notif-icon.emergency),
.feed-card:has(.feed-notif-icon.emergency_broadcast),
.feed-card:has(.feed-notif-icon.evacuation),
.feed-card:has(.feed-notif-icon.evac_broadcast),
.feed-card:has(.feed-badge-urgent) { --fc: 255,91,82; }
.feed-card:has(.feed-notif-icon.emergency)           .feed-card-title,
.feed-card:has(.feed-notif-icon.emergency_broadcast) .feed-card-title,
.feed-card:has(.feed-notif-icon.evacuation)          .feed-card-title,
.feed-card:has(.feed-notif-icon.evac_broadcast)      .feed-card-title,
.feed-card:has(.feed-badge-urgent)                   .feed-card-title { color: #ffb0ab; }
.feed-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 30px rgba(0,0,0,.45);
  border-color: rgb(var(--fc));
}
.feed-card-title {
  font-size: .86rem; font-weight: 700; color: #ffffff; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.feed-card-meta {
  font-size: .75rem; color: #ffffff;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
}
.feed-card-meta i { font-size: .85rem; }
.feed-dot { opacity: .4; }
.feed-badge {
  font-size: .68rem; padding: 2px 8px; border-radius: 8px; font-weight: 600;
  display: inline-block;
}
.feed-badge-general  { background: rgba(var(--accent-rgb),.12); color: #ffffff; }
.feed-badge-urgent   { background: rgba(255,91,82,.12);  color: var(--danger); }
.feed-badge-event    { background: rgba(61,220,151,.12); color: var(--success); }
.feed-badge-service  { background: rgba(227,154,58,.12); color: var(--warn); }
.feed-badge-active    { background: none; color: var(--success); }
.feed-badge-birthday  { background: none; color: #ffffff; font-size: .86rem; font-weight: 700; padding: 0; }
/* On-request "🌐 translate" control (feed cards, detail modal, comments) — a link-
   like button; after translating it toggles between the translation and the original. */
.feed-tr-row { margin-top: .5rem; }
.feed-tr-btn {
  cursor: pointer; border: none; background: none; font-family: inherit;
  font-size: .78rem; font-weight: 600; padding: 2px 4px;
  /* AI Visual Language (WOW-UX review): was hardcoded white -- coincidental
     card chrome (matched sibling controls on the same dark card), not an AI
     signal, even though translate is AI-backed. Was also a raw 🌐 emoji, not
     a Phosphor icon -- now ph-sparkle, matching every other AI surface. */
  display: inline-flex; align-items: center; gap: .3rem; color: var(--ai-accent);
}
.feed-tr-btn:hover { text-decoration: underline; }
.feed-tr-btn[disabled] { opacity: .6; cursor: default; }
.fd-tr-row { margin: 0 0 .6rem; }
/* Quick actions strip (opportunity #5) — one-tap agentic actions above the grid. */
.feed-quick-actions { margin-bottom: .75rem; }
.feed-qa-title { font-size: .8rem; color: var(--muted); margin-bottom: .4rem; font-weight: 600; }
.feed-qa-btns { display: flex; gap: .5rem; flex-wrap: wrap; }
.feed-qa-btn {
  display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  border-radius: 999px; padding: .45rem .9rem; font-size: .85rem;
  font-family: inherit; cursor: pointer;
  /* Pre-dates the centre, and snapped for the same reason its controls did. Included
     because it sits in the pinned bar directly above them: leaving one row of pills
     on Home instant while the row below eases is the inconsistency this pass is for. */
  transition: border-color .18s, color .18s;
}
.feed-qa-btn:hover { border-color: var(--accent); color: var(--accent); }
.feed-qa-btn i { font-size: 1rem; color: var(--accent); }
@media (max-width: 640px) {
  .feed-qa-btns { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .feed-qa-btn { flex: 0 0 auto; }
}
/* ── Birthday Panel (Feature #10) ── */
.bday-panel {
  margin: 0 0 .75rem;
  border: 1.5px solid rgba(var(--accent-rgb),.22);
  border-radius: var(--radius, 12px);
  overflow: hidden;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),.07), rgba(var(--accent-rgb),.02));
}
.bday-panel-header {
  display: flex; align-items: center; gap: .5rem;
  padding: .55rem 1rem; border-bottom: 1px solid rgba(var(--accent-rgb),.15);
  background: rgba(var(--accent-rgb),.07);
  cursor: pointer; user-select: none;
}
.bday-panel-title {
  font-weight: 700; font-size: .92rem; color: var(--text); display: flex; align-items: center; gap: .4rem; flex: 1;
}
.bday-toggle-btn {
  border: none; background: none; cursor: pointer; font-size: 1.1rem;
  color: var(--muted); padding: 0 .25rem; line-height: 1;
}
.bday-panel-body {
  overflow: hidden;
}
/* Scroll track — wraps normally when few cards, scrolls when .bday-panel-body--scroll */
.bday-scroll-track {
  display: flex; flex-wrap: wrap; gap: .75rem; padding: .75rem 1rem;
}
/* Ticker mode (4+ birthday people) */
@keyframes bdayTicker {
  from { transform: translateX(50%); }   /* RTL: start 50% right, slide into position */
  to   { transform: translateX(0); }
}
.bday-panel-body--scroll .bday-scroll-track {
  flex-wrap: nowrap;
  width: max-content;
  animation: bdayTicker var(--bday-ticker-dur, 40s) linear infinite;
}
/* Pause on hover/focus so the user can click a card */
.bday-panel-body--scroll:hover .bday-scroll-track,
.bday-panel-body--scroll:focus-within .bday-scroll-track {
  animation-play-state: paused;
}
/* Fade edges to hint that content continues */
.bday-panel-body--scroll {
  -webkit-mask-image: linear-gradient(to left, transparent 0, #000 3rem, #000 calc(100% - 3rem), transparent 100%);
          mask-image: linear-gradient(to left, transparent 0, #000 3rem, #000 calc(100% - 3rem), transparent 100%);
}
.bday-card {
  display: flex; align-items: flex-start; gap: .6rem;
  border: 1.5px solid var(--border); border-radius: 10px;
  background: var(--bg); padding: .65rem .8rem;
  min-width: 180px; flex: 1 1 180px; max-width: 240px;
  position: relative; transition: border-color .2s;
}
.bday-card-greeted { border-color: var(--success); }
/* ── Birthday decoration animations ─────────────────────────────── */
@keyframes bdayFloat    { 0%,100%{transform:translateY(0)}       50%{transform:translateY(-5px)} }
@keyframes bdayFlicker  { 0%,100%{opacity:1;transform:scaleY(1) translateY(0)} 40%{opacity:.45;transform:scaleY(.72) translateY(2px)} 70%{opacity:.8;transform:scaleY(.9) translateY(1px)} }
@keyframes bdayPulse    { 0%,100%{transform:scale(1);opacity:1}  50%{transform:scale(1.18);opacity:.6} }
@keyframes bdayTwinkle  { 0%,100%{opacity:1;transform:scale(1)}  50%{opacity:.25;transform:scale(.72)} }
@keyframes bdayConfSpin { from{transform:rotate(0deg)}            to{transform:rotate(360deg)} }
@keyframes bdayBallBob  { 0%,100%{transform:translateY(0)}       50%{transform:translateY(-4px)} }
/* Global float for the whole decoration icon */
.bday-decor { flex: 0 0 auto; width: 48px; height: 56px; display: flex; align-items: center; justify-content: center;
              animation: bdayFloat 3s ease-in-out infinite; }
.bday-decor svg { width: 48px; height: 56px; overflow: visible; }
/* Per-element animation hooks (classes added directly to SVG elements in feed.js) */
.bday-decor .bday-fl {
  transform-box: fill-box; transform-origin: bottom center;
  animation: bdayFlicker .85s ease-in-out infinite;
}
.bday-decor .bday-fl:nth-child(2) { animation-delay: -.28s; }
.bday-decor .bday-fl:nth-child(3) { animation-delay: -.56s; }
.bday-decor .bday-pulse {
  transform-box: fill-box; transform-origin: center center;
  animation: bdayPulse 1.1s ease-in-out infinite;
}
.bday-decor .bday-tw {
  transform-box: fill-box; transform-origin: center center;
  animation: bdayTwinkle 1.6s ease-in-out infinite;
}
.bday-decor .bday-tw:nth-child(2) { animation-delay: -.38s; }
.bday-decor .bday-tw:nth-child(3) { animation-delay: -.76s; }
.bday-decor .bday-tw:nth-child(4) { animation-delay: -1.1s; }
.bday-decor .bday-tw:nth-child(5) { animation-delay: -1.4s; }
.bday-decor .bday-cs {
  transform-box: fill-box; transform-origin: center center;
  animation: bdayConfSpin 4s linear infinite;
}
.bday-decor .bday-cs:nth-child(2) { animation-delay: -.6s;  animation-duration: 3.4s; }
.bday-decor .bday-cs:nth-child(3) { animation-delay: -1.3s; animation-duration: 5.1s; animation-direction: reverse; }
.bday-decor .bday-cs:nth-child(4) { animation-delay: -2s;   animation-duration: 4.6s; }
.bday-decor .bday-cs:nth-child(5) { animation-delay: -.9s;  animation-duration: 3.8s; animation-direction: reverse; }
.bday-decor .bday-cs:nth-child(6) { animation-delay: -1.7s; animation-duration: 5.5s; }
.bday-decor .bday-ball {
  transform-box: fill-box; transform-origin: bottom center;
  animation: bdayBallBob 2.2s ease-in-out infinite;
}
.bday-decor .bday-ball:nth-child(2) { animation-delay: -.55s; }
.bday-decor .bday-ball:nth-child(3) { animation-delay: -1.1s; }
.bday-avatar { flex: 0 0 auto; }
.bday-avatar-img, .bday-avatar-init {
  width: 38px; height: 38px; border-radius: 50%; object-fit: cover;
}
.bday-avatar-init {
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: .95rem; color: #fff;
}
.bday-info { flex: 1; min-width: 0; }
.bday-name { font-weight: 700; font-size: .9rem; margin-bottom: .35rem; }
.bday-actions-row { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.bday-greet-btn {
  display: inline-flex; align-items: center; gap: .2rem;
  border: 1px solid var(--accent); color: var(--accent);
  background: rgba(var(--accent-rgb),.07); border-radius: 999px;
  padding: .2rem .6rem; font-size: .78rem; cursor: pointer; font-family: inherit;
  transition: background .15s;
}
.bday-greet-btn:hover { background: rgba(var(--accent-rgb),.15); }
.bday-greeted-badge {
  font-size: .78rem; color: #16a34a; font-weight: 600;
}
.bday-count {
  font-size: .75rem; color: var(--muted);
}
.bday-greet-form { margin-top: .4rem; }
.bday-emoji-row { display: flex; gap: .15rem; flex-wrap: wrap; }
.bday-emoji {
  border: none; background: none; cursor: pointer; font-size: 1.1rem;
  padding: .1rem .15rem; border-radius: 4px; transition: background .1s;
}
.bday-emoji:hover { background: rgba(var(--accent-rgb),.12); }
/* Birthday bulletin card — avatar section (bulletin board view) */
.bulletin-bday-card { border-top: 3px solid rgba(var(--accent-rgb),.4); }
.bulletin-bday-avatar-wrap {
  position: relative; display: flex; align-items: center; justify-content: center;
  height: 140px; background: linear-gradient(135deg, rgba(var(--accent-rgb),.12), rgba(var(--accent-rgb),.04));
  border-radius: var(--radius,12px) var(--radius,12px) 0 0;
}
.bday-av-lg {
  width: 76px; height: 76px; border-radius: 50%;
  font-size: 1.6rem; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, rgba(var(--accent-rgb),1), rgba(var(--accent-rgb),.6));
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(var(--accent-rgb),.35);
}
.bulletin-bday-emoji {
  position: absolute; bottom: 10px; right: 10px; font-size: 1.5rem; line-height: 1;
}
/* Daily AI Summary card (opportunity #3) */
.daily-summary-card {
  /* AI Visual Language (WOW-UX review, Signature B): --ai-accent, not the
     site's general --accent -- this card is AI-generated content. */
  background: linear-gradient(135deg, rgba(var(--ai-accent-rgb),.08), rgba(var(--ai-accent-rgb),.02));
  border: 1px solid rgba(var(--ai-accent-rgb),.25);
  border-radius: var(--radius, 12px); padding: 1rem 1.25rem; margin-bottom: .75rem;
}
.ds-card-header { display: flex; align-items: center; gap: .5rem; margin-bottom: .6rem; color: var(--ai-accent); }
.ds-card-title { font-weight: 600; font-size: .95rem; color: var(--text); }
/* Shared "AI made/touched this" badge -- one rule for every surface (daily
   summary, forum summary, translate, future document-summary pass), instead
   of each inventing its own (AI Visual Language, WOW-UX review Signature B). */
.ai-badge {
  font-size: .65rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  background: var(--ai-accent); color: #fff; border-radius: 4px; padding: .15rem .4rem;
  margin-inline-start: auto;
}
/* Shared "this icon marks AI content" color -- one rule for every AI-touched
   icon (document summaries, and any future surface) instead of each site
   repeating its own inline color (AI Visual Language, Stage 2a). */
.ai-icon { color: var(--ai-accent); }
.ds-card-body { font-size: .88rem; line-height: 1.55; color: var(--text); }
.ds-card-body ul.ds-card-list { margin: 0; padding-inline-start: 1.2rem; }
.ds-card-body ul.ds-card-list li { margin-bottom: .25rem; }
.ds-card-footer { font-size: .75rem; color: var(--muted); margin-top: .5rem; }

/* Daily Tip card (feature-discovery engine) -- same card shape as
   .daily-summary-card, but --accent (a curated tip, not AI-generated content)
   rather than --ai-accent. Lives inside #dailyTipSlot (feed.js), owned/rendered
   by static/js/tips.js. */
.daily-tip-card {
  background: linear-gradient(135deg, rgba(var(--accent-rgb),.08), rgba(var(--accent-rgb),.02));
  border: 1px solid rgba(var(--accent-rgb),.25);
  border-radius: var(--radius, 12px); padding: 1rem 1.25rem; margin-bottom: .75rem;
}
/* Now nested inside the generic .feed-section shell (collapsible, matches every other
   panel) -- that shell already supplies its own surface/border/padding box, so the
   card's own box here would double it up (border-in-border). Neutralize just the box,
   keep everything else (icon, eyebrow, pill, spacing between children) unchanged. */
.daily-tip-section .daily-tip-card {
  background: none; border: none; border-radius: 0; padding: 0; margin-bottom: 0;
}
/* The daily tip otherwise looks identical to every other feed panel (same navy
   .feed-section surface, same blue accent) -- nothing marks it as special even though
   it's the one panel meant to stand out. --warn/--warn-rgb (already theme-aware, same
   token used for the identical background+border pairing at :3443-3444) gives it its
   own warm identity instead of introducing a new color. */
.daily-tip-section {
  background: linear-gradient(135deg, rgba(var(--warn-rgb),.10), rgba(var(--warn-rgb),.02));
  border-color: rgba(var(--warn-rgb),.35);
}
.daily-tip-section .feed-section-title { color: var(--warn); }
/* The default theme gives EVERY .feed-section its own decorative navy+accent-glow
   treatment (:root:not([data-theme]) .feed-section, ~style.css:6305) at higher
   specificity than the plain rule above, so it would silently win back the blue
   glow here. Same treatment, recolored warm instead of overridden away. */
:root:not([data-theme]) .daily-tip-section {
  background:
    radial-gradient(120% 90% at 88% -10%, rgba(var(--warn-rgb),.20), transparent 55%),
    #0a1526;
  border-color: rgba(var(--warn-rgb),.35);
}
:root:not([data-theme]) .daily-tip-section::before {
  background: linear-gradient(90deg, var(--warn), #f5c877, var(--warn));
}
.daily-tip-cycle-note {
  display: flex; align-items: center; gap: .4rem; font-size: .78rem; color: var(--muted);
  margin-bottom: .6rem; padding-bottom: .5rem; border-bottom: 1px solid var(--border);
}
.daily-tip-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem; }
.daily-tip-icon {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(var(--accent-rgb),.15); color: var(--accent);
}
.daily-tip-eyebrow {
  font-size: .72rem; font-weight: 700; letter-spacing: .03em; color: var(--accent);
  display: flex; align-items: center; gap: .3rem;
}
.daily-tip-cat-pill {
  font-size: .68rem; font-weight: 600; color: var(--muted); background: var(--border);
  padding: .1rem .55rem; border-radius: 99px; margin-inline-start: auto;
}
.daily-tip-title { font-weight: 700; font-size: .95rem; color: var(--text); margin-bottom: .3rem; }
.daily-tip-body { font-size: .87rem; line-height: 1.55; color: var(--text); margin: 0 0 .8rem; max-width: 62ch; }
.daily-tip-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.daily-tip-btn { font-size: .82rem; padding: .45rem .9rem; border-radius: 8px; }
.daily-tip-btn-text {
  background: transparent; border: none; color: var(--text); cursor: pointer;   /* was var(--muted) */
  font-size: .82rem; margin-inline-start: auto; display: inline-flex; align-items: center; gap: .3rem;
}
.daily-tip-btn-text:hover { color: var(--warn); }

/* Daily Tip — "more info" modal steps (see #tipInfoModal, _modals_shared.html) */
.tip-info-steps { display: flex; flex-direction: column; gap: .5rem; margin-bottom: .3rem; }
.tip-info-row { display: flex; gap: .55rem; align-items: flex-start; font-size: .85rem; line-height: 1.55; color: var(--text); }
.tip-info-n {
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; margin-top: 1px;
  background: var(--border); color: var(--muted); font-size: .7rem;
  display: flex; align-items: center; justify-content: center; font-variant-numeric: tabular-nums;
}

.feed-status { display: flex; align-items: center; gap: 5px; }
.feed-status-dot { width: 7px; height: 7px; border-radius: 50%; }
.feed-status-new      { background: rgba(var(--accent-rgb),.15); color: #ffffff; }
.feed-status-handling { background: rgba(227,154,58,.15); color: var(--warn); }
.feed-status-dot.feed-status-new     { background: var(--accent); }
.feed-status-dot.feed-status-handling { background: var(--warn); }
.feed-date-block {
  display: flex; align-items: center; gap: 2px; flex-direction: column;
  background: rgba(var(--accent-rgb),.08); border-radius: 8px;
  padding: 4px 10px; min-width: 48px; flex-shrink: 0;
}
.feed-date-day   { font-size: 1.2rem; font-weight: 700; color: #ffffff; line-height: 1; }
.feed-date-month { font-size: .68rem; color: #ffffff; }
/* Event card: date block + info side by side (non-thumb fallback) */
.feed-card:not(.feed-card-has-thumb):has(.feed-date-block) { flex-direction: row; gap: 12px; align-items: center; }
.feed-date-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.feed-deadline { color: var(--warn); }
.feed-deadline i { font-size: .85rem; }
/* Notification card layout: icon + text side by side */
.feed-card-notif { flex-direction: row !important; gap: 12px; align-items: flex-start; }
.feed-notif-icon {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  display: grid; place-items: center; font-size: .95rem;
  /* E: solid accent disc with a soft glow (dark glyph for crisp contrast). */
  background: #4C9AFF; color: #08192e;
  box-shadow: 0 0 12px rgba(76,154,255,.45);
}
.feed-notif-icon.evacuation, .feed-notif-icon.emergency,
.feed-notif-icon.evac_broadcast, .feed-notif-icon.emergency_broadcast {
  background: #ff5b52; color: #2a0806; box-shadow: 0 0 12px rgba(255,91,82,.5);
}
.feed-notif-icon.ticket_new, .feed-notif-icon.ticket_comment, .feed-notif-icon.ticket_status {
  background: #E39A3A; color: #241402; box-shadow: 0 0 12px rgba(227,154,58,.45);
}
.feed-notif-content { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
/* Thumbnail on feed cards (bulletin / event / ticket) */
.feed-card-has-thumb { flex-direction: row; align-items: center; }
.feed-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.feed-card-has-thumb:has(.feed-date-block) .feed-card-body { flex-direction: row; gap: 12px; align-items: center; }
.feed-thumb {
  width: 48px; height: 48px; border-radius: 8px; object-fit: cover;
  flex-shrink: 0; cursor: zoom-in;
  border: 1px solid var(--border);
  transition: transform .15s ease, box-shadow .15s ease;
}
.feed-thumb:hover {
  transform: scale(1.08);
  box-shadow: 0 2px 8px rgba(0,0,0,.18);
}
/* Doc-card actions: view-summary button + topics hover chip (home feed) */
.feed-doc-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 2px; }
.feed-doc-btn {
  display: inline-flex; align-items: center; gap: 4px; font-family: inherit;
  font-size: .7rem; font-weight: 600; padding: 3px 9px; border-radius: 8px; cursor: pointer;
  background: rgba(var(--accent-rgb),.12); color: #ffffff; border: none;
  transition: background .15s;
}
.feed-doc-btn:hover { background: rgba(var(--accent-rgb),.22); }
.feed-doc-btn i { font-size: .85em; }
.feed-doc-topics {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .7rem; color: #ffffff; padding: 3px 6px; cursor: default;
}
.feed-doc-topics:hover { color: var(--text); }
.feed-doc-topics i { font-size: .85em; }
.feed-empty {
  text-align: center; padding: 48px 20px; color: var(--muted); font-size: .9rem;
}
.feed-empty-icon { font-size: 2.4rem; margin-bottom: 8px; opacity: .5; }
/* High-contrast themes: keep FLAT, high-contrast feed cards (NO accent tint) so
   the WCAG-AAA palette is preserved — the "E" dark tile is a visual look; the
   a11y themes override it back to a bordered flat card. */
[data-theme="high-contrast"] .feed-card,
[data-theme="high-contrast-max"] .feed-card {
  background: var(--bg); border: 1.5px solid var(--border);
}
[data-theme="high-contrast"] .feed-card::after,
[data-theme="high-contrast-max"] .feed-card::after { display: none; }
[data-theme="high-contrast"] .feed-card:hover,
[data-theme="high-contrast-max"] .feed-card:hover { border-color: var(--accent); }
[data-theme="high-contrast"] .feed-card-title,
[data-theme="high-contrast-max"] .feed-card-title { color: var(--text); }
[data-theme="high-contrast"] .feed-card-meta,
[data-theme="high-contrast-max"] .feed-card-meta { color: var(--muted); }

/* Light theme: text ON the card, which is a committed DARK tile in EVERY theme.
   The tile's background is fixed brand navy, but --accent/--muted/--danger flip with
   the theme, so in light they resolve to values tuned for a white page and land on
   navy. Measured against rgb(14,33,68):

       call to action   #4f46e5   2.53      why disclosure  #64748b   3.34
       urgent badge     #dc2626   3.29      -- WCAG AA needs 4.5

   Unreadable, and invisible unless you switch themes and look. Fixed by giving the
   tile the same colours the default theme already puts on it (5.21-6.20 there), the
   way the high-contrast themes above already override card text for their own
   palette -- rather than by changing the light tokens, which are correct for the
   white surfaces they were chosen for.

   Scoped to .feed-card so only text on the dark tile is affected; the high-contrast
   blocks above still win for those themes, since they flatten the tile entirely. */
[data-theme="light"] .feed-card .hc-cta            { color: #4C9AFF; }
[data-theme="light"] .feed-card .hc-why,
[data-theme="light"] .feed-card .hc-why > summary  { color: #8ea3c4; }
[data-theme="light"] .feed-card .hc-why > summary:hover { color: #4C9AFF; }
[data-theme="light"] .feed-card .hc-prio-urgent    { color: #ff5b52; }
[data-theme="light"] .feed-card .hc-prio-soon      { color: #8ea3c4; }
[data-theme="light"] .feed-card .hc-kind           { color: #4C9AFF; }
[data-theme="light"] .feed-card .hc-dismiss        { color: #8ea3c4; }
[data-theme="light"] .feed-card .feed-card-meta    { color: #8ea3c4; }
/* "This week in the community" card. Sits below the daily-summary card and
   deliberately reads as a piece of writing, not a stat block: generous line-height,
   no borders inside, numbers bolded in place rather than pulled out into figures.
   Colours come from tokens only, so it follows every theme -- including the light
   one, whose --accent-text was the subject of its own fix. */
/* The frame, header, fold caret and grid width all come from .feed-section, which
   is the point -- the panel was previously a bespoke box, and that is exactly why
   it ran wider than its neighbours, sat outside the grid and could not be folded.
   What is left here is only what is genuinely particular to this panel: the prose
   itself, the date, and the link out. */
.cs-card-range {
  font-size: .78rem; color: var(--text); white-space: nowrap;   /* was var(--muted) -- read dim next to the white section title */
}
.cs-body { padding: .9rem 1.1rem; }
.cs-card-body {
  margin: 0; font-size: .9rem; line-height: 1.75; color: var(--text);
}
.cs-card-body strong { color: var(--accent); font-weight: 700; }
/* "Read the full story". A quiet text link rather than a filled button: the card
   is a paragraph, and a solid button in the middle of the feed would compete with
   the real actions around it. */
.cs-card-more {
  margin-top: .6rem; padding: 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: .85rem; font-weight: 600;
  color: var(--accent);
}
.cs-card-more:hover { text-decoration: underline; }
.cs-card-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (max-width: 600px) {
  .cs-body { padding: .8rem .9rem; }
  /* On a phone the date is the first thing to go: the header already carries a
     title and a fold caret, and three items wrap into an awkward second line. */
  .cs-card-range { display: none; }
}

/* ── The full story page (bulletin sub-view) ──────────────────────────────────
   Same voice as the card, more room: one column, measure capped so the paragraph
   stays readable on a wide screen. Logical properties throughout, because this
   renders right-to-left in Hebrew and Arabic and left-to-right in the other 13. */
.cs-page { max-width: 720px; padding: .5rem .25rem 2rem; }
.cs-page-head {
  display: flex; align-items: baseline; gap: .6rem;
  flex-wrap: wrap; margin-bottom: .9rem;
}
.cs-page-title { margin: 0; font-size: 1.25rem; font-weight: 700; color: var(--text); }
.cs-page-range { margin-inline-start: auto; font-size: .85rem; color: var(--text); }   /* was var(--muted) -- same fix as .cs-card-range */
.cs-period-row { display: flex; gap: .4rem; margin-bottom: 1.2rem; flex-wrap: wrap; }
.cs-period {
  padding: .35rem .9rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 999px;
  font: inherit; font-size: .85rem; cursor: pointer;
}
.cs-period:hover { border-color: var(--accent); }
.cs-period.active {
  background: var(--accent);
  /* --accent-text, not a hard-coded white: on the light theme the accent is pale
     enough that white fails contrast, which is what that token exists to fix. */
  color: var(--accent-text); border-color: var(--accent);
}
.cs-period:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cs-page-body {
  margin: 0; font-size: 1rem; line-height: 1.9; color: var(--text);
}
.cs-page-body strong { color: var(--accent); font-weight: 700; }
/* A quiet period is stated plainly rather than dressed up as an error. */
.cs-page-empty {
  margin: 0; padding: 1.5rem 0;
  font-size: .95rem; line-height: 1.7; color: var(--muted);
}
@media (max-width: 600px) {
  .cs-page { padding-inline: 0; }
  .cs-page-range { margin-inline-start: 0; width: 100%; }
  .cs-page-body { font-size: .95rem; line-height: 1.8; }
}

/* Feed card footer — likes + comments badge (F131) */
.feed-card-has-thumb:has(.feed-card-footer) { flex-wrap: wrap; }
.feed-card-footer {
  display: flex; align-items: center; gap: .75rem;
  padding: .35rem 0 0; margin-top: auto;
  width: 100%; font-size: .82rem;
}
.feed-like-btn {
  background: none; border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: .3rem;
  color: #ffffff; font-size: .82rem;
  padding: .15rem .35rem; border-radius: var(--radius, 6px);
  transition: color .15s;
}
.feed-like-btn:hover { color: #ffffff; }
.feed-like-btn.liked { color: #ffffff; }
.feed-like-btn.liked .app-icon { color: #ffffff; }
.feed-comment-badge {
  display: inline-flex; align-items: center; gap: .25rem;
  color: #ffffff; font-size: .82rem;
}
/* ── F076 Community forum / discussion ────────────────────────────────── */
.forum-wrap { padding: 1rem 1.25rem; }
.forum-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-bottom: 1rem; }
.forum-new-btn { display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap; }
.forum-chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.forum-chip {
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  border-radius: 999px; padding: .25rem .8rem; font-size: .82rem; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.forum-chip:hover { border-color: var(--accent); }
.forum-chip.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.forum-list { display: flex; flex-direction: column; gap: .55rem; }
.forum-card {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: 100%;
  text-align: start; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius, 8px); padding: .8rem 1rem; cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}
.forum-card:hover { border-color: var(--accent); box-shadow: 0 1px 6px rgba(0,0,0,.08); }
.forum-card-title { font-weight: 600; color: var(--text); margin-bottom: .2rem; }
.forum-card-meta { font-size: .78rem; color: var(--text); }
.forum-cat-badge {
  display: inline-block; background: rgba(0,0,0,.06); color: var(--accent);
  border-radius: 999px; padding: .05rem .5rem; font-size: .72rem;
}
.forum-card-stats { display: flex; gap: .9rem; color: var(--text); font-size: .82rem; white-space: nowrap; }
.forum-card-stats span { display: inline-flex; align-items: center; gap: .25rem; }
.forum-empty { padding: 2rem; text-align: center; color: var(--muted); }
.forum-back {
  background: none; border: none; color: var(--accent); cursor: pointer; font-size: .9rem;
  display: inline-flex; align-items: center; gap: .3rem; padding: .2rem 0; margin-bottom: .8rem;
}
.forum-topic-title { margin: 0 0 .3rem; font-size: 1.3rem; color: var(--text); }
.forum-topic-body { margin: .9rem 0; color: var(--text); line-height: 1.6; white-space: pre-wrap; }
.forum-topic-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1rem;
  margin: .8rem 0; padding-top: .6rem; border-top: 1px solid var(--border);
}
.forum-sum-btn, .forum-del-btn {
  background: none; border: 1px solid var(--border); border-radius: var(--radius, 6px); cursor: pointer;
  display: inline-flex; align-items: center; gap: .35rem; padding: .3rem .7rem; font-size: .82rem; color: var(--text);
}
.forum-sum-btn:hover { border-color: var(--accent); color: var(--accent); }
.forum-del-btn { color: var(--danger); border-color: transparent; }
.forum-del-btn:hover { border-color: var(--danger); }
/* Locked-discussion banner */
/* UI-0016 (quality-audit): --warning/--warning-rgb were never declared --
   redirected to the already-declared, per-theme-tuned --warn/--warn-rgb. */
.forum-locked-banner {
  display: flex; align-items: center; gap: .4rem;
  margin: .6rem 0; padding: .5rem .8rem; border-radius: var(--radius, 6px);
  background: rgba(var(--warn-rgb), .12);
  color: var(--warn); font-size: .82rem;
}
/* AI summary — collapsible box (default collapsed on topic load) */
.forum-summary-box { margin: .5rem 0 1rem; }
.forum-summary-toggle {
  display: inline-flex; align-items: center; gap: .4rem;
  background: none; border: none; cursor: pointer;
  /* AI Visual Language (WOW-UX review): --ai-accent, not the site's general
     --accent -- this toggle reveals AI-generated content. */
  color: var(--ai-accent); font-weight: 600; font-size: .85rem; padding: .25rem 0;
}
.forum-summary-caret { transition: transform .15s ease; }
.forum-summary[hidden] { display: none; }
.forum-summary-box .forum-summary { margin: .35rem 0 0; }
.forum-summary {
  background: rgba(0,0,0,.04); border: 1px solid var(--border); border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius, 8px); padding: .8rem 1rem; margin: .5rem 0 1rem;
  color: var(--text); line-height: 1.6; font-size: .9rem;
}
/* Reply-to-a-comment (F076): per-comment reply button, quoted parent, compose context bar */
.forum-reply-btn {
  display: inline-flex; align-items: center; gap: .25rem;
  background: none; border: none; cursor: pointer;
  color: var(--text); font-size: .76rem; padding: .1rem .3rem;
}
.forum-reply-btn:hover { color: var(--accent); }
.forum-quote {
  display: block; text-align: start; width: 100%; margin: .1rem 0 .35rem;
  padding: .3rem .55rem; border: none; cursor: pointer;
  border-inline-start: 3px solid var(--accent); border-radius: var(--radius, 8px);
  background: rgba(0,0,0,.04); font-size: .78rem; line-height: 1.35;
}
.forum-quote-author { display: block; font-weight: 600; color: var(--accent); }
.forum-quote-body { display: block; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.forum-quote-deleted { color: var(--muted); font-style: italic; cursor: default; }
.forum-reply-ctx {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem .55rem; border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius, 8px); background: rgba(0,0,0,.04); font-size: .8rem;
}
.forum-reply-ctx-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.forum-reply-ctx-x { background: none; border: none; cursor: pointer; color: var(--muted); padding: .1rem; line-height: 0; }

/* ── @Mention rendering + autocomplete dropdown ── */
.mention { color: var(--accent); font-weight: 600; }
.mention-dropdown {
  position: absolute; z-index: 20; background: var(--surface);
  border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
  max-height: 240px; overflow-y: auto; min-width: 180px; padding: .25rem 0;
}
.mention-dropdown-item {
  display: flex; align-items: center; gap: .5rem;
  padding: .4rem .75rem; cursor: pointer; font-size: .82rem;
  width: 100%; border: none; background: none; color: var(--text); text-align: start;
}
.mention-dropdown-item:hover, .mention-dropdown-item.active {
  background: var(--bg-hover, rgba(0,0,0,.06));
}

/* ── Forum discussion summaries sub-view ── */
.forum-summ-header { display: flex; flex-direction: column; gap: .6rem; margin-bottom: 1rem; }
.forum-summ-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.forum-summ-actions { white-space: nowrap; }
.um-table td a[data-action="forum-open"] { color: #ffffff; }
.forum-summ-actions .forum-sum-btn { margin-inline-end: .25rem; }
/* Summary modal overlay — NO backdrop close (like img-modal-overlay) */
.forum-summary-overlay {
  position: fixed; inset: 0; z-index: 900;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.55); padding: 1rem;
}
.forum-summ-box { max-width: 900px; }
@media (min-width: 641px) {
  .forum-summ-box { min-width: 320px; resize: horizontal; overflow: auto; }
}
.forum-summary-modal-body { max-height: 60vh; overflow-y: auto; }
.forum-summ-meta {
  display: flex; flex-wrap: wrap; gap: .75rem; margin-bottom: .75rem;
  font-size: .82rem; color: var(--muted);
}
.forum-summ-meta span { display: inline-flex; align-items: center; gap: .3rem; }
.forum-summ-section { color: var(--accent); font-size: .95rem; font-weight: 700; margin: .8rem 0 .3rem; }
.forum-summ-content { line-height: 1.65; font-size: .9rem; }
/* UI-0016 (quality-audit): the background was a hardcoded rgba literal AND
   the border used the never-declared --warning -- both now derive from the
   already-declared, per-theme-tuned --warn/--warn-rgb. */
.forum-summ-stale-banner {
  display: flex; align-items: center; gap: .5rem; padding: .5rem .75rem;
  background: rgba(var(--warn-rgb), .12); border: 1px solid var(--warn);
  border-radius: var(--radius, 8px); margin-bottom: .75rem; font-size: .85rem;
  color: var(--text);
}
@media (max-width: 640px) {
  .forum-summ-header { gap: .4rem; }
  .forum-summ-meta { flex-direction: column; gap: .3rem; }
  .forum-summary-modal-body { max-height: 50vh; }
}

/* ── Emoji reactions ── */
.reaction-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; position: relative; }
.reaction-pill {
  display: inline-flex; align-items: center; gap: .15rem;
  padding: .15rem .45rem; border-radius: 999px; font-size: .82rem;
  border: 1px solid var(--border); background: var(--surface); cursor: pointer;
  transition: background .15s; line-height: 1.3;
}
.reaction-pill:hover { background: var(--bg-hover, rgba(0,0,0,.06)); }
.reaction-pill.reacted { border-color: var(--accent); background: rgba(59,130,246,.1); }
.feed-card .reaction-pill { color: #ffffff; }
.reaction-pill.sm { font-size: .72rem; padding: .1rem .35rem; }
.reaction-add {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; font-size: .82rem; color: var(--muted);
}
.reaction-add:hover { background: var(--bg-hover, rgba(0,0,0,.06)); }
.reaction-add.sm { width: 22px; height: 22px; font-size: .72rem; }
.reaction-picker {
  position: absolute; z-index: 25; display: flex; gap: .2rem;
  padding: .3rem .4rem; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border);
  box-shadow: 0 4px 16px rgba(0,0,0,.15);
}
.reaction-picker[hidden] { display: none !important; }
.reaction-picker button {
  border: none; background: none; cursor: pointer; font-size: 1.15rem;
  padding: .15rem; border-radius: 6px; line-height: 1;
}
.reaction-picker button:hover { background: var(--bg-hover, rgba(0,0,0,.06)); }
.comment-reactions { display: flex; flex-wrap: wrap; align-items: center; gap: .2rem; margin-top: .2rem; position: relative; }
.forum-reply-ctx-x:hover { color: var(--danger); }
.forum-flash { animation: forum-flash-kf 1.2s ease; }
@keyframes forum-flash-kf { 0%, 100% { background: transparent; } 30% { background: rgba(128,128,128,.22); } }
/* Detail modal: interaction row + comments */
.fd-interact {
  display: flex; align-items: center; gap: .75rem;
  margin: .75rem 0; padding-top: .5rem;
  border-top: 1px solid var(--border);
}
.fd-interact .feed-like-btn { color: var(--muted); }
.fd-interact .feed-like-btn:hover { color: var(--accent); }
.fd-interact .feed-like-btn.liked { color: var(--accent); }
.fd-interact .feed-like-btn.liked .app-icon { color: var(--accent); }
.fd-comments-area {
  margin-top: .75rem; padding-top: .5rem;
  border-top: 1px solid var(--border);
}
/* Collapsible comment thread — default collapsed to a full-width "תגובות (N)"
   bar, mirrors .ot-group-header exactly (the tickets-list category-group
   accordion) rather than the small rounded .pdf-topics-toggle pill — a
   deliberate visual choice: the comment thread is a full section of its own,
   not a compact inline chip. */
.fd-comments-toggle {
  display: flex; align-items: center; gap: .5rem; width: 100%; font-family: inherit;
  font-size: .85rem; font-weight: 700; color: #fff; text-align: start;
  background: var(--accent); border: none; border-radius: 8px;
  padding: .7rem 1.1rem; cursor: pointer;
}
.fd-comments-toggle i { font-size: .85rem; }
.fd-comments-count {
  margin-inline-end: auto; background: rgba(255,255,255,.2); color: #fff;
  border-radius: 99px; padding: .1rem .55rem; font-size: .75rem; font-weight: 700;
}
.fd-comments-caret { font-size: .7rem; opacity: .7; transition: transform .18s ease; }
.fd-comments-toggle[aria-expanded="true"] .fd-comments-caret { transform: rotate(180deg); }
.fd-comments-body { margin-top: .6rem; }
.fd-comments-body[hidden] { display: none; }
/* High-contrast: feed interaction buttons use theme tokens */
[data-theme="high-contrast"] .feed-like-btn,
[data-theme="high-contrast-max"] .feed-like-btn { color: var(--muted); }
[data-theme="high-contrast"] .feed-like-btn.liked,
[data-theme="high-contrast-max"] .feed-like-btn.liked { color: var(--accent); }
[data-theme="high-contrast"] .feed-comment-badge,
[data-theme="high-contrast-max"] .feed-comment-badge { color: var(--muted); }
[data-theme="high-contrast"] .feed-notif-icon,
[data-theme="high-contrast-max"] .feed-notif-icon {
  background: var(--surface); color: var(--accent);
  border: 1.5px solid var(--border); box-shadow: none;
}
@media (max-width: 980px) {
  /* .feed-grid is single-column at every width now (phase 1.2), so the override that
     used to live here is gone rather than restating the base rule. */
  .feed-section.fs-over-before { box-shadow: inset 0 3px 0 var(--accent); }
  .feed-section.fs-over-after  { box-shadow: inset 0 -3px 0 var(--accent); }
}
@media (max-width: 600px) {
  .feed-cards { grid-template-columns: 1fr; }
  .feed-card { padding: 12px; }
  .feed-grid { padding: 12px 8px 32px; gap: 12px; }
}

[data-icon-style="flat"] .ribbon-item[data-panel="feed"]       .app-icon { color: #3b82f6; }
[data-icon-style="flat"] .ribbon-item[data-panel="info"]       .app-icon { color: #6366f1; }
[data-icon-style="flat"] .ribbon-item[data-panel="regulations"] .app-icon { color: #3b82f6; }
[data-icon-style="flat"] .ribbon-item[data-panel="protocols"]   .app-icon { color: #06b6d4; }
[data-icon-style="flat"] .ribbon-item[data-panel="committees"]  .app-icon { color: #8b5cf6; }
[data-icon-style="flat"] .ribbon-item[data-panel="audit"]       .app-icon { color: #f59e0b; }
[data-icon-style="flat"] .ribbon-item[data-panel="faults"]      .app-icon { color: #ef4444; }
[data-icon-style="flat"] .ribbon-item[data-panel="directory"]   .app-icon { color: #10b981; }
[data-icon-style="flat"] .ribbon-item[data-panel="population"]  .app-icon { color: #14b8a6; }
[data-icon-style="flat"] .ribbon-item[data-panel="votes"]       .app-icon { color: #22c55e; }
[data-icon-style="flat"] .ribbon-item[data-panel="fan"]         .app-icon { color: #f97316; }
[data-icon-style="flat"] .ribbon-item[data-panel="evacuation"]  .app-icon { color: #dc2626; }
[data-icon-style="flat"] .ribbon-item[data-panel="events"]      .app-icon { color: #a855f7; }
[data-icon-style="flat"] .ribbon-item[data-panel="surveys"]     .app-icon { color: #0ea5e9; }
[data-icon-style="flat"] .ribbon-item[data-panel="facilities"]  .app-icon { color: #84cc16; }
[data-icon-style="flat"] .ribbon-item[data-panel="reports"]     .app-icon { color: #f59e0b; }
[data-icon-style="flat"] .ribbon-item[data-panel="search"]      .app-icon { color: #94a3b8; }
[data-icon-style="flat"] .ribbon-item[data-panel="ai"]          .app-icon { color: #6366f1; }
[data-icon-style="flat"] .ribbon-item[data-panel="personal"]    .app-icon { color: #64748b; }
[data-icon-style="flat"] .ribbon-item[data-panel="settings"]    .app-icon { color: #64748b; }
[data-icon-style="flat"] .ribbon-item[data-panel="admin"]       .app-icon { color: #64748b; }

/* Style-set chip UI */
.tm-ss-wrap {
  margin-bottom: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}
.tm-ss-label {
  font-size: .8rem;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: .04em;
  text-transform: uppercase;
  margin-bottom: .55rem;
}
.tm-ss-row {
  display: flex;
  gap: .45rem;
  flex-wrap: wrap;
}
.tm-ss-chip {
  display: flex;
  align-items: center;
  gap: .45rem;
  padding: .4rem .85rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text);
  font-size: .82rem;
  cursor: pointer;
  font-family: inherit;
  transition: border-color .12s, background .12s;
}
.tm-ss-chip:hover { border-color: var(--muted); background: rgba(255,255,255,.04); }
.tm-ss-chip.tm-ss-sel {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 500;
}
.tm-ss-chip .ss-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: .6;
  flex-shrink: 0;
}

/* ══════════════════════════════════════
   Bulletin Board
══════════════════════════════════════ */
.bulletin-admin-wrap { margin-bottom: 1.2rem; }
.bulletin-form {
  margin-top: .8rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: .6rem;
}
.bulletin-form-row { display: flex; flex-direction: column; gap: .25rem; }
.bulletin-form-label { font-size: .83rem; color: var(--muted); font-weight: 500; }

.bulletin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 1rem;
  width: 100%;
}
.bulletin-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: box-shadow .18s;
}
.bulletin-card:hover { box-shadow: 0 4px 18px rgba(0,0,0,.12); }

.bulletin-img-wrap {
  width: 100%;
  height: 180px;
  overflow: hidden;
  background: var(--surface2, var(--bg));
  cursor: zoom-in;
}
.bulletin-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .2s;
}
.bulletin-img-wrap:hover .bulletin-thumb { transform: scale(1.04); }

/* Placeholder shown when a post has no image, so every card is the same height. */
.bulletin-img-empty {
  width: 100%;
  height: 180px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  background: var(--surface2, var(--bg));
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}
.bulletin-img-empty .app-icon { font-size: 2rem; }
.bulletin-img-empty span { font-size: .82rem; }

.bulletin-card-body {
  padding: .85rem 1rem .5rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: .35rem;
}
.bulletin-card-title {
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.3;
}
.bulletin-card-text {
  color: var(--muted);
  font-size: .87rem;
  line-height: 1.45;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}
.bulletin-card-text.expanded {
  display: block;
  overflow: visible;
}
.bulletin-read-more {
  display: none;
  background: none;
  border: none;
  color: var(--accent);
  font-size: .8rem;
  cursor: pointer;
  padding: .1rem 0;
  align-self: flex-start;
  font-weight: 500;
}
.bulletin-card-bottom {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: .15rem;
}
.bulletin-card-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  font-size: .76rem;
  color: var(--text);
  padding-top: .1rem;
}
.bulletin-meta-actions {
  display: flex;
  gap: 2px;
  margin-inline-start: auto;
}

.bulletin-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: .4rem .8rem .6rem;
  border-top: 1px solid var(--border);
  gap: .5rem;
}
.bulletin-like-btn {
  display: flex;
  align-items: center;
  gap: .35rem;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: .88rem;
  padding: .3rem .5rem;
  border-radius: 20px;
  transition: color .15s, background .15s;
}
.bulletin-like-btn:hover { color: var(--accent); background: rgba(var(--accent-rgb, 76,154,255),.08); }
.bulletin-like-btn.liked { color: var(--accent); }
.bulletin-edit-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text);
  padding: 2px 5px;
  border-radius: 5px;
  font-size: .85rem;
  line-height: 1;
  transition: color .15s, background .15s;
}
.bulletin-edit-btn:hover { color: var(--accent); background: rgba(var(--accent-rgb, 79,112,234),.1); }

.bulletin-empty {
  text-align: center;
  padding: 3rem;
  color: var(--muted);
  font-size: .95rem;
}

.bulletin-preview {
  position: fixed;
  z-index: 1500;
  pointer-events: none;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0,0,0,.28);
  border: 2px solid var(--border);
  background: var(--surface);
  width: 600px;
  max-height: 520px;
}
.bulletin-preview img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* ── bulletin: tab bar ───────────────────────────────────────────────────── */
.bulletin-tab-bar {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: .75rem;
  flex-wrap: wrap;
}
.bulletin-tab-sep {
  flex: 1;
}
.bulletin-tab-btn {
  flex: 0 0 auto;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: .35rem .9rem;
  font-size: .85rem;
  cursor: pointer;
  color: var(--muted);
  font-weight: 500;
  white-space: nowrap;
  margin-bottom: -1px;
  transition: color .15s, border-color .15s;
}
.bulletin-tab-btn:hover { color: var(--text); }
.bulletin-tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.bulletin-tab-actions {
  display: flex;
  gap: .5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: .75rem;
}

/* ── bulletin: badges ───────────────────────────────────────────────────── */
.bulletin-sh-badge {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  padding: .15rem .5rem;
  border-radius: 20px;
  letter-spacing: .02em;
}
.bulletin-cat-badge {
  display: inline-block;
  background: none;
  color: var(--muted);
  font-size: .68rem;
  font-weight: 600;
  padding: .15rem .5rem;
  border-radius: 20px;
}
.bulletin-del-badge {
  display: inline-block;
  background: #16a34a;
  color: #fff;
  font-size: .68rem;
  font-weight: 700;
  padding: .15rem .5rem;
  border-radius: 20px;
}
.bulletin-card.delivered { opacity: .7; }

/* ── bulletin: image carousel ───────────────────────────────────────────── */
.bulletin-carousel {
  position: relative;
  width: 100%;
  height: 180px;
  overflow: hidden;
  background: var(--surface2, var(--bg));
}
.bcar-slide { width: 100%; height: 100%; }
.bcar-slide img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.bcar-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0,0,0,.45);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background .14s;
}
.bcar-arrow:hover { background: rgba(0,0,0,.7); }
/* L10N-0053 (quality-audit): was hardcoded left/right with no [dir] override --
   unlike the sibling .fd-carousel-nav, which already handles RTL. Logical
   properties here instead of duplicating that [dir="rtl"] pattern a third time. */
.bcar-prev { inset-inline-start: .4rem; }
.bcar-next { inset-inline-end: .4rem; }

/* Gallery navigation inside the shared image modal — mirrors .bcar-arrow */
.img-modal-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(0,0,0,.45);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 2.4rem;
  height: 2.4rem;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: background .14s;
}
.img-modal-nav:hover { background: rgba(0,0,0,.7); }
/* L10N-0053 (quality-audit): same fix as .bcar-prev/.bcar-next above. */
.img-modal-nav.prev { inset-inline-start: .6rem; }
.img-modal-nav.next { inset-inline-end: .6rem; }
.img-modal-counter {
  position: absolute;
  bottom: .6rem;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0,0,0,.55);
  color: #fff;
  border-radius: 10px;
  padding: .12rem .55rem;
  font-size: .78rem;
  z-index: 3;
}
.bcar-counter {
  position: absolute;
  bottom: .35rem;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0,0,0,.45);
  color: #fff;
  font-size: .7rem;
  padding: .1rem .45rem;
  border-radius: 20px;
}
.bulletin-img-caption {
  position: absolute;
  bottom: 1.8rem;
  left: 0; right: 0;
  background: rgba(0,0,0,.45);
  color: #fff;
  font-size: .72rem;
  text-align: center;
  padding: .18rem .4rem;
}

/* ── bulletin: poster read-only display ─────────────────────────────────── */
.bulletin-poster-info {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-size: .88rem;
  color: var(--text);
  background: var(--surface2, var(--bg));
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: .4rem .7rem;
}

/* ── bulletin: contact / footer actions ─────────────────────────────────── */
.bulletin-contact {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-size: .82rem;
  color: var(--muted);
}
.bulletin-comments-btn,
.bulletin-deliver-btn {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  padding: .3rem .4rem;
  border-radius: 6px;
  font-size: .85rem;
  display: flex;
  align-items: center;
  gap: .3rem;
  transition: color .15s, background .15s;
}
.bulletin-comments-btn:hover { color: var(--accent); background: rgba(var(--accent-rgb, 59,130,246),.08); }
.bulletin-comment-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.2em;
  height: 1.2em;
  padding: 0 .3em;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: .72rem;
  font-weight: 600;
  line-height: 1;
}
.bulletin-deliver-btn:hover,
.bulletin-deliver-btn.active { color: #16a34a; background: rgba(22,163,74,.08); }

/* ── bulletin: comments ─────────────────────────────────────────────────── */
.bulletin-comments-area {
  border-top: 1px solid var(--border);
  padding: .6rem .8rem .8rem;
  background: var(--surface2, var(--bg));
}
.bcomments-list { display: flex; flex-direction: column; gap: .4rem; margin-bottom: .5rem; }
/* Forum comments: avatar column beside the bubble (chat-style; avatar sits on the
   leading/right side under RTL). */
.forum-comment-row { display: flex; gap: .5rem; align-items: flex-start; }
.forum-comment-ava { flex: 0 0 auto; padding-top: .1rem; }
.forum-comment-row .bcomment { flex: 1 1 auto; min-width: 0; }
/* Indent the compose form so it aligns with the comment bubbles (past the avatar column) */
.forum-comment-form { margin-inline-start: calc(32px + .5rem); }

/* ── Recommendations module ("מומלצים") ──────────────────────────────── */
/* sidebar */
.rec-sidebar { min-width: 180px; max-width: 220px; }
.rec-sidebar-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: .6rem .75rem; border-bottom: 1px solid var(--border);
  gap: .4rem;
}
.rec-sidebar-title { font-weight: 600; font-size: .85rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.rec-cat-list { list-style: none; padding: .35rem 0; margin: 0; }
.rec-cat-item { display: flex; align-items: center; justify-content: space-between; gap: .3rem; padding: .45rem .75rem; }
.rec-cat-item-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-cat-del {
  flex: 0 0 auto; background: none; border: none; color: var(--muted); cursor: pointer;
  font-size: .85rem; padding: 0 .15rem; line-height: 1; border-radius: 3px;
  transition: color .12s; display: none;
}
.rec-cat-item:hover .rec-cat-del { display: inline; }
/* A11Y-0022 (quality-audit): the button was tabindex="-1" (out of the tab order
   entirely) with no keyboard-visible reveal -- now that it's a normal tab stop,
   Tab must be able to reveal it too, not just mouse hover. */
.rec-cat-del:focus { display: inline; }
.rec-cat-del:hover { color: var(--danger); }
/* viewer */
.rec-list { display: flex; flex-direction: column; gap: .5rem; padding: .75rem 1rem; }

.rec-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius, 8px); padding: .85rem 1rem;
  margin-bottom: .55rem; transition: border-color .15s, box-shadow .15s;
}
.rec-card:hover { border-color: var(--accent); box-shadow: 0 1px 6px rgba(0,0,0,.06); }
.rec-card.rec-voted { border-inline-start: 3px solid var(--accent); }

.rec-card-head {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .35rem;
}
.rec-provider { font-weight: 600; color: var(--text); font-size: 1rem; }
.rec-cat-badge {
  background: rgba(0,0,0,.06); color: var(--accent);
  border-radius: 999px; padding: .05rem .55rem; font-size: .72rem;
}
.rec-desc { color: var(--text); font-size: .88rem; margin: .25rem 0; line-height: 1.5; }
.rec-phone { color: var(--text); font-size: .82rem; margin: .2rem 0; display: flex; align-items: center; gap: .3rem; }   /* was var(--muted) */

.rec-card-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: .5rem; gap: .5rem; flex-wrap: wrap;
}
.rec-author { font-size: .78rem; color: var(--text); }   /* was var(--muted) */
.rec-actions { display: flex; align-items: center; gap: .4rem; }

.rec-vote-btn {
  display: inline-flex; align-items: center; gap: .3rem;
  background: none; border: 1px solid var(--border); border-radius: var(--radius, 6px);
  padding: .25rem .7rem; font-size: .82rem; color: var(--text); cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.rec-vote-btn:hover { border-color: var(--accent); color: var(--accent); }
.rec-vote-btn--active { border-color: var(--accent); color: var(--text); background: rgba(var(--accent-rgb, 0,0,0),.07); }   /* was color: var(--accent) -- border+background already signal "voted", text reads white like everything else */
.rec-vote-btn:disabled { opacity: .6; cursor: default; }

.rec-edit-btn   { color: var(--muted); border-color: transparent; }
.rec-edit-btn:hover { color: var(--accent); border-color: var(--accent); }
.rec-delete-btn { color: var(--danger); border-color: transparent; }
.rec-delete-btn:hover { border-color: var(--danger); }

/* rec — inline edit form */
.rec-edit-form { padding: .75rem; display: flex; flex-direction: column; gap: .6rem; }
.rec-edit-row  { display: flex; flex-direction: column; gap: .25rem; }
.rec-edit-actions { display: flex; gap: .5rem; margin-top: .25rem; }

/* rec card — image (thumbnail; ot-img sets max-width/height/border; rec-card-img adds margin) */
.rec-card-img { display: block; margin-bottom: .5rem; }
/* rec card — address */
.rec-address { color: var(--text); font-size: .82rem; margin: .2rem 0; display: flex; align-items: center; gap: .3rem; }   /* was var(--muted) */
/* rec form — image input + preview */
.rec-img-input { padding: .35rem .5rem; cursor: pointer; }
.rec-img-preview { margin-top: .4rem; }
.rec-img-preview-img { max-width: 100%; max-height: 160px; border-radius: 6px; object-fit: cover; }
/* rec empty state */
.rec-empty { padding: 2rem; text-align: center; color: var(--muted); }

/* rec — comments button */
.rec-comments-btn { background: none; border: 1px solid var(--border); border-radius: 6px; padding: .25rem .55rem; font-size: .82rem; color: var(--text); cursor: pointer; display: inline-flex; align-items: center; gap: .25rem; transition: border-color .12s, color .12s; }   /* was var(--muted) */
.rec-comments-btn:hover { border-color: var(--accent); color: var(--accent); }
.rec-comments-btn--open { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb,0,0,0),.06); }

/* rec — comments panel */
.rec-comments { display: none; border-top: 1px solid var(--border); margin-top: .5rem; }
.rec-comments--open { display: block; }
.rec-comments-list { padding: .5rem .75rem; display: flex; flex-direction: column; gap: .4rem; }
.rec-no-comments { font-size: .82rem; color: var(--muted); padding: .4rem 0; margin: 0; }
.rec-comment { border-radius: 6px; background: var(--surface-alt, var(--surface)); padding: .45rem .65rem; }
.rec-comment-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .2rem; }
.rec-comment-author { font-weight: 600; font-size: .82rem; color: var(--text); }
.rec-comment-time { font-size: .75rem; color: var(--muted); margin-inline-start: auto; }
.rec-comment-del { background: none; border: none; color: var(--muted); cursor: pointer; font-size: .9rem; padding: 0 .1rem; line-height: 1; margin-inline-start: .3rem; }
.rec-comment-del:hover { color: var(--danger); }
.rec-comment-body { font-size: .85rem; color: var(--text); margin: 0; line-height: 1.5; word-break: break-word; }
.rec-comment-body a { color: var(--accent); text-decoration: underline; word-break: break-all; }
.rec-comment-body a:hover { opacity: .8; }

/* rec — comment form */
.rec-comment-form { display: flex; gap: .4rem; padding: .5rem .75rem; border-top: 1px solid var(--border); align-items: center; }
.rec-comment-input-wrap { flex: 1 1 auto; min-width: 0; position: relative; }
.rec-comment-input { width: 100%; }
.rec-comment-submit { flex: 0 0 auto; padding: .35rem .75rem; border-radius: 6px; border: 1px solid var(--accent); background: var(--accent); color: #fff; font-size: .82rem; cursor: pointer; white-space: nowrap; transition: opacity .12s; }
.rec-comment-submit:hover { opacity: .85; }
.rec-comment-submit:disabled { opacity: .5; cursor: default; }

.bcomment {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: .4rem .65rem;
}
/* Inline comment editing (owner-only): textarea-swap of .bcomment-body */
.bcomment-edit { display: flex; flex-direction: column; gap: .4rem; }
.bcomment-edit-input { width: 100%; resize: vertical; font-size: .85rem; }
.bcomment-edit-actions { display: flex; gap: .4rem; justify-content: flex-end; }
.bcomment-edit-actions button { font-size: .78rem; padding: .25rem .6rem; }
.bulletin-edit-btn { background: none; border: none; cursor: pointer; color: var(--text); }
.bulletin-edit-btn:hover { color: var(--accent); }
.bcomment-meta { display: flex; gap: .5rem; align-items: center; margin-bottom: .15rem; }
.bcomment-author { font-size: .75rem; font-weight: 700; }
.bcomment-date { font-size: .7rem; color: var(--text); }
.bcomment-edited { color: var(--muted); font-size: .7rem; font-style: italic; }
.bcomment-body { font-size: .82rem; color: var(--text); line-height: 1.4; }

/* ── lang-card ──────────────────────────────────────────────────────────── */
.lang-card { background: #fff; border-radius: 14px; box-shadow: 0 2px 16px rgba(0,0,0,.06); padding: 18px 28px; margin-top: 12px; display: none; }
.lang-card label { font-size: .88rem; color: #64748b; display: block; margin-bottom: 8px; }
.lang-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.lang-select { flex: 1; min-width: 160px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; font-size: .9rem; background: var(--bg); color: var(--text); cursor: pointer; }
.lang-saved { font-size: .84rem; color: var(--success); font-weight: 600; display: none; }

/* lang-card flat variant (login page) */
.lang-card.lang-card-flat { background: none; border-radius: 0; box-shadow: none; padding: 12px 0 0; }
.lang-card.lang-card-flat .lang-select { flex: none; width: 100%; }
/* .lang-card label's #64748b is a dark-gray-on-WHITE color, correct for the boxed
   variant's own white background (rsvp.html) -- but the flat variant drops that
   white box and sits directly on the dark page, where the same gray read almost
   illegible. */
.lang-card.lang-card-flat label { color: var(--text); }

/* The ticket form was a fixed `1fr 210px` grid with no breakpoint, so on a
   phone the main column collapsed to ~117px and the category/subject fields
   were unreadable. Stack it instead: sidebar (opener/date/status/submit)
   below the fields it summarises. */
@media (max-width: 767.98px) {
  .ticket-layout { grid-template-columns: 1fr; gap: 1rem; }
  .ticket-row-2  { grid-template-columns: 1fr; gap: .85rem; }
  .ticket-upload-label { flex: 1 1 auto; justify-content: center; }

  /* Picker beside caption leaves the caption ~31px on a 390px screen — far too
     narrow to type in. Stack them, and separate the five rows so it stays
     readable as which caption belongs to which image. */
  .bulletin-img-row {
    flex-direction: column;
    align-items: stretch;
    gap: .4rem;
    padding-bottom: .6rem;
    border-bottom: 1px solid var(--border);
  }
  .bulletin-img-row:last-child { border-bottom: none; }
  .bulletin-img-row .um-input { width: 100%; }
}

/* ── Emergency FAB ───────────────────────────────────────────── */
/* "Coming soon" badge for settings rows that aren't wired up yet */
.stg-badge-soon {
  display: inline-block;
  background: var(--border);
  color: var(--muted);
  border-radius: 20px;
  padding: .05rem .5rem;
  font-size: .68rem;
  font-weight: 600;
  vertical-align: middle;
  margin-inline-start: .35rem;
}

/* .emergency-fab (old floating red FAB) removed — the button moved into the
   ribbon row as .emergency-ribbon-btn (see _body_top.html). */

/* ── Emergency modal ─────────────────────────────────────────── */
.emergency-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.6);
  z-index: 10500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  animation: um-fade-in .15s ease;
}
.emergency-modal-box {
  background: #fff;   /* fixed white card — a critical alert must read in every theme */
  border-radius: 14px;
  width: 100%;
  max-width: 400px;
  box-shadow: 0 8px 40px rgba(0,0,0,.35);
  overflow: hidden;
}
.emergency-modal-header {
  background: #e53935;
  color: #fff;
  padding: 1rem 1.2rem;
  display: flex;
  align-items: center;
  gap: .75rem;
  font-size: 1rem;
  font-weight: 700;
}
.emergency-modal-header i {
  font-size: 1.4rem;
}
/* Bell glyph (same as the ribbon distress button) in the modal header + send button. */
.emergency-modal-header .emg-bell { width: 1.4rem; height: 1.4rem; fill: currentColor; flex-shrink: 0; }
.btn-emergency-send .emg-bell { width: 1.15rem; height: 1.15rem; fill: currentColor; flex-shrink: 0; }
.emergency-modal-body {
  padding: 1.2rem;
}
.emergency-modal-body p {
  margin: 0 0 1.1rem;
  color: #262b36;   /* dark text on the white card (not var(--text), which is light in dark themes) */
  line-height: 1.55;
}
.emergency-modal-footer {
  display: flex;
  gap: .6rem;
  justify-content: flex-end;
  padding: 0 1.2rem 1.2rem;
}
/* Cancel button sits on the white card — muted/border tokens are light in dark
   themes, so pin readable dark-on-white values here. */
.emergency-modal-footer .um-btn-cancel {
  color: #3a4150;
  border-color: #cfd6e0;
}
.emergency-modal-footer .um-btn-cancel:hover {
  color: #1f2733;
  border-color: #9aa6b5;
}
.btn-emergency-send {
  background: #e53935;
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: .6rem 1.2rem;
  font-size: .9rem;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: .4rem;
  transition: background .15s;
}
.btn-emergency-send:hover { background: #c62828; }
.btn-emergency-send:disabled { opacity: .6; cursor: not-allowed; }

/* ── Emergency alert cards ────────────────────────────────────── */
.emergency-alert-card {
  border: 1.5px solid var(--border);
  border-radius: 10px;
  padding: .9rem 1rem;
  margin-bottom: .75rem;
  background: var(--panel-bg, #fff);
  transition: border-color .15s;
}
.emergency-alert-card.is-open {
  border-color: #e53935;
  background: rgba(229,57,53,.04);
}
.emergency-alert-card .ea-header {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-bottom: .45rem;
}
.emergency-alert-card .ea-badge {
  background: #e53935;
  color: #fff;
  border-radius: 20px;
  padding: .1rem .55rem;
  font-size: .75rem;
  font-weight: 700;
}
.emergency-alert-card .ea-badge.closed {
  background: var(--muted);
}
.emergency-alert-card .ea-name {
  font-weight: 700;
  font-size: .95rem;
}
.emergency-alert-card .ea-time {
  color: var(--muted);
  font-size: .8rem;
  margin-inline-start: auto;
}
.emergency-alert-card .ea-location {
  font-size: .85rem;
  color: var(--muted);
  margin-bottom: .5rem;
}
.emergency-alert-card .ea-close-info {
  font-size: .82rem;
  color: var(--muted);
  border-top: 1px solid var(--border);
  padding-top: .45rem;
  margin-top: .45rem;
}
.emergency-filter-bar {
  display: flex;
  gap: .4rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.emergency-filter-bar button {
  border: 1.5px solid var(--border);
  /* was var(--panel-bg, #fff) — --panel-bg is undefined, so it fell back to white,
     making the near-white text invisible. Match the .fan-filter-chip style: a
     theme-aware surface (dark navy in dark, white in light) that reads in both. */
  background: var(--surface);
  border-radius: 20px;
  padding: .3rem .8rem;
  font-size: .82rem;
  cursor: pointer;
  color: var(--text);
  transition: background .15s, border-color .15s;
}
.emergency-filter-bar button.active {
  background: #e53935;
  border-color: #e53935;
  color: #fff;
  font-weight: 700;
}

/* ── Cancel countdown timer ──────────────────────────────────── */
.emergency-banner {
  background: #fdecea;
  border-bottom: 2px solid #e53935;
  padding: .55rem 1rem;
  display: flex;
  align-items: center;
  gap: .75rem;
  font-size: .88rem;
  animation: um-fade-in .2s ease;
}
.emergency-banner .eb-icon {
  color: #c62828;
  font-size: 1.15rem;
  flex-shrink: 0;
}
.emergency-banner .eb-title {
  color: #7f1d1d;
  font-weight: 600;
}
.emergency-banner .eb-timer {
  color: #c62828;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  min-width: 34px;
}
.emergency-banner .eb-spacer { flex: 1; }
.emergency-banner button {
  background: #e53935;
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: .32rem .9rem;
  font-size: .82rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}
.emergency-banner button:hover { background: #c62828; }
@media (max-width: 500px) {
  .emergency-banner { padding: .5rem .6rem; gap: .5rem; font-size: .8rem; }
  .emergency-banner .eb-title { font-size: .8rem; }
}

/* ── Reduced motion (WCAG 2.3.3) ─────────────────────────────────────────
   Two independent triggers, same catch-all rules:
     (1) OS preference — @media (prefers-reduced-motion: reduce)
         (Windows: Settings → Accessibility → Animation effects OFF;
          macOS: System Settings → Accessibility → Display → Reduce motion).
     (2) In-app override — [data-motion="reduce"] on <html>, stamped by the
         template when the user picked "always off" in Personal Settings,
         so viewers who don't know the OS toggle still get relief.
   The two triggers coexist:  system  = only (1) fires;  on  = (2) is stamped
   regardless of OS; off = neither, plain-vanilla motion.
   Three earlier scoped `@media (prefers-reduced-motion: reduce)` blocks
   stay in place and coexist: the emergency ribbon halo (@962), a dashboard
   fadeUp section (@5175), and the report bar/donut grow-ins (@5963). Those
   set `animation:none` on specific selectors and agree with the catch-all
   below (they're stricter — no conflict). */
@media (prefers-reduced-motion: reduce) {
  /* Kill decorative animations — infinite pulses, splash/skeleton bounces,
     fadeUp/slide-in reveals on every panel/modal open, tooltip enters,
     donut/bar grow-ins, tour/callout entries. */
  html:not([data-motion="full"]) *, html:not([data-motion="full"]) *::before, html:not([data-motion="full"]) *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Loading spinners — keep visible motion so users know work is happening.
     A gentle 2s rotation is a documented reduce-motion-friendly pattern
     (a static ring reads as broken). */
  html:not([data-motion="full"]) .ph-spin,
  html:not([data-motion="full"]) [class*="ip-spin"],
  html:not([data-motion="full"]) .app-icon.ph-spin {
    animation-duration: 2s !important;
    animation-iteration-count: infinite !important;
  }
  /* The app's OWN loader. _spin() renders .sp-bounce from 49 call sites and
     #page-loader uses it for the very first paint, but only ph-spin/ip-spin were
     exempted above -- so the catch-all collapsed it to 0.01ms and one iteration and
     every "saving..." button and loading region showed three frozen dots. That is
     precisely the "a static ring reads as broken" failure the note above was written
     to prevent, on the one indicator that matters most.
     It does NOT get its bounce back: sp-bounce translates 7px, and displacement is
     the vestibular trigger. sp-fade carries the same signal with none of it. The
     nth-child stagger survives untouched -- the catch-all never sets
     animation-delay -- so the dots still cascade. */
  html:not([data-motion="full"]) .sp-bounce i {
    animation-name: sp-fade !important;
    animation-duration: 1.4s !important;
    animation-iteration-count: infinite !important;
  }
}
[data-motion="reduce"] *,
[data-motion="reduce"] *::before,
[data-motion="reduce"] *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  scroll-behavior: auto !important;
}
[data-motion="reduce"] .ph-spin,
[data-motion="reduce"] [class*="ip-spin"],
[data-motion="reduce"] .app-icon.ph-spin {
  animation-duration: 2s !important;
  animation-iteration-count: infinite !important;
}
/* Same exemption for the in-app toggle. The two triggers must carry the identical
   exempt set or turning motion off in Personal Settings reintroduces the frozen
   loader that the OS path just stopped producing. Guarded by
   tests/test_reduced_motion_progress_indicators.py. */
[data-motion="reduce"] .sp-bounce i {
  animation-name: sp-fade !important;
  animation-duration: 1.4s !important;
  animation-iteration-count: infinite !important;
}

/* ── Mobile: proc-viewer layout overrides (migrated from _body_top.html inline <style> — H1 PR4) ── */
/* These rules must come after the body.is-mobile section above to win same-specificity
   !important conflicts; they were previously in an inline <style> in <body>. */
/* A percentage height needs a definite height on every ancestor, and .proc-wrap sits
   inside .content-area > .panel, both plain blocks. Give a definite height to exactly
   the chains that contain one -- :has() keeps every other module's panel on auto, where
   it scrolls inside #appMain as before. */

/* height:100% rather than calc(100dvh - 200px). The 200px was the chrome above this
   wrap when the rule was written, and it stopped being true the moment #ribbonWrap
   stopped reserving 314px of flow: measured at 360x740, .proc-wrap got 540px inside an
   #appMain that offered 628px, leaving 88px of dead space under the document viewer on
   every phone. Deriving it from the parent means the next change to the top bar or the
   status bar does not silently re-open the same gap. */
/* Touch ergonomics belong to the INPUT device, not to the phone build.
   touch-action:manipulation suppresses the ~300ms double-tap-to-zoom delay, and the tap
   highlight is the visual acknowledgement a finger needs and a mouse does not. Keyed on
   [data-pointer="coarse"] (set in app.js beside data-vp) rather than body.is-mobile, so a
   touch-screen laptop gets them for the first time and a phone driving an external mouse
   does not. No !important needed once the rule is not fighting the block above it. */
[data-pointer="coarse"] .proc-sidebar .proc-item,
[data-pointer="coarse"] .regs-tree-doc,
[data-pointer="coarse"] .regs-tree-header {
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(0,0,0,.08);
}
.mob-back-fab { display:none; }
body.is-mobile:has(.proc-wrap.mob-viewing) .mob-back-fab { display:flex !important; position:fixed; bottom:70px; inset-inline-end:16px; z-index:9999; width:44px; height:44px; border-radius:50%; background:var(--accent,#2563eb); color:#fff; border:none; cursor:pointer; font-size:1.1rem; box-shadow:0 2px 8px rgba(0,0,0,.35); align-items:center; justify-content:center; }



/* ── Vehicle accessibility badges ── */
/* UI-0016 (quality-audit): --info/--info-bg/--warning-bg/--warning-dark were
   never declared anywhere in this file -- every one of these var() calls
   always silently rendered its hardcoded light-pastel fallback regardless of
   theme, so these badges never actually adapted to dark mode (the earlier
   UI-0007 fix that introduced them never really worked). No blue "info"
   token exists in the palette, but --accent already IS blue/cyan-ish in 3 of
   4 themes and is the established fold-target for secondary hues in the 2
   high-contrast themes (see --notif-purple/--notif-blue above) -- reuse it
   instead of inventing a new, untested token. --warn is already declared and
   tuned in all 4 themes. Both derive their background wash via color-mix,
   the same technique already used elsewhere in this file (vehicles.js's
   timeline-reload overlay). */
/* A11Y-0134 (quality-audit): the timeline's date-jump input is borderless/
   transparent by design (blends into the sticky header row) -- its inline style
   suppressed the focus outline with nothing standing in for it. A plain outline
   on focus doesn't disturb the blended unfocused look. */
.veh-timeline-date-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.veh-badge { display:inline-flex; align-items:center; gap:.3rem; font-size:.75rem; padding:.2rem .5rem; border-radius:999px; font-weight:500; }
.veh-badge-access { background:color-mix(in srgb, var(--accent) 15%, var(--surface)); color:var(--accent); }
.veh-badge-child  { background:color-mix(in srgb, var(--warn) 15%, var(--surface)); color:var(--warn); }


/* ══════════════════════════════════════════════════════════════════════════
   MOBILE FOUNDATION  (phase 1)
   Everything below is inside a compact-width media query, so desktop rendering
   is byte-for-byte unchanged. Appended at the end of the file deliberately:
   the body.is-mobile block above wins by source order, and these rules must be
   able to win over it in turn.
   ══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 767.98px) {

  /* ── Modals keep their margin on a phone ─────────────────────────────────
     .um-modal-box declares `width: 420px; max-width: 95vw`, but 79 modal boxes
     across 15 files (templates/partials/_modals_all.html, _modals_shared.html,
     _body_top.html, _feedback.html, and template literals in app.js,
     broadcast.js, directory.js, events.js, facilities.js, fan.js, feed.js,
     forum.js, notifications.js, settings.js, vehicles.js) override max-width
     INLINE, and inline beats a class rule. Measured on a 360px phone: the
     confirm/prompt boxes compute max-width 420px instead of 342px.

     What that costs is a margin, NOT a broken layout -- worth being precise,
     because the first read of this said "every dialog scrolls the page
     sideways" and the browser says otherwise. .um-modal-overlay is a centring
     flex container, so it clamps an over-wide box to the viewport rather than
     letting it overflow: document scrollWidth stays equal to innerWidth. The
     visible defect is that the box renders edge-to-edge at 360px instead of the
     342px the author asked for, so it touches both screen edges.

     One !important rule restores that for all 79 without editing any of them:
     an author !important declaration outranks an inline one that is not itself
     !important, and none of the 79 are.

     CONSTRAIN max-width, NEVER width. showAlert() sets `width` INLINE WITH
     !important (app.js:333 and :351) -- the one declaration a stylesheet cannot
     outrank -- but max-width clamps width regardless, so capping max-width works
     where capping width would not. `max-width: none` here would undo all of it.

     The value is the 95vw the base rule already asked for; this restores the
     author's own intent rather than inventing a new one. Full-bleed sheets are
     a later phase. */
  .um-modal-box {
    max-width: 95vw !important;
  }

  /* ── Stop iOS zooming on every field ─────────────────────────────────────
     Mobile Safari auto-zooms when a focused input's font-size is under 16px, and
     it does NOT zoom back out afterwards -- the user is left on a magnified,
     sideways-scrolling page and has to pinch out by hand. It happens on every
     form in the app, and nobody reports it as a bug because it reads as "phones
     are just like that".

     16px is the threshold, not a preference, so this is a floor rather than a
     size: anything already larger keeps its own. Compact widths only, so desktop
     typography is untouched. */
  input, select, textarea {
    font-size: max(16px, 1em);
  }

  /* Anything anchored to the bottom rides above the keyboard rather than under
     it, and the floating buttons get out of the way entirely -- a FAB over an
     open keyboard is never what anyone wants. --kb is written by app.js from
     visualViewport; it is 0px until a keyboard actually opens. */
  .um-modal-footer,
  .status-bar {
    transform: translateY(calc(-1 * var(--kb, 0px)));
    transition: transform .15s ease;
  }
  html.kb-open .dap-fab,
  html.kb-open .feedback-fab,
  html.kb-open .a11y-fab,
  html.kb-open .emergency-ribbon-btn {
    display: none;
  }

}

/* ── AI chat input: stacked on mobile (RPT-000011) ────────────────────────
   .ai-input-row is a single flex ROW (new-chat button + textarea + send
   button, all inline) with NO responsive override anywhere in this file --
   on a ~384px phone the textarea was squeezed to almost nothing, and
   body.ai-chat-open's 90px padding-inline-end (reserved so the row doesn't
   sit under the fixed .dap-fab rail) alone ate ~23% of the screen width.
   Wrapped so the textarea gets its own full-width row; the buttons drop to a
   row below it. The FAB-clearing padding moves to that button row (still the
   row nearest the fixed .dap-fab) instead of the whole flex row, so the
   textarea itself gets nearly the full screen width. Desktop (>767.98px) is
   untouched -- same rule as every other block in this media query. */
@media (max-width: 767.98px) {
  .ai-input-row {
    flex-wrap: wrap;
    padding-inline-end: 1rem !important;
  }
  .ai-input {
    flex-basis: 100%;
    min-height: 3.2rem;
  }
  .ai-input-row > .ai-new-chat-btn,
  .ai-input-row > #aiSendBtn {
    flex: 1;
  }
  body.ai-chat-open .ai-input-row {
    padding-inline-end: 1rem;
  }
  body.ai-chat-open .ai-input-row > #aiSendBtn {
    margin-inline-end: 90px;
  }
}

/* ── Documents viewer: stacked layout ─────────────────────────────────────
   Moved out of `body.is-mobile` (the user-agent sniff) into the width axis, which is
   what these rules were always about: at this width the sidebar and the viewer cannot
   sit side by side, on a phone or in a narrow desktop window alike. The block they came
   from carried a comment saying it "must come after the body.is-mobile section above to
   win same-specificity !important conflicts" -- that ordering war is over, because the
   competing rules were dead and have been deleted.

   `!important` is kept for now. Dropping `body.is-mobile` lowers specificity from (0,2,1)
   to (0,1,0), so removing both at once would be two changes at a time; the second is its
   own commit with its own measurement.

   The .mob-back-fab rules stay on body.is-mobile deliberately: a back affordance exists
   because the phone build has no browser chrome to go back with, which is a device fact,
   not a width one. */
@media (max-width: 767.98px) {
  #appMain { padding: 0 !important; }
  .panel:has(.proc-wrap),
.content-area:has(.proc-wrap) { height: 100% !important; }
  .proc-wrap { flex-direction: column !important; gap: 0 !important; height: 100% !important; overflow: hidden !important; }
  .proc-sidebar { width: 100% !important; max-width: 100% !important; height: 100% !important; max-height: none !important; overflow-y: auto !important; border-radius: 0 !important; border: none !important; flex-shrink: 0 !important; }
  #regsListEl { overflow-y: visible !important; }
  .proc-viewer-wrap { width: 100% !important; height: 100% !important; overflow-y: auto !important; display: none !important; }
  .proc-wrap.mob-viewing .proc-sidebar { display: none !important; }
  .proc-wrap.mob-viewing .proc-viewer-wrap { display: flex !important; flex-direction: column !important; }
}


/* ══════════════════════════════════════════════════════════════════════════
   MOBILE FAB CLUSTER
   ══════════════════════════════════════════════════════════════════════════
   Four floating buttons stacked along the trailing edge cost 4x48 + 3x12 =
   228px of screen height -- about a quarter of a phone screen, permanently,
   over the content. Collapsed into one trigger that is 44px.

   Mobile only. On desktop the distress button is not floating at all: it sits
   inside the ribbon row with position:static, and _adjustFabStack() already
   skips any member whose computed position is not fixed. Everything below is
   scoped to body.is-mobile so the desktop layout is untouched.

   The member buttons keep their own ids and their own markup in their own
   partials -- _panel_dap.html, _body_top.html, _a11y_widget.html,
   _feedback.html. This only repositions them, so every getElementById in
   dap.js / broadcast.js / app.js keeps working.                            */

body.is-mobile .fab-cluster {
  position: fixed;
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px));
  z-index: 9991;
  width: 48px;
  height: 48px;
  /* Positioned from the top so the drag maths is one coordinate space, and
     clamped by JS inside the safe areas rather than by a bottom offset. */
  transition: top .28s cubic-bezier(.2,.8,.2,1);
}

body.is-mobile .fab-cluster-trigger {
  position: absolute;
  inset: 0;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  padding: 0;
  cursor: grab;
  background: var(--accent);
  color: var(--accent-text, #fff);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(0,0,0,.45);
  z-index: 2;
  /* Only the trigger opts out of native gestures -- page scrolling everywhere
     else is unaffected. */
  touch-action: none;
  transition: transform .2s, box-shadow .2s;
}
body.is-mobile .fab-cluster-trigger:active { cursor: grabbing; }
body.is-mobile .fab-cluster-trigger .app-icon { font-size: 1.25rem; transition: transform .2s; }
body.is-mobile .fab-cluster.is-open .fab-cluster-trigger .app-icon { transform: rotate(45deg); }

/* A red rim when the distress button is one of the members, so the collapsed
   state still signals that distress lives in here. Driven by a class rather
   than :has() so it works the same on every supported browser. */
body.is-mobile .fab-cluster.has-sos .fab-cluster-trigger::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid var(--danger);
  opacity: .6;
  pointer-events: none;
}

/* Members. JS sets --fab-y per member; the collapsed state parks them all
   under the trigger. */
body.is-mobile .fab-cluster-member {
  position: fixed !important;
  inset-inline-end: calc(var(--fab-inset, 16px) + var(--fab-gutter, 0px)) !important;
  bottom: auto !important;
  top: var(--fab-top, 0px) !important;
  z-index: 9990;
  opacity: 0;
  pointer-events: none;
  transform: translateY(0) scale(.4);
  transition: opacity .15s, transform .24s cubic-bezier(.2,.9,.3,1.15);
}
/* Keyed off a BODY class, not `.fab-cluster.is-open .fab-cluster-member`. The
   members are never moved into #fabCluster -- _clusterBuild() appends a wrapper
   holding only the trigger, and _clusterLayout() just adds the class to the
   buttons where they already sit on <body>. So the descendant form matched zero
   elements and the group never opened: tapping the trigger left all four at
   opacity 0 / pointer-events none, distress included. Same reason this is not
   `:has()` -- see the has-sos note above. */
body.is-mobile.fab-cluster-open .fab-cluster-member {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(var(--fab-y, 0px)) scale(1);
}

/* Backdrop: catches the tap that closes the group, and dims the page enough
   that the expanded buttons read against a busy feed. */
body.is-mobile .fab-cluster-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9989;
  background: rgba(0,0,0,.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s;
}
body.is-mobile .fab-cluster-backdrop.is-open { opacity: 1; pointer-events: auto; }

/* CSP phase 2: was onmouseover/onmouseout inline (dead under CSP) toggling
   background between the two navy shades. */
.session-expired-login-btn {
  background: #12294c; color: #fff; border: none;
  padding: .65rem 2rem; border-radius: 8px; font-size: .95rem;
  cursor: pointer; font-family: inherit; transition: background .15s;
}
.session-expired-login-btn:hover { background: #274a7d; }

@media (prefers-reduced-motion: reduce) {
  html:not([data-motion="full"]) body.is-mobile .fab-cluster,
  html:not([data-motion="full"]) body.is-mobile .fab-cluster-member,
  html:not([data-motion="full"]) body.is-mobile .fab-cluster-backdrop { transition-duration: .01ms; }
}

/* ── Trip modal: which car, what the odometer last read, when it is due back ──
   All three answer questions a driver has while standing at the vehicle, and none of
   them were on the screen that asks for a number. The identity line matters most on
   the QR path: you scanned a sticker on a windscreen and are about to record an
   odometer reading against whatever it pointed at. */
.veh-trip-vehicle {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  padding-bottom: .5rem; border-bottom: 1px solid var(--border);
}
.veh-trip-name { font-weight: 600; color: var(--text); }
.veh-trip-plate {
  font-size: .78rem; color: var(--muted);
  padding: .1rem .4rem; border: 1px solid var(--border); border-radius: 4px;
  font-variant-numeric: tabular-nums;   /* a plate is digits; keep them even */
}
.veh-trip-note { font-size: .78rem; color: var(--muted); }
.veh-trip-note:empty { display: none; }   /* before the lookup answers, take no space */
.veh-trip-note-warn { color: var(--warn); font-weight: 600; }

/* The deadline line now carries an action, so it has to lay two things out. It keeps
   working as a bare text node (the start screen passes no button) because an empty
   flex row collapses exactly as the :empty rule above intends. */
#vehTripDeadline { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.veh-extend-btn {
  font: inherit; font-size: .78rem; font-weight: 600;
  color: var(--accent); background: none;
  border: 1px solid var(--accent); border-radius: 999px;
  padding: .12rem .6rem; cursor: pointer;
  /* 44px is the touch target this app settled on; the pill itself stays small, so the
     hit area is grown with padding-free spacing rather than by inflating the visual. */
  min-height: 30px;
}
.veh-extend-btn:hover { background: var(--accent); color: #fff; }
.veh-extend-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The dialog's width lives here rather than inline: an inline max-width overrides the
   responsive cap that .um-modal-box already carries, so the box would overflow a phone
   -- which is what tests/test_inline_modal_width_ratchet.py exists to prevent. */
.prof-assign-box { max-width: 560px; width: 100%; }

/* Bulk-assign users to a profile. A scrolling list of rows inside a modal, so the box
   itself must not grow with the community -- the list scrolls, the dialog does not. */
.prof-assign-list {
  max-height: 320px; overflow-y: auto;
  border: 1px solid var(--rule, var(--border)); border-radius: 8px;
  background: var(--surface2, var(--soft)); margin-top: .5rem;
}
.prof-assign-row {
  display: flex; align-items: center; gap: .5rem;
  padding: .38rem .6rem; font-size: .84rem; cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.prof-assign-row:last-child { border-bottom: none; }
.prof-assign-row:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
/* Pinned so it stays reachable while the list scrolls -- a select-all you have to
   scroll back up to find is a select-all nobody uses. */
.prof-assign-all {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface, var(--card)); font-weight: 600;
}
.prof-assign-name { font-weight: 600; }
.prof-assign-user { color: var(--muted); font-size: .78rem; }
.prof-assign-has {
  margin-inline-start: auto; color: var(--muted); font-size: .72rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%;
}
.prof-assign-empty { padding: 1rem; text-align: center; color: var(--muted); font-size: .85rem; }
.prof-assign-note { margin-top: .5rem; font-size: .8rem; color: var(--muted); }
.prof-assign-hint { margin-top: .2rem; font-style: italic; }

/* The on-demand trip record under a booking row. Read-only: fix-mileage already
   exists for correcting a trip, and a second editing surface is a second place for the
   same rules to drift. */
.veh-det {
  padding: .6rem .95rem .75rem calc(.95rem + 3px);
  background: color-mix(in srgb, var(--accent) 4%, var(--surface));
  border-bottom: 1px solid var(--border);
  font-size: .82rem;
}
.veh-det-grid { display: flex; flex-wrap: wrap; gap: .3rem 1.6rem; }
.veh-det-item { display: inline-flex; gap: .4rem; align-items: baseline; }
.veh-det-k { color: var(--muted); font-size: .76rem; }
.veh-det-v { font-weight: 600; font-variant-numeric: tabular-nums; }
/* The driver's own words -- given room to wrap rather than squeezed onto the grid row,
   because this is the one field here that is a sentence and not a value. */
.veh-det-notes {
  display: flex; gap: .4rem; align-items: baseline; margin-top: .45rem;
  padding-top: .45rem; border-top: 1px dashed var(--border);
}
.veh-det-note-body { white-space: pre-wrap; font-style: italic; }
.veh-det-btn i { transition: transform .15s; }
/* Gated on html:not([data-motion="full"]) so the in-app "full motion" setting can still
   win over the OS preference -- round-13 L5, the shape every other reduce block here
   uses. The companion line below is the in-app "reduce" half. */
@media (prefers-reduced-motion: reduce) { html:not([data-motion="full"]) .veh-det-btn i { transition: none; } }
html[data-motion="reduce"] .veh-det-btn i { transition: none; }

/* The fault report. Same body-not-footer placement as the extend button, and
   deliberately NOT the same colour: --danger against extend's --accent, so the two
   inline actions on this screen never read as a pair. */
.veh-trip-fault { display: flex; margin-top: .1rem; font-size: .78rem; color: var(--muted); }
.veh-fault-btn {
  font: inherit; font-size: .78rem; font-weight: 600;
  display: inline-flex; align-items: center; gap: .3rem;
  color: var(--danger); background: none;
  border: 1px solid var(--danger); border-radius: 999px;
  padding: .12rem .6rem; cursor: pointer; min-height: 30px;
}
.veh-fault-btn:hover { background: var(--danger); color: #fff; }
.veh-fault-btn:focus-visible { outline: 2px solid var(--danger); outline-offset: 2px; }

/* The manager's stranded-bookings notice, above the all-reservations table. */
.veh-stranded-banner {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border-inline-start: 3px solid var(--warn);
  border-radius: 0 6px 6px 0; padding: .6rem .8rem; margin-bottom: .6rem;
  font-size: .86rem;
}
.veh-stranded-banner button {
  font: inherit; font-weight: 600; color: var(--warn); background: none;
  border: 1px solid var(--warn); border-radius: 6px;
  padding: .2rem .7rem; cursor: pointer; min-height: 30px;
}
.veh-stranded-banner button:hover { background: var(--warn); color: #fff; }
.veh-stranded-banner button:focus-visible { outline: 2px solid var(--warn); outline-offset: 2px; }

.veh-extend-opts { display: flex; flex-direction: column; gap: .1rem; }
.veh-extend-opt {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .4rem; border-radius: 8px; cursor: pointer;
  min-height: 44px; box-sizing: border-box;
}
.veh-extend-opt:hover { background: var(--hover-bg, rgba(128,128,128,.08)); }
.veh-extend-opt input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }
