/* ================================================================
   CANAOPTICALCLINIC — Cana Optical Clinic Management System
   styles.css
   Brand primary: #E8760A  |  Dark: #1C1C1C
   Font: Poppins (300, 400, 500, 600, 700)
================================================================ */

/* ════════════════════════════════════════════════════════════════
   DESIGN TOKENS — change these to retheme the entire admin app
════════════════════════════════════════════════════════════════ */
:root {
  /* Brand */
  --clr-primary:        #E8760A;
  --clr-primary-dk:     #C4620A;
  --clr-primary-tint:   #FFE0B2;

  /* Semantic */
  --clr-success:        #10B981;
  --clr-success-tint:   #BBF7D0;
  --clr-danger:         #DC2626;
  --clr-danger-tint:    #FECACA;
  --clr-info:           #3B82F6;
  --clr-info-tint:      #BFDBFE;

  /* Neutrals */
  --clr-dark:           #1C1C1C;
  --clr-bg:             #f5f6fa;
  --clr-border:         #E5E7EB;
  --clr-text:           #374151;
  --clr-muted:          #6B7280;
}

/* ── Reset & Base ─────────────────────────────────────────────── */
/* Override Bootstrap Reboot so existing design is preserved */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Always show number input spinners */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { opacity: 1; }
/* Hide native spinner for gallery max input — uses custom −/+ buttons */
#gallery-max-input::-webkit-inner-spin-button,
#gallery-max-input::-webkit-outer-spin-button { display: none; }
#gallery-max-input { -moz-appearance: textfield; }
/* Gallery admin grid — 3 columns on mobile, auto-fill on desktop */
#gallery-admin-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  min-height: 60px;
}
@media (min-width: 480px) {
  #gallery-admin-grid { grid-template-columns: repeat(auto-fill, minmax(90px, 1fr)); }
}
html { font-size: 15px; }
body {
  font-family: 'Poppins', sans-serif !important;
  background: var(--clr-bg) !important;
  background-attachment: fixed !important;
  color: #1C1C1C !important;
  line-height: 1.5 !important;
}
a { color: #E8760A; text-decoration: none; }
a:hover { text-decoration: underline; }
img { display: block; max-width: 100%; }
/* Prevent Bootstrap from altering base element styles */
button, input, select, textarea { font-family: 'Poppins', sans-serif; }
/* Bootstrap adds default margins to headings; reset them */
h1, h2, h3, h4, h5, h6 { margin: 0; }
/* Bootstrap Reboot sets border-radius:0 on button — restore border-radius per class */
button { border-radius: unset; }
/* Bootstrap pointer-events:none on :disabled can linger; our classes re-enable explicitly */
.lf-btn, .btn-primary, .fp-btn-primary, .fp-back-link, .fp-resend-link,
.topbar-toggle, .topbar-notify, .topbar-user-chip, .nav-item, .sidebar-logout {
  pointer-events: auto;
}

/* ── Scrollbar ─────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: #F3F4F6; }
::-webkit-scrollbar-thumb { background: #D1D5DB; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #9CA3AF; }

/* ════════════════════════════════════════════════════════════════
   AUTH SCREENS — split card layout (login + register)
════════════════════════════════════════════════════════════════ */
#login-screen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* justify-content:center alone clips the TOP of the content when it's
     taller than the viewport — centering distributes the overflow equally
     above and below, but the page's natural scroll top (scrollY:0) lands
     at the container's own top edge, which is already past the content's
     real top. safe center is the CSS-spec fix: falls back to start-
     alignment specifically when centering would overflow, so scrolling to
     the top always actually reaches the top. Declared after the plain
     center above as progressive enhancement — a browser that doesn't
     recognize "safe" ignores this whole declaration and keeps center. */
  justify-content: safe center;
  background: #EDE9E0;
  padding: 24px 16px;
  gap: 16px;
  box-sizing: border-box;
}

@keyframes card-in {
  from { opacity: 0; transform: translateY(15px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Split card */
.auth-split-card {
  display: flex;
  width: 100%;
  max-width: 780px;
  /* Fixed, not min-height — login, forgot-password (4 steps) and
     registration (3 steps) are each a *separate* element using this same
     class, not one shared element swapping content. With only a min-height
     floor, whichever one's content happened to be tallest (registration's
     password step, forgot-password's OTP/reset steps) could grow past it
     while shorter screens (e.g. plain login) sat at the floor — a visible
     height jump switching between screens. A fixed height plus
     .auth-form-panel's overflow-y:auto below (any content that doesn't
     fit scrolls internally) keeps every screen pinned to the exact same
     height instead. 640px comfortably fits the tallest known content
     (registration step 3: password + its 5-item checklist + confirm +
     terms), with the scroll as a safety net for anything unexpectedly
     taller rather than a hard requirement to get the number exactly right. */
  height: 640px;
  background: #fff;
  border-radius: 24px;
  box-shadow:
    0 0 0 1px rgba(0,0,0,.05),
    0 24px 80px rgba(0,0,0,.1),
    0 8px 24px rgba(232,118,10,.06);
  overflow: hidden;
  animation: card-in 0.42s cubic-bezier(.22,1,.36,1) both;
}

/* ── Left: Brand panel ── */
.auth-brand-panel {
  flex: 0 0 44%;
  position: relative;
  overflow: hidden;
  background: #1C0E00;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 52px 42px;
}
.auth-brand-panel::after {
  content: "";
  position: absolute; inset: 0;
  opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

.auth-bp-inner {
  position: relative; z-index: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.auth-bp-logo-wrap {
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 32px;
  flex-shrink: 0;
}
.auth-bp-logo {
  width: 120px; height: 120px;
  object-fit: contain;
  filter: drop-shadow(0 4px 18px rgba(232,118,10,.5));
}

.auth-bp-text-block {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.auth-bp-brand-name {
  font-size: 2.4rem; font-weight: 800;
  color: #fff; letter-spacing: -0.03em; line-height: 1.2;
  margin-bottom: 10px;
}
.auth-bp-desc {
  font-size: 0.92rem; line-height: 1.7;
  color: rgba(255,255,255,.65);
  max-width: 300px;
}
.auth-bp-divider {
  width: 44px; height: 3px;
  margin: 22px 0 20px;
  border-radius: 2px;
  background: #E8760A;
}
.auth-bp-features {
  display: flex;
  flex-direction: column;
  gap: 13px;
  align-items: flex-start;
}
.auth-bp-feature {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.85rem;
  color: rgba(255,255,255,.72);
  letter-spacing: -0.01em;
  text-align: left;
  animation: bp-feature-in .5s cubic-bezier(.22,1,.36,1) both;
}
.auth-bp-feature:nth-child(1) { animation-delay: .08s; }
.auth-bp-feature:nth-child(2) { animation-delay: .16s; }
.auth-bp-feature:nth-child(3) { animation-delay: .24s; }
.auth-bp-feature-icon {
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  border-radius: 9px;
  background: rgba(232,118,10,.16);
  border: 1px solid rgba(232,118,10,.32);
  color: #FDBA74;
}
.auth-bp-feature-icon svg { width: 15px; height: 15px; }
@keyframes bp-feature-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.auth-bp-clinic-name {
  font-size: 0.85rem; font-weight: 600;
  color: rgba(255,220,160,.85);
  text-transform: uppercase; letter-spacing: 0.1em;
}

/* ── Right: Form panel ── */
.auth-form-panel {
  flex: 1; min-width: 0;
  padding: 52px 48px;
  display: flex; flex-direction: column; justify-content: center;
  /* Was previously only set on the --register variant below — with
     .auth-split-card now a fixed height (see comment there), every panel
     needs this same safety net, not just registration's, or a login/
     forgot-password step with unusually tall content would still grow the
     card past the fixed height instead of scrolling internally. */
  overflow-y: auto;
  /* Plain "center" splits overflow evenly above/below and clips whichever
     end the scroll container can't reach — on a tall step (registration's
     password step: title + stepper + password/strength UI + terms + QR
     notice + buttons) that clips padding-top clean off, so the title reads
     as jammed against the edge with no space above it. "safe center" falls
     back to start-alignment once content overflows, so the real
     padding-top stays visible and the safety net is scrolling down to see
     the rest, not scrolling up past a clipped top. Same fix already
     applied to the outer screen wrappers (#register-screen etc.) — this is
     the same bug one layer deeper, on the inner scrolling panel itself. */
  justify-content: safe center;
}
.auth-form-panel--register {
  /* Equal padding values here don't read as equal — the top edge is
     text (the "Create Patient Account" title, whose glyphs sit lower
     than its own line-height box, leaving extra invisible space above
     the visible letters), while the bottom edge is a solid button
     (Back/Create Account), which fills its box edge-to-edge with no
     comparable invisible margin. A few extra px on top compensates for
     that optical difference so the two ends actually look balanced. */
  padding-top: 44px; padding-bottom: 36px;
}

/* Back link inside form panel */
.auth-back-link {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.79rem; font-weight: 600; color: #9ca3af;
  margin-bottom: 26px; text-decoration: none; width: fit-content;
  transition: color 0.2s ease;
}
.auth-back-link svg { transition: transform 0.2s ease; }
/* Overrides the global a:hover underline (further down this file) — this
   link's own color-shift + arrow-slide is the intended hover treatment;
   an underline on top of that looks busy on an inline icon+text link. */
.auth-back-link:hover { color: #E8760A; text-decoration: none; }
.auth-back-link:hover svg { transform: translateX(-2px); }
.auth-back-link:focus-visible { outline: 2px solid #E8760A; outline-offset: 3px; border-radius: 4px; }

/* Welcome text */
.login-title {
  font-size: 1.3rem; font-weight: 700;
  color: #1f2937; letter-spacing: -0.02em; margin-bottom: 5px;
}
.login-desc {
  font-size: 0.87rem; color: #6b7280;
  margin-bottom: 26px;
}

/* ── Responsive: mobile stacks vertically ── */
@media (max-width: 768px) {
  #login-screen {
    min-height: 100vh;
    min-height: 100dvh;
    padding: 16px;
    align-items: center;
    box-sizing: border-box;
  }
  .auth-split-card {
    flex-direction: column;
    max-width: 420px;
    width: 100%;
    /* height:auto too (not just min-height) — the desktop rule above now
       sets a fixed height for cross-screen consistency there, which would
       otherwise clip/break this stacked mobile layout's naturally taller
       content. */
    height: auto;
    min-height: auto;
    border-radius: 16px;
  }
  .auth-brand-panel {
    flex: none;
    padding: 12px 16px;
    border-radius: 16px 16px 0 0;
  }
  .auth-bp-inner { flex-direction: row; align-items: center; gap: 10px; text-align: left; }
  .auth-bp-logo-wrap { width: 36px; height: 36px; border-radius: 10px; margin-bottom: 0; }
  .auth-bp-logo { width: 24px; height: 24px; }
  .auth-bp-text-block { align-items: center; flex-direction: row; gap: 0; }
  .auth-bp-brand-name { font-size: 1rem; margin-bottom: 0; line-height: 1.15; }
  .auth-bp-desc, .auth-bp-divider, .auth-bp-features { display: none; }
  .auth-form-panel { padding: 20px; justify-content: flex-start; }
  .auth-form-panel--register { padding-top: 22px; padding-bottom: 16px; }
  .auth-back-link { margin-bottom: 12px; }
  .login-title { font-size: 1.2rem; margin-bottom: 4px; }
  .login-desc { margin-bottom: 18px; }
  .lf-group { margin-bottom: 12px; }

  /* Compact registration form — fit all 3 steps without page scroll */
  .reg-stepper { margin: 12px auto 16px; }
  .reg-step-dot { width: 32px; height: 32px; font-size: 0.76rem; }
  .reg-step-line { margin: 14px 4px 0; }
  .reg-step-lbl { font-size: 0.62rem; }
  .reg-title { font-size: 1.05rem; }
  .reg-desc { margin-bottom: 10px; font-size: 0.78rem; }
  .reg-input { padding: 8px 12px; font-size: 0.83rem; }
  .reg-form-grid { gap: 8px; }
  .reg-row-2 { gap: 8px; }
  .reg-hint { font-size: 0.65rem; margin-top: 2px; }
  .reg-terms { margin: 10px 0 10px; font-size: 0.75rem; }
  .reg-terms-hint { font-size: 0.74rem; padding: 7px 11px; margin-bottom: 8px; }
  .qr-notice { margin: 4px 0 8px; padding: 8px 12px; font-size: 0.72rem; }
}

/* Field groups */
.lf-group { margin-bottom: 16px; }
.lf-label {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  color: #374151;
  margin-bottom: 6px;
}
.lf-input {
  width: 100%;
  padding: 11px 14px;
  border: 1.5px solid #e5e7eb;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.9rem;
  color: #1C1C1C;
  background: #fff;
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  box-sizing: border-box;
  appearance: none;
}
.lf-input:focus {
  border-color: #E8891C;
  box-shadow: 0 0 0 3px rgba(232,137,28,.1);
}
.lf-input.error {
  border-color: #DC2626;
  box-shadow: 0 0 0 3px rgba(220,38,38,.08);
}

/* Password + eye */
.lf-pw-wrap { position: relative; }
.lf-pw-wrap .lf-input { padding-right: 44px; }
.lf-pw-eye {
  position: absolute;
  right: 0; top: 0; bottom: 0;
  width: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  color: #9CA3AF;
  transition: color 0.2s ease;
}
.lf-pw-eye:hover { color: #E8891C; }

/* Error */
.lf-error {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: #FEF2F2;
  border: 1px solid #FECACA;
  border-left: 4px solid #DC2626;
  border-radius: 8px;
  padding: 11px 14px;
  font-size: 0.83rem;
  font-weight: 500;
  color: #B91C1C;
  margin-bottom: 12px;
  line-height: 1.5;
}
.lf-error svg { flex-shrink: 0; margin-top: 2px; }

/* Remember + forgot */
.lf-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.lf-remember {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.82rem;
  font-weight: 500;
  color: #6B7280;
  cursor: pointer;
  user-select: none;
}
.lf-remember .chk {
  width: 16px;
  height: 16px;
}

.lf-forgot {
  font-size: 0.82rem;
  font-weight: 500;
  color: #E8891C;
  text-decoration: none;
}
.lf-forgot:hover { text-decoration: underline; }

/* Sign in button */
.lf-btn {
  width: 100%;
  padding: 12px;
  background: var(--clr-primary);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 18px;
  transition: opacity 0.2s, transform 0.15s;
}
.lf-btn:hover {
  opacity: 0.9;
  transform: translateY(-1px);
}
.lf-btn:active { transform: scale(0.98); }
.lf-btn:disabled { opacity: 0.55; cursor: not-allowed; transform: none; }

/* Register link */
.lf-register {
  text-align: center;
  font-size: 0.85rem;
  color: #6B7280;
  margin-bottom: 14px;
}
.lf-register a { color: #E8891C; font-weight: 500; text-decoration: none; }
.lf-register a:hover { text-decoration: underline; }

/* Demo hint */
.lf-demo {
  display: flex;
  align-items: center;
  margin-top: 20px;
  gap: 10px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 8px 12px;
}
.demo-tag {
  background: var(--clr-success);
  color: white;
  font-size: 0.68rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 4px;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}
#demo-creds { color: #6B7280; font-family: monospace; font-size: 0.7rem; }

/* Footer below card */
.login-footer {
  font-size: 0.72rem;
  color: #9ca3af;
  text-align: center;
  margin: 0;
  pointer-events: none;
}

/* ════════════════════════════════════════════════════════════════
   FORGOT PASSWORD SCREEN  /  EMAIL VERIFY SCREEN
════════════════════════════════════════════════════════════════ */
#forgot-screen,
#verify-screen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* See #login-screen's comment above — same overflow-clips-the-top fix. */
  justify-content: safe center;
  gap: 16px;
  background: #EDE9E0;
  padding: 24px 16px;
  box-sizing: border-box;
}
@media (max-width: 768px) {
  #forgot-screen, #verify-screen { padding: 16px; }
}
.fp-card {
  /* now used as the inner form content — no card shadow/radius of its own */
  padding: 0;
  width: 100%;
  animation: card-in 0.42s cubic-bezier(.22,1,.36,1) both;
}
.fp-brand { display:flex;flex-direction:column;align-items:center;margin-bottom:20px }
.fp-logo  { height:28px;width:auto;object-fit:contain;margin-bottom:8px }
.fp-brand-name { font-size:1.1rem;font-weight:700;color:#1f2937;letter-spacing:-0.01em;line-height:1.1 }
.fp-brand-sub  { font-size:0.7rem;color:#9ca3af;margin-top:2px }
.fp-step { opacity:0;transition:opacity 0.3s ease;display:none }
.fp-step.active { display:block;opacity:1 }
.fp-icon-row { display:flex;justify-content:center;margin-bottom:16px }
.fp-icon-circle {
  width:60px;height:60px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  flex-shrink:0;
}
.fp-icon-circle.orange { background:var(--clr-primary-tint); }
.fp-icon-circle.green  { background:var(--clr-success-tint); }
.fp-icon-circle.blue   { background:var(--clr-info-tint); }
.fp-icon-circle.red    { background:var(--clr-danger-tint); }
.fp-icon-circle svg    { width:26px;height:26px;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round }
.fp-icon-circle.orange svg { stroke:#C4620A }
.fp-icon-circle.green  svg { stroke:#15803d }
.fp-icon-circle.blue   svg { stroke:#1d4ed8 }
.fp-icon-circle.red    svg { stroke:#b91c1c }
.fp-title { font-size:1.15rem;font-weight:700;color:#1f2937;text-align:center;letter-spacing:-0.02em;margin-bottom:6px }
.fp-title.success-color { color:#16a34a }
.fp-desc  { font-size:0.84rem;color:#6b7280;text-align:center;line-height:1.55;margin-bottom:6px }
.fp-desc strong { color:#1f2937;font-weight:600 }
.fp-sub   { font-size:0.76rem;color:#9ca3af;text-align:center;margin-bottom:16px }
.fp-group { margin-bottom:14px }
.fp-label { display:block;font-size:0.78rem;font-weight:600;color:#374151;margin-bottom:5px }
.fp-input { width:100%;padding:11px 14px;border:1.5px solid #e5e7eb;border-radius:8px;font-family:'Poppins',sans-serif;font-size:0.9rem;color:#1C1C1C;background:#fff;outline:none;transition:border-color .2s,box-shadow .2s }
.fp-input:focus { border-color:#E8891C;box-shadow:0 0 0 3px rgba(232,137,28,.1) }
.fp-input.error { border-color:#DC2626;box-shadow:0 0 0 3px rgba(220,38,38,.08) }
.fp-pw-wrap { position:relative }
.fp-pw-wrap .fp-input { padding-right:44px }
.fp-pw-eye { position:absolute;right:0;top:0;bottom:0;width:42px;display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;color:#9CA3AF;transition:color .2s }
.fp-pw-eye:hover { color:#E8891C }
.fp-field-error, .field-error {
  display: none;
  align-items: flex-start;
  gap: 10px;
  background: #FEF2F2;
  border: 1px solid #FECACA;
  border-left: 4px solid #DC2626;
  border-radius: 8px;
  padding: 11px 14px;
  font-size: 0.83rem;
  font-weight: 500;
  color: #B91C1C;
  line-height: 1.5;
  margin-top: 14px;
}
.fp-field-error.show, .field-error.show { display: flex; }
.fp-field-error::before, .field-error::before {
  content: "";
  width: 16px; height: 16px; flex-shrink: 0; margin-top: 2px;
  background: no-repeat center / contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23DC2626' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12' y2='16'/%3E%3C/svg%3E");
}
.fp-hint { font-size:0.73rem;color:#9ca3af;margin-bottom:14px;line-height:1.5 }
/* Progress dots */
.fp-progress { display:flex;align-items:center;justify-content:center;gap:6px;margin:0 0 20px }
.fp-dot { width:7px;height:7px;border-radius:50%;background:#e5e7eb;transition:all .35s cubic-bezier(.34,1.56,.64,1) }
.fp-dot.active { background:var(--clr-primary);width:20px;border-radius:4px }
.fp-dot.done   { background:var(--clr-primary);opacity:.38 }

/* Buttons */
.fp-btn-primary { display:inline-flex;align-items:center;gap:6px;background:var(--clr-primary);color:#fff;border:none;border-radius:9px;padding:11px 22px;font-family:'Poppins',sans-serif;font-size:0.88rem;font-weight:600;cursor:pointer;transition:opacity .2s,transform .1s }
.fp-btn-primary:hover { opacity:.9 }
.fp-btn-primary:active { transform:scale(.98) }
.fp-btn-primary:disabled { opacity:.55;cursor:not-allowed;transform:none }
.fp-btn-primary.full { width:100%;justify-content:center }
.fp-btn-outline { display:inline-flex;align-items:center;justify-content:center;gap:6px;background:#fff;color:var(--clr-primary);border:1.5px solid var(--clr-primary);border-radius:9px;padding:11px 22px;font-family:'Poppins',sans-serif;font-size:0.88rem;font-weight:600;cursor:pointer;transition:background .2s,transform .1s }
.fp-btn-outline:hover { background:var(--clr-primary-tint) }
.fp-btn-outline:active { transform:scale(.98) }
.fp-btn-outline.full { width:100%;justify-content:center }
/* Unified with .auth-back-link ("Back to Website" on the login screen) —
   same color/weight/hover-arrow-slide/focus-ring, so every "go back" link
   across the auth flow (login, forgot-password, registration) reads as the
   same component instead of two similar-but-different treatments. */
.fp-back-link { display:inline-flex;align-items:center;gap:5px;font-size:0.79rem;color:#9ca3af;background:none;border:none;cursor:pointer;font-family:'Poppins',sans-serif;padding:0;font-weight:600;transition:color .2s ease;text-decoration:none }
.fp-back-link svg { transition:transform .2s ease }
.fp-back-link:hover { color:#E8760A;text-decoration:none }
.fp-back-link:hover svg { transform:translateX(-2px) }
.fp-back-link:focus-visible { outline:2px solid #E8760A;outline-offset:3px;border-radius:4px }
.fp-btn-row { display:flex;align-items:center;justify-content:space-between;margin-top:6px }

/* OTP inputs */
.otp-row { display:flex;gap:9px;justify-content:center;margin:16px 0 }
.otp-input { width:46px;height:54px;border:1.5px solid #e5e7eb;border-radius:10px;text-align:center;font-size:1.25rem;font-weight:700;font-family:'Poppins',sans-serif;color:#1f2937;background:#fff;outline:none;transition:border-color .2s,box-shadow .2s,transform .15s cubic-bezier(.34,1.56,.64,1) }
.otp-input:focus { border-color:#E8891C;box-shadow:0 0 0 3px rgba(232,137,28,.12);transform:translateY(-2px) }
.otp-input.error { border-color:#DC2626;box-shadow:0 0 0 3px rgba(220,38,38,.08) }

/* Timer pill */
.fp-timer { display:flex;align-items:center;gap:5px;font-size:0.73rem;font-weight:600;color:#6b7280;background:#f3f4f6;border-radius:99px;padding:4px 12px;margin:0 auto 12px;width:fit-content }
.fp-timer svg { flex-shrink:0 }
.fp-timer.expired { color:#DC2626;background:#fef2f2 }
.fp-resend-row { text-align:center;font-size:0.78rem;color:#9ca3af;margin-bottom:14px }
#fp-s1-cooldown-row { margin-top:10px;margin-bottom:0 }
.fp-resend-link { background:none;border:none;color:#E8891C;cursor:pointer;font-size:0.78rem;font-family:'Poppins',sans-serif;font-weight:600;padding:0;transition:opacity .15s }
.fp-resend-link:hover:not(:disabled) { opacity:.75 }
.fp-resend-link:disabled { color:#9ca3af;cursor:not-allowed;opacity:1 }
.fp-spinner { width:14px;height:14px;border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:fp-spin .7s linear infinite;display:inline-block }
@keyframes fp-spin { to { transform:rotate(360deg) } }
@keyframes fp-bounce { 0%,100%{transform:scale(1)}40%{transform:scale(1.18)}70%{transform:scale(.93)} }
.fp-success-anim { animation:fp-bounce .55s ease both }
.fp-toast { position:fixed;bottom:24px;right:24px;background:#1f2937;color:#fff;padding:10px 18px;border-radius:8px;font-size:0.82rem;font-weight:500;opacity:0;transform:translateY(8px);transition:opacity .3s,transform .3s;pointer-events:none;z-index:999 }
.fp-toast.show { opacity:1;transform:translateY(0) }

/* ════════════════════════════════════════════════════════════════
   REGISTRATION SCREEN
════════════════════════════════════════════════════════════════ */
#register-screen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* See #login-screen's comment (above in this file) — same overflow-
     clips-the-top fix, and the most relevant of the four here: this is
     the screen most likely to actually exceed one viewport (register's
     Step 3, on a short/zoomed-in window). */
  justify-content: safe center;
  gap: 10px;
  background: #EDE9E0;
  /* Trimmed from the previous 32px — the card itself is already sized
     tightly to its tallest step (see .auth-split-card's min-height
     comment), so this outer padding plus the footer line below it was
     just enough extra height to push the page a few pixels past one
     viewport and force a scrollbar even though the content basically
     already fits in one view. */
  padding: 20px 16px;
}

@media (max-width: 768px) {
  #register-screen {
    padding: 20px 16px;
    align-items: center;
  }
}

/* Title */
.reg-title {
  font-size: 1.15rem;
  font-weight: 700;
  color: #1f2937;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}
.reg-desc {
  font-size: 0.8rem;
  color: #6b7280;
  margin-bottom: 18px;
}
.reg-desc a, .reg-terms-link {
  color: #E8891C; font-weight: 600; text-decoration: underline; cursor: pointer;
  transition: color 0.2s ease;
}
.reg-desc a:hover, .reg-terms-link:hover { color: #C4620A; }

/* Field groups */
.reg-group { margin-bottom: 0; }
.reg-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  color: #374151;
  margin-bottom: 4px;
}
.reg-req { color: #E8891C; }
.reg-input {
  width: 100%;
  padding: 10px 12px;
  border: 1.5px solid #e5e7eb;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
  color: #1C1C1C;
  background: #fff;
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  box-sizing: border-box;
}
select.reg-input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
  cursor: pointer;
}
select.reg-input:focus {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23E8891C' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
select.reg-input option[value=""] { color: #9CA3AF; }
select.reg-input option { color: #1C1C1C; }
input[type="date"].reg-input {
  cursor: text;
  /* Force light-mode rendering so the browser's native date-field text
     (mm/dd/yyyy hint + edit fields) uses dark-on-light colours regardless
     of the OS dark-mode setting. Without this, Chrome Android/Safari render
     those internal fields with light (nearly invisible) text against the
     white background set by .reg-input. */
  color-scheme: light;
}
/* Matches the .form-input date fields used in the admin modals: plain
   native <input type="date">, native icon, native click/typing behaviour —
   no custom overlay icon or click-zone JS. Pointer only over the icon
   itself (browser default); text cursor everywhere else. */
input[type="date"].reg-input::-webkit-calendar-picker-indicator {
  cursor: pointer;
}
/* Explicitly colour the webkit date-edit sub-fields on WebKit/Blink so they
   remain visible even when the system prefers dark mode. */
input[type="date"].reg-input::-webkit-datetime-edit,
input[type="date"].reg-input::-webkit-datetime-edit-fields-wrapper,
input[type="date"].reg-input::-webkit-datetime-edit-text,
input[type="date"].reg-input::-webkit-datetime-edit-month-field,
input[type="date"].reg-input::-webkit-datetime-edit-day-field,
input[type="date"].reg-input::-webkit-datetime-edit-year-field {
  color: #1C1C1C;
  -webkit-text-fill-color: #1C1C1C;
}
.reg-input:focus {
  border-color: #E8891C;
  box-shadow: 0 0 0 3px rgba(232,137,28,.1);
}
.reg-input.error {
  border-color: #DC2626;
  box-shadow: 0 0 0 3px rgba(220,38,38,.08);
}
.reg-row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 16px;
}
.reg-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 16px;
}
/* min-width:0 overrides the grid item's default min-width:auto, which
   otherwise lets a field's intrinsic content size (e.g. a real <input>'s
   own browser-default min width, wider than a plain <span> ever needed)
   force its column wider than its 1fr sibling — breaking the equal
   side-by-side sizing .reg-form-grid is meant to guarantee. */
.reg-form-grid .reg-group { margin-bottom: 0; min-width: 0; }
.reg-full { grid-column: 1 / -1; }
.reg-row-3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px 16px;
}

/* QR notice */
.qr-notice {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  background: #FFF7ED;
  border-left: 3px solid #E8891C;
  border-radius: 8px;
  padding: 7px 12px;
  margin: 6px 0 0;
  font-size: 0.75rem;
  color: #92400e;
  line-height: 1.5;
}
.qr-notice svg { flex-shrink: 0; margin-top: 2px; }
.qr-notice p { margin: 0; }

/* Terms & Conditions / Data Privacy agreement row */
.reg-terms {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 8px 0 8px;
  font-size: 0.78rem;
  color: #6b7280;
  line-height: 1.5;
}
.reg-terms .chk { flex-shrink: 0; margin-top: -1px; }
.reg-terms a { color: #E8891C; font-weight: 600; text-decoration: underline; cursor: pointer; transition: color 0.2s ease; }
.reg-terms a:hover { color: #C4620A; }
.appt-policy-link { color: #C2410C; font-weight: 600; text-decoration: underline; cursor: pointer; transition: color 0.2s ease; }
.appt-policy-link:hover { color: #9A3412; }
/* Sits as its own block right below the "I have read and agree..." row
   (previously nested inline at the tail end of that paragraph) and in
   blue rather than the same muted orange as everything else on this
   screen — testers said the old version (smaller, orange, buried inside
   the paragraph text) was easy to miss on first glance. Blue reads as a
   distinct "read this first" notice rather than blending into the page's
   own brand-orange accents.
   Structurally matches .qr-notice below it (same shaded-left-edge pill:
   flat background + border-left accent instead of a full border, full-
   width block instead of shrink-wrapped, align-items:flex-start + a
   small icon margin-top so the icon lines up with the first line of text
   instead of floating centered across the whole 2-line block) — the two
   should read as the same visual language, not two different pill styles. */
.reg-terms-hint {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  /* This class also gets reused nested inline right after the "I have
     read and agree..." paragraph text in the booking wizard's own
     Appointment Policy checkbox (pages.js, #appt-terms-hint) — unlike
     registration's own instance, which sits as its own block below a
     margined row, that one has nothing else providing separation from
     the text directly above it, so it read as jammed against it without
     this. Harmless extra breathing room on the registration instance too. */
  margin-top: 8px;
  margin-bottom: 8px;
  font-size: 0.82rem;
  font-weight: 600;
  color: #1D4ED8;
  background: #EFF6FF;
  border-left: 3px solid #1D4ED8;
  border-radius: 8px;
  padding: 7px 12px;
  line-height: 1.5;
}
.reg-terms-hint svg { flex-shrink: 0; margin-top: 2px; }
/* Appointment Policy's own instance reads better shrink-wrapped to its text
   instead of stretching the full width of the review step (registration's
   instance stays full width — untouched). */
#appt-terms-hint { display: inline-flex; width: fit-content; max-width: 100%; }

/* Scrollable Terms & Conditions modal body */
.terms-body {
  max-height: 48vh;
  overflow-y: auto;
  font-size: 0.84rem;
  color: #374151;
  line-height: 1.7;
  padding-right: 4px;
}
.terms-body h4 {
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #1C1C1C;
  margin: 18px 0 6px;
}
.terms-body h4:first-child { margin-top: 0; }
.terms-body p, .terms-body ul { margin: 0 0 10px; }
.terms-body ul { padding-left: 20px; }
.terms-body li { margin-bottom: 4px; }
.terms-scroll-hint {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.74rem;
  color: #9ca3af;
  margin-right: auto;
}

/* Actions row */
.reg-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid #F3F4F6;
}

/* Step transition animations */
@keyframes reg-slide-right {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes reg-slide-left {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.reg-slide-in-right { animation: reg-slide-right 0.32s cubic-bezier(.22,1,.36,1) both; }
.reg-slide-in-left  { animation: reg-slide-left  0.32s cubic-bezier(.22,1,.36,1) both; }

/* Step 3 compact overrides — keeps total content within 640px card */
#reg-panel-3 .reg-desc { margin-bottom: 10px; }
#reg-panel-3 .reg-form-grid { gap: 8px; }

@keyframes card-step-in {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.auth-card-step-in { animation: card-step-in 0.38s cubic-bezier(.22,1,.36,1) both; }
.reg-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1.5px solid #d1d5db;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
  font-weight: 500;
  color: #374151;
  cursor: pointer;
  padding: 10px 20px;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.reg-back-btn:hover { background: #f3f4f6; border-color: #9ca3af; }

.reg-next-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--clr-primary);
  border: 1.5px solid var(--clr-primary);
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  color: #fff;
  cursor: pointer;
  padding: 10px 22px;
  transition: background 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
  white-space: nowrap;
}
.reg-next-btn:hover { background: var(--clr-primary-dk); box-shadow: 0 3px 10px rgba(232,137,28,.3); transform: translateY(-1px); }
.reg-next-btn:active { transform: scale(0.98); }
/* Same dimmed + not-allowed convention as .btn-primary/.btn-danger
   (global.css) — this button just never had its own :disabled rule, so
   _btnBusy()'s disabled=true (main.js, handleRegister()) had nothing to
   visually show while "Creating account…" was up, no matter how real
   its spinner was. */
.reg-next-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.reg-next-btn:disabled:hover { background: var(--clr-primary); box-shadow: none; transform: none; }
.reg-next-btn svg { flex-shrink: 0; }

/* Password wrap in reg form */
.reg-pw-wrap { position: relative; }
.reg-pw-wrap .reg-input { padding-right: 44px; }

/* Section divider */
.reg-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 10px;
  color: #9ca3af;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.reg-divider::before, .reg-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #e5e7eb;
}

/* Hint text below fields */
.reg-hint {
  font-size: 0.68rem;
  color: #9ca3af;
  margin-top: 2px;
  margin-bottom: 0;
  min-height: 14px;
}
.reg-hint.error { color: #dc2626; }

/* ── Multi-step registration stepper ── */
.reg-stepper {
  display: flex;
  align-items: flex-start;
  margin: 20px auto 28px;
  max-width: 360px;
  width: 100%;
}
.reg-step-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
}
.reg-step-dot {
  width: 38px; height: 38px; border-radius: 50%;
  border: 2px solid #E5E7EB; background: #F9FAFB;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.82rem; font-weight: 700; color: #C4C9D4;
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
  transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease, box-shadow 0.3s ease;
}
.reg-step-lbl {
  font-size: 0.68rem; font-weight: 500; color: #B0B8C8;
  white-space: nowrap; letter-spacing: 0.01em;
  transition: color 0.25s ease, font-weight 0.1s ease;
}
.reg-step-line {
  flex: 1; height: 2px; background: #EAECF0; border-radius: 2px;
  margin: 18px 6px 0; /* (38-2)/2 = 18 — aligns line with dot center */
  transition: background 0.3s ease;
  min-width: 24px;
}
.reg-step-line.reg-step-line-done { background: #E8891C; }
.reg-step-active .reg-step-dot {
  background: #E8891C; border-color: #E8891C; color: #fff;
  box-shadow: 0 0 0 4px rgba(232,137,28,.15), 0 2px 10px rgba(232,137,28,.35);
}
.reg-step-active .reg-step-lbl { color: #E8891C; font-weight: 700; }
.reg-step-done .reg-step-dot {
  background: #E8891C; border-color: #E8891C; color: #fff;
  box-shadow: 0 1px 6px rgba(232,137,28,.25);
}
.reg-step-done .reg-step-lbl { color: #B45309; font-weight: 600; }

/* T&C open button (Step 3) */
.reg-terms-open-btn {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 11px 16px; margin: 18px 0 10px;
  background: #fff; border: 1.5px solid #E8760A; border-radius: 8px;
  color: #E8760A; font-size: 0.84rem; font-weight: 600; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.reg-terms-open-btn:hover { background: #fff7ed; border-color: #C4620A; color: #C4620A; }

/* Inline T&C scrollable box (Step 3) */
.reg-terms-box {
  border: 1px solid #E5E7EB; border-radius: 8px;
  padding: 14px 16px; max-height: 220px; overflow-y: auto;
  font-size: 0.78rem; color: #374151; line-height: 1.65;
  margin-top: 20px; margin-bottom: 14px; background: #FAFAFA;
}
.reg-terms-box h4 {
  font-size: 0.78rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: #1C1C1C; margin: 14px 0 5px;
}
.reg-terms-box h4:first-child { margin-top: 0; }
.reg-terms-box p { margin: 0 0 8px; }
.reg-terms-box ul { margin: 4px 0 8px; padding-left: 18px; }
.reg-terms-box li { margin-bottom: 3px; }

/* ════════════════════════════════════════════════════════════════
   SIDEBAR
════════════════════════════════════════════════════════════════ */
#sidebar {
  width: 236px;
  height: 100vh;
  height: 100dvh;
  background: #ffffff;
  border-right: 1px solid #e5e7eb;
  position: fixed;
  left: 0; top: 0;
  display: flex;
  flex-direction: column;
  z-index: 1045;
  transition: width 0.28s cubic-bezier(.4,0,.2,1), transform 0.28s cubic-bezier(.4,0,.2,1);
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#sidebar.collapsed { width: 60px; }

#main-area {
  flex: 1;
  min-width: 0;
  margin-left: 236px;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  transition: margin-left 0.28s cubic-bezier(.4,0,.2,1);
}
#main-area.collapsed { margin-left: 60px; }

/* Mobile sidebar backdrop */
#sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1040;
  background: rgba(0, 0, 0, 0.45);
  cursor: pointer;
}
#sidebar-overlay.show { display: block; }

/* Sidebar profile (top of sidebar) */
.sidebar-profile-wrap {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 16px 14px 14px;
  border-bottom: 1px solid #E5E7EB;
  flex-shrink: 0;
  overflow: hidden;
}
.sidebar-profile-avatar {
  width: 42px !important;
  height: 42px !important;
  font-size: .9rem !important;
  flex-shrink: 0;
}
.sidebar-profile-info {
  min-width: 0;
  overflow: hidden;
  opacity: 1;
  transition: opacity 0.2s ease;
}
.sidebar-profile-name {
  font-size: .85rem;
  font-weight: 700;
  color: #1f2937;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-profile-role {
  font-size: .7rem;
  font-weight: 600;
  color: #E8760A;
  text-transform: uppercase;
  letter-spacing: .05em;
  white-space: nowrap;
}

/* Sidebar brand */
.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 20px 16px;
  border-bottom: 1px solid #e5e7eb;
  overflow: hidden;
  flex-shrink: 0;
}
.sidebar-brand-img {
  width: 36px;
  height: 36px;
  object-fit: contain;
  border-radius: 50%;
  background: white;
  flex-shrink: 0;
  padding: 2px;
}
.sidebar-brand-text {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  white-space: nowrap;
}
.sidebar-brand-name {
  font-family: 'Poppins', sans-serif;
  font-size: 1rem;
  font-weight: 700;
  color: #1f2937;
  letter-spacing: -0.01em;
}
.sidebar-brand-clinic {
  font-size: 0.7rem;
  color: #9CA3AF;
  letter-spacing: 0.04em;
}

/* Role badge */
.sidebar-role-wrap {
  display: none;
}
.sidebar-role-badge {
  display: inline-block;
  background: rgba(232,118,10,.2);
  color: #E8760A;
  font-family: 'Poppins', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
}

/* Sidebar nav */
.sidebar-nav {
  flex: 0 0 auto;
  padding: 8px 0;
  overflow: visible;
}

/* Nav section label */
.nav-section-label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px 4px;
  overflow: hidden;
}
.nav-section-label span {
  font-size: .62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: #9CA3AF;
  white-space: nowrap;
  opacity: 1;
  transition: opacity 0.2s ease;
}
.nav-section-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #E5E7EB;
  min-width: 0;
}

/* Nav item */
.nav-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
  margin: 1px 6px;
  border-radius: 8px;
  color: #374151;
  cursor: pointer;
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.15s, color 0.15s, padding 0.28s cubic-bezier(.4,0,.2,1);
  user-select: none;
}
.nav-item:hover { background: #f3f4f6; color: #111827; }
.nav-item.active {
  background: var(--clr-primary);
  color: white;
  font-weight: 600;
}
.nav-item.active svg { stroke: white !important; }
.nav-item.nav-parent-open { background: #f3f4f6; color: #374151; }
.nav-item.nav-parent-open.active { background: #FFF8F0; color: #E8760A; font-weight: 600; }
.nav-item.nav-parent-open.active svg { stroke: #374151 !important; }
.nav-item svg { flex-shrink: 0; }
.nav-item-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 1;
  line-height: 1.3;
  transition: opacity 0.2s ease;
}

/* Dropdown arrow */
.nav-arrow {
  flex-shrink: 0;
  width: 14px; height: 14px;
  transition: transform 0.2s, opacity 0.2s ease;
  stroke: currentColor;
  opacity: 1;
}
.nav-arrow.open { transform: rotate(180deg); }

/* Sub-menu */
.nav-submenu {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.25s ease;
}
.nav-submenu.open { max-height: 300px; }

.nav-sub-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 16px 7px 43px;
  margin: 1px 8px;
  border-radius: 7px;
  color: #374151;
  cursor: pointer;
  font-family: 'Poppins', sans-serif;
  font-size: 0.79rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  transition: background 0.15s, color 0.15s;
}
.nav-sub-item:hover { background: #f3f4f6; color: #111827; }
.nav-sub-item.active { background: #FFF8F0; color: #E8891C; font-weight: 600; }
.nav-sub-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* Exam wizard — OD/OS inner field grid */
.wiz-eye-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

/* Exam wizard stepper — overflow-x:auto only kicks in on a viewport too
   narrow to fit all 7 steps, and the browser already only renders a
   scrollbar then; the thin/subtle styling here just keeps that scrollbar
   from being the thick default OS bar when it does show, without ever
   hiding it outright — a step scrolled off-screen (e.g. Consultation at
   phone width) needs to stay discoverable, not disappear silently. */
#wiz-stepper {
  scrollbar-width: thin;
}
#wiz-stepper::-webkit-scrollbar {
  height: 5px;
}
#wiz-stepper::-webkit-scrollbar-thumb {
  background: #e5e7eb;
  border-radius: 4px;
}
#wiz-stepper::-webkit-scrollbar-track {
  background: transparent;
}

/* Sidebar footer */
.sidebar-foot {
  border-top: 1px solid #e5e7eb;
  padding: 12px 8px;
  overflow: hidden;
  flex-shrink: 0;
  margin-top: auto;
}
.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border-radius: 8px;
  overflow: hidden;
  white-space: nowrap;
}
.sidebar-avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--clr-primary);
  color: white;
  font-family: 'Poppins', sans-serif;
  font-size: 0.72rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sidebar-user-info { overflow: hidden; }
.sidebar-user-name {
  font-size: 0.82rem;
  font-weight: 600;
  color: #1f2937;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-user-email {
  font-size: 0.7rem;
  color: #9CA3AF;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-logout {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 8px;
  border-radius: 8px;
  color: #374151;
  cursor: pointer;
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  margin-top: 4px;
  transition: background 0.15s, color 0.15s;
}
.sidebar-logout span {
  opacity: 1;
  transition: opacity 0.2s ease;
}
.sidebar-logout:hover { background: #f3f4f6; color: #ef4444; }
.sidebar-view-link:hover { background: #FFF8F0; color: #E8760A; }

/* Role badge color variants */
.sidebar-role-badge.role-admin   { background: rgba(232,137,28,0.18); color: #E8891C; }
.sidebar-role-badge.role-staff   { background: rgba(59,130,246,0.18); color: #60A5FA; }
.sidebar-role-badge.role-doctor  { background: rgba(16,185,129,0.18); color: #34D399; }
.sidebar-role-badge.role-patient { background: rgba(139,92,246,0.18); color: #A78BFA; }

/* Collapsed sidebar: fade + collapse text so icons center cleanly */
#sidebar.collapsed .nav-item-label,
#sidebar.collapsed .nav-arrow,
#sidebar.collapsed .sidebar-profile-info,
#sidebar.collapsed .nav-section-label span,
#sidebar.collapsed .sidebar-logout span {
  opacity: 0;
  pointer-events: none;
  width: 0;
  flex: none;
  overflow: hidden;
}
/* Submenu closes instantly when sidebar collapses */
#sidebar.collapsed .nav-submenu { max-height: 0 !important; }
/* Center icon in the collapsed item, strip horizontal padding and gap */
#sidebar.collapsed .nav-item {
  justify-content: center;
  padding: 9px 0;
  gap: 0;
}
#sidebar.collapsed .nav-item.active { padding: 9px 0; }
#sidebar.collapsed .sidebar-profile-wrap { padding: 12px 0; justify-content: center; gap: 0; }
#sidebar.collapsed .sidebar-logout { justify-content: center; padding: 8px 0; gap: 0; }
#sidebar.collapsed .nav-section-label { padding: 10px 0 4px; justify-content: center; }

/* ════════════════════════════════════════════════════════════════
   TOPBAR
════════════════════════════════════════════════════════════════ */
.topbar {
  height: 58px;
  background: white;
  border-bottom: 1px solid #E5E7EB;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  position: sticky;
  top: 0;
  z-index: 30;
  flex-shrink: 0;
  transition: box-shadow 0.2s;
}
.topbar.scrolled {
  box-shadow: 0 4px 16px rgba(0,0,0,0.08);
  border-bottom-color: transparent;
}
.topbar-left { display: flex; align-items: center; gap: 14px; }
.topbar-toggle {
  width: 34px; height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  border-radius: 7px;
  cursor: pointer;
  color: #6B7280;
  transition: background 0.15s;
}
.topbar-toggle:hover { background: #F3F4F6; color: #374151; }
.topbar-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-right: 14px;
  border-right: 1px solid #E5E7EB;
  flex-shrink: 0;
}
.topbar-brand-img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  border-radius: 6px;
}
.topbar-brand-name {
  font-family: 'Poppins', sans-serif;
  font-size: 1rem;
  font-weight: 800;
  color: #1C1C1C;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.topbar-crumb {
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  color: #6B7280;
  display: flex;
  align-items: center;
  gap: 6px;
}
.topbar-crumb strong { color: #1C1C1C; font-weight: 600; }
.topbar-crumb-link { cursor: pointer; transition: color 0.15s; }
.topbar-crumb-link:hover, .topbar-crumb-link:focus-visible { color: var(--clr-primary); text-decoration: underline; }
.topbar-right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.topbar-clinic {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-left: 12px;
  border-left: 1px solid #E5E7EB;
}
.topbar-clinic-img {
  width: 32px;
  height: 32px;
  object-fit: contain;
  border-radius: 6px;
  background: #F8F9FA;
  padding: 2px;
  border: 1px solid #E5E7EB;
}
.topbar-clinic-text {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}
.topbar-clinic-name {
  font-size: .82rem;
  font-weight: 700;
  color: #1C1C1C;
  white-space: nowrap;
}
.topbar-clinic-sub {
  font-size: .68rem;
  color: #9CA3AF;
  white-space: nowrap;
}
.topbar-user-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  background: #F8F9FA;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  color: #374151;
}
.topbar-avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--clr-primary);
  color: white;
  font-family: 'Poppins', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.topbar-notify-wrap { position: relative; }
.topbar-notify {
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  color: #6B7280;
  cursor: pointer;
  background: white;
  position: relative;
  transition: background 0.15s;
}
.topbar-notify:hover { background: #F3F4F6; }
.notify-badge {
  min-width: 17px; height: 17px;
  background: var(--clr-danger);
  color: white;
  font-size: 0.6rem;
  font-weight: 700;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  position: absolute;
  top: -4px; right: -5px;
  border: 2px solid white;
  padding: 0 3px;
  pointer-events: none;
}

/* Notification Dropdown */
.notify-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 340px;
  background: white;
  border: 1px solid #E5E7EB;
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.14), 0 2px 8px rgba(0,0,0,0.06);
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
  z-index: 200;
}
.notify-dropdown.open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.notify-dropdown-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
  border-bottom: 1px solid #F3F4F6;
}
.notify-dropdown-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: #1C1C1C;
}
.notify-mark-read {
  background: none;
  border: none;
  font-size: 0.75rem;
  font-weight: 600;
  color: #E8891C;
  cursor: pointer;
  padding: 0;
  font-family: 'Poppins', sans-serif;
}
.notify-mark-read:hover { text-decoration: underline; }
.notify-list { padding: 6px 0; max-height: 300px; overflow-y: auto; }
.notify-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  transition: background 0.12s;
  position: relative;
}
.notify-item:hover { background: #F9FAFB; }
.notify-item.unread { border-left: 3px solid #E8891C; padding-left: 13px; }
.notify-item-icon {
  width: 34px; height: 34px;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.notify-item-icon.orange { background: #FFF0DC; color: #E8891C; }
.notify-item-icon.blue   { background: #DBEAFE; color: #2563EB; }
.notify-item-icon.green  { background: #D1FAE5; color: #059669; }
.notify-item-icon.purple { background: #EDE9FE; color: #7C3AED; }
/* Both were missing entirely — _NOTIF_COLOR (router.js) maps cancelled/
   disapproved/no_show/waitlist_removed to 'red' and waitlist_left/info to
   'gray', but with no matching rule here those icons fell back to no
   background and default (black) text instead of the same red/gray the
   full Notifications page already uses (pages.js) for the identical types. */
.notify-item-icon.red    { background: #FEF2F2; color: #EF4444; }
.notify-item-icon.gray   { background: #F3F4F6; color: #6B7280; }
.notify-item-body { flex: 1; min-width: 0; }
.notify-item-title {
  font-size: 0.8rem;
  font-weight: 600;
  color: #1C1C1C;
  margin-bottom: 2px;
}
.notify-item-msg {
  font-size: 0.75rem;
  color: #6B7280;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.notify-item-time {
  font-size: 0.7rem;
  color: #9CA3AF;
  margin-top: 4px;
}
.notify-dropdown-foot {
  padding: 10px 16px;
  border-top: 1px solid #F3F4F6;
  text-align: center;
}
.notify-dropdown-foot a {
  font-size: 0.78rem;
  font-weight: 600;
  color: #E8891C;
}

/* User Dropdown */
.topbar-user-wrap { position: relative; }
.topbar-user-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  background: #F8F9FA;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  color: #374151;
  cursor: pointer;
  transition: background 0.15s;
  user-select: none;
}
.topbar-user-chip:hover { background: #F0F1F3; }
.icon-xs { width: 12px; height: 12px; }
.user-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 220px;
  background: white;
  border: 1px solid #E5E7EB;
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.14), 0 2px 8px rgba(0,0,0,0.06);
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.18s, transform 0.18s;
  z-index: 200;
  overflow: hidden;
}
.user-dropdown.open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.user-dropdown-profile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
}
.user-dropdown-avatar {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: #E8891C;
  color: white;
  font-size: 0.72rem;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.user-dropdown-name {
  font-size: 0.82rem;
  font-weight: 700;
  color: #1C1C1C;
}
.user-dropdown-email {
  font-size: 0.7rem;
  color: #9CA3AF;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}
.user-dropdown-divider { height: 1px; background: #F3F4F6; }
.user-dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  font-size: 0.82rem;
  font-weight: 500;
  color: #374151;
  cursor: pointer;
  transition: background 0.12s;
}
.user-dropdown-item:hover { background: #F9FAFB; }
.user-dropdown-item.danger { color: #DC2626; }
.user-dropdown-item.danger:hover { background: #FEF2F2; }

/* ════════════════════════════════════════════════════════════════
   MAIN CONTENT
════════════════════════════════════════════════════════════════ */
#main-content {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  background: #f5f6fa;
  scrollbar-gutter: stable;
  -webkit-overflow-scrolling: touch;
}

/* Page header */
.page-header {
  padding: 24px 32px 20px;
  background: white;
  border-bottom: 1px solid #E5E7EB;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.page-header-left {}
/* Right-side header cluster (button group + a caption below it, e.g. the
   Dashboard's Waitlist/New Appointment buttons with the date underneath).
   Desktop: right-aligned column. Mobile override further down un-aligns
   it back to full width so it stacks the same clean way every other
   page-header does (see the 480px block below). */
.page-header-right { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.page-title {
  font-family: 'Poppins', sans-serif;
  font-size: 1.5rem;
  font-weight: 700;
  color: #1C1C1C;
  letter-spacing: -0.02em;
  margin-bottom: 3px;
}
.page-subtitle { font-size: 0.82rem; color: #9CA3AF; }
.page-body {
  padding: 28px 32px;
}

/* ════════════════════════════════════════════════════════════════
   STAT CARDS
════════════════════════════════════════════════════════════════ */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}
/* 6-card grid — stays 3+3 on medium, wraps on small */
.stats-grid-6 {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
  margin-bottom: 24px;
}
.stat-card {
  background: white;
  border-radius: 12px;
  padding: 22px 24px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  min-height: 100px;
}
/* Clickable press effect */
.stat-card--clickable {
  cursor: pointer;
  transition: transform 0.12s cubic-bezier(.2,.8,.4,1), box-shadow 0.12s;
}
.stat-card--clickable:hover {
  box-shadow: 0 4px 20px rgba(0,0,0,0.09), 0 1px 4px rgba(0,0,0,0.05);
  transform: translateY(-1px);
}
.stat-card--clickable:active {
  transform: scale(0.97);
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.stat-info {}
.stat-label {
  font-family: 'Poppins', sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  color: #9CA3AF;
  margin-bottom: 6px;
}
.stat-value {
  font-family: 'Poppins', sans-serif;
  font-size: 2rem;
  font-weight: 700;
  color: #1C1C1C;
  line-height: 1;
  margin-bottom: 4px;
}
.stat-delta {
  font-size: 0.75rem;
  color: #10B981;
  font-weight: 500;
}
.stat-delta.down { color: #EF4444; }
.stat-icon {
  width: 46px; height: 46px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.stat-icon.orange { background: #FFF0DC; color: #E8760A; }
.stat-icon.green  { background: #D1FAE5; color: #059669; }
.stat-icon.blue   { background: #DBEAFE; color: #2563EB; }
.stat-icon.purple { background: #EDE9FE; color: #7C3AED; }
.stat-icon.red    { background: #FEE2E2; color: #DC2626; }
.stat-icon.teal   { background: #CCFBF1; color: #0D9488; }

/* ════════════════════════════════════════════════════════════════
   CARDS
════════════════════════════════════════════════════════════════ */
.card {
  background: white;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
  overflow: hidden;
}
.card-header {
  padding: 16px 20px;
  border-bottom: 1px solid #F3F4F6;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.card-title {
  font-family: 'Poppins', sans-serif;
  font-size: 0.9rem;
  font-weight: 700;
  color: #1C1C1C;
  display: flex;
  align-items: center;
  gap: 6px;
}
.card-subtitle { font-size: 0.78rem; color: #9CA3AF; margin-top: 1px; }
.card-body { padding: 20px; }
.chart-wrap { position: relative; height: 220px; }

/* ════════════════════════════════════════════════════════════════
   TABLES
════════════════════════════════════════════════════════════════ */
.table-wrap {
  background: white;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
  overflow: hidden;
}

/* Record row (Patient Profile Consultations / Prescriptions / Examinations
   tabs, and any similar date+meta list row): the info column wraps its own
   text at narrow widths, so it needs a guaranteed minimum width instead of
   shrinking to 0 — otherwise the trailing badge/buttons squeeze into the
   text as it wraps. Once the row is too narrow to fit everything on one
   line, the trailing group drops to its own line instead of overlapping. */
.record-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  row-gap: 8px;
  gap: 12px;
  padding: 13px 20px;
}
.record-row-info { flex: 1 1 170px; min-width: 170px; }
.record-row-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  margin-left: auto;
}
.table-toolbar {
  padding: 14px 20px;
  border-bottom: 1px solid #F3F4F6;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  min-height: 52px;
}
.table-title {
  font-family: 'Poppins', sans-serif;
  font-size: 0.9rem;
  font-weight: 700;
  color: #1C1C1C;
}
.table-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* Reusable "many fields + buttons in a row" toolbar layout — a plain flex
   row on desktop, a 2-column grid on mobile (see the media query below).
   Kept as a real class rather than inline styles specifically so that
   mobile override can switch display:flex to display:grid cleanly; an
   inline style on the element would otherwise outrank it entirely.
   Deliberately no padding/border opinions here — those vary by where it's
   used (Activity Log's bordered toolbar strip vs. Reports' plain card
   section), so each page keeps its own chrome around it. */
.filter-grid {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: flex-end;
}
/* Activity Log's specific chrome on top of .filter-grid's layout */
.activity-filter-bar {
  padding: 12px 16px;
  border-bottom: 1px solid #F3F4F6;
}

.tbl {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}
/* Archives' colgroup needs real room for 6 columns (Type/Name/Archived
   By/Reason/Date/Actions) to not feel cramped on desktop — this used to
   be an inline `min-width:700px` on the <table> itself, but an inline
   style beats any class selector regardless of media query, so the
   mobile card-stacking reset below (.tbl { min-width:0 } inside its own
   max-width:767px block) could never actually override it — the table
   stayed pinned to 700px and forced horizontal overflow on a narrow
   screen instead of collapsing into cards like every other .tbl already
   does. Scoping this to min-width:768px (desktop only) instead of an
   inline style keeps that overflow from ever happening. */
@media (min-width: 768px) {
  .archives-tbl { min-width: 700px; }
}
.tbl thead tr { background: #f8f9fa; }
.tbl th {
  padding: 12px 16px;
  text-align: left;
  font-family: 'Poppins', sans-serif;
  font-size: 0.72rem;
  font-weight: 600;
  color: #6b7280;
  border-bottom: 1px solid #e5e7eb;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tbl td {
  padding: 12px 16px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  color: #374151;
  border-bottom: 1px solid #e5e7eb;
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background 0.15s;
}
.tbl tbody tr:last-child td { border-bottom: none; }
.tbl tbody tr { transition: background 0.15s; }
.tbl tbody tr:hover td { background: #FFFBF5; }

/* Patient appointments — action buttons: always one row, smaller on mobile */
.pt-appt-act { display: flex; gap: 4px; align-items: center; }
@media (max-width: 767px) {
  .pt-appt-act { gap: 2px; }
  .pt-appt-act .btn-icon { width: 26px; height: 26px; }
  .pt-appt-act .btn-icon .icon-sm { width: 12px; height: 12px; }
}

/* Patient name cell — allow wrap for two-line name+ID layout */
.patient-name-cell { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: visible; }
.patient-name-info { min-width: 0; overflow: hidden; }
.patient-name-info strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.patient-name-info span   { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Solid fill for all default (no-photo) person avatars */
.patient-avatar,
.profile-avatar-lg {
  border-radius: 50%;
  background: var(--clr-primary);
  color: #fff;
  font-family: 'Poppins', sans-serif;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}

.patient-avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--clr-primary);
  color: #fff;
  font-family: 'Poppins', sans-serif;
  font-size: 0.72rem;
  font-weight: 700;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.patient-name-info strong { font-weight: 600; color: #1C1C1C; }

/* Contact Messages inbox — Gmail-style unread emphasis */
.msg-unread .patient-name-info strong { font-weight: 800; }
.msg-unread td { color: #1C1C1C; }
.msg-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--clr-primary); flex-shrink: 0; margin-right: -2px; }
.tbl tbody tr:hover { background: #FAFAFA; }

/* Sidebar item unread-count badge (e.g. Contact Messages) */
.nav-badge {
  margin-left: auto; flex-shrink: 0;
  background: var(--clr-primary); color: #fff;
  font-size: 0.66rem; font-weight: 700;
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  line-height: 1;
}
.nav-item.active .nav-badge { background: rgba(255,255,255,0.3); }
#sidebar.collapsed .nav-badge { display: none; }
/* Waitlist button's count badge reuses .nav-badge, but its margin-left:auto
   (meant to pin it to the far edge of a width-stretched sidebar row) fights
   justify-content:center inside a button — the auto margin still eats all
   the free space, shoving the icon+label to one side while the badge sits
   alone at the opposite edge. Most visible once the button goes full-width
   on mobile. Sit it right next to the label instead so icon+label+badge
   center together as one group. */
.btn-primary .nav-badge, .btn-secondary .nav-badge { margin-left: 2px; }
.patient-name-info span { font-size: 0.75rem; color: #9CA3AF; }

/* Table empty */
.table-empty {
  text-align: center;
  padding: 24px 20px;
  color: #9CA3AF;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
}

/* Shared row layout for the patient-facing "history list with search"
   pattern (Prescriptions/Examination History/Consultations — .rx-hist-row/
   .exam-hist-row/.con-hist-row). Deliberately a real class, not inline
   style: the search filters toggle visibility via row.style.display = ''
   to un-hide a row, which clears the CURRENT inline display value rather
   than restoring whatever it used to be — when display:flex lived only in
   that same inline style, clearing it left the row with no display
   declared at all, so it fell back to a <div>'s default block and the
   whole row collapsed into a vertical stack the moment a search matched
   it again. Living in a stylesheet rule instead means that fallback is
   flex, not block, regardless of how many times a filter clears the
   inline override. */
.hist-row { display: flex; align-items: center; flex-wrap: wrap; row-gap: 8px; gap: 12px; padding: 13px 20px; border-bottom: 1px solid #F3F4F6; }
.hist-row-featured { background: #FAFAF8; }
.hist-row-info { flex: 1 1 170px; min-width: 170px; }
.hist-row-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; margin-left: auto; }
/* Real-time "no results" row a live text search inserts into a .tbl table
   (see main.js's _syncSearchEmptyState()) — .table-empty already gives it
   the exact same look every other "nothing here" message uses; this just
   also stops it from picking up .tbl tbody tr:hover's cream highlight,
   since unlike a real data row it isn't clickable and shouldn't read as
   interactive. */
.tbl tbody tr.tbl-search-empty:hover td { background: transparent; }

/* ════════════════════════════════════════════════════════════════
   BADGES
════════════════════════════════════════════════════════════════ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 12px;
  border-radius: 9999px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.72rem;
  font-weight: 500;
  white-space: nowrap;
}
/* Pending → orange */
.badge-pending      { background: #FFF3E0; color: #E8891C; }
/* Approved → green */
.badge-approved     { background: #E8F5E9; color: #2E7D32; }
/* Cancelled / Inactive → red */
.badge-cancelled    { background: #FFEBEE; color: #C62828; }
.badge-inactive     { background: #FFEBEE; color: #C62828; }
/* Disapproved → dark muted red */
.badge-disapproved  { background: #fef2f2; color: #991b1b; }
/* Completed → gray */
.badge-completed    { background: #F5F5F5; color: #616161; }
.badge-no-show      { background: #EDE9FE; color: #6D28D9; }
/* Active → blue */
.badge-active       { background: #E3F2FD; color: #1565C0; }
/* Role badges */
.badge-admin        { background: #EDE9FE; color: #5B21B6; }
.badge-staff        { background: #DBEAFE; color: #1D4ED8; }
.badge-doctor       { background: #E8F5E9; color: #2E7D32; }
.badge-patient      { background: #FFF0DC; color: #92400E; }

/* ════════════════════════════════════════════════════════════════
   BUTTONS
════════════════════════════════════════════════════════════════ */
.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 20px;
  background: var(--clr-primary);
  color: white;
  border: none;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.2s, transform 0.1s;
  white-space: nowrap;
}
.btn-primary:hover:not(:disabled) { opacity: 0.9; }
.btn-primary:active:not(:disabled) { transform: scale(0.98); }
.btn-primary:focus-visible { outline: 2px solid #E8760A; outline-offset: 2px; }
.btn-primary:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-secondary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 20px;
  background: white;
  color: #374151;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.btn-secondary:hover { background: #F9FAFB; border-color: #D1D5DB; }
.btn-secondary:focus-visible { outline: 2px solid #E5E7EB; outline-offset: 2px; }

.btn-danger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: var(--clr-danger);
  color: #fff;
  border: none;
  border-radius: 7px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.18s ease, opacity 0.15s ease;
}
.btn-danger:hover:not(:disabled) { background: #B91C1C; }
.btn-danger:active:not(:disabled) { background: #991B1B; }
.btn-danger:focus-visible { outline: 2px solid #DC2626; outline-offset: 2px; }
.btn-danger:disabled { opacity: 0.45; cursor: not-allowed; }
/* .btn-danger/.btn-success/.btn-warning/.btn-disapprove/.btn-ghost are all
   deliberately sized as the smaller "compact toolbar" class for pairings
   like "Clear Filters" + "Clear All Logs". Inside a modal footer they're
   instead paired with .btn-primary/.btn-secondary, a size class up —
   match that pairing everywhere it happens.
   This used to be a couple of adjacent-sibling selectors (e.g.
   `.btn-secondary + .btn-danger`), which only matched when that exact
   button happened to sit immediately next to .btn-secondary in the
   markup — a modal footer with more than two buttons (e.g. Close,
   Approve, Cancel, Disapprove) put .btn-danger right after .btn-success
   instead, so the size-match silently never applied and buttons in the
   same footer ended up visibly two different sizes. An ancestor selector
   on .modal-footer itself matches regardless of order/adjacency. */
.modal-footer .btn-danger,
.modal-footer .btn-success,
.modal-footer .btn-warning,
.modal-footer .btn-disapprove,
.modal-footer .btn-ghost {
  padding: 9px 20px; font-size: 0.85rem; border-radius: 8px;
}

.btn-success {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: #E8F5E9;
  color: #2E7D32;
  border: none;
  border-radius: 7px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
  white-space: nowrap;
}
.btn-success:hover { background: #C8E6C9; }
.btn-success:disabled { opacity: 0.6; cursor: not-allowed; }

.btn-warning {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: #FFF3E0;
  color: #E8891C;
  border: none;
  border-radius: 7px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
  white-space: nowrap;
}
.btn-warning:hover { background: #FFE0B2; }

.btn-disapprove {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: #fef2f2;
  color: #991b1b;
  border: 1px solid #fecaca;
  border-radius: 7px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.btn-disapprove:hover { background: #fee2e2; border-color: #fca5a5; }
.btn-disapprove:disabled { opacity: 0.6; cursor: not-allowed; }

/* Live password policy checklist */
.pw-checklist { display: flex; flex-direction: column; gap: 5px; margin: 8px 0 2px; }
.pw-check-item { display: flex; align-items: center; gap: 7px; font-size: 0.78rem; color: #9CA3AF; transition: color 0.15s ease; }
.pw-check-item svg { width: 14px; height: 14px; flex-shrink: 0; }
.pw-check-item.met { color: #059669; }
.pw-check-item.unmet { color: #DC2626; }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  background: transparent;
  color: #6B7280;
  border: 1px solid #E5E7EB;
  border-radius: 7px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;
  white-space: nowrap;
}
.btn-ghost:hover { background: #F3F4F6; color: #374151; border-color: #D1D5DB; }
.btn-ghost:active { transform: scale(0.97); }
.btn-ghost:focus-visible { outline: 2px solid #E5E7EB; outline-offset: 2px; }

.btn-block { width: 100%; justify-content: center; }

.btn-icon {
  width: 32px; height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #E5E7EB;
  border-radius: 7px;
  color: #6B7280;
  cursor: pointer;
  background: white;
  transition: background 0.15s, color 0.15s, transform 0.1s, box-shadow 0.15s;
}
.btn-icon:hover { background: #F3F4F6; color: #374151; box-shadow: 0 2px 6px rgba(0,0,0,.06); }
.btn-icon:active { transform: scale(0.92); }
.btn-icon:focus-visible { outline: 2px solid #E5E7EB; outline-offset: 2px; }

/* ════════════════════════════════════════════════════════════════
   FORMS
════════════════════════════════════════════════════════════════ */
.form-group { margin-bottom: 0; }
.form-label {
  display: block;
  font-family: 'Poppins', sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  color: #374151;
  margin-bottom: 6px;
}
.req { color: #E8760A; }
.form-input {
  width: 100%;
  padding: 11px 14px;
  border: 1.5px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.875rem;
  color: #111827;
  background: #FAFAFA;
  outline: none;
  transition: border 0.15s, box-shadow 0.15s;
}
.form-input:focus {
  border-color: #E8760A;
  box-shadow: 0 0 0 3px rgba(232,118,10,.12);
  background: white;
}
.form-input::placeholder { color: #C4C9D4; }
/* Same red-outline treatment as .reg-input.error / .lf-input.error (login,
   registration, forgot-password) — applied to every dashboard admin/staff
   modal field (Add/Edit Patient, Add/Edit User, etc.) so a required-field
   or invalid-value error reads the same way everywhere in the app, not
   just a toast with no visual pointer to which field caused it. Covers
   the custom select and DOB-picker's visible trigger box for free too —
   both already carry the plain .form-input class alongside their own
   (.cust-select-trigger / .dob-picker-trigger), so marking that trigger
   element .error hits this same rule. markFieldError()/clearFormErrors()
   (main.js) toggle this. */
.form-input.error,
.form-textarea.error {
  border-color: #DC2626;
  box-shadow: 0 0 0 3px rgba(220,38,38,.08);
}
/* Standard native behaviour: pointer only over the calendar icon itself
   (the browser's own click target for opening the picker); the rest of
   the field keeps the normal text cursor so typing a date manually still
   feels like editing text, not clicking a button. */
input[type="date"].form-input { cursor: text; }
input[type="date"].form-input::-webkit-calendar-picker-indicator { cursor: pointer; }
/* Same dark-mode fix already applied to .reg-input (registration page) —
   these are the DOB/date fields used in the admin/staff modals (Add
   Patient, Edit Patient, New User, Block Date, etc). Without forcing light
   rendering, Chrome on Android (very commonly set to system dark mode) and
   Safari draw the native mm/dd/yyyy text almost invisibly on the field's
   light background, which reads as "the date picker is broken" even though
   a value is actually there. */
input[type="date"].form-input {
  color-scheme: light;
}
input[type="date"].form-input::-webkit-datetime-edit,
input[type="date"].form-input::-webkit-datetime-edit-fields-wrapper,
input[type="date"].form-input::-webkit-datetime-edit-text,
input[type="date"].form-input::-webkit-datetime-edit-month-field,
input[type="date"].form-input::-webkit-datetime-edit-day-field,
input[type="date"].form-input::-webkit-datetime-edit-year-field {
  color: #111827;
  -webkit-text-fill-color: #111827;
}
/* Mobile Safari (and some Android WebViews) auto-zoom the whole viewport
   when a focused input's font-size is under 16px. .form-input is 14px and
   .reg-input drops to ~13px on mobile (see the 768px breakpoint above) —
   for a date field sitting inside a modal, that zoom makes the whole
   dialog visibly jump/shift on tap, which looks like the picker glitching.
   Scoped to type=date only so no other field's sizing changes. */
@media (max-width: 768px) {
  input[type="date"].reg-input,
  input[type="date"].form-input {
    font-size: 16px;
  }
}

/* ── Custom DOB date picker ────────────────────────────────────────
   Every date-of-birth field (registration + Add/Edit Patient + New User)
   uses this instead of native <input type="date"> — native rendering
   (icon, internal text colour, fallback UI on unsupported browsers) is too
   inconsistent across Android OEM/WebView versions and iOS Safari, even
   with the fixes above. This renders identically everywhere since nothing
   is left to the OS; a same-id hidden <input> still holds the plain
   "YYYY-MM-DD" value so existing code reading `.value` is unaffected. */
.dob-picker { position: relative; }
/* Trigger is a <div> now, not a <button> — it hosts a real, typeable
   <input> (.dob-picker-text) alongside the calendar-icon button, instead
   of a button+span that could only ever be clicked open, never typed
   into. The div keeps the same "looks like a form field" role the button
   used to have (border/padding/background all come from whatever `cls`
   was passed in, e.g. form-input) — cursor:pointer is dropped since only
   specific children are actually clickable now, not the whole box. */
.dob-picker-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  text-align: left;
  font-family: 'Poppins', sans-serif;
}
.dob-picker-trigger svg { flex-shrink: 0; color: #9CA3AF; }
.dob-picker-trigger.open { border-color: #E8891C; box-shadow: 0 0 0 3px rgba(232,137,28,.1); }
/* Strips the native <input> chrome (border/outline/background) so it reads
   as plain text sitting inside .dob-picker-trigger's own box, exactly like
   the old <span> did — but is now a real, focusable, typeable field.
   .dob-picker-text-wrap (not the input itself) is the flex item now — it
   hosts the absolutely-positioned mask span (see .dob-picker-mask) behind
   the real input, so both layers share the exact same box instead of the
   input needing to be its own positioning context on top of also being a
   flex/grid child (min-width:0 + width:0 keeps it from ever imposing its
   native intrinsic width on that shared box or a parent grid track). */
.dob-picker-text-wrap { position: relative; flex: 1; width: 0; min-width: 0; overflow: hidden; }
.dob-picker-text {
  position: relative; z-index: 1;
  width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border: none; outline: none; background: transparent; padding: 0; margin: 0;
  font: inherit; font-family: 'Poppins', sans-serif;
  font-variant-numeric: tabular-nums; letter-spacing: inherit;
  color: inherit; cursor: text;
}
.dob-picker-text.placeholder { color: #9CA3AF; }
.dob-picker-text::placeholder { color: #9CA3AF; }
/* Hidden twin of the real input's current text, in the exact same font —
   exists purely so its rendered offsetWidth (read in _dobSyncMask) tells
   us in real pixels where the typed text actually ends, instead of
   estimating from a character count (a proportional font's glyphs don't
   share a single fixed width, which is what made an earlier per-character
   version of this drift out of alignment or overlap). */
.dob-mask-mirror {
  position: absolute; top: 0; left: 0; visibility: hidden;
  font: inherit; font-family: 'Poppins', sans-serif;
  font-variant-numeric: tabular-nums; letter-spacing: inherit;
  white-space: pre;
}
/* The still-untyped "mm/dd/yyyy" tail (see dateFieldHtml's mirrorMaskHtml
   + _dobMaskHtml/_dobSyncMask in main.js) — one plain grey text run, not
   split into per-character cells, positioned via JS to start exactly
   where .dob-mask-mirror measured the typed text to end. Same font as
   the real input so the two runs read as one continuous line. */
.dob-picker-mask {
  position: absolute; top: 0; left: 0; height: 100%; z-index: 0;
  display: flex; align-items: center;
  pointer-events: none; color: #9CA3AF;
  font: inherit; font-family: 'Poppins', sans-serif;
  font-variant-numeric: tabular-nums; letter-spacing: inherit;
  white-space: nowrap;
}
/* Next slot the user's about to type (see _dobMaskHtml) — a light
   highlight box behind that one character, like a selected/active cell,
   rather than colouring the letter itself; only while the field actually
   has focus, so it reads as live typing guidance and not a permanent
   mark on an idle field. */
.dob-picker-trigger:focus-within .dob-mask-active {
  background: rgba(37, 99, 235, .16);
  border-radius: 3px;
}
.dob-picker-icon-btn {
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; background: none; border: none; padding: 0;
  color: #9CA3AF; cursor: pointer;
}

.dob-picker-popover {
  position: fixed;
  z-index: 1600; /* above .modal-overlay (1500) so it also works inside modals */
  width: 280px;
  max-width: calc(100vw - 24px);
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.08);
  border: 1px solid #EEF0F2;
  padding: 12px;
  font-family: 'Poppins', sans-serif;
  animation: modalIn 0.15s ease;
  display: none;
}
.dob-picker-head { display: flex; gap: 6px; margin-bottom: 10px; }
/* Month/year mini dropdowns in the calendar head — a <button> styled to
   look identical to the old native <select> (same border/chevron/padding),
   but its open option list (.dob-mini-popover) is our own markup instead of
   the OS's native listbox, so it can actually be styled/matches the rest
   of the app instead of rendering as a plain browser dropdown. */
.dob-mini-select { position: relative; flex: 1; min-width: 0; }
.dob-picker-select {
  width: 100%;
  display: block;
  text-align: left;
  padding: 7px 26px 7px 10px;
  border: 1.5px solid #E5E7EB;
  border-radius: 7px;
  font-family: inherit;
  font-size: .8rem;
  color: #1C1C1C;
  background-color: #fff;
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
  background-size: 13px;
}
.dob-picker-select:hover { border-color: #D1D5DB; }
.dob-picker-select.open {
  border-color: #E8891C;
  box-shadow: 0 0 0 3px rgba(232,137,28,.1);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23E8891C' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
.dob-mini-popover {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 2;
  max-height: 200px;
  overflow-y: auto;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.08);
  border: 1px solid #EEF0F2;
  padding: 5px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: modalIn 0.12s ease;
}
.dob-mini-item {
  padding: 7px 10px;
  border-radius: 6px;
  font-size: .8rem;
  color: #374151;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.dob-mini-item:hover { background: #FFF0DC; }
.dob-mini-item.selected { background: #E8891C; color: #fff; font-weight: 600; }
.dob-mini-item.highlighted { outline: 2px solid #E8891C; outline-offset: -2px; }
.dob-picker-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dob-picker-hdr {
  text-align: center; font-size: .62rem; font-weight: 700; color: #9CA3AF;
  padding: 4px 0; text-transform: uppercase;
}
.dob-day {
  aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  border-radius: 6px;
  font-size: .78rem;
  cursor: pointer;
  transition: background .15s, color .15s;
  color: #374151;
}
.dob-day:hover:not(.dob-day-disabled):not(.dob-day-empty) { background: #FFF0DC; }
.dob-day-today { outline: 1.5px solid #E8891C; font-weight: 700; }
.dob-day-selected { background: #E8891C !important; color: #fff !important; font-weight: 700; }
.dob-day-disabled { opacity: .3; cursor: default; }
.dob-day-empty { cursor: default; }

/* ── Custom Select — replaces native <select> everywhere in the app (see
   selectFieldHtml()/timeFieldHtml() in main.js). A native <select> with
   many options (e.g. a 30-48 slot time list) renders as the OS's own
   listbox, which can swallow nearly the whole viewport height on open;
   this caps it at a compact, scrollable popover instead — same visual
   language as the DOB picker above. A same-id hidden <input> still holds
   the raw value so existing code reading `.value` is unaffected. */
.cust-select { position: relative; }
.cust-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: 'Poppins', sans-serif;
}
.cust-select-trigger svg { flex-shrink: 0; color: #9CA3AF; transition: transform .15s; }
.cust-select-trigger.open svg { transform: rotate(180deg); }
.cust-select-trigger.open { border-color: #E8891C; box-shadow: 0 0 0 3px rgba(232,137,28,.1); }
.cust-select-text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cust-select-text.placeholder { color: #9CA3AF; }

.cust-select-popover {
  position: fixed;
  z-index: 1600; /* above .modal-overlay (1500) so it also works inside modals */
  max-width: calc(100vw - 24px);
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.18), 0 2px 8px rgba(0,0,0,.08);
  border: 1px solid #EEF0F2;
  padding: 6px;
  font-family: 'Poppins', sans-serif;
  animation: modalIn 0.15s ease;
  display: none;
}
/* padding-right on the list (not just the items) reserves room so the
   scrollbar track never sits flush against a selected/hovered item's
   rounded highlight; the 2px gap keeps adjacent rows from touching. */
.cust-select-list { max-height: 260px; overflow-y: auto; display: flex; flex-direction: column; gap: 2px; padding-right: 4px; }
.cust-select-item {
  padding: 8px 12px;
  border-radius: 7px;
  font-size: .82rem;
  color: #374151;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.cust-select-item:hover { background: #FFF0DC; }
.cust-select-item.selected { background: #E8891C; color: #fff; font-weight: 600; }
/* Keyboard cursor — an outline ring so it reads correctly whether or not
   the row it's on is also .selected (solid fill) or plain (no fill). */
.cust-select-item.highlighted { outline: 2px solid #E8891C; outline-offset: -2px; }

/* Appointment row action icons (view/approve/disapprove/cancel/complete/
   no-show/reschedule) — up to 5 buttons for an approved row. Desktop has
   plenty of column width for one row; on mobile the narrower cell was
   wrapping them across 3+ rows, making the row noticeably taller than its
   neighbours. Capped at exactly 2 rows below the breakpoint by flowing
   buttons down each column instead of wrapping by available width. */
.appt-actions-row { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
@media (max-width: 768px) {
  .appt-actions-row {
    display: grid;
    grid-template-rows: repeat(2, auto);
    grid-auto-flow: column;
    grid-auto-columns: min-content;
    justify-content: start;
  }
}

/* Exam record row action icons — same wrapping pattern as
   .appt-actions-row above, but always on (not just <=768px): Examination
   Records can show up to 5 icons (View/Print/Edit/Clearance/Delete) in a
   column that's narrower than Appointments' own Actions column even on
   desktop. max-width fits exactly 4 buttons (4 * 32px + 3 * 4px gap =
   140px) before the 5th wraps to its own row, instead of every icon
   shrinking to fit one cramped line. */
.exam-actions-row { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; max-width: 145px; }

.form-select {
  width: 100%;
  padding: 11px 38px 11px 14px;
  border: 1.5px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.875rem;
  color: #374151;
  background-color: #FAFAFA;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
  outline: none;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color 0.15s, box-shadow 0.15s, background-color 0.15s;
}
.form-select:hover {
  border-color: #D1D5DB;
  background-color: #fff;
}
.form-select:focus {
  border-color: #E8760A;
  box-shadow: 0 0 0 3px rgba(232,118,10,.12);
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23E8760A' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
.form-select option[value=""] { color: #9CA3AF; }
.form-select option { color: #374151; }
.form-textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1.5px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.875rem;
  color: #111827;
  background: #FAFAFA;
  outline: none;
  resize: vertical;
  min-height: 80px;
  transition: border 0.15s, box-shadow 0.15s;
}
.form-textarea:focus {
  border-color: #E8760A;
  box-shadow: 0 0 0 3px rgba(232,118,10,.12);
  background: white;
}
.form-hint { font-size: 0.74rem; color: #9CA3AF; margin-top: 4px; }

.form-row-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
/* minmax(0, 1fr), not plain 1fr — a plain 1fr track can still grow past its
   fair equal share to fit a grid item's own content (a select showing a
   long option label, e.g. "Yes, offered as an appointment type"), squeezing
   its siblings and making all 3 columns visibly shift width every time a
   different option gets picked. minmax(0, 1fr) caps each track's minimum at
   0 so content shrinks/ellipsizes inside a stable, always-equal column
   instead of resizing it — same fix .form-row-2 already had. */
.form-row-3 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }

.section-label {
  font-family: 'Poppins', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #9CA3AF;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid #F3F4F6;
}

/* Search input */
.search-input-wrap { position: relative; }
.search-input-wrap svg {
  position: absolute;
  left: 10px; top: 50%;
  transform: translateY(-50%);
  color: #9CA3AF;
  pointer-events: none;
}
.search-input {
  padding-left: 34px;
  padding-right: 12px;
  padding-top: 8px;
  padding-bottom: 8px;
  border: 1.5px solid #E5E7EB;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  background: #FAFAFA;
  outline: none;
  width: 220px;
  transition: border 0.15s, width 0.2s;
}
.search-input:focus {
  border-color: #E8760A;
  background: white;
  box-shadow: 0 0 0 3px rgba(232,118,10,.1);
  width: 260px;
}

/* Filter tabs (status) */
.filter-tabs {
  display: flex;
  gap: 4px;
  padding: 0 20px;
  height: 48px;
  align-items: flex-end;
  border-bottom: 1px solid #F3F4F6;
  overflow-x: auto;
  overflow-y: hidden;
}
.filter-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border: none;
  background: transparent;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  font-weight: 600;
  color: #9CA3AF;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s, border-color 0.2s;
}
.filter-tab:hover { color: #374151; }
.filter-tab.active { color: #E8760A; border-bottom-color: #E8760A; }

/* ── Patient profile card responsive layout ── */
.patient-profile-row  { display: flex; gap: 24px; padding: 24px; flex-wrap: wrap; align-items: stretch; }
.patient-avatar-col   { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; min-width: 140px; }
.patient-info-col     { flex: 1; min-width: 200px; display: flex; flex-direction: column; justify-content: center; }
.patient-stats-col    { display: flex; flex-direction: column; gap: 8px; min-width: 110px; justify-content: center; }
.profile-two-col      { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.patient-info-chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
@media (max-width: 900px) { .patient-info-chips { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px)  { .patient-info-chips { grid-template-columns: 1fr 1fr; } }
.patient-section-label {
  font-size: .75rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: #E8760A; margin-bottom: 12px;
  display: flex; align-items: center; gap: 6px; white-space: nowrap;
}
.patient-section-label.muted { color: #6B7280; }
.patient-tab-body { padding: 20px; }

/* ── Empty state placeholder ── */
.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 24px;
  text-align: center;
}
.empty-state-desc {
  font-size: .82rem;
  color: #9CA3AF;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .patient-profile-row  { flex-direction: column; gap: 16px; padding: 16px; }
  .patient-avatar-col   { width: 100%; flex-direction: column; align-items: center; justify-content: center; gap: 12px; min-width: unset; }
  .patient-info-col     { width: 100%; min-width: unset; }
  .patient-stats-col    { flex-direction: row; flex-wrap: wrap; gap: 8px; min-width: unset; width: 100%; }
  .patient-stats-col > div { flex: 1; min-width: calc(50% - 4px); }
  .profile-two-col      { grid-template-columns: 1fr; gap: 14px; }
  .patient-tab-body     { padding: 14px; }
}

.patient-avatar {
  outline: 2px solid transparent;
  outline-offset: 2px;
  transition: outline-color 0.2s ease;
}
.patient-avatar:hover,
.patient-name-cell:hover .patient-avatar,
.tbl tbody tr:hover .patient-avatar {
  outline-color: #E8760A;
}

/* ════════════════════════════════════════════════════════════════
   ALERTS / ERRORS
════════════════════════════════════════════════════════════════ */
.alert-error {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: #FFEBEE;
  color: #C62828;
  border-radius: 8px;
  padding: 10px 14px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
}
.alert-error svg { flex-shrink: 0; margin-top: 2px; }
.alert-success {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: #E8F5E9;
  color: #2E7D32;
  border-radius: 8px;
  padding: 10px 14px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
}
.alert-success svg { flex-shrink: 0; margin-top: 2px; }
.alert-info {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: #FFF8F0;
  color: #92400E;
  border-radius: 8px;
  padding: 10px 14px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  font-weight: 500;
  border: 1px solid #FFD9A8;
}
.alert-info svg { flex-shrink: 0; margin-top: 2px; }

/* ════════════════════════════════════════════════════════════════
   MODAL
════════════════════════════════════════════════════════════════ */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,.45);
  z-index: 1500; /* must clear #sidebar (1045) / .topbar (1041) or the sidebar clips modal content */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  backdrop-filter: blur(3px);
}
.modal-box {
  background: white;
  border-radius: 16px;
  width: 100%;
  min-width: 0; /* Without this, a flex item's default min-width:auto lets its
    content's intrinsic width (e.g. the mini-calendar's 7-column grid, or
    long unwrapped text) force this box wider than modal-overlay's available
    space instead of letting it shrink to fit — the box then renders past
    the left edge of narrow/phone screens, clipping the header/labels flush
    against the edge instead of centering with padding on both sides. */
  max-width: 540px;
  /* vh is measured against the LARGEST possible viewport (as if the
     browser's address bar were hidden) — on mobile Chrome/Safari with the
     bar actually showing, 90vh can be taller than what's really on screen.
     The overlay has no scroll of its own (it centers via flexbox), so a
     modal-box that renders taller than the true visible area just has its
     top and/or bottom pushed off-screen with nothing to scroll — the
     .modal-body overflow-y below never gets a chance to kick in because
     the box itself already doesn't fit. dvh tracks the real, current
     viewport and wins in browsers that support it; vh is just the
     fallback for the ones that don't. */
  max-height: 90vh;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(0,0,0,.2);
  animation: modalIn 0.2s ease;
  isolation: isolate; /* own stacking context — without this, the parent's
    backdrop-filter can make Chromium mis-paint this box's rounded/clipped
    corners, letting the dark overlay show through the header/footer */
  position: relative;
}
.modal-box.modal-lg { max-width: 720px; }
.modal-box.modal-sm { max-width: 400px; }
.modal-box.modal-xl { max-width: 840px; }
.modal-header {
  background: #fff;
  padding: 20px 24px 16px;
  border-bottom: 1px solid #F3F4F6;
  border-radius: 16px 16px 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.modal-title {
  font-family: 'Poppins', sans-serif;
  font-size: 1rem;
  font-weight: 700;
  color: #1C1C1C;
  display: flex;
  align-items: center;
  gap: 8px;
}
.modal-close {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border: none;
  background: #F3F4F6;
  border-radius: 6px;
  cursor: pointer;
  color: #6B7280;
  font-size: 1.1rem;
  line-height: 1;
  transition: background 0.15s;
}
.modal-close:hover { background: #E5E7EB; color: #374151; }
.modal-body {
  background: #fff;
  padding: 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1;
  min-width: 0; /* same auto-min-size fix as .modal-box, one level down —
    otherwise wide grid/flex children (the mini calendar, time-slot rows)
    re-introduce the same overflow via this box instead. */
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch; /* without this, touch drags inside an
    overflow:auto box can fail to register as a scroll gesture at all on
    iOS Safari and some Android/Chrome touch-emulation paths, even though
    overflow-y:auto is otherwise correctly set and a mouse wheel would
    have scrolled it fine */
  overscroll-behavior: contain; /* stop a drag that reaches the top/bottom
    of this box from "chaining" into scrolling the page behind the modal */
  touch-action: pan-y;
}
.modal-body::-webkit-scrollbar { width: 4px; }
.modal-body::-webkit-scrollbar-track { background: transparent; margin: 8px 0; }
.modal-body::-webkit-scrollbar-thumb { background: #E5E7EB; border-radius: 4px; }
.modal-body::-webkit-scrollbar-thumb:hover { background: #D1D5DB; }
@media (max-width: 480px) {
  /* Claw back space on phones — same spirit as the booking wizard's own
     max-width:480px breakpoint (pages.js), so the modal's mini calendar
     gets roughly as much width to work with as the wizard page's does. */
  .modal-overlay { padding: 10px; }
  .modal-header { padding: 16px 16px 14px; }
  .modal-body { padding: 16px; }
  .modal-footer { padding: 12px 16px; }

  /* Prescription/exam-results modals' "Patient + Doctor" strip (main.js
     viewPrescriptionModal()/viewExamDetail()) — on desktop this is 2 rows
     side by side (patient avatar+info, doctor info+avatar), but that has no
     room to breathe on a phone. .rx-pd-block has exactly 2 children —
     .rx-patient-row and .rx-issued-block — each already its own internal
     avatar+text flex row, so switching just the outer block to a column
     stacks those two rows cleanly without splitting an avatar away from its
     own text (an earlier version of this rule set flex-direction:column
     directly on 3 unwrapped children — avatar, info, issued-block — which
     stacked the avatar and name onto separate lines instead of side by
     side; .rx-patient-row exists specifically to prevent that). */
  .rx-pd-block { flex-direction: column; gap: 0; }
  .rx-patient-row { width: 100%; }
  /* !important needed on the alignment props here — the element also
     carries inline text-align:right/justify-content:flex-end (the correct,
     intentional look on desktop), and inline style always outranks an
     external class regardless of media query, so a plain override never
     actually took effect. */
  .rx-issued-block {
    width: 100%;
    text-align: left !important;
    justify-content: flex-start !important;
    padding-top: 12px;
    margin-top: 12px;
    border-top: 1px dashed #E5E7EB;
  }
  .rx-issued-block > div:first-child { text-align: left !important; }
  /* Both the photo and initials-fallback avatar render as the last child —
     reorder it before the text so it reads avatar-then-name like the
     patient row above it. */
  .rx-issued-block > div:last-child { order: -1; }
  /* Sizing/margin come from an inline style attribute, so !important is
     required to shrink them here — see note above. Keeps the row from
     feeling oversized once it's full-width instead of one of three squeezed
     columns. */
  .rx-pat-avatar { width: 38px !important; height: 38px !important; font-size: .82rem !important; }
  .rx-doc-avatar { width: 32px !important; height: 32px !important; font-size: .65rem !important; }

  /* renderRxDocumentCard()'s "Issued by" strip (pages.js, the printable Rx
     card on the Prescriptions/Patient Records pages — a different component
     from the modals above). Same root cause as .rx-pd-block: at this width
     the avatar+name group and the date+pill group don't fit side by side,
     so flex-wrap drops the date+pill onto its own line — but that group's
     own text-align:right does nothing for its position on the row (a
     single wrapped flex item under justify-content:space-between just sits
     flush left), so it lands under the avatar instead of under the name,
     out of step with the row above it. Stack on purpose instead, both
     flush left. */
  .rx-issuer-strip { flex-direction: column; align-items: flex-start !important; gap: 8px; }
  .rx-issuer-meta { text-align: left !important; width: 100%; }
}
.modal-footer {
  background: #fff;
  padding: 14px 24px;
  border-top: 1px solid #F3F4F6;
  border-radius: 0 0 16px 16px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  /* No wrap meant a footer with 3-4 buttons (e.g. Appointment Details'
     Mark No-Show/Reschedule/Cancel) simply overflowed past modal-box's own
     edge on a phone-width screen — modal-box's overflow:hidden then clipped
     it, so only a thin sliver of the leftmost button was left visible,
     looking cut off/broken instead of wrapping to a second row. */
  flex-wrap: wrap;
  gap: 10px;
  flex-shrink: 0;
}

/* ════════════════════════════════════════════════════════════════
   PICK-A-PERSON ROW — a selectable "assign this doctor" style row
   (avatar + name + subtitle), used inside modals that can be opened from
   ANY page (e.g. the Assign Doctor modal, main.js openAssignDoctorModal()).
   Deliberately its own global class, not the booking wizard's .doc-card —
   that class only exists inside appointmentWizardHtml()'s own <style>
   block (pages.js), so it renders completely unstyled (no border-radius,
   no avatar circle, no hover/transition) anywhere outside the wizard.
════════════════════════════════════════════════════════════════ */
.pick-person-row {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 14px; border-radius: 10px; border: 1.5px solid #E5E7EB;
  background: #fff; cursor: pointer; text-align: left;
  font-family: 'Poppins', sans-serif;
  transition: border-color .18s ease, background-color .18s ease,
              transform .18s ease, box-shadow .18s ease;
}
.pick-person-row:hover {
  border-color: #E8760A;
  background: #FFFBF5;
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(232,118,10,.12), 0 1px 3px rgba(0,0,0,.04);
}
.pick-person-row:active { transform: translateY(0) scale(.99); }
.pick-person-row:focus-visible { outline: 2px solid #E8760A; outline-offset: 2px; }
.pick-person-avatar {
  width: 40px; height: 40px; border-radius: 50%; background: #E8760A; color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: .78rem; font-weight: 700; flex-shrink: 0;
}
.pick-person-arrow { color: #D1D5DB; flex-shrink: 0; transition: color .18s ease, transform .18s ease; }
.pick-person-row:hover .pick-person-arrow { color: #E8760A; transform: translateX(2px); }

/* ════════════════════════════════════════════════════════════════
   CUSTOM CHECKBOX — fully reskinned (not just accent-color), so it
   renders identically everywhere instead of inheriting each OS/browser's
   native checkbox chrome (which often shows a plain black/grey box).
════════════════════════════════════════════════════════════════ */
.chk {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  border: 1.5px solid #D1D5DB;
  border-radius: 5px;
  background: #fff;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.1s;
}
.chk:hover { border-color: #E8760A; }
.chk:checked {
  background: var(--clr-primary);
  border-color: #E8760A;
  animation: chkBoxPop 0.25s cubic-bezier(.34,1.56,.64,1);
}
.chk:checked::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 5px;
  height: 9px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: translate(-50%, -60%) rotate(45deg);
  animation: chkMarkPop 0.25s cubic-bezier(.34,1.56,.64,1);
}
.chk:focus-visible {
  outline: 2px solid #E8760A;
  outline-offset: 2px;
}
.chk:active { transform: scale(0.9); }
.chk:disabled { opacity: 0.5; cursor: not-allowed; }

@keyframes chkBoxPop {
  0%   { transform: scale(0.8); }
  60%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}
@keyframes chkMarkPop {
  0%   { opacity: 0; transform: translate(-50%, -60%) rotate(45deg) scale(0); }
  50%  { opacity: 1; }
  100% { opacity: 1; transform: translate(-50%, -60%) rotate(45deg) scale(1); }
}

@keyframes modalIn {
  from { opacity: 0; transform: scale(.96) translateY(8px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ── Clinic Days pill toggle (Consultation Settings) ───────────── */
.cs-day-pills { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.cs-day-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding: 7px 14px;
  border-radius: 20px;
  border: 1.5px solid #E5E7EB;
  background: #fff;
  font-family: 'Poppins', sans-serif;
  font-size: 0.8rem;
  font-weight: 600;
  color: #6B7280;
  user-select: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
}
.cs-day-pill:hover { border-color: #E8760A; color: #374151; }
.cs-day-pill.active {
  background: #FFF7ED;
  border-color: #E8760A;
  color: #C4620A;
  box-shadow: 0 0 0 3px rgba(232,118,10,.1);
}
.cs-day-pill input[type="checkbox"] {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.cs-day-pill-check {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 1.5px solid #D1D5DB;
  color: transparent;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.cs-day-pill-check svg { width: 9px; height: 9px; stroke-width: 3; }
.cs-day-pill.active .cs-day-pill-check {
  background: var(--clr-primary);
  border-color: #E8760A;
  color: #fff;
}

/* ── Lunch break toggle (reuses .chk) ───────────────────────────── */
.cs-lunch-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  margin-bottom: 6px;
  font-size: 0.82rem;
  font-weight: 500;
  color: #374151;
  user-select: none;
}

/* ════════════════════════════════════════════════════════════════
   PAGE ANIMATIONS
════════════════════════════════════════════════════════════════ */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fade-up { animation: fadeUp 0.22s ease forwards; }

/* ════════════════════════════════════════════════════════════════
   ICONS
════════════════════════════════════════════════════════════════ */
.icon    { width: 18px; height: 18px; flex-shrink: 0; vertical-align: middle; }
.icon-sm { width: 14px; height: 14px; flex-shrink: 0; vertical-align: middle; }
.icon-lg { width: 22px; height: 22px; flex-shrink: 0; vertical-align: middle; }
.icon-xl { width: 32px; height: 32px; flex-shrink: 0; vertical-align: middle; }

/* ════════════════════════════════════════════════════════════════
   PROFILE / PATIENT RECORD
════════════════════════════════════════════════════════════════ */
.profile-hero {
  background: var(--clr-dark);
  padding: 28px;
  display: flex;
  align-items: center;
  gap: 24px;
}
.profile-avatar-lg {
  width: 72px; height: 72px;
  border-radius: 50%;
  background: var(--clr-primary);
  color: white;
  font-family: 'Poppins', sans-serif;
  font-size: 1.6rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border: 3px solid rgba(255,255,255,.2);
}
.profile-info-name {
  font-family: 'Poppins', sans-serif;
  font-size: 1.3rem;
  font-weight: 700;
  color: white;
  margin-bottom: 4px;
}
.profile-info-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 0.8rem;
  color: #9CA3AF;
}
.profile-meta-item {
  display: flex;
  align-items: center;
  gap: 5px;
}
.profile-meta-item svg { color: #E8760A; }

.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0;
}
.info-item {
  padding: 10px 0;
}
.info-key {
  font-family: 'Poppins', sans-serif;
  font-size: 0.68rem;
  font-weight: 600;
  color: #9CA3AF;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 3px;
}
.info-val {
  font-family: 'Poppins', sans-serif;
  font-size: 0.875rem;
  font-weight: 500;
  color: #111827;
}

/* ════════════════════════════════════════════════════════════════
   OPTICAL EXAMINATION FORM
════════════════════════════════════════════════════════════════ */
.eye-grid {
  display: grid;
  grid-template-columns: 80px 1fr 1fr 1fr 1fr;
  gap: 10px;
  align-items: center;
}
.eye-label {
  font-family: 'Poppins', sans-serif;
  font-size: 0.8rem;
  font-weight: 700;
  color: #374151;
  padding: 8px 0;
}
.eye-header {
  font-family: 'Poppins', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  color: #9CA3AF;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  text-align: center;
}

/* ════════════════════════════════════════════════════════════════
   CALENDAR
════════════════════════════════════════════════════════════════ */
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.cal-day-header {
  text-align: center;
  font-family: 'Poppins', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  color: #9CA3AF;
  padding: 8px 0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.cal-day {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-family: 'Poppins', sans-serif;
  /* Matches the booking wizard's own calendar (.amc-day, pages.js) —
     same "make the numbers slightly bigger" pass applied there. */
  font-size: 0.88rem;
  cursor: pointer;
  position: relative;
  transition: background 0.15s;
  color: #374151;
}
.cal-day:hover { background: #FFF0DC; }
.cal-day.other-month { color: #D1D5DB; }
.cal-day.has-event { color: #E8760A; font-weight: 700; }
.cal-day.has-event::after {
  content: '';
  position: absolute;
  bottom: 4px;
  left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px;
  background: var(--clr-primary);
  border-radius: 50%;
}
.cal-day.today {
  outline: 2px solid #E8760A;
  font-weight: 700;
}
.cal-day.cal-selected {
  background: #E8760A !important;
  color: #fff !important;
  font-weight: 700;
}
.cal-day.blocked { background: #F3F4F6; color: #9CA3AF; cursor: not-allowed; }
.cal-day.cal-holiday { background: #FFF1F2; color: #f43f5e; cursor: not-allowed; font-weight: 600; }
.cal-holiday-lbl { position: absolute; left: 2px; right: 2px; top: calc(50% + 8px); font-size: .58rem; line-height: 1.1; text-align: center; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-weight: 500; padding: 0 1px; }
/* Short one-word labels ("Too Far", "Too Soon", "Booked") — .cal-holiday-lbl
   above is sized down specifically to fit a 2-line-wrapped holiday name
   (e.g. "Ninoy Aquino Day") in a narrow cell; reusing it for these shorter
   captions read visibly smaller than the matching labels on the booking
   wizard's own calendar (.amc-nodoc-lbl, pages.js). This mirrors that
   class's sizing instead — single line, no wrap, same .7rem. */
.cal-nodoc-lbl { position: absolute; left: 2px; right: 2px; top: calc(50% + 8px); font-size: .7rem; line-height: 1.15; text-align: center; overflow: hidden; white-space: nowrap; font-weight: 600; color: #6B7280; }
@media (max-width: 480px) {
  .cal-day.cal-holiday { font-size: 0.7rem; }
  .cal-holiday-lbl { font-size: .35rem; }
  .cal-nodoc-lbl { font-size: .44rem; top: calc(50% + 4px); line-height: 1.05; }
}
.cal-day.avail   { background: #ECFDF5; color: #065F46; font-weight: 600; }
.cal-day.avail:hover { background: #D1FAE5; }
.cal-day.has-appts::before {
  content: '';
  position: absolute;
  bottom: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
}

/* Explicit single-date block (leave/conference/holiday) — distinct from
   .blocked, which just means "not a recurring working day". Stronger red
   + a small slash badge so it reads as "actively unavailable", not just off. */
.cal-day.date-blocked {
  background: #FEE2E2;
  color: #B91C1C;
  font-weight: 700;
  cursor: not-allowed;
  text-decoration: line-through;
  text-decoration-color: rgba(185,28,28,0.5);
}
.cal-day.date-blocked:hover { background: #FECACA; }
.cal-day.date-blocked::after {
  content: '';
  position: absolute;
  top: 3px; right: 3px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--clr-danger);
  box-shadow: 0 0 0 1.5px #fff;
}

/* Calendar hover tooltip (fixed-position, appended to body) */
#cal-tooltip {
  display: none;
  opacity: 0;
  position: fixed;
  z-index: 9999;
  background: #1C1C1C;
  color: #fff;
  border-radius: 10px;
  padding: 10px 13px;
  min-width: 200px;
  max-width: 280px;
  font-size: .72rem;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(0,0,0,0.25);
  transform: translateX(-50%);
  transition: opacity .15s ease;
}
#cal-tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: #1C1C1C;
}
#cal-tooltip.tip-below::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: #1C1C1C;
}

/* Schedule page — doctor header action buttons */
.sched-header-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

/* Doctor selector tab grid */
.pat-doc-tabs-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
}
.pat-doc-cal-body {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 24px;
  align-items: start;
}

/* "Selected Date" banner — Doctor Availability page, shown under the
   calendar once a date is picked. Reuses .modal-close (see JS) for the
   exit button and .btn-primary for Book This Date; this class only owns
   the banner's own box (fadeUp is the app's existing entrance animation,
   also used elsewhere for freshly-inserted content). */
.pat-cal-selected-banner {
  position: relative;
  margin-top: 10px;
  background: #fff;
  border: 1.5px solid #E8760A;
  border-radius: 10px;
  padding: 16px 18px;
  box-shadow: 0 4px 16px rgba(232,118,10,.12), 0 1px 4px rgba(0,0,0,.05);
  animation: fadeUp 0.25s ease;
}
.pat-cal-selected-banner .modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
}

/* Doctor selector cards (schedule + patient avail pages) */
.doctor-sel-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 14px 12px;
  width: 130px;
  flex: 0 0 130px;
  border: 2px solid #F3F4F6;
  border-radius: 12px;
  background: #fff;
  cursor: pointer;
  text-align: center;
  font-family: inherit;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}
.doctor-sel-card:hover {
  border-color: #E8760A;
  background: #FFFBF7;
}
.doctor-sel-card.active {
  border-color: #E8760A;
  background: #FFF8F0;
  box-shadow: 0 0 0 3px rgba(232,118,10,0.10);
}
.doctor-sel-card .doc-card-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #FFF0DC;
  color: #E8760A;
  font-size: .85rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s;
}
/* Small availability status dot on the avatar corner — a doctor's
   Available/Not Available state (set in the Edit Schedule modal) was
   otherwise invisible until you actually opened that doctor's panel and
   read their day pills, with no way to tell at a glance from the
   selector row itself.
   .doc-avatar-wrap (not .doc-card-avatar itself) is the positioning
   context — a photo avatar sets overflow:hidden on itself to clip the
   <img> to the circle, which would also clip this badge if it lived
   inside that same box, since the badge deliberately sits half outside
   the circle's edge. */
.doc-avatar-wrap { position: relative; display: inline-flex; }
.doc-avail-badge {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 2px solid #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.doc-avail-badge--yes { background: #16A34A; }
.doc-avail-badge--no  { background: #9CA3AF; }
.doctor-sel-card.active .doc-card-avatar {
  background: #E8760A;
  color: #fff;
}
.doctor-sel-card .doc-card-name {
  flex: 1;
  font-size: .78rem;
  font-weight: 600;
  color: #1C1C1C;
  line-height: 1.3;
}
.doctor-sel-card .doc-card-spec {
  font-size: .67rem;
  color: #9CA3AF;
  margin-top: 1px;
}

/* ════════════════════════════════════════════════════════════════
   QR CODE DISPLAY
════════════════════════════════════════════════════════════════ */
.qr-display-card {
  background: white;
  border-radius: 16px;
  padding: 32px;
  text-align: center;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
  max-width: 340px;
  margin: 0 auto;
  width: 100%;
}
.qr-display-card canvas { border-radius: 8px; margin: 0 auto; }
.qr-patient-id {
  font-family: 'Poppins', monospace;
  font-size: 0.82rem;
  color: #6B7280;
  background: #F3F4F6;
  padding: 6px 14px;
  border-radius: 6px;
  display: inline-block;
  margin-top: 14px;
}

/* ════════════════════════════════════════════════════════════════
   ACTIVITY LOG
════════════════════════════════════════════════════════════════ */
.activity-item {
  display: flex;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid #F3F4F6;
  align-items: flex-start;
}
.activity-item:last-child { border-bottom: none; }

/* Icon circle (replaces the old dot) */
.activity-icon-wrap {
  width: 34px; height: 34px;
  border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.activity-icon-wrap.green  { background: #D1FAE5; color: #059669; }
.activity-icon-wrap.blue   { background: #DBEAFE; color: #2563EB; }
.activity-icon-wrap.orange { background: #FFF0DC; color: #E8891C; }
.activity-icon-wrap.red    { background: #FEE2E2; color: #DC2626; }
.activity-icon-wrap.purple { background: #EDE9FE; color: #7C3AED; }
.activity-icon-wrap.gray   { background: #F3F4F6; color: #6B7280; }

/* Keep legacy dot in case other pages use it */
.activity-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: #E8760A;
  flex-shrink: 0;
  margin-top: 6px;
}
.activity-dot.green  { background: var(--clr-success); }
.activity-dot.blue   { background: var(--clr-info); }
.activity-dot.red    { background: var(--clr-danger); }
.activity-dot.gray   { background: #9CA3AF; }

.activity-content { flex: 1; min-width: 0; }
.activity-action {
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  font-weight: 500;
  color: #1C1C1C;
  line-height: 1.4;
}
.activity-meta {
  font-family: 'Poppins', sans-serif;
  font-size: 0.76rem;
  color: #9CA3AF;
  margin-top: 3px;
}

/* Chart card legend dot */
.chart-legend-dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  align-self: center;
}
.chart-legend-dot.orange { background: #E8891C; }

/* ════════════════════════════════════════════════════════════════
   GRID HELPERS
════════════════════════════════════════════════════════════════ */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; }
.grid-sidebar { display: grid; grid-template-columns: 1fr 300px; gap: 20px; }
.gap-y { display: flex; flex-direction: column; gap: 20px; }
.gap-y-sm { display: flex; flex-direction: column; gap: 12px; }

/* ════════════════════════════════════════════════════════════════
   DOCTOR AVAILABILITY LIST
════════════════════════════════════════════════════════════════ */
.doctor-avail-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #F3F4F6;
}
.doctor-avail-item:last-child { border-bottom: none; }
.doctor-avail-info { display: flex; align-items: center; gap: 10px; }
.avail-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.avail-dot.available { background: var(--clr-success); }
.avail-dot.unavailable { background: var(--clr-danger); }

/* ════════════════════════════════════════════════════════════════
   SETTINGS
════════════════════════════════════════════════════════════════ */
.settings-layout { display: grid; grid-template-columns: 220px 1fr; gap: 24px; align-items: start; }
.settings-nav { background: white; border-radius: 12px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.settings-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  font-weight: 500;
  color: #6B7280;
  cursor: pointer;
  border-left: 3px solid transparent;
  transition: background 0.15s, color 0.15s;
}
.settings-nav-item:hover { background: #FAFAFA; color: #374151; }
.settings-nav-item.active { border-left-color: #E8760A; color: #E8760A; background: #FFF8F0; }

.settings-panel { background: white; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); overflow: hidden; }
.settings-panel-header { padding: 20px 24px; border-bottom: 1px solid #F3F4F6; }
.settings-panel-body { padding: 24px; display: flex; flex-direction: column; gap: 18px; }
.settings-panel-footer { padding: 14px 24px; border-top: 1px solid #F3F4F6; display: flex; justify-content: flex-end; }

/* Logo upload zone */
.logo-upload-zone {
  border: 2px dashed #E5E7EB;
  border-radius: 10px;
  padding: 28px;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.logo-upload-zone:hover { border-color: #E8760A; background: #FFF8F0; }

/* ════════════════════════════════════════════════════════════════
   PATIENT DASHBOARD WIDGETS
════════════════════════════════════════════════════════════════ */
.hero-btn-row {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  position: relative;
  z-index: 1;
}
.hero-btn-row > button { flex-shrink: 0; }
@media (max-width: 600px) {
  .hero-btn-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  .hero-btn-row > button {
    flex-shrink: unset;
    padding: 7px 8px !important;
    font-size: .74rem !important;
    white-space: nowrap;
  }
}
.welcome-banner {
  background: var(--clr-dark);
  border-radius: 12px;
  padding: 24px 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  overflow: hidden;
  position: relative;
}
.welcome-banner::before {
  content: '';
  position: absolute;
  width: 200px; height: 200px;
  background: rgba(232,118,10,.12);
  border-radius: 50%;
  right: -40px; top: -60px;
}
.welcome-banner-text h2 {
  font-family: 'Poppins', sans-serif;
  font-size: 1.3rem;
  font-weight: 700;
  color: white;
  margin-bottom: 4px;
}
.welcome-banner-text p {
  font-family: 'Poppins', sans-serif;
  font-size: 0.82rem;
  color: #9CA3AF;
}
.welcome-qr-mini {
  background: white;
  padding: 10px;
  border-radius: 10px;
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}

/* Appointment request form */
.appt-request-card {
  background: white;
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
}

/* ════════════════════════════════════════════════════════════════
   TOAST NOTIFICATIONS
════════════════════════════════════════════════════════════════ */
.toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 999;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 10px;
  background: white;
  box-shadow: 0 4px 20px rgba(0,0,0,0.12);
  font-family: 'Poppins', sans-serif;
  font-size: 0.84rem;
  font-weight: 500;
  color: #1C1C1C;
  animation: fadeUp 0.2s ease;
  border-left: 3px solid #E8760A;
  max-width: 340px;
}
.toast.toast-success { border-left-color: #10B981; }
.toast.toast-error   { border-left-color: #EF4444; }
.toast.toast-info    { border-left-color: #3B82F6; }

/* ════════════════════════════════════════════════════════════════
   RESPONSIVE
════════════════════════════════════════════════════════════════ */

/* ── Tablet / small laptop (768px–1024px) ──
   The sidebar itself defaults to icon-rail mode here via the JS-driven
   `.collapsed` class (see applySidebarBucket in router.js), which reuses
   the same always-on #sidebar.collapsed / #main-area.collapsed rules as
   the desktop hamburger toggle — one mechanism, no conflicting overrides.
   These rules only handle page CONTENT layout at this width. */
@media (min-width: 768px) and (max-width: 1024px) {
  .grid-2, .grid-3, .grid-sidebar { grid-template-columns: 1fr; }
  .stats-grid-6 { grid-template-columns: repeat(3, 1fr); }
  .reg-row-2, .reg-row-3, .reg-form-grid, .form-row-2, .form-row-3 { grid-template-columns: 1fr; }
  .settings-layout { grid-template-columns: 1fr; }
  .eye-grid { grid-template-columns: 60px 1fr 1fr 1fr 1fr; }
  .page-body { padding: 20px; }
  .page-header { padding: 20px 20px 16px; }
  .topbar { padding: 0 18px; }
}

/* ── Mobile: off-canvas sidebar (<768px) ── */
@media (max-width: 767px) {
  #sidebar {
    width: 236px;
    transform: translateX(-100%);
  }
  #sidebar.mobile-open { transform: translateX(0); }
  #main-area { margin-left: 0 !important; }

  .grid-2, .grid-3, .grid-sidebar { grid-template-columns: 1fr; }
  .stats-grid { grid-template-columns: 1fr 1fr; }
  .stats-grid-6 { grid-template-columns: 1fr; }

  /* Doctor availability — card picker: 2-col equal-width grid */
  .pat-doc-tabs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  /* Base padding (14px 12px) was tuned for the desktop's fixed 130px-wide
     card — stretched across half of a mobile grid cell instead, the same
     padding reads as flat/compressed since there's much more width for
     the same amount of breathing room top-to-bottom. More vertical
     padding and a bit more gap between avatar/name/spec gives it room to
     match the wider footprint. A bigger avatar (44px was sized for the
     desktop's narrow fixed-width card) fills more of that extra height
     itself, rather than just padding trying to carry it alone. */
  .doctor-sel-card { width: auto; flex: unset; padding: 26px 14px; gap: 12px; }
  .doctor-sel-card .doc-card-avatar { width: 60px; height: 60px; font-size: 1.05rem; }
  .doc-avail-badge { width: 20px; height: 20px; }
  /* Calendar panel: single column on mobile */
  .pat-doc-cal-body { grid-template-columns: 1fr; gap: 16px; }
  /* Doctor header: stack Book button below on mobile */
  .pat-doc-panel .card-body > button.btn-primary { width: 100%; justify-content: center; margin-top: 4px; }
  /* Schedule page — action buttons fill row on mobile */
  .sched-header-actions { width: 100%; justify-content: flex-end; }

  /* .tbl-scroll is injected by wrapTableScroll() after each page render.
     On mobile, tables no longer scroll horizontally inside it — every
     .tbl instead collapses into a stacked list of cards, one per row,
     with each cell showing its own column header inline via a
     data-label attribute (see the *TableHtml()/…Table() builders in
     pages.js/main.js). A <td> with no data-label just shows no header —
     it degrades, it doesn't break. */
  /* A light tray behind the cards (table-wrap itself is white, same as
     each card) — without some background contrast, the cards' only
     separation was a thin border + a small gap, which read as barely
     separated at all. No border-radius of its own: this sits flush
     against table-wrap's straight side edges (below the toolbar, above
     table-wrap's own bottom edge), so rounding it independently just
     carved a notch out of its own top corners instead of matching
     anything — table-wrap's radius + overflow:hidden already handles all
     the actual rounding/clipping at the real outer edges. */
  .tbl-scroll { overflow-x: visible; width: 100%; background: #F7F5F2; padding: 12px; box-sizing: border-box; }
  /* <table>/<tbody> stay display:table/table-row-group by default even
     though thead/tr/td below are overridden to block/flex — a block-level
     <tr> inside a still-tabular <tbody> has no defined containing-block
     width to fill, so it was sizing to its own shrink-to-fit content width
     instead of stretching across the tray. Making the whole chain block
     gives width:100% something consistent to cascade through. */
  .tbl {
    display: block;
    table-layout: auto;
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }
  .tbl tbody { display: block; width: 100%; }
  .tbl thead { display: none; }
  .tbl tbody tr {
    display: block;
    width: 100%;
    box-sizing: border-box;
    background: #fff;
    border: 1px solid #E5E7EB;
    border-radius: 12px;
    padding: 2px 14px;
    margin-bottom: 14px;
    box-shadow: 0 1px 2px rgba(28,28,28,.04);
  }
  .tbl tbody tr:last-child { margin-bottom: 0; }
  .tbl tbody tr:hover td { background: transparent; } /* no mouse on mobile — the hover highlight never clears without it */
  .tbl td {
    display: flex;
    /* flex-start, not center: a value that's a single line of text looks
       identical either way, but several cells (Status pill + its "Expires…"
       subtext, the Waitlist Slot cell's badge + date + time stack) are
       multi-line blocks — centered, the label floated against the middle
       of that block instead of reading as attached to it. Top-aligning
       matches the same convention .rev-row/.sum-row already use elsewhere
       in the app for the same label-next-to-content shape. */
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    padding: 11px 0;
    border-bottom: 1px solid #F3F4F6;
    white-space: normal;
    text-align: right;
    overflow: visible;
    text-overflow: clip;
  }
  .tbl td:last-child { border-bottom: none; }
  .tbl td[data-label]::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: #9CA3AF;
    text-align: left;
    /* Nudges the label down to sit level with the first line of the value
       text instead of its own box's literal top edge — the label's own
       line-height (from its bigger font-size) otherwise sits a couple
       pixels higher than the value's first line despite both starting at
       the same flex-start position. */
    padding-top: 1px;
  }
  /* Several tables set white-space:nowrap + max-width:0 + ellipsis inline
     on individual <td>s to truncate long values in the desktop table's
     fixed columns — exactly the opposite of what a mobile card needs,
     where there's no column width to protect and truncating just hides
     the value the label is right next to. Inline styles otherwise win over
     the class rules above, so this has to fight them with !important. */
  .tbl td {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    max-width: none !important;
  }
  /* Full-width rows (empty states, "no records" placeholders) use colspan
     to span every column — there's no second column left to pair a label
     against, so they render as plain centered text instead. */
  .tbl td[colspan] {
    display: block;
    text-align: center;
    padding: 20px 0;
  }
  .reg-row-2, .reg-row-3, .reg-form-grid, .form-row-2, .form-row-3 { grid-template-columns: 1fr; }
  .settings-layout { grid-template-columns: 1fr; }
  .eye-grid { grid-template-columns: 60px 1fr 1fr; }
  .page-header { padding: 16px; }
  .page-body { padding: 16px; }
  .topbar { padding: 0 14px; z-index: 1041; }
  #login-screen { padding: 16px; min-height: 100svh; box-sizing: border-box; }
  .register-bg { padding: 24px 16px; }
  .login-card, .register-card { width: 100%; max-width: 420px; padding: 32px 24px; }
  /* Hint: kept at the same prominent size/weight as desktop — this is the
     one thing testers said was too easy to miss, so mobile shouldn't
     shrink it back down. */
  .reg-terms-hint { font-size: 0.76rem; padding: 8px 12px; }

  /* Filter tabs: scroll horizontally on mobile — one single line, no wrap */
  .filter-tabs { overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: thin; scrollbar-color: #D1D5DB transparent; }
  .filter-tabs::-webkit-scrollbar { height: 3px; display: block; }
  .filter-tabs::-webkit-scrollbar-track { background: transparent; }
  .filter-tabs::-webkit-scrollbar-thumb { background: #D1D5DB; border-radius: 99px; }
  .table-wrap { overflow-x: auto; }
  .table-toolbar { padding: 12px 16px; flex-direction: column; align-items: stretch; gap: 8px; }
  /* .filter-grid — any "many fields + buttons" toolbar (Activity Log's
     Role/Type/dates/search/Clear buttons, Reports' report-type/date-range/
     Generate-Print-Reset). A straight column (one field per row) was
     needlessly tall for fields this narrow; two-up grid instead — fields
     pair off two to a row, and anything marked .filter-grid-full (a wide
     field like Search, or a .filter-grid-actions button group) spans both
     columns on its own row instead of trailing off next to whatever
     field came before it. */
  .filter-grid { display: grid; grid-template-columns: 1fr 1fr; align-items: flex-end; }
  .filter-grid .form-group { min-width: 0; }
  .filter-grid .search-input-wrap,
  .filter-grid .filter-grid-full,
  .filter-grid .filter-grid-actions { grid-column: 1 / -1; }
  .filter-grid-actions .btn-ghost,
  .filter-grid-actions .btn-danger,
  .filter-grid-actions .btn-primary,
  .filter-grid-actions .btn-secondary { flex: 1; justify-content: center; }
  .table-actions { width: 100%; margin-left: 0; justify-content: flex-end; }
  .search-input-wrap { flex: 1; }
  .search-input { width: 100%; }
  .search-input:focus { width: 100%; }

  /* ── Topbar: too many elements for a narrow viewport — drop the
     decorative clinic block. The breadcrumb itself scrolls horizontally
     instead of wrapping to a second line (same convention as .filter-tabs
     above) — an ellipsis-on-the-last-segment approach used to sit here,
     but a flex item's default min-width:auto stops it actually shrinking
     enough to trigger, so on a long enough label the row wrapped anyway
     instead of truncating. Scrolling sidesteps that: nothing needs to
     shrink, it just scrolls to what doesn't fit. ── */
  .topbar { gap: 8px; }
  .topbar-left { min-width: 0; gap: 8px; }
  .topbar-clinic { display: none; }
  .topbar-brand { padding-right: 8px; gap: 6px; }
  .topbar-brand-name { font-size: 0.88rem; }
  .topbar-crumb {
    min-width: 0;
    flex: 1;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: #D1D5DB transparent;
    white-space: nowrap;
  }
  .topbar-crumb::-webkit-scrollbar { height: 3px; display: block; }
  .topbar-crumb::-webkit-scrollbar-track { background: transparent; }
  .topbar-crumb::-webkit-scrollbar-thumb { background: #D1D5DB; border-radius: 99px; }
  .topbar-crumb-link,
  .topbar-crumb strong {
    flex-shrink: 0;
    white-space: nowrap;
  }

  /* ── Card headers: title + select/button combo needs to wrap, not
     overflow, on narrow cards ── */
  .card-header {
    flex-wrap: wrap;
    gap: 8px;
  }
  .card-header > *:last-child:not(.card-title):not(button):not(.chart-legend-dot) { width: 100%; }
  .card-header .form-select { width: 100%; }

  /* ── Safety net: any ad-hoc inline grid (registration forms, exam
     forms, settings panels, QR scanner's camera/results split, modal
     forms, etc.) collapses to a single column instead of cramming on
     a narrow screen. ── */
  .page-body [style*="grid-template-columns"],
  .modal-body [style*="grid-template-columns"] {
    grid-template-columns: 1fr !important;
  }
  /* .clearance-document mirrors a fixed print layout — keep its exact
     column proportions instead of collapsing, so the certificate
     preview still resembles the printed document. */
  .clearance-document [style*="grid-template-columns"] {
    grid-template-columns: 17% 17% 44% 22% !important;
  }

  /* ── Exam wizard: compact padding + "Step X of Y" fallback label on
     mobile — the actual "doesn't fit, scroll instead of squish" behavior
     (fixed min-width per step, relying on #wiz-stepper's own
     overflow-x:auto) is now baked into stepperHTML's own inline styles
     (pages.js) as the universal default, not just a mobile override — a
     tablet-width viewport (too wide for this max-width:767px block, but
     not wide enough to fit all 6 steps at their natural size) needs the
     exact same "stop shrinking, scroll" fallback and was falling through
     to squished/overlapping labels with only a mobile-scoped fix. */
  #wiz-stepper { padding: 14px 16px; margin-bottom: 0; }
  #wiz-step-label { display: block !important; }

  /* ── Exam wizard: keep OD/OS inner field pairs at 2-column ── */
  .wiz-eye-fields { gap: 10px !important; }
}

/* ── Small mobile: single-column stats (<480px) ── */
@media (max-width: 480px) {
  .stats-grid { grid-template-columns: 1fr; }
  .stats-grid-6 { grid-template-columns: 1fr; gap: 10px; }
  .page-header { flex-direction: column; align-items: flex-start; gap: 8px; }
  .page-header > *:not(.page-header-left) { width: 100%; }
  .page-header > *:not(.page-header-left) .btn-primary,
  .page-header > *:not(.page-header-left) .btn-secondary,
  .page-header > *:not(.page-header-left) .btn-ghost,
  .page-header > .btn-primary,
  .page-header > .btn-secondary,
  .page-header > .btn-ghost {
    width: 100%;
    justify-content: center;
  }
  /* A page-header with more than one button (e.g. Appointments' Waitlist +
     New Appointment, Dashboard's Print/Download/Waitlist/New Appointment)
     would otherwise have all of them fighting over width:100% inside the
     same flex row above — each gets shrunk to a sliver, squeezed together
     instead of the same clean full-width look every single-button
     page-header already has. A 2-up grid instead of stacking one per row —
     full-width stacking a 4-button header (Dashboard) burned real vertical
     space before any actual page content showed; each button still gets a
     comfortably tappable full-width-of-its-column target, just two per row
     instead of one. An odd button count's last item naturally spans just
     its own column, not the full row — acceptable rather than worth
     special-casing. Every call site sets style="display:flex;gap:10px"
     inline for its own desktop layout — an inline style always wins over
     an external stylesheet rule regardless of specificity, media query,
     or source order, so display:grid here needs !important to actually
     take over on mobile at all (same reason .pt-sett-col's own desktop
     grid override needs it, pages.js). */
  .page-header-btn-group { display: grid !important; grid-template-columns: 1fr 1fr; gap: 8px !important; }
  /* .page-header-right (e.g. Dashboard's Waitlist/New Appointment cluster
     with the date caption underneath) is a nested wrapper, one level
     deeper than .page-header-btn-group itself — its own align-items:flex-end
     (set above for desktop) stops it and its button group from stretching
     to the full width the width:100% rule above already granted it, which
     right-aligns the whole cluster into a narrow column instead of the
     clean full-width stack every other page-header gets. Un-align it. */
  .page-header-right { align-items: stretch; }
  /* Single-column cards: full width, compact */
  .stat-card { padding: 14px 18px; gap: 12px; align-items: center; min-height: unset; }
  .stat-info { min-width: 0; flex: 1; }
  .stat-icon { width: 40px; height: 40px; border-radius: 10px; flex-shrink: 0; }
  .stat-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .stat-value { font-size: 1.6rem; }
  .stat-delta { font-size: 0.75rem; }
  .chart-wrap { height: 190px; }

  /* QR scanner camera area: less vertical bulk on small phones */
  #qr-camera-area { min-height: 220px !important; padding: 28px 16px !important; }
  #qr-cam-idle > div:first-child { width: 48px !important; height: 48px !important; }

  /* Security card temp password row: stack label above pill on narrow screens */
  #ep-temp-row { flex-direction: column !important; align-items: flex-start !important; gap: 6px !important; }
  #ep-temp-wrap { align-items: flex-start !important; }
}

/* ══════════════════════════════════════════════
   SCREEN — Ophthalmic Clearance's two editable paragraphs
   (clearance-remarks-1/-2, main.js). These used to only reveal
   themselves as editable once actually focused (a dashed outline that
   appeared, then vanished on blur) — nothing distinguished them from
   the surrounding plain certificate text beforehand, so there was no way
   to tell they were editable without clicking into one first. A
   persistent tint + dashed border makes that obvious up front instead.
   Screen-only on purpose: @media print below already strips this class
   back to plain text for real printing, and downloadClearancePDF()
   (main.js) swaps each textarea for a plain <div> that only inherits its
   INLINE style, never its class — so this never leaks into the PDF either.
══════════════════════════════════════════════ */
.clearance-textarea {
  border: 1px dashed #E8760A;
  background: #FFFAF3;
  border-radius: 5px;
  padding: 8px 10px;
  transition: background .15s ease, border-color .15s ease;
}
.clearance-textarea:hover { background: #FFF3E0; }
.clearance-textarea:focus { outline: none; background: #FFF3E0; border-style: solid; }

/* ══════════════════════════════════════════════
   PRINT — default page size for anything printed
   directly from the main window (e.g. the Ophthalmic
   Clearance certificate). Iframe-based prints (exam
   records, prescriptions, QR) set their own @page
   rule inside their own generated document instead.
   margin:0 so Chrome has no page-margin band left to draw its own print
   header/footer (URL, date, page number) into — the same visual margin is
   restored via .clearance-document's own print padding below instead.
══════════════════════════════════════════════ */
@page { size: A4; margin: 0; }

/* ══════════════════════════════════════════════
   PRINT — Ophthalmic Clearance isolation
══════════════════════════════════════════════ */
@media print {
  /* Hide everything, but ONLY when the clearance certificate overlay is
     actually open — without this :has() guard, every other print in the
     app (Print Records, table print buttons, etc.) would print a blank
     page, since this rule applied unconditionally on every window.print(). */
  body:has(.clearance-document) * { visibility: hidden; }
  body:has(.clearance-document) .clearance-document,
  body:has(.clearance-document) .clearance-document * { visibility: visible; }

  /* Lay the certificate out from the top of the page, like the reference
     document it's modeled on — not vertically centered. It's pulled out
     of normal flow (position:absolute) because its ancestors are only
     visibility:hidden, not display:none, so they'd otherwise still
     reserve their normal layout space and push/misplace it; top:0 anchors
     it to the page box itself (the containing block for an absolutely-
     positioned element with no positioned ancestors) starting at the
     top margin instead of floating mid-page. */
  /* Padding here should mirror the on-screen preview's own
     padding:48px 56px (≈13mm/15mm at 96dpi), not an arbitrary print
     margin — 40mm of side padding used to squeeze the content into a
     much narrower column than the modal shows, so the printed page
     looked visibly smaller/more whitespace-heavy than the preview even
     though it's the exact same markup. */
  .clearance-document {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    padding: 13mm 15mm;
    font-size: 12pt;
    background: #fff !important;
  }

  /* Ensure all text prints black — except the orange mobile-number bar
     (below), which is a deliberate branded banner in the reference
     document this was built to match, not incidental screen color. */
  .clearance-document * { color: #000 !important; }

  /* Chrome/Edge drop an element's own background-color when printing
     unless explicitly told to keep it — without this the branded orange
     mobile-number bar printed as a plain white strip with invisible
     white-on-white text, even though the on-screen preview shows it
     correctly. Scoped to the one element that actually needs a printed
     background, not the whole document, so nothing else in the ": ensure
     all text prints black" rule above gets second-guessed. */
  .clearance-mobile-bar {
    background: #E8760A !important;
    color: #fff !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* Textareas look like plain typed text */
  .clearance-document textarea,
  .clearance-document .clearance-textarea {
    border: none !important;
    outline: none !important;
    resize: none !important;
    background: transparent !important;
    padding: 0 !important;
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    overflow: visible !important;
    height: auto !important;
  }

  /* Hide modal chrome */
  .clearance-modal-header,
  .clearance-actions { display: none !important; }
}

/* ════════════════════════════════════════════════════════════════
   PDF DOWNLOAD — EXAM DOCUMENT (downloadExamRecordPDF(), main.js)
   Real, permanent classes — not a dynamically-injected <style> block
   built from a parsed HTML string — so this renders exactly like
   downloadClearancePDF()'s own live-DOM capture: html2canvas reading
   ordinary class-based styling from a stylesheet that's been part of
   the page the whole time, same as .clearance-document above, instead
   of freshly parsed/injected CSS (which kept coming out with panels
   silently missing or mispositioned — several different underlying
   causes across several attempts, but the common thread was always
   "reconstructing style from a string on the fly"). Every selector
   scoped under .pdf-exam-doc so none of these (.info-grid is already
   used elsewhere in this file for something unrelated) ever leak
   outside this one specific document. */
.pdf-exam-doc, .pdf-exam-doc * { box-sizing: border-box; margin: 0; padding: 0; }
.pdf-exam-doc { font-family: Arial, Helvetica, sans-serif; color: #111; font-size: 14px; line-height: 1.65; background: #fff; }
.pdf-exam-doc table { width: 100%; border-collapse: collapse; }
.pdf-exam-doc .clinic-hdr  { display: flex; align-items: center; gap: 14px; border-bottom: 3px solid #E8760A; padding-bottom: 14px; margin-bottom: 20px; }
.pdf-exam-doc .clinic-hdr-text { text-align: left; }
.pdf-exam-doc .clinic-name { font-size: 24px; font-weight: 900; color: #E8760A; letter-spacing: -.02em; }
.pdf-exam-doc .clinic-logo { height: 70px; flex-shrink: 0; }
.pdf-exam-doc .clinic-sub  { font-size: 16px; font-weight: 700; color: #1C1C1C; }
.pdf-exam-doc .clinic-doc  { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #bbb; margin-top: 6px; }
.pdf-exam-doc .patient-block { display: flex; gap: 18px; align-items: flex-start; padding: 16px 18px; background: #f9f9f9; border: 1px solid #eee; border-radius: 10px; margin-bottom: 18px; }
.pdf-exam-doc .avatar { width: 60px; height: 60px; border-radius: 50%; background: #E8760A; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 21px; font-weight: 900; flex-shrink: 0; }
.pdf-exam-doc .pt-name   { font-size: 18px; font-weight: 800; color: #111; margin-bottom: 2px; }
.pdf-exam-doc .pt-id     { font-size: 11px; font-family: monospace; color: #aaa; margin-bottom: 5px; }
.pdf-exam-doc .pt-meta   { display: flex; flex-wrap: wrap; gap: 5px 14px; }
.pdf-exam-doc .pt-meta span { font-size: 11px; color: #555; }
.pdf-exam-doc .pt-addr   { font-size: 11px; color: #999; margin-top: 3px; }
.pdf-exam-doc .issuer    { text-align: right; flex-shrink: 0; min-width: 160px; }
.pdf-exam-doc .iss-lbl   { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #bbb; margin-bottom: 3px; }
.pdf-exam-doc .iss-name  { font-size: 15px; font-weight: 700; color: #111; }
.pdf-exam-doc .iss-date  { font-size: 11px; color: #888; }
.pdf-exam-doc .iss-id    { font-size: 10px; font-family: monospace; color: #bbb; margin-top: 2px; }
.pdf-exam-doc .tbl-hdr th { background: #f5f5f5; padding: 9px 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.pdf-exam-doc .tbl-border { border: 1px solid #eee; border-radius: 10px; overflow: hidden; margin-bottom: 16px; }
.pdf-exam-doc .info-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 16px; }
.pdf-exam-doc .info-box  { background: #f9f9f9; border: 1px solid #eee; border-radius: 8px; padding: 10px 12px; min-width: 0; }
.pdf-exam-doc .ib-lbl    { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #aaa; margin-bottom: 3px; }
.pdf-exam-doc .ib-val    { font-size: 16px; font-weight: 800; color: #111; overflow-wrap: anywhere; }
.pdf-exam-doc .ib-unit   { font-size: 10px; color: #aaa; font-weight: 400; }
.pdf-exam-doc .diag-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.pdf-exam-doc .diag-box  { background: #f9f9f9; border: 1px solid #eee; border-radius: 8px; padding: 12px 14px; min-width: 0; }
.pdf-exam-doc .db-lbl    { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #aaa; margin-bottom: 4px; }
.pdf-exam-doc .db-val    { font-size: 16px; font-weight: 800; color: #111; margin-bottom: 3px; overflow-wrap: anywhere; }
.pdf-exam-doc .db-sub    { font-size: 11px; color: #555; }
.pdf-exam-doc .remarks-block { border-top: 1px solid #eee; padding-top: 12px; margin-top: 8px; font-style: italic; font-size: 13px; color: #555; }
.pdf-exam-doc .sig-grid  { display: grid; grid-template-columns: 1fr 1fr; gap: 50px; margin-top: 26px; padding-top: 16px; border-top: 1px dashed #ccc; }
.pdf-exam-doc .sig-line  { border-top: 1px solid #111; padding-top: 7px; text-align: center; font-size: 11px; font-weight: 700; text-transform: uppercase; }
.pdf-exam-doc .sig-sub   { font-size: 10px; color: #888; margin-top: 3px; text-align: center; }
.pdf-exam-doc .prep-by   { font-size: 10px; color: #888; text-align: right; margin-top: 12px; }
.pdf-exam-doc .stamp     { font-size: 10px; color: #ccc; text-align: right; font-family: monospace; margin-top: 16px; }

/* ── PDF DOWNLOAD — PRESCRIPTION DOCUMENT (downloadRxRecordPDF(), main.js) ──
   Same reasoning/architecture as .pdf-exam-doc above. */
.pdf-rx-doc, .pdf-rx-doc * { box-sizing: border-box; margin: 0; padding: 0; }
.pdf-rx-doc { font-family: Arial, Helvetica, sans-serif; color: #111; font-size: 14px; line-height: 1.5; background: #fff; }
.pdf-rx-doc table { width: 100%; border-collapse: collapse; }
.pdf-rx-doc .clinic-hdr  { display: flex; align-items: center; gap: 14px; border-bottom: 3px solid #E8760A; padding-bottom: 10px; margin-bottom: 14px; }
.pdf-rx-doc .clinic-hdr-text { text-align: left; }
.pdf-rx-doc .clinic-name { font-size: 22px; font-weight: 900; color: #E8760A; letter-spacing: -.02em; }
.pdf-rx-doc .clinic-logo { height: 58px; flex-shrink: 0; }
.pdf-rx-doc .clinic-sub  { font-size: 15px; font-weight: 700; color: #1C1C1C; }
.pdf-rx-doc .clinic-doc  { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #bbb; margin-top: 4px; }
.pdf-rx-doc .patient-block { display: flex; gap: 16px; align-items: flex-start; padding: 12px 16px; background: #f9f9f9; border: 1px solid #eee; border-radius: 10px; margin-bottom: 12px; }
.pdf-rx-doc .avatar { width: 52px; height: 52px; border-radius: 50%; background: #E8760A; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 19px; font-weight: 900; flex-shrink: 0; }
.pdf-rx-doc .pt-name   { font-size: 17px; font-weight: 800; color: #111; margin-bottom: 2px; }
.pdf-rx-doc .pt-id     { font-size: 11px; font-family: monospace; color: #aaa; margin-bottom: 4px; }
.pdf-rx-doc .pt-meta   { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.pdf-rx-doc .pt-meta span { font-size: 11px; color: #555; }
.pdf-rx-doc .issuer    { text-align: right; flex-shrink: 0; min-width: 160px; }
.pdf-rx-doc .iss-lbl   { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #bbb; margin-bottom: 3px; }
.pdf-rx-doc .iss-name  { font-size: 14px; font-weight: 700; color: #111; }
.pdf-rx-doc .iss-date  { font-size: 11px; color: #888; }
.pdf-rx-doc .iss-id    { font-size: 10px; font-family: monospace; color: #bbb; margin-top: 2px; }
.pdf-rx-doc .tbl-hdr th { background: #f5f5f5; padding: 7px 12px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.pdf-rx-doc .tbl-border { border: 1px solid #eee; border-radius: 10px; overflow: hidden; margin-bottom: 12px; }
.pdf-rx-doc .diag-box  { background: #f9f9f9; border: 1px solid #eee; border-radius: 8px; padding: 9px 12px; margin-bottom: 12px; min-width: 0; }
.pdf-rx-doc .db-lbl    { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #aaa; margin-bottom: 3px; }
.pdf-rx-doc .db-val    { font-size: 15px; font-weight: 800; color: #111; overflow-wrap: anywhere; }
.pdf-rx-doc .info-grid { display: grid; gap: 8px; margin-bottom: 12px; }
.pdf-rx-doc .info-box  { background: #f9f9f9; border: 1px solid #eee; border-radius: 8px; padding: 8px 10px; min-width: 0; }
.pdf-rx-doc .ib-lbl    { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: #aaa; margin-bottom: 2px; }
.pdf-rx-doc .ib-val    { font-size: 15px; font-weight: 800; color: #111; overflow-wrap: anywhere; }
.pdf-rx-doc .ib-unit   { font-size: 10px; color: #aaa; font-weight: 400; }
.pdf-rx-doc .remarks-block { border-top: 1px solid #eee; padding-top: 10px; margin-top: 6px; font-style: italic; font-size: 13px; color: #555; }
.pdf-rx-doc .sig-grid  { display: grid; grid-template-columns: 1fr 1fr; gap: 50px; margin-top: 16px; padding-top: 12px; border-top: 1px dashed #ccc; }
.pdf-rx-doc .sig-line  { border-top: 1px solid #111; padding-top: 6px; text-align: center; font-size: 11px; font-weight: 700; text-transform: uppercase; }
.pdf-rx-doc .sig-sub   { font-size: 10px; color: #888; margin-top: 2px; text-align: center; }
.pdf-rx-doc .prep-by   { font-size: 10px; color: #888; text-align: right; margin-top: 8px; }
.pdf-rx-doc .stamp     { font-size: 10px; color: #ccc; text-align: right; font-family: monospace; margin-top: 8px; }
.pdf-rx-doc .valid-pill { display: inline-block; font-size: 10px; font-weight: 700; padding: 3px 10px; border-radius: 20px; margin-top: 4px; }

/* ── PDF DOWNLOAD — DASHBOARD REPORT (downloadDashboardReportPDF(), main.js) ──
   Same reasoning/architecture as .pdf-exam-doc above. */
.pdf-dash-doc, .pdf-dash-doc * { box-sizing: border-box; margin: 0; padding: 0; }
.pdf-dash-doc { font-family: Arial, Helvetica, sans-serif; color: #111; font-size: 13px; line-height: 1.6; background: #fff; }
.pdf-dash-doc table { width: 100%; border-collapse: collapse; }
.pdf-dash-doc .clinic-hdr  { display: flex; align-items: center; gap: 14px; border-bottom: 3px solid #E8760A; padding-bottom: 14px; margin-bottom: 16px; }
.pdf-dash-doc .clinic-logo { height: 60px; flex-shrink: 0; }
.pdf-dash-doc .clinic-name { font-size: 22px; font-weight: 900; color: #E8760A; letter-spacing: -.02em; }
.pdf-dash-doc .clinic-sub  { font-size: 15px; font-weight: 700; color: #1C1C1C; }
.pdf-dash-doc .clinic-doc  { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #bbb; margin-top: 4px; }
.pdf-dash-doc .rpt-meta    { display: flex; justify-content: space-between; font-size: 11px; color: #888; margin-bottom: 22px; }
.pdf-dash-doc .rpt-section { margin-bottom: 20px; }
.pdf-dash-doc tr { page-break-inside: avoid; }
.pdf-dash-doc .rpt-sec-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: #999; margin-bottom: 6px; }
.pdf-dash-doc .rpt-empty   { font-size: 12px; color: #aaa; font-style: italic; padding: 8px 0; }
.pdf-dash-doc .tbl-hdr th  { background: #f5f5f5; padding: 8px 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.pdf-dash-doc .tbl-border  { border: 1px solid #eee; border-radius: 8px; overflow: hidden; }
/* Real signature line, generous blank space above it, no crowding
   divider — see the matching comment on .sig-block in
   printDashboardReport() (main.js) for why. */
.pdf-dash-doc .sig-block   { margin-top: 48px; display: flex; justify-content: flex-end; }
.pdf-dash-doc .sig-col     { text-align: center; min-width: 220px; }
.pdf-dash-doc .sig-line    { border-top: 1px solid #111; padding-top: 7px; font-size: 11px; font-weight: 700; text-transform: uppercase; }
.pdf-dash-doc .sig-sub     { font-size: 10px; color: #888; margin-top: 3px; }

/* ── PDF DOWNLOAD — REPORTS PAGE (downloadReportPDF(), pages.js) ──
   Same reasoning/architecture as .pdf-exam-doc above. */
.pdf-report-doc, .pdf-report-doc * { box-sizing: border-box; margin: 0; padding: 0; }
.pdf-report-doc { font-family: Arial, Helvetica, sans-serif; font-size: 9pt; color: #111; background: #fff; }
.pdf-report-doc .hdr          { display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 2px solid #111; padding-bottom: 10px; margin-bottom: 10px; }
.pdf-report-doc .hdr-left     { display: flex; align-items: center; gap: 10px; }
.pdf-report-doc .hdr-logo     { height: 42px; width: 42px; object-fit: contain; flex-shrink: 0; }
.pdf-report-doc .clinic-name  { font-size: 14pt; font-weight: 700; letter-spacing: -.02em; }
.pdf-report-doc .clinic-sub   { font-size: 7.5pt; color: #555; margin-top: 3px; }
.pdf-report-doc .hdr-right    { text-align: right; }
.pdf-report-doc .hdr-tag      { font-size: 6.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #888; }
.pdf-report-doc .rpt-title    { font-size: 11pt; font-weight: 700; margin-bottom: 2px; }
.pdf-report-doc .rpt-meta     { font-size: 7.5pt; color: #555; margin-bottom: 14px; }
.pdf-report-doc .rpt-meta span { margin-right: 12px; }
.pdf-report-doc table { width: 100%; border-collapse: collapse; font-size: 8pt; }
.pdf-report-doc thead tr { background: #f3f4f6 !important; }
.pdf-report-doc th { padding: 6px 8px; text-align: left; font-size: 7.5pt; font-weight: 700; border: 1px solid #d1d5db; background: #f3f4f6; }
.pdf-report-doc td { padding: 5px 8px; border: 1px solid #e5e7eb; vertical-align: top; line-height: 1.35; }
.pdf-report-doc tbody tr:nth-child(even) td { background: #fafafa; }
.pdf-report-doc tr { page-break-inside: avoid; }
.pdf-report-doc code { font-family: 'Courier New', monospace; font-size: 7.5pt; }
/* The results table (#rpt-table-area) is CLONED straight from the live,
   on-screen table — not hand-built like the Exam/Rx/Dashboard markup —
   so it carries the app's own .tbl class along with it. html2canvas's
   own windowWidth option (set to the printable content width, ~643px,
   for correct proportions) makes ITS internal render pass evaluate
   @media queries against that narrow width, which activates this app's
   real mobile-responsive .tbl CSS (global.css) — the one that turns
   each row into a stacked, labeled card instead of a table row. That's
   exactly the stacked layout that showed up instead of real columns.
   Forcing plain table display back on, regardless of which breakpoint
   html2canvas's capture pass happens to be evaluating against. */
.pdf-report-doc .tbl { display: table !important; }
.pdf-report-doc .tbl thead { display: table-header-group !important; }
.pdf-report-doc .tbl tbody { display: table-row-group !important; }
.pdf-report-doc .tbl tr { display: table-row !important; background: transparent !important; border: none !important; border-radius: 0 !important; box-shadow: none !important; padding: 0 !important; margin-bottom: 0 !important; }
.pdf-report-doc .tbl th,
.pdf-report-doc .tbl td { display: table-cell !important; text-align: left !important; white-space: normal !important; }
.pdf-report-doc .tbl td[data-label]::before { content: none !important; }
.pdf-report-doc .badge { display: inline-block; padding: 1px 7px; border-radius: 20px; font-size: 7pt; font-weight: 700; }
.pdf-report-doc .badge-pending     { background: #FFF3E0; color: #E8891C; }
.pdf-report-doc .badge-approved    { background: #E8F5E9; color: #2E7D32; }
.pdf-report-doc .badge-cancelled   { background: #FFEBEE; color: #C62828; }
.pdf-report-doc .badge-inactive    { background: #FFEBEE; color: #C62828; }
.pdf-report-doc .badge-disapproved { background: #fef2f2; color: #991b1b; }
.pdf-report-doc .badge-completed   { background: #F5F5F5; color: #616161; }
.pdf-report-doc .badge-no-show     { background: #EDE9FE; color: #6D28D9; }
.pdf-report-doc .badge-active      { background: #E3F2FD; color: #1565C0; }
.pdf-report-doc .badge-admin       { background: #EDE9FE; color: #5B21B6; }
.pdf-report-doc .badge-staff       { background: #DBEAFE; color: #1D4ED8; }
.pdf-report-doc .badge-doctor      { background: #E8F5E9; color: #2E7D32; }
.pdf-report-doc .badge-patient     { background: #FFF0DC; color: #92400E; }
.pdf-report-doc .charts-section { margin-top: 20px; }
.pdf-report-doc .section-header { border-bottom: 1px solid #ddd; padding-bottom: 8px; margin-bottom: 14px; }
.pdf-report-doc .section-title  { font-size: 11pt; font-weight: 700; }
.pdf-report-doc .section-sub    { font-size: 7.5pt; color: #666; margin-top: 2px; }
.pdf-report-doc .chart-grid   { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.pdf-report-doc .chart-box    { border: 1px solid #e5e7eb; border-radius: 4px; padding: 12px; page-break-inside: avoid; }
.pdf-report-doc .chart-label  { font-size: 8.5pt; font-weight: 700; margin-bottom: 8px; }
/* Real signature line, generous blank space above it, no crowding
   divider — see the matching comment on .sig-block in printReport()
   (pages.js) for why. */
.pdf-report-doc .sig-block { margin-top: 40px; display: flex; justify-content: flex-end; }
.pdf-report-doc .sig-col   { text-align: center; min-width: 200px; }
.pdf-report-doc .sig-line  { border-top: 1px solid #111; padding-top: 6px; font-size: 8pt; font-weight: 700; text-transform: uppercase; }
.pdf-report-doc .sig-sub   { font-size: 7pt; color: #888; margin-top: 2px; }


/* ── Login card shake animation ─────────────────────────────── */
@keyframes login-shake {
  0%, 100% { transform: translateX(0); }
  15%       { transform: translateX(-6px); }
  30%       { transform: translateX(6px); }
  45%       { transform: translateX(-5px); }
  60%       { transform: translateX(5px); }
  75%       { transform: translateX(-3px); }
  90%       { transform: translateX(3px); }
}
.login-shake {
  animation: login-shake 0.45s ease;
}
