/* ─── Veterinary Clinic — Custom Theme ──────────────────────────────────────── */

:root {
  /* The skin tokens (--vs-*) and their classic defaults live in assets/theme-base.css; a clinic's or the platform's
     skin file (uploads/brand/…/theme-<sha8>.css) redefines them after this file. These legacy names stay as
     aliases so the ~100 rules below — and any .js reading them — need no change
     (docs/rebranding-and-skins/03-skins.md §2). --vc-green-light is the lighter brand fill (≈ the former lighter button green);
     the brand-vs-status reclassification of the rules using it is tracked in 03-skins.md S0 item 5. */
  --vc-green:       var(--vs-primary);
  --vc-green-light: var(--vs-primary-light);
  --vc-green-pale:  var(--vs-primary-subtle);
  --vc-teal:        var(--vs-accent);
  --vc-bg:          var(--vs-page-bg);
}

html { height: 100%; font-size: var(--vs-font-size-base); }
body {
  background: var(--vc-bg);
  color: var(--vs-text);
  display: flex;
  flex-direction: column;
  min-height: 100%;
  font-family: var(--vs-font-body);
}
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--vs-font-heading);
  font-weight: var(--vs-heading-weight);
}

/* ─── Links, tabs & form controls (green theme, not Bootstrap's default blue) ── */
a {
  color: var(--vs-link);
}
a:hover,
a:focus {
  color: var(--vs-link-hover);
}

/* Inactive nav-tabs/nav-pills links (e.g. doctor/cabinet.php tabs) — Bootstrap
   defaults these to link-blue; the active state is already dark-on-white via
   Bootstrap's own more specific .nav-tabs .nav-link.active rule, untouched here. */
.nav-link {
  color: var(--vs-link);
}
.nav-link:hover,
.nav-link:focus {
  color: var(--vs-link-hover);
}

/* Bootstrap renders checked checkboxes/radios via appearance:none + an SVG
   background-image tied to --bs-primary (blue) — accent-color alone can't
   reach those, so override the Bootstrap variables/state directly too. */
input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--vs-control);
}
/* checked / indeterminate / focus states of .form-check-input are in assets/theme-base.css (Part 2c) */

/* ─── Navbar ─────────────────────────────────────────────────────────────────── */
.vc-navbar {
  background-color: var(--vs-header-bg);
  background-image: var(--vs-header-bg-image);
  border-bottom: 1px solid var(--vs-header-border);
  box-shadow: var(--vs-header-shadow);
}
/* Uploaded clinic logo (admin/clinic_settings.php), shown in place of the
   bandaid icon — capped to the icon's rough footprint so a wide or tall
   upload never blows out the navbar's height. */
/* header.nav_icons = off: icons drop out of the menu (docs/rebranding-and-skins/03-skins.md §1) */
.vc-navbar.vc-no-nav-icons .navbar-nav .nav-link > i.bi,
.vc-navbar.vc-no-nav-icons .navbar-nav .dropdown-item > i.bi { display: none; }
.vc-navbar-logo { height: var(--vs-logo-height); max-width: calc(var(--vs-logo-height) * 5); width: auto; object-fit: contain; vertical-align: -6px; }
/* The global `a`/`.nav-link` green-text rules above are meant for the white
   page body, not this already-green bar — on a green background they read as
   near-invisible dark-on-dark. Keep navbar text white/light, matching
   Bootstrap's own .navbar-dark default that those rules had overridden. */
.vc-navbar .nav-link,
.vc-navbar .navbar-brand {
  color: var(--vs-header-fg);
}
/* :not(.btn) — a plain nav-link should dim slightly on hover, but a few nav
   items (e.g. the "Регистрация" outline button) are ALSO .btn-outline-light,
   whose own hover state swaps to a white background with dark text; without
   this exclusion the rule above out-specifies Bootstrap's button hover color
   and leaves white text on that white background. */
.vc-navbar .nav-link:not(.btn):hover,
.vc-navbar .nav-link:not(.btn):focus,
.vc-navbar .navbar-brand:hover,
.vc-navbar .navbar-brand:focus {
  color: var(--vs-header-fg-muted);
}
/* A clinic can enable enough nav groups (includes/admin_nav.php — item count
   is data-driven, no fixed cap) that even the expanded (>=992px,
   navbar-expand-lg) row of top-level items doesn't fit one line on an
   actually-narrow "wide" screen (a laptop, not an ultrawide monitor). Bootstrap's
   un-wrapped flex row then overflows past .vc-navbar's own painted background
   — the nav items keep rendering into that overflow, but the green background
   stops at the bar's real (unexpanded) width, so scrolling right shows them
   on the bare white page background instead. flex-wrap turns that overflow
   into extra rows *inside* the bar instead — nothing ever renders outside its
   background, at any item count. */
.vc-navbar .navbar-nav {
  flex-wrap: wrap;
}
/* Packed layout (icon above label, smaller type) so more items fit per row
   before wrapping — a heavily-customized nav needs 1-2 rows like this
   instead of 3+ at the normal side-by-side size. Applied by assets/nav_fit.js
   only once it's actually measured that the roomy (side-by-side) layout
   doesn't fit in one row at the current width — a fixed width range can't
   tell that on its own, since it depends on how many groups THIS admin has
   enabled, not just viewport width: a wide screen with many groups may need
   it, a narrow-ish screen with few groups may not. Below the collapse
   breakpoint (navbar-expand-lg, <992px) it's the vertical hamburger menu
   and nav_fit.js leaves this class off — side-by-side there is fine either
   way, plenty of width once stacked vertically. */
.vc-navbar.nav-compact .navbar-nav .nav-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .1rem;
  font-size: .72rem;
  padding-left: .5rem;
  padding-right: .5rem;
  line-height: 1.1;
}
.vc-navbar.nav-compact .navbar-nav .nav-link i {
  font-size: 1rem;
  /* icon sits above the label now — drop the beside-label `me-1` gap so it
     stays centered over the text. */
  margin-right: 0 !important;
}

/* Right-hand group (search + the signed-in user): ONE line always, search to the left of the user icon. A long name (a support
   login, «Служба поддержки…») used to push the search icon onto its own row; now the group stays put and the NAME is cropped
   with an ellipsis (full name = the link's hover title). In the icons-only layout the name is dropped altogether. */
.vc-navbar #mainNav .navbar-nav:not(.me-auto) { flex-wrap: nowrap; min-width: 0; }
.vc-navbar #mainNav .navbar-nav:not(.me-auto) > .nav-item { min-width: 0; }
.vc-navbar .vc-user-link { display: flex; align-items: center; min-width: 0; }
.vc-navbar .vc-user-link > i.bi { flex: none; }
.vc-navbar .vc-user-name { flex: 0 1 auto; min-width: 0; max-width: 11rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Icons only (assets/nav_fit.js, tried before the compact layout when the roomy one wraps): the label's text node cannot be
   targeted, so the link's font-size is zeroed and the icon / caret / badge get their own sizes back. The name stays in the DOM
   (screen readers) and is shown on hover through the link's title attribute (nav_fit.js sets it; the user entry always has one). Covers
   the right-hand group too: search + the user's icon. */
.vc-navbar.nav-icons-only #mainNav .navbar-nav > .nav-item > .nav-link {
  font-size: 0;
  padding-left: .45rem;
  padding-right: .45rem;
}
.vc-navbar.nav-icons-only #mainNav .navbar-nav > .nav-item > .nav-link > i.bi {
  font-size: 1.2rem;
  margin-right: 0 !important;
}
.vc-navbar.nav-icons-only #mainNav .navbar-nav > .nav-item > .nav-link.dropdown-toggle::after {
  border-top-width: .3rem;
  border-left-width: .3rem;
  border-right-width: .3rem;
  margin-left: .3rem;
}
.vc-navbar.nav-icons-only #mainNav .navbar-nav > .nav-item > .nav-link .badge { font-size: .65rem; }

/* Mobile menu on a wide screen: set by nav_fit.js when even two rows do not hold the items. Re-states what Bootstrap's
   navbar-expand-lg switches off at >=992px (that is why every rule needs !important). */
@media (min-width: 992px) {
  .vc-navbar.nav-force-collapse > .container { flex-wrap: wrap; }
  .vc-navbar.nav-force-collapse .navbar-toggler { display: block !important; }
  .vc-navbar.nav-force-collapse .navbar-collapse { display: none !important; flex-basis: 100%; }
  .vc-navbar.nav-force-collapse .navbar-collapse.show,
  .vc-navbar.nav-force-collapse .navbar-collapse.collapsing { display: block !important; }
  .vc-navbar.nav-force-collapse .navbar-nav { flex-direction: column; }
  .vc-navbar.nav-force-collapse .navbar-nav .dropdown-menu { position: static; float: none; }
  .vc-navbar.nav-force-collapse .vc-qs-toggle { display: block !important; }
}

/* Count bubbles inside the collapsed menu. Pinned to the corner of a full-width row (top-0 start-100) a bubble lands at the
   screen edge, straddling the line above — it reads as belonging to the neighbouring item. In the vertical menu they follow
   the label instead («Задачи 1 ▾»). The hamburger's own bubble (#navToggleBadge) keeps its corner. */
@media (max-width: 991.98px) {
  #mainNav .chat-badge.position-absolute {
    position: static !important;
    transform: none !important;
    margin-left: .5rem;
    vertical-align: middle;
  }
}
@media (min-width: 992px) {
  .vc-navbar.nav-force-collapse #mainNav .chat-badge.position-absolute {
    position: static !important;
    transform: none !important;
    margin-left: .5rem;
    vertical-align: middle;
  }
}

/* ─── Footer ─────────────────────────────────────────────────────────────────── */
.vc-footer {
  background: var(--vs-footer-bg);
  color: var(--vs-footer-fg);
  border-top: 1px solid var(--vs-footer-border);
  margin-top: auto;
}

/* ─── Cookie consent banner ──────────────────────────────────────────────────── */
.cookie-banner {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 1080;
  background: #212529;
  color: #fff;
  box-shadow: 0 -2px 12px rgba(0, 0, 0, .2);
}
.cookie-banner a { color: var(--vs-primary-border-subtle); }

/* ─── Cards ──────────────────────────────────────────────────────────────────── */
.card {
  border: none;
  border-radius: var(--vs-card-radius);
  box-shadow: var(--vs-shadow);
  transition: box-shadow .2s;
}
.card:hover { box-shadow: var(--vs-shadow-hover); }

.card-header {
  background: var(--vs-card-header-bg);
  color: var(--vs-card-header-fg);
  border-bottom: var(--vs-card-header-border);
  border-radius: var(--vs-card-radius) var(--vs-card-radius) 0 0 !important;
  font-weight: 600;
}
/* Secondary text inside a themed header (a group's hint on admin/roles.php, …): .text-muted is a fixed grey that vanishes on a
   coloured header — follow the header's own text colour, a little dimmer. */
.card-header .text-muted { color: inherit !important; opacity: .8; }
/* An outline button inside a themed (coloured) header: Bootstrap's grey outline vanishes on blue/green — follow the header's text colour. */
.card-header .btn-on-header {
  --bs-btn-color: var(--vs-card-header-fg);
  --bs-btn-border-color: currentColor;
  --bs-btn-hover-color: var(--vs-card-header-fg);
  --bs-btn-hover-bg: rgba(255, 255, 255, .18);
  --bs-btn-hover-border-color: currentColor;
  --bs-btn-active-color: var(--vs-card-header-fg);
  --bs-btn-active-bg: rgba(255, 255, 255, .28);
  --bs-btn-active-border-color: currentColor;
}

/* A card asking for a Bootstrap "subtle" tint (e.g. admin/register_sessions.php's
   cash-shift cards) used to get the unconditional white-on-green above
   anyway — unreadable on a pale background
   (docs/rebranding-and-skins/01-audit.md §B.1 #18). Each of these is a
   two-class selector, strictly more specific than the single-class
   `.card-header` above, so it wins regardless of source order. */
.card-header.bg-primary-subtle   { background-color: var(--bs-primary-bg-subtle);   color: var(--bs-primary-text-emphasis); }
.card-header.bg-success-subtle   { background-color: var(--bs-success-bg-subtle);   color: var(--bs-success-text-emphasis); }
.card-header.bg-danger-subtle    { background-color: var(--bs-danger-bg-subtle);    color: var(--bs-danger-text-emphasis); }
.card-header.bg-warning-subtle   { background-color: var(--bs-warning-bg-subtle);   color: var(--bs-warning-text-emphasis); }
.card-header.bg-info-subtle      { background-color: var(--bs-info-bg-subtle);      color: var(--bs-info-text-emphasis); }
.card-header.bg-secondary-subtle { background-color: var(--bs-secondary-bg-subtle); color: var(--bs-secondary-text-emphasis); }

/* ─── Buttons ────────────────────────────────────────────────────────────────── */
/* .btn-primary / .btn-outline-primary (and the status buttons) are fully themed by the variable blocks in
   assets/theme-base.css — every state, from the skin's tokens. (Rules here used to paint a literal green over them.) */

/* ─── Doctor cards on listing ────────────────────────────────────────────────── */
.doctor-card { cursor: pointer; transition: box-shadow .15s, background-color .15s; }
.doctor-card .badge-spec {
  background: var(--vc-green-pale);
  color: var(--vc-green);
  font-size: .75rem;
  padding: .3em .7em;
  border-radius: 20px;
}
.doctor-card:hover { box-shadow: 0 2px 10px rgba(0,0,0,.08); }

/* ─── Selected doctor / pet card (wizard) ────────────────────────────────────── */
.doctor-card.border-success,
.doctor-card.border-primary,
[data-pet-card].border-success,
[data-pet-card].border-primary {
  background: var(--vc-green-pale);
  border-color: var(--vc-green) !important;
  box-shadow: 0 0 0 2px var(--vc-green);
}

/* ─── Booking mode cards (step 0) ─────────────────────────────────────────────── */
.mode-card { transition: box-shadow .2s, transform .15s, border-color .15s; }
.mode-card:hover {
  box-shadow: 0 6px 24px rgba(0,0,0,.13);
  transform: translateY(-2px);
  border-color: var(--vc-green);
}

/* ─── Booking wizard ─────────────────────────────────────────────────────────── */
.wizard-step { display: none; }
.wizard-step.active { display: block; }

.step-indicator .step {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem 1rem;
  border-radius: 20px;
  font-size: .85rem;
  color: #6c757d;
}
.step-indicator .step.done  { color: var(--vc-green); }
.step-indicator .step.active { color: var(--vc-green); font-weight: 700; }

.step-num {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: .75rem;
  font-weight: 700;
  border: 2px solid currentColor;
  flex-shrink: 0;
}

/* ─── Time slots grid ────────────────────────────────────────────────────────── */
.slot-grid { display: flex; flex-wrap: wrap; gap: .4rem; }
.slot-btn {
  min-width: 70px;
  font-size: .9rem;
  border-radius: 8px;
  border: 2px solid var(--vc-green-light);
  background: #fff;
  color: var(--vc-green);
  padding: .35rem .6rem;
  cursor: pointer;
  transition: all .15s;
}
.slot-btn:hover  { background: var(--vc-green-light); color: #fff; }
.slot-btn.selected { background: var(--vc-green); color: #fff; border-color: var(--vc-green); }
.slot-btn.taken  { border-color: #dee2e6; color: #adb5bd; cursor: not-allowed; background: #f8f9fa; }

/* ─── Calendar ───────────────────────────────────────────────────────────────── */
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.cal-day {
  /* min-width:0 overrides the grid item's default auto min-width, which
     otherwise floors each column at its widest un-wrapped content (e.g. a
     long doctor name in .duty-bar) regardless of that content's own
     overflow:hidden — without this, columns come out uneven and the grid
     can overflow its container. */
  min-width: 0;
  text-align: center;
  padding: .45rem .2rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: .9rem;
  border: 2px solid transparent;
  transition: all .15s;
}
/* Layout-shift guard (docs/tenant-page-speed/README.md): assets/search.js fills the public page's mini calendar after
   first paint, so reserve its final height — --cal-rows is set server-side for the initial month; one row =
   .cal-day's own height (2 × .45rem padding + 1.5 × .9rem line + 4px border), 4px gaps. */
#miniCalGrid {
  --cal-row: calc(2.25rem + 4px);
  align-content: start;
  min-height: calc(var(--cal-rows, 5) * var(--cal-row) + (var(--cal-rows, 5) - 1) * 4px);
}
.sched-heading { min-height: 1.5rem; }
.sched-count   { min-height: 1.25rem; }
.cal-day:hover        { border-color: var(--vc-green-light); }
.cal-day.working      { background: var(--vc-green-pale); position: relative; }
.cal-day.working-night { background: linear-gradient(135deg, var(--vc-green-pale) 60%, rgba(30,41,59,.12) 100%); }
.cal-day-moon         { position: absolute; top: 1px; right: 2px; font-size: .6rem; }
.cal-day.selected     { background: var(--vc-green); color: #fff; }
.cal-day.weekend      { background: #eef1f4; }
.cal-day.today        { border-color: var(--vc-green-light); font-weight: 700; box-shadow: inset 0 3px 0 var(--vc-green-light); }
.cal-day.past         { color: #ccc; cursor: default; pointer-events: none; }
/* Admin-only: a past date that's still clickable (viewing history), styled
   distinct from both a disabled .past day and a normal upcoming day. */
.cal-day.past-nav:not(.selected) { color: #888; }
.cal-day.empty        { pointer-events: none; }

/* Weekday header row: MUST share the exact same grid-template-columns/gap as
   .cal-grid below it, or the two rows drift apart column-by-column (flexbox's
   equal-width distribution doesn't match grid's gap-aware track sizing) —
   by Sunday the drift was enough to misalign labels and clip the last column. */
.cal-header-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: .25rem;
}
.cal-header-day { text-align: center; font-size: .75rem; font-weight: 700; color: #5c636a; padding: .2rem; }
.cal-header-day.weekend { color: color-mix(in srgb, var(--vc-teal) 70%, #000); }   /* darkened: the accent alone fails text contrast (PageSpeed a11y) */

/* ─── Duty-planning calendar (admin & doctor) ───────────────────────────────── */
.duty-cal-grid { min-height: 480px; align-items: start; }
.duty-cal-grid .cal-day.empty { background: transparent; }
.duty-cal-day {
  display: flex;
  flex-direction: column;
  text-align: left;
  min-height: 96px;
  padding: .3rem;
  vertical-align: top;
  cursor: pointer;
}
.duty-cal-day.readonly { cursor: default; }
.duty-cal-daynum { font-size: .8rem; font-weight: 600; color: #555; }
.duty-cal-day.weekend { background: #eef1f4; }
.duty-cal-day.today { box-shadow: inset 0 3px 0 var(--vc-green); }
.duty-cal-day.today .duty-cal-daynum { color: var(--vc-green); }
.duty-cal-day.vacation { background: #f8d7da; }

/* ─── Weekly-schedule calendar (admin/schedules.php) ────────────────────────── */
.duty-cal-day.sched-work   { background: var(--vc-green-pale); }
.duty-cal-day.sched-custom { background: #fff3cd; }
.sched-cal-hours { font-size: .72rem; color: #495057; margin-top: .2rem; }
.sched-cal-reason { font-size: .68rem; color: #6c757d; font-style: italic; }
.sched-legend-swatch { width: .9rem; height: .9rem; border-radius: 4px; border: 1px solid #dee2e6; vertical-align: -2px; }
.sched-legend-swatch.sched-work   { background: var(--vc-green-pale); }
.sched-legend-swatch.sched-custom { background: #fff3cd; }
.sched-legend-swatch.vacation     { background: #f8d7da; }

/* Full-width bars, stacked, height proportional to clinic capacity — a
   single doctor at capacity=1 fills the whole cell; fewer doctors than
   capacity leaves visible blank headroom below their bar(s). */
.duty-bars {
  height: 56px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: .25rem;
  overflow: hidden;
}
.duty-bar {
  position: relative;
  display: flex;
  align-items: center;
  border-radius: 3px;
  padding: 0 .3rem;
  color: #fff;
  font-size: .68rem;
  font-weight: 600;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.duty-bar--night { box-shadow: inset 0 0 0 2px #1e293b; }
.duty-bar-moon { margin-left: .25rem; font-size: .7rem; flex: none; }

/* Old small circular chips — still used by the read-only doctor/my_duties.php calendar. */
.duty-chips { display: flex; flex-wrap: wrap; gap: 3px; margin-top: .25rem; }
.duty-chip {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  color: #fff; font-size: .65rem; font-weight: 700;
}
.duty-chip--night { box-shadow: 0 0 0 2px #1e293b; }
.duty-chip-moon {
  position: absolute;
  bottom: -3px; right: -3px;
  font-size: .55rem;
  line-height: 1;
  background: #fff;
  border-radius: 50%;
  padding: 0 1px;
}
.duty-chip-more {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .65rem; color: #6c757d; padding: 0 .3rem;
}

/* ─── Duty-planning paintbrush ───────────────────────────────────────────────── */
.doctor-swatch.active {
  background: var(--vc-green-pale);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--vc-green);
}
#dutyCalGrid.paint-mode .duty-cal-day { cursor: crosshair; }
#dutyCalGrid.paint-mode .duty-cal-day:hover { border-color: var(--vc-green); }
.duty-cal-day { user-select: none; }
.duty-cap-warn { display: none; color: #b45309; font-size: .75rem; margin-left: .25rem; }
.duty-cal-day.over-capacity { background: #fff8ec; }
.duty-cal-day.over-capacity .duty-cap-warn { display: inline; }

/* ─── Live queue (unexpected walk-ins, see assets/live_queue.js) ─────────────── */
.live-queue-strip {
  border: 1px solid #f5c26b;
  background: #fff8ec;
  border-radius: 8px;
}
.live-queue-item {
  display: flex;
  gap: .75rem;
  align-items: flex-start;
  justify-content: space-between;
  padding: .5rem .25rem;
  border-bottom: 1px solid rgba(0,0,0,.06);
}
.live-queue-item:last-child { border-bottom: none; }

/* ─── Rich-text legal document rendering (register/footer/admin previews) ─────── */
.legal-doc-preview p, .legal-doc-preview ul, .legal-doc-preview ol { margin-bottom: .75rem; }
.legal-doc-preview p:last-child { margin-bottom: 0; }
.legal-doc-preview blockquote { border-left: 3px solid var(--vc-green-light); padding-left: .75rem; color: #555; }

/* ─── Client shop item cards ─────────────────────────────────────────────────── */
/* Title and description get a fixed line-clamped height regardless of actual
   text length, so the price/availability lines below them land at the same
   vertical offset on every card in a row instead of "jumping" around. */
.shop-item-title {
  min-height: 2.6rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.shop-item-desc {
  min-height: 2.5rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.shop-item-price, .shop-item-badge { min-height: 1.5rem; }

/* ─── Appointment status badges ──────────────────────────────────────────────── */
.badge-active    { background: var(--vc-green-pale); color: var(--vc-green); }
.badge-cancelled { background: #f8d7da; color: #721c24; }
.badge-completed { background: #d1ecf1; color: #0c5460; }

/* ─── Patient avatar circle ──────────────────────────────────────────────────── */
.pet-avatar {
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--vc-green-pale);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem;
  flex-shrink: 0;
}
.pet-avatar-img {
  border-radius: 50%;
  object-fit: cover;
  background: var(--vc-green-pale);
  flex-shrink: 0;
}
.avatar-clickable { cursor: pointer; transition: box-shadow .15s; }
.avatar-clickable:hover { box-shadow: 0 0 0 3px var(--vc-green-light); }

/* Marks a deceased pet wherever its name appears — see includes/avatars.php's
   deceasedRibbonHtml() / assets/pet_info_modal.js's JS twin. */
.deceased-ribbon { display: inline-flex; vertical-align: middle; margin-left: .35rem; cursor: help; }

/* ─── Tables ─────────────────────────────────────────────────────────────────── */
/* table head tint + row hover moved to assets/ui.css (shared with the cabinet) */

/* ─── Auth forms ─────────────────────────────────────────────────────────────── */
.auth-card {
  max-width: 420px;
  margin: 3rem auto;
}

/* ─── Admin sidebar ──────────────────────────────────────────────────────────── */
.admin-sidebar .nav-link {
  color: #333;
  border-radius: 8px;
  margin-bottom: 2px;
  padding: .55rem 1rem;
}
.admin-sidebar .nav-link:hover,
.admin-sidebar .nav-link.active {
  background: var(--vc-green-pale);
  color: var(--vc-green);
}
.admin-sidebar .nav-link i { margin-right: .5rem; }

/* ─── Search / filter sidebar ───────────────────────────────────────────────── */
.search-sidebar {
  position: sticky;
  top: 1rem;
}

/* ── Doctor cards (search page) ─────────────────────────────────────────────── */
.doctor-card2 {
  transition: box-shadow .2s, transform .15s;
}
.doctor-card2:hover {
  box-shadow: 0 6px 24px rgba(0,0,0,.13);
  transform: translateY(-2px);
}

/* ── Schedule chips inside doctor card ──────────────────────────────────────── */
.sched-row {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  min-height: 1.8rem;
}
.sched-chip {
  display: inline-flex;
  align-items: center;
  gap: .25rem;
  font-size: .72rem;
  font-weight: 600;
  padding: .2em .55em;
  border-radius: 20px;
  background: var(--vs-row-hover);
  color: var(--vs-link);
  border: 1px solid var(--vs-primary-border-subtle);
  white-space: nowrap;
}
.sched-chip--hl {
  background: var(--vc-green);
  color: #fff;
  border-color: var(--vc-green);
}
.sched-time {
  font-weight: 400;
  opacity: .85;
}

/* ── Day-of-week quick buttons ──────────────────────────────────────────────── */
.dow-btn {
  padding: .2rem .5rem;
  font-size: .78rem;
  min-width: 2.1rem;
}
.dow-btn.btn-success,
.dow-btn.btn-primary { color: #fff; }

/* ─── Doctor availability grid (Outlook-style) ───────────────────────────────── */
/* Row heights follow --hour-px, set from HOUR_PX by assets/sched_zoom.js (zoomable; 52px = 100%) */
.sched-wrap {
  overflow: hidden;
}
.sched-scroll {
  overflow: auto;
  max-height: 70vh;
  min-height: 420px;
}
.sched-grid {
  display: grid;
  position: relative;
}

.sched-corner {
  position: sticky;
  top: 0; left: 0; z-index: 3;
  background: #fff;
  border-bottom: 1px solid #e9ecef;
  border-right: 1px solid #e9ecef;
}

.sched-doc-header {
  position: sticky;
  top: 0; z-index: 2;
  background: #fff;
  border-bottom: 1px solid #e9ecef;
  border-right: 1px solid #f1f3f5;
  padding: .6rem .7rem;
  display: flex;
  align-items: center;
  gap: .5rem;
}
.sched-doc-avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.sched-doc-avatar--icon {
  display: flex; align-items: center; justify-content: center;
  background: var(--vc-green-pale);
  color: var(--vc-green);
  font-size: 1rem;
}
.sched-doc-info { flex: 1 1 auto; min-width: 0; }
.sched-doc-name {
  font-weight: 600; font-size: .85rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sched-doc-spec {
  font-size: .72rem; color: #6c757d;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sched-book-btn {
  flex-shrink: 0;
  width: 28px; height: 28px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--vc-green-pale);
  color: var(--vc-green);
  text-decoration: none;
  font-size: .85rem;
  transition: background .15s, color .15s;
}
.sched-book-btn:hover { background: var(--vc-green); color: #fff; }

.sched-axis-body {
  position: sticky;
  left: 0; z-index: 1;
  background: #fff;
  border-right: 1px solid #e9ecef;
  height: var(--sched-total, calc(24 * var(--hour-px, 52px)));
}
.sched-hour-label {
  position: absolute;
  left: 0; right: 4px;
  transform: translateY(-50%);
  font-size: .68rem;
  color: #6c757d;
  text-align: right;
  padding-right: 6px;
}
.sched-subs .sched-hour-label { color: #adb5bd; }
.sched-subs .sched-hour-label.is-hour { color: #212529; font-weight: 700; }
.sched-now-dot {
  position: absolute;
  right: -4px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #e03131;
  transform: translateY(-50%);
}

.sched-doc-body {
  position: relative;
  height: var(--sched-total, calc(24 * var(--hour-px, 52px)));
  border-right: 1px solid #f1f3f5;
  cursor: pointer;
}

/* Hour gridlines per visible stretch / hatched band per folded one (assets/sched_zoom.js) */
.sched-seg {
  position: absolute; left: 0; right: 0;
  background-image: repeating-linear-gradient(to bottom, #eef0f2 0, #eef0f2 1px, transparent 1px, transparent var(--hour-px, 52px));
}
/* zoomed in: lighter lines at the :30 / :15 / :10 / :05 steps, whole hours stay the stronger line */
.sched-subs .sched-seg {
  background-image:
    repeating-linear-gradient(to bottom, #dee2e6 0, #dee2e6 1px, transparent 1px, transparent var(--hour-px, 52px)),
    repeating-linear-gradient(to bottom, #f1f3f5 0, #f1f3f5 1px, transparent 1px, transparent var(--sub-px, 52px));
}
.sched-gap, .sched-gap-axis {
  position: absolute; left: 0; right: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: .66rem; color: #868e96; cursor: pointer;
  border-top: 1px dashed #ced4da; border-bottom: 1px dashed #ced4da;
  background: repeating-linear-gradient(135deg, #f8f9fa 0 6px, #f1f3f5 6px 12px);
}
.sched-gap:hover, .sched-gap-axis:hover { color: #495057; background: #e9ecef; }
.sched-gap-axis { right: 4px; letter-spacing: .1em; }

.sched-block {
  position: absolute;
  left: 2px; right: 2px;
  border-radius: 4px;
  overflow: hidden;
}
.sched-block--off {
  background: rgba(0, 0, 0, .045);
  pointer-events: none;
}
/* A night shift's working hours are still working hours — no dark wash over
   them (that used to read as "off"/unavailable to users, and was easy to
   confuse with .sched-block--off's own dark tint just below). The 🌙 icon
   alone marks it as a night window. */
.sched-block--night {
  pointer-events: none;
  z-index: 0;
}
.sched-night-icon {
  position: absolute;
  top: 2px; right: 3px;
  font-size: .8rem;
  opacity: .7;
}
.sched-block--fullday {
  position: absolute;
  inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: #f8f9fa;
  color: #adb5bd;
  font-size: .8rem;
  font-weight: 600;
  text-align: center;
}
.sched-block--busy {
  background: var(--vc-green-light);
  color: #fff;
  padding: 2px 5px;
  font-size: .68rem;
  line-height: 1.15;
  cursor: default;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
/* Pending bookings (admin only) — dashed border + accent stripe shows who
   booked it; both look identical to .sched-block--busy again once confirmed. */
.sched-block--pending-client,
.sched-block--pending-admin {
  background: repeating-linear-gradient(
    135deg, var(--vc-green-light) 0 8px, var(--vs-primary) 8px 16px
  );
  box-shadow: inset 3px 0 0 var(--vs-accent), inset 0 0 0 1px rgba(0, 0, 0, .08);
}
.sched-block--pending-admin {
  box-shadow: inset 3px 0 0 #6c757d, inset 0 0 0 1px rgba(0, 0, 0, .08);
}
/* Pending bookings on the doctor's own calendar — same striped cue, no
   client/admin distinction (the doctor just needs to notice it's unconfirmed). */
.sched-block--pending {
  background: repeating-linear-gradient(
    135deg, var(--vc-green-light) 0 8px, var(--vs-primary) 8px 16px
  );
  box-shadow: inset 3px 0 0 var(--vs-accent), inset 0 0 0 1px rgba(0, 0, 0, .08);
}
/* Client physically checked in and waiting — a blinking dot draws the eye
   without needing a whole different block color (the appointment is still
   fundamentally "busy", just with one extra fact worth noticing at a glance). */
.sched-block--attended {
  box-shadow: inset 3px 0 0 var(--vc-teal), inset 0 0 0 1px rgba(0, 0, 0, .08);
}
/* Reception grid / doctor calendar: block fill per appointment status (Оформление → «Статусы записей»). Placed after the
   pending/attended rules above so the status colour wins; the pending client/admin edge stripe is kept. */
.sched-block--st-pending   { background: var(--vs-appt-pending-block);   color: var(--vs-appt-pending-block-fg); }
.sched-block--st-confirmed { background: var(--vs-appt-confirmed-block); color: var(--vs-appt-confirmed-block-fg); }
.sched-block--st-attended  { background: var(--vs-appt-attended-block);  color: var(--vs-appt-attended-block-fg); }
.sched-block--st-executed  { background: var(--vs-appt-executed-block);  color: var(--vs-appt-executed-block-fg); }
@keyframes led-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: .25; }
}
.led-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #0dcaf0;
  box-shadow: 0 0 3px #0dcaf0;
  margin-right: 3px;
  vertical-align: middle;
  animation: led-blink 1.2s ease-in-out infinite;
}
.led-dot--inline {
  width: 7px;
  height: 7px;
  margin-right: 4px;
}
.sched-block--break {
  background: #f5c26b;
  color: #6b4a10;
  padding: 2px 5px;
  font-size: .68rem;
  line-height: 1.15;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
.sched-busy-line1 { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sched-busy-tiny { margin-top: -2px; }   /* cancels the block's 2px top padding: the line is exactly the block's height */
.sched-busy-line2 { opacity: .9; }
.sched-busy-line3 { opacity: .9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.sched-now-line {
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: #e03131;
  z-index: 1;
}

.sched-loading {
  grid-column: 1 / -1;
  display: flex; align-items: center; justify-content: center;
  padding: 3rem;
}

.sched-legend { display: flex; gap: .9rem; flex-wrap: wrap; }
.sched-zoom { flex-shrink: 0; }
.sched-zoom .btn { flex: 0 0 auto; }
.sched-zoom .sched-zoom-label { min-width: 3.2rem; font-variant-numeric: tabular-nums; }
.sched-legend-item { display: inline-flex; align-items: center; gap: .35rem; font-size: .78rem; color: #5c636a; }
.sched-swatch { width: 14px; height: 14px; border-radius: 3px; display: inline-block; }
.sched-swatch--free  { background: #fff; border: 1px solid #dee2e6; }
.sched-swatch--busy  { background: var(--vc-green-light); }
.sched-swatch--break { background: #f5c26b; }
.sched-swatch--off   { background: rgba(0, 0, 0, .08); }
.sched-swatch--night { background: rgba(30, 41, 59, .18); }
.sched-swatch--pending {
  background: repeating-linear-gradient(135deg, var(--vc-green-light) 0 4px, var(--vs-primary) 4px 8px);
}

@media (max-width: 991px) {
  .sched-legend { display: none; }
}

/* ─── Slot click context menu ─────────────────────────────────────────────────── */
.sched-ctx-menu {
  position: fixed;
  z-index: 1060;
  min-width: 200px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .18);
  padding: .4rem;
  font-size: .85rem;
}
.sched-ctx-header {
  padding: .4rem .6rem .5rem;
  border-bottom: 1px solid #f1f3f5;
  margin-bottom: .3rem;
  line-height: 1.3;
}
.sched-ctx-item {
  display: flex;
  align-items: center;
  width: 100%;
  border: none;
  background: none;
  text-align: left;
  padding: .5rem .6rem;
  border-radius: 6px;
  color: #212529;
  cursor: pointer;
}
.sched-ctx-item:hover { background: var(--vc-green-pale); color: var(--vc-green); }
.sched-ctx-item--danger { color: #c0392b; }
.sched-ctx-item--danger:hover { background: #f8d7da; color: #842029; }

/* ─── Drag-and-drop sortable lists (SortableJS) ──────────────────────────────── */
.drag-handle { cursor: grab; }
.drag-handle:active { cursor: grabbing; }
.sortable-ghost { opacity: .35; background: var(--vc-green-pale); }
.sortable-chosen td { background: var(--vs-row-hover); }

/* ─── Responsive tweaks ──────────────────────────────────────────────────────── */
@media (max-width: 576px) {
  .slot-btn { min-width: 60px; font-size: .8rem; }
  .cal-day  { padding: .3rem .1rem; font-size: .8rem; }
  #miniCalGrid { --cal-row: calc(1.8rem + 4px); }
}
@media (max-width: 991px) {
  .search-sidebar { position: static; }
}

/* ─── Internal chat ──────────────────────────────────────────────────────────── */
/* flex-wrap: nowrap overrides Bootstrap .row's default `wrap` — with `wrap`,
   a flex line is allowed to grow past the container's explicit height to fit
   content (these two columns never need to stack), which silently defeats
   the height/min-height chain below and was why long threads grew the whole
   page instead of scrolling inside .chat-messages. */
.chat-shell { height: 70vh; min-height: 420px; flex-wrap: nowrap; }
.chat-conv-list-wrap { overflow-y: auto; }
.chat-conv-list .list-group-item { cursor: pointer; border-left: 0; border-right: 0; }
.chat-conv-list .list-group-item.active { background: var(--vc-green-pale); color: #212529; border-color: #dee2e6; }
.chat-conv-list .conv-preview { color: #6c757d; font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-thread-wrap { min-width: 0; min-height: 0; }
/* min-height:0 overrides the flex-item default of min-height:auto, which
   otherwise lets this grow to fit all messages instead of scrolling inside
   its own box — the parent (.chat-shell) already has a fixed height. */
.chat-messages { overflow-y: auto; min-height: 0; }
.chat-msg { max-width: 75%; margin-bottom: .5rem; padding: .4rem .7rem; border-radius: .8rem; word-wrap: break-word; }
.chat-msg.mine { margin-left: auto; background: var(--vc-green); color: #fff; border-bottom-right-radius: .2rem; }
.chat-msg.theirs { margin-right: auto; background: #eef1f3; border-bottom-left-radius: .2rem; }
.chat-msg .chat-msg-meta { font-size: .7rem; opacity: .7; margin-top: .15rem; }
/* the rating stars under the support's «rate our help» message (assets/chat.js chatCsatBlock) */
.chat-csat .chat-star { background: none; border: 0; padding: 0 .12rem; font-size: 1.5rem; line-height: 1; color: var(--bs-warning); cursor: pointer; }
.chat-csat .chat-star:focus-visible { outline: 2px solid var(--bs-primary); outline-offset: 2px; border-radius: .25rem; }
.chat-csat .chat-csat-note { margin-top: .15rem; }
.chat-msg-read-icon { font-size: .8rem; margin-left: .3rem; opacity: .75; }
.chat-msg.mine[data-read="1"] .chat-msg-read-icon { opacity: 1; color: var(--vs-primary-border-subtle); }
.chat-badge { font-size: .65rem; }
/* Client ↔ administrator support threads (migr. 0093) — deliberately loud so
   an admin never mistakes one for an internal staff chat. */
.chat-conv-list .list-group-item.chat-conv-client { border-left: 3px solid #ffc107; background: #fff9ec; }
.chat-conv-list .list-group-item.chat-conv-client.active { background: #ffeaba; }
.chat-client-icon { color: #b5860b; }
.chat-client-badge {
  display: inline-block; font-size: .6rem; font-weight: 700; letter-spacing: .04em;
  padding: .02rem .3rem; border-radius: .25rem; background: #ffc107; color: #3a2f00;
  vertical-align: middle;
}
#chatThreadHeader.chat-client-header { background: #fff3cd; color: #7a5b00; border-bottom-color: #ffe69c; }
.chat-thread-client #chatSendForm,
.chat-thread-client #chatAttachPreview { background: #fff9ec; }
.chat-thread-client #chatSendInput { border-color: #ffda6a; background: #fffdf6; }
.chat-thread-client #chatSendInput:focus { border-color: #ffc107; box-shadow: 0 0 0 .2rem rgba(255,193,7,.25); }
.chat-msg-delete { cursor: pointer; opacity: .55; margin-left: .4rem; }
.chat-msg-delete:hover { opacity: 1; }

/* Platform-support thread (migr. 0100) — pinned first in the conversation
   list (assets/chat.js sorts it there). A distinct teal, deliberately not
   the client-thread amber above, so the two external-ish threads read as
   different things at a glance: amber = "a client is watching", teal =
   "the platform is on the other end". */
.chat-conv-list .list-group-item.chat-conv-support { border-left: 3px solid #0dcaf0; background: #eafcff; }
.chat-conv-list .list-group-item.chat-conv-support.active { background: #cdf5fb; }
.chat-support-icon { color: #087990; }
.chat-support-badge {
  display: inline-block; font-size: .6rem; font-weight: 700; letter-spacing: .04em;
  padding: .02rem .3rem; border-radius: .25rem; background: #0dcaf0; color: #033c47;
  vertical-align: middle;
}
#chatThreadHeader.chat-support-header { background: #cff8fd; color: #055160; border-bottom-color: #9eecf7; }
.chat-thread-support #chatSendForm,
.chat-thread-support #chatAttachPreview { background: #eafcff; }
.chat-thread-support #chatSendInput { border-color: #6edff2; background: #f5feff; }
.chat-thread-support #chatSendInput:focus { border-color: #0dcaf0; box-shadow: 0 0 0 .2rem rgba(13,202,240,.25); }
.chat-msg.deleted { font-style: italic; opacity: .6; }
/* Links the chat made clickable: readable on the green «mine» bubble too. */
.chat-msg a.chat-link { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.chat-msg.theirs a.chat-link { color: var(--bs-link-color, #0d6efd); }
/* Selected conversation: the preview line is grey by default, which vanishes on a coloured row. */
.chat-conv-list .list-group-item.active .conv-preview { color: #343a40; }
.chat-conv-list .list-group-item.active:not(.chat-conv-client):not(.chat-conv-support) { box-shadow: inset 3px 0 0 var(--vc-green, #198754); }
.chat-read-status { font-size: .7rem; color: #6c757d; text-align: right; margin-top: -.2rem; margin-bottom: .5rem; }
.chat-attach-img { max-width: 220px; max-height: 220px; border-radius: .4rem; display: block; }
.chat-attach-wrap { margin-bottom: .35rem; }
.chat-attach-file { color: inherit; text-decoration: none; background: rgba(0,0,0,.04); border-radius: .4rem; padding: .3rem .5rem; }
.chat-msg.mine .chat-attach-file { background: rgba(255,255,255,.15); color: #fff; }
/* Small text+icon action links under an attachment (download / open-in-new-tab) —
   shared by assets/chat.js (staff) and assets/client_chat.js (client), see
   chatAttachmentHtml()/attachmentHtml(). */
.chat-attach-actions { display: flex; gap: .75rem; margin-top: .15rem; }
.chat-attach-mini-link { display: inline-block; margin-top: .15rem; color: inherit; opacity: .75; text-decoration: none; font-size: .75rem; white-space: nowrap; }
.chat-attach-mini-link:hover { opacity: 1; text-decoration: underline; color: inherit; }
/* Full-screen image viewer (chat[_]*.js's ensureChatImageModal/ensureImageModal) */
#chatImageModal .modal-body, #ccImageModal .modal-body { overflow: hidden; }
#chatSearchResults { background: #fff; border: 1px solid #dee2e6; border-radius: .4rem; box-shadow: 0 4px 16px rgba(0,0,0,.15); }

/* ─── Event notifications ────────────────────────────────────────────────────── */
.notif-unread { background: var(--vc-green-pale); border-left: 3px solid var(--vc-green); }
.notif-toast-wrap { position: fixed; right: 1rem; bottom: 1rem; z-index: 1080; display: flex; flex-direction: column; gap: .5rem; max-width: 320px; }
.notif-toast {
  background: #fff; border: 1px solid #dee2e6; border-left: 3px solid var(--vc-green);
  border-radius: .5rem; box-shadow: 0 6px 20px rgba(0,0,0,.15); padding: .6rem .8rem;
  cursor: pointer; animation: notif-toast-in .2s ease-out;
}
.notif-toast:hover { box-shadow: 0 8px 24px rgba(0,0,0,.2); }
.notif-toast-title { font-weight: 600; font-size: .9rem; }
.notif-toast-body { font-size: .8rem; color: #6c757d; margin-top: .15rem; }
@keyframes notif-toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

/* ─── Reception book (admin/reception_book.php) ──────────────────────────────── */
/* table-layout:fixed makes <col> widths (set inline by assets/reception_book.js
   on drag) actually stick — the browser doesn't reflow columns to fit content,
   which is what column resizing needs to feel real. */
.rb-table { table-layout: fixed; }
.rb-table th { position: relative; user-select: none; overflow: hidden; }
.rb-table th, .rb-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rb-th-label { cursor: pointer; display: inline-flex; align-items: center; gap: .3rem; }
.rb-th-label:hover { color: var(--vc-green); }
.rb-resize-handle { position: absolute; top: 0; right: -3px; bottom: 0; width: 6px; cursor: col-resize; z-index: 2; }
.rb-resize-handle:hover, .rb-resize-handle.rb-resizing { background: rgba(var(--vs-primary-rgb), .35); }
.rb-condition-row { display: flex; gap: .5rem; align-items: center; margin-bottom: .5rem; flex-wrap: wrap; background: var(--vc-bg); border-radius: .4rem; padding: .4rem .5rem; }
.rb-columns-drag { cursor: grab; }
.rb-autocomplete-list {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 1050;
  max-height: 220px; overflow-y: auto; box-shadow: 0 4px 16px rgba(0,0,0,.15);
}

/* ─── Clinical case timeline pane (assets/clinical_case_ui.js) ───────────────────
   Sits beside the appointment card (#apptCardModal is modal-lg,
   #apptViewModal is modal-xl) without touching either modal's own size — a
   plain sibling element. `left` and `width` are set inline by
   assets/clinical_case_ui.js's positionPaneAndModal(), computed against the
   window's actual current width (and re-run on resize) rather than fixed
   breakpoints — on a narrower window it shifts the modal dialog itself
   rightward (translateX, also applied there) to open up room, shrinking the
   pane if even that isn't quite enough, so the card's own dimensions still
   never change while the pane always stays fully on-screen. The values here
   are just the pre-JS fallback shown for an instant while a case is loading. */
.case-pane {
  position: fixed;
  top: 1.75rem;
  left: 8px;
  width: 300px;
  max-height: calc(100vh - 3.5rem);
  background: #fff;
  border-radius: .6rem;
  box-shadow: 0 6px 24px rgba(0,0,0,.18);
  z-index: 1056; /* just above Bootstrap's modal (1055) so it never hides behind it */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.case-pane-header {
  background: var(--vc-green); color: #fff; padding: .6rem .8rem;
  display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem;
}
.case-pane-title { font-weight: 600; font-size: .92rem; word-break: break-word; }
.case-pane-daterange { color: rgba(255,255,255,.85); font-size: .75rem; margin-top: .1rem; }
.case-pane-actions { display: flex; gap: .25rem; flex-shrink: 0; }
.case-pane-actions .btn { padding: .1rem .35rem; }
.case-pane-body { padding: .8rem; overflow-y: auto; flex: 1; }

/* ─── Stacked modals ─────────────────────────────────────────────────────────
   A dialog that is a QUESTION on top of a card (the «Рецепт» modal, the advanced-search pick, a new-item form) carries the class
   `ui-question`; assets/ui.css §15 lifts it and its own backdrop above the card / modal chain underneath. */

.case-timeline { position: relative; padding-left: 1.5rem; }
.case-timeline::before {
  content: ""; position: absolute; left: .4rem; top: .3rem; bottom: .3rem; width: 2px; background: #e2e6ea;
}
.case-timeline-item { position: relative; padding-bottom: 1rem; cursor: pointer; }
.case-timeline-item:last-child { padding-bottom: 0; }
.case-timeline-dot {
  position: absolute; left: -1.5rem; top: .15rem; width: .7rem; height: .7rem;
  border-radius: 50%; background: var(--vc-green-light); border: 2px solid #fff; box-shadow: 0 0 0 1px var(--vc-green-light);
}
.case-timeline-item--active .case-timeline-dot { background: var(--vc-green); box-shadow: 0 0 0 3px var(--vc-green-pale); }
.case-timeline-item--muted { opacity: .55; }
.case-timeline-item--muted .case-timeline-dot { background: #adb5bd; box-shadow: 0 0 0 1px #adb5bd; }
.case-timeline-item--lab { cursor: default; }
.case-timeline-item--lab .case-timeline-dot {
  background: var(--vc-teal); box-shadow: 0 0 0 1px var(--vc-teal);
  display: flex; align-items: center; justify-content: center;
}
.case-timeline-item--lab a { cursor: pointer; }
.case-timeline-date { font-size: .78rem; font-weight: 600; }
.case-timeline-label { font-size: .82rem; }
.case-timeline-item:hover:not(.case-timeline-item--lab) .case-timeline-label { color: var(--vc-green); }

/* ─── Case indicator on the appointment card (assets/clinical_case_ui.js) ────── */
.case-indicator { font-size: .82rem; }
.case-indicator .btn { padding: .1rem .5rem; font-size: .78rem; }

/* ── Quick search (assets/quick_search.js, docs/quick-search/README.md) ───────── */
.vc-qs-toggle { padding: .5rem; }
.qs-bar { position: fixed; right: 12px; width: min(460px, calc(100vw - 24px)); z-index: 1060;
  background: var(--bs-body-bg); color: var(--bs-body-color); border: 1px solid var(--bs-border-color);
  border-radius: .6rem; box-shadow: 0 .75rem 2rem rgba(0,0,0,.22); padding: .6rem; margin-top: .35rem; }
.qs-input-wrap { position: relative; }
.qs-input-wrap > i { position: absolute; left: .75rem; top: 50%; transform: translateY(-50%); color: var(--bs-secondary-color); pointer-events: none; }
.qs-input-wrap input { padding-left: 2.2rem; padding-right: 3rem; }
.qs-input-wrap kbd { position: absolute; right: .5rem; top: 50%; transform: translateY(-50%); font-size: .7rem; }
.qs-results { max-height: min(60vh, 440px); overflow-y: auto; margin-top: .5rem; }
.qs-note { padding: .5rem .6rem; font-size: .85rem; color: var(--bs-secondary-color); }
.qs-item { display: flex; align-items: center; gap: .65rem; padding: .5rem .6rem; border-radius: .45rem; color: inherit; text-decoration: none; }
.qs-item > i { font-size: 1.1rem; width: 1.4rem; text-align: center; color: var(--bs-primary); flex: none; }
.qs-item.active { background: var(--bs-tertiary-bg); }
.qs-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.qs-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qs-group { font-size: .78rem; color: var(--bs-secondary-color); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qs-badge { flex: none; font-weight: 400; }
@keyframes qs-flash { 0%, 55% { box-shadow: 0 0 0 .3rem rgba(var(--bs-primary-rgb), .45); } 100% { box-shadow: 0 0 0 0 rgba(var(--bs-primary-rgb), 0); } }
.qs-flash { animation: qs-flash 2.4s ease-out; }

/* Public front page FAQ (index.php) — native <details>, no JS, content stays in the HTML for search engines */
.vc-faq { max-width: 52rem; }
.vc-faq-item { border: 1px solid var(--bs-border-color); border-radius: .5rem; padding: .65rem 1rem; margin-bottom: .5rem; background: var(--bs-body-bg); }
.vc-faq-item summary { cursor: pointer; font-weight: 600; }
.vc-faq-item[open] summary { margin-bottom: .5rem; }

/* Demo-access box (includes/demo.php): Bootstrap's pink <code> on the yellow alert fails text contrast */
[data-demo-box] code { color: #664d03; }

/* ─── Menu hints & empty states (docs/staff-ease-of-use §6.3, §6.7) ──────────────────────────────────────────── */
.dropdown-item .nav-hint { white-space: normal; max-width: 19rem; line-height: 1.25; font-size: .75rem; margin-top: .1rem; }
/* .empty-state rules moved to assets/ui.css (shared with the cabinet) */

/* ─── Toast with «Вернуть» (assets/ui_toast.js, docs/staff-ease-of-use §7.2) ─────────────────────────────────── */
.ui-toast-wrap { position: fixed; left: 1rem; bottom: 1rem; z-index: 1090; display: flex; flex-direction: column; gap: .5rem; max-width: min(24rem, calc(100vw - 2rem)); }
.ui-toast { display: flex; align-items: center; gap: .75rem; background: #212529; color: #fff; border-radius: .5rem; padding: .55rem .75rem;
  box-shadow: 0 .25rem .75rem rgba(0,0,0,.25); opacity: 0; transform: translateY(.5rem); transition: opacity .18s, transform .18s; }
.ui-toast.show { opacity: 1; transform: none; }
.ui-toast-text { flex: 1 1 auto; font-size: .9rem; }
.ui-toast-action { background: none; border: 0; color: #8ec5ff; font-weight: 600; padding: 0 .25rem; cursor: pointer; }
.ui-toast-action:hover { text-decoration: underline; }
.ui-toast-close { background: none; border: 0; color: rgba(255,255,255,.6); font-size: 1.2rem; line-height: 1; padding: 0 .15rem; cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .ui-toast { transition: none; } }

/* ─── In-app help panel (assets/help.js, docs/staff-ease-of-use §4.2) ─────────────────────────────────────── */
.help-btn { color: var(--bs-secondary-color, #6c757d); font-size: .8em; text-decoration: none; }
.help-btn:hover, .help-btn:focus { color: var(--bs-primary, #0d6efd); }
.help-panel { --bs-offcanvas-width: 24rem; }
.help-terms dt { font-weight: 600; margin-top: .6rem; }
.help-terms dd { margin: 0; color: var(--bs-secondary-color, #6c757d); font-size: .9rem; }
.help-hit { display: block; padding: .5rem .6rem; border-radius: .4rem; text-decoration: none; color: inherit; border: 1px solid var(--bs-border-color, #dee2e6); margin-bottom: .4rem; }
.help-hit:hover { background: var(--bs-tertiary-bg, #f8f9fa); }
@media print { .help-btn, .help-panel { display: none !important; } }

/* ─── Guided tours (assets/help_tour.js, docs/staff-ease-of-use §3) ───────────────────────────────────────── */
.help-tour-spot { position: fixed; z-index: 1100; border-radius: .5rem; pointer-events: none;
  box-shadow: 0 0 0 9999px rgba(0,0,0,.55); outline: 2px solid var(--bs-primary, #0d6efd); transition: top .2s, left .2s, width .2s, height .2s; }
.help-tour-pop { position: fixed; z-index: 1101; background: var(--bs-body-bg, #fff); color: var(--bs-body-color, #212529);
  border-radius: .6rem; padding: .85rem 1rem; box-shadow: 0 .5rem 1.5rem rgba(0,0,0,.3); max-width: calc(100vw - 24px); }
.help-tour-count { font-size: .75rem; color: var(--bs-secondary-color, #6c757d); margin-bottom: .15rem; }
.help-tour-title { font-weight: 600; margin-bottom: .25rem; }
.help-tour-body { font-size: .9rem; margin-bottom: .75rem; }
.help-tour-actions { display: flex; align-items: center; gap: .5rem; }
.help-tour-never { display: block; font-size: .75rem; color: var(--bs-secondary-color, #6c757d); margin-top: .6rem; }
@media (prefers-reduced-motion: reduce) { .help-tour-spot { transition: none; } }
@media print { .help-tour-spot, .help-tour-pop { display: none !important; } }

/* ─── Guided tours: «do» step hint and the phone layout (assets/help_tour.js) ────────────────────────────────── */
.help-tour-do { font-size: .85rem; color: var(--bs-primary, #0d6efd); margin-bottom: .75rem; }
.help-panel { max-width: 100vw; }
@media (max-width: 575.98px) {
  .help-tour-pop { left: 0 !important; right: 0 !important; top: auto !important; bottom: 0 !important; width: 100% !important; max-width: 100% !important;
    border-radius: .9rem .9rem 0 0; padding: .9rem 1rem calc(.9rem + env(safe-area-inset-bottom)); max-height: 55vh; overflow-y: auto; }
  .help-tour-pop .btn { min-height: 2.5rem; padding-left: .9rem; padding-right: .9rem; }
  .help-tour-pop .btn-link { min-height: 2.5rem; display: inline-flex; align-items: center; }
  .help-tour-body { font-size: .95rem; }
}

/* ─── Field hints «(i)» (assets/help_hints.js, docs/staff-ease-of-use §6.2) and the shortcut sheet ──────────── */
.help-hint { background: none; border: 0; padding: 0 .15rem; margin-left: .25rem; color: var(--bs-secondary-color, #6c757d); font-size: .9em; line-height: 1; vertical-align: baseline; cursor: pointer; }
.help-hint:hover, .help-hint:focus-visible { color: var(--bs-primary, #0d6efd); }
.popover { max-width: 22rem; }
@media print { .help-hint { display: none !important; } }

/* ─── Ctrl+K palette: commands with their keys, people results (assets/quick_search.js) ──────────────────────── */
.qs-section { font-size: .72rem; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--bs-secondary-color, #6c757d); padding: .5rem .85rem .15rem; }
.qs-keys { margin-left: auto; white-space: nowrap; font-size: .75rem; color: var(--bs-secondary-color, #6c757d); }
.qs-keys kbd { font-size: .72rem; }
.qs-then { margin: 0 .25rem; font-size: .7rem; }

/* ─── Catalog navigation (includes/catalog_ui.php, docs/catalog-navigation/README.md) ───────────────────────────
   One colour per KIND of relation, the same on every catalog page and in the manual's diagram:
   h = the same record in another role («роль»),  v = group → members («тип»),  t = price on a date («цена»),
   u = where it is used / what it feeds,  bad = a gap worth fixing. Fixed palette on purpose: it is a convention, not a skin. */
.cat-chip { display: inline-flex; align-items: center; gap: .25rem; font-size: .78rem; line-height: 1.5; padding: .05rem .55rem; border-radius: 1rem; border: 1px solid transparent; text-decoration: none; white-space: nowrap; }
a.cat-chip:hover { filter: brightness(.95); text-decoration: none; }
.cat-chip.h   { color: #0b6b5d; background: #dcf2ee; }
.cat-chip.v   { color: #5b3aa0; background: #ece5f8; }
.cat-chip.t   { color: #8a5200; background: #fbefd7; }
.cat-chip.u   { color: #35507a; background: #e2e9f3; }
.cat-chip.bad { color: #a3241a; background: #fde4e1; }
.cat-chip.ghost { color: #6c757d; background: transparent; border-color: #dee2e6; }
.cat-filters { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem .5rem; font-size: .875rem; color: #6c757d; margin: -.5rem 0 1rem; }
.cat-filters a:not(.cat-chip) { text-decoration: none; }
.cat-lens { display: flex; flex-wrap: wrap; gap: .25rem; margin-bottom: 1rem; }
.cat-lens .nav-link { padding: .4rem .85rem; }
.cat-lens .nav-link .badge { margin-left: .3rem; }
.cat-dot { display: inline-block; min-width: 1.15rem; height: 1.15rem; line-height: 1.15rem; text-align: center; border-radius: .6rem; font-size: .68rem; font-weight: 700; color: #fff; background: #dc3545; padding: 0 .3rem; margin-left: .3rem; }
.cat-layout { display: grid; grid-template-columns: 14.5rem minmax(0, 1fr); gap: 1.25rem; align-items: start; }
@media (max-width: 991.98px) { .cat-layout { grid-template-columns: minmax(0, 1fr); } }
.cat-facets { background: var(--bs-body-bg, #fff); border: 1px solid var(--bs-border-color, #dee2e6); border-radius: .6rem; padding: .75rem; font-size: .875rem; }
.cat-facets h6 { margin: .75rem 0 .25rem; font-size: .72rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #6c757d; }
.cat-facets h6:first-child { margin-top: 0; }
.cat-facet-item { display: flex; justify-content: space-between; gap: .5rem; padding: .2rem .5rem; border-radius: .4rem; color: inherit; text-decoration: none; }
a.cat-facet-item:hover { background: #f1f3f5; }
.cat-facet-item.on { background: #e3eff7; color: #0e5a85; font-weight: 600; }
.cat-facet-item .c { color: #6c757d; font-size: .78rem; }
.cat-facet-item .c.bad { color: #dc3545; font-weight: 600; }
.cat-facet-item.zero { color: #adb5bd; }
.cat-facet-manage { display: block; margin-top: .35rem; padding: .2rem .5rem; font-size: .8rem; text-decoration: none; }
@media (max-width: 991.98px) { .cat-facets { display: none; } .cat-facets.open { display: block; } }
.cat-howto summary { cursor: pointer; font-weight: 600; }
.cat-howto img { max-width: 100%; height: auto; }
@media print { .cat-lens, .cat-facets, .cat-howto, .cat-filters { display: none !important; } }
