@import url('https://fonts.googleapis.com/css2?family=Sora:wght@500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

/* =====================================================================
   COLOR SYSTEM — 4 switchable palettes × light/dark mode.
   Two independent HTML attributes drive the whole system:
     <html data-palette="control|signal|slate|violet" data-mode="light|dark">
   Component CSS below never hardcodes a color — everything reads these
   custom properties, so switching palette/mode is a pure attribute swap
   (see applyTheme() in viewer.js / applyAdminTheme() in admin.js).
   Base :root = "control" palette, light mode (closest to the app's
   original identity — safe default, zero migration risk for anyone who
   doesn't touch the picker). The 3 alternate palettes + all 4 dark
   variants are defined further down as attribute-selector overrides.
   ===================================================================== */
:root{
  --ink:        #0d1424;   /* deep navy-black, modern "control room" */
  --ink-soft:   #16213a;
  --paper:      #f5f7fb;   /* cool off-white */
  --paper-dim:  #e8ecf6;
  --brass:      #5b7fff;   /* primary accent */
  --brass-dark: #3f5fe0;
  --sage:       #5b6479;   /* muted label/hint gray — darkened slightly from the original for WCAG AA contrast at small sizes */
  --clay:       #e5484d;   /* alert / destructive */
  --line:       #dbe1ee;
  --text-dark:  #1a2233;
  --text-light: #eef1f9;
  --glow:       #22d3ee;   /* live/status accent — used sparingly (pulses, "đang hoạt động"), never as a base surface color */
  --glow-soft:  rgba(34,211,238,.28);
  --auto:       #d98c1f;   /* amber — flags auto-computed/read-only fields, kept distinct from --glow */
  --auto-soft:  rgba(217,140,31,.16);
  --brass-soft: rgba(91,127,255,.20); /* "currently editing" highlight in Admin */
  --holo-blue:  var(--brass);   /* management-tier accent — theme-aware */
  --holo-green: #22b573;        /* staff-tier accent — held constant across palettes for role recognition */
  --holo-red:   #e5484d;        /* "related colleague" highlight ring — held constant across palettes */
  --radius:     16px;
  --shadow:     0 10px 28px rgba(13,20,36,.10), 0 2px 8px rgba(13,20,36,.06);
  --font-display: 'Sora', sans-serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;

  /* ---- Liquid Glass tokens (elevation tier 2 — floating panels: topbar,
     org-chart node, modal, assistant bubble). Tier-1 surfaces (dense
     forms/tables in Admin) stay flat/opaque — see .card below — so glass
     stays "có kiểm soát" rather than covering the whole app.
     Tinted with a whisper of the palette accent (not plain white) so the
     glass has visible colour/character instead of reading as washed-out
     against the near-white page. ---- */
  --glass-bg:      #ffffff; /* fallback for browsers without color-mix() */
  --glass-bg:      color-mix(in srgb, var(--brass) 7%, rgba(255,255,255,.72));
  --glass-bg-2:    color-mix(in srgb, var(--brass) 5%, rgba(255,255,255,.85)); /* slightly less translucent — modal body, needs longer reading */
  --glass-border:  color-mix(in srgb, var(--brass) 22%, rgba(255,255,255,.75));
  --glass-blur:    20px;
  --glass-shadow:  0 12px 32px rgba(13,20,36,.20), inset 0 1px 0 rgba(255,255,255,.7);
  --glass-shadow-sm: 0 6px 18px rgba(13,20,36,.15), inset 0 1px 0 rgba(255,255,255,.6);
}


*{ box-sizing:border-box; }
html,body{ margin:0; padding:0; }
body{
  font-family: var(--font-body);
  background: var(--paper);
  color: var(--text-dark);
  line-height:1.5;
}
h1,h2,h3,h4{ font-family: var(--font-display); font-weight:600; margin:0 0 .4em; color: var(--ink); }
a{ color: var(--brass-dark); }
button{ font-family: inherit; cursor:pointer; }
input, select, textarea{ font-family: inherit; font-size:14px; }

/* ---------- Top bar (shared) — Liquid Glass, elevation tier 2 -------- */
.topbar{
  display:flex; align-items:center; gap:16px;
  background: var(--ink); /* fallback for browsers without color-mix() support */
  background: linear-gradient(180deg, color-mix(in srgb, var(--ink) 88%, transparent), color-mix(in srgb, var(--ink-soft) 82%, transparent));
  backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%);
  color: var(--text-light);
  padding: 14px 24px;
  position: sticky; top:0; z-index: 1000;
  box-shadow: 0 8px 24px rgba(0,0,0,.18), inset 0 -1px 0 rgba(255,255,255,.06);
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.topbar .brand{ display:flex; align-items:center; gap:12px; }
.topbar .brand .crest{
  width:40px; height:40px; border-radius:50%;
  background: radial-gradient(circle at 30% 30%, var(--brass), var(--brass-dark));
  display:flex; align-items:center; justify-content:center;
  font-family: var(--font-display); font-weight:700; color:var(--ink);
  flex-shrink:0;
}
.topbar h1{ color: var(--text-light); font-size: 1.15rem; margin:0; }
.topbar .subtitle{ font-size:.75rem; opacity:.7; letter-spacing:.03em; }
.topbar-spacer{ flex:1; }
.topbar-actions{ display:flex; gap:8px; flex-wrap:wrap; }

/* ---- Task: nút bấm dạng nổi 3D + phản hồi khi nhấp (press-down). ---- */
.btn{
  border:1px solid var(--brass); background: transparent; color: var(--text-light);
  padding:8px 14px; border-radius:999px; font-size:.82rem; font-weight:500;
  transition: transform .12s ease, box-shadow .12s ease, background .15s ease, color .15s ease;
  white-space:nowrap; position:relative;
  box-shadow: 0 2px 0 rgba(0,0,0,.16), 0 4px 10px rgba(13,20,36,.14);
}
.btn:hover{ background: var(--brass); color: var(--ink); transform: translateY(-1px); box-shadow: 0 3px 0 rgba(0,0,0,.18), 0 8px 16px rgba(13,20,36,.20); }
.btn:active{ transform: translateY(1px); box-shadow: 0 0 0 rgba(0,0,0,0), 0 2px 6px rgba(13,20,36,.18); }
.btn.solid{ background: linear-gradient(160deg, color-mix(in srgb, var(--brass) 92%, white), var(--brass)); color: var(--ink); border-color: var(--brass-dark); }
.btn.solid:hover{ background: linear-gradient(160deg, color-mix(in srgb, var(--brass-dark) 85%, white), var(--brass-dark)); }
.btn.ghost-dark{ border-color: var(--line); color: var(--ink); box-shadow: 0 2px 0 rgba(0,0,0,.08), 0 3px 8px rgba(13,20,36,.08); }
.btn.ghost-dark:hover{ background: var(--ink); color: var(--text-light); }
.btn.danger{ border-color: var(--clay); color: var(--clay); }
.btn.danger:hover{ background: var(--clay); color: #fff; }
.btn:disabled{ opacity:.4; cursor:not-allowed; transform:none !important; box-shadow:none !important; }
.btn.small{ padding:5px 10px; font-size:.72rem; }
/* Same 3D press treatment for the icon-only chevron/action buttons used
   throughout Admin (year-card ▲▼✏️🙈✕ etc.) so the "nhận định khi nhấp"
   feedback is consistent everywhere, not just .btn. */
.achievement-year-icon-btn, .mode-btn, .theme-menu .palette-swatch{
  transition: transform .12s ease, box-shadow .12s ease;
  box-shadow: 0 2px 0 rgba(0,0,0,.12), 0 3px 6px rgba(13,20,36,.10);
}
.achievement-year-icon-btn:active, .mode-btn:active{ transform: translateY(1px) scale(.97); box-shadow:none; }

/* ---------- Layout shells ---------- */
.shell{ max-width: 1280px; margin: 0 auto; padding: 24px; }
.card{
  background:#fff; border:1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding:22px 24px; margin-bottom:22px;
  transition: background .15s ease, box-shadow .18s ease, border-color .15s ease, transform .15s ease;
}
.card > h3:first-child{ margin-bottom:14px; }
/* While actively typing/selecting inside a card (person, facility,
   department, library info...), the WHOLE card tints so it's obvious at a
   glance which section is being edited — reverts automatically the
   moment focus moves elsewhere, no JS needed. */
.card:focus-within{
  background: var(--paper-dim);
  border-color: var(--brass);
  box-shadow: 0 0 0 2px var(--brass-soft), var(--shadow);
}
.grid-2{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
.grid-3{ display:grid; grid-template-columns:repeat(3,1fr); gap:14px; }
@media (max-width:820px){ .grid-2,.grid-3{ grid-template-columns:1fr; } }

.field{ margin-bottom:12px; display:flex; flex-direction:column; gap:4px; }
.field label{ font-size:.75rem; font-weight:600; color: var(--sage); text-transform:uppercase; letter-spacing:.03em; }
.field input, .field select, .field textarea{
  padding:10px 12px; border:1px solid var(--line); border-radius:9px; background: var(--paper); transition: border-color .12s ease, box-shadow .12s ease;
}
.field textarea{ min-height:64px; resize:vertical; }
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-soft);
}
/* Auto-computed / read-only fields (age, leave used/remaining, staff
   counts, party-age...) are all rendered as disabled inputs throughout
   Admin — flag them visually so it's obvious they can't be typed into and
   update themselves from other data. */
.field input:disabled, .field select:disabled, .field textarea:disabled{
  border:1px dashed var(--auto); background: var(--auto-soft); color: var(--text-dark); cursor: default;
}
.field input:disabled::placeholder{ color: var(--sage); }
.field label:has(+ input:disabled)::after,
.field label:has(+ select:disabled)::after{ content: ' 🔄'; }
.bilingual-row{ display:grid; grid-template-columns: 1fr 1fr; gap:10px; }
.bilingual-row .lang-tag{ font-size:.65rem; color:var(--brass-dark); font-weight:700; }

/* ---------- Tabs (admin) ---------- */
.tabs{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:18px; border-bottom:2px solid var(--line); }

/* ---------- Achievement evidence: year-card grid (Admin) --------------- */
.achievement-year-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(230px, 1fr)); gap:12px; }
.achievement-year-card{ border:1px solid var(--line); border-radius:10px; overflow:hidden; background:#fff; }
.achievement-year-head{
  display:flex; align-items:center; gap:8px; padding:10px 14px; cursor:pointer;
  background: linear-gradient(120deg, var(--ink), color-mix(in srgb, var(--brass-dark) 30%, var(--ink-soft))); color:#fff;
}
.achievement-year-num{ font-family:var(--font-display); font-weight:700; font-size:1.15rem; flex:1; }
.achievement-year-head .chevron{ transition: transform .15s; }
.achievement-year-head .chevron.collapsed{ transform: rotate(-90deg); }
.achievement-year-body{ padding:12px; background: var(--paper-dim); min-height:40px; }
.achievement-item-card{ border:1px solid var(--line); border-radius:8px; }
.achievement-item-head{
  display:flex; align-items:center; gap:8px; padding:9px 12px; cursor:pointer; background:var(--paper);
  border-radius:8px 8px 0 0;
}
.achievement-item-card.collapsed .achievement-item-head{ border-radius:8px; }
.achievement-item-head .chevron{ transition: transform .15s; flex-shrink:0; }
.achievement-item-head .chevron.collapsed{ transform: rotate(-90deg); }
.achievement-item-card[draggable="true"] .achievement-item-head{ cursor:grab; }
.achievement-item-card.dragging{ opacity:.4; }
.tab{
  padding:10px 16px; border:none; background:none; font-weight:600; color:#8a8371;
  border-bottom:3px solid transparent; font-size:.88rem;
}
.tab.active{ color: var(--ink); border-color: var(--brass); }
.tab-panel{ display:none; }
.tab-panel.active{ display:block; }

/* ---------- Person "index card" ---------- */
.person-card{
  border:1px solid var(--line); border-radius: var(--radius); margin-bottom:12px;
  background: linear-gradient(180deg, #fff, var(--paper) 240%);
  overflow:hidden; transition: background .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.person-card:focus-within{
  background: linear-gradient(180deg, var(--brass-soft), var(--paper-dim) 240%);
  border-color: var(--brass);
  box-shadow: 0 0 0 2px var(--brass-soft), var(--shadow);
}
.person-card > .head{
  display:flex; align-items:center; gap:10px; padding:12px 16px; background: var(--paper-dim);
  cursor:pointer; border-bottom:1px solid var(--line);
}
.person-card > .head .tab-index{
  width:6px; align-self:stretch; background: var(--brass); border-radius:3px; flex-shrink:0;
}
.person-card > .head .name{ font-weight:700; flex:1; }
.person-card > .head .meta-tag{
  font-size:.7rem; padding:3px 8px; border-radius:999px; background: var(--sage); color:#fff;
}
.person-card > .body{ padding:18px; background: var(--paper); }
.person-card.collapsed > .body{ display:none; }
.chevron{ transition: transform .15s; }
.chevron.collapsed{ transform: rotate(-90deg); }
.person-card.collapsed .chevron{ transform: rotate(-90deg); }

/* =====================================================================
   FIELD SECTIONS — groups related inputs inside a person-card (or any
   other data-entry body) into a distinct, colour-coded "cụm" so a long
   form reads as a handful of clear blocks instead of one continuous wall
   of fields. Purely visual (see fieldSection() in admin.js) — never
   changes any data-bind path, so it is completely safe to introduce.
   Accent colours are fixed hues (not palette-driven) so every section
   keeps a stable, recognisable identity across all 4 colour palettes and
   both light/dark modes — only their exact tone shifts for legibility.
   ===================================================================== */
.field-section{
  --fs-accent: var(--brass);
  position:relative;
  border:1px solid var(--line); border-radius:14px;
  background: color-mix(in srgb, var(--fs-accent) 3%, var(--paper));
  padding:16px 18px 4px; margin-bottom:16px;
  transition: box-shadow .15s ease, border-color .15s ease, transform .12s ease;
}
.field-section::before{
  content:''; position:absolute; left:0; top:12px; bottom:12px; width:3px; border-radius:3px;
  background: var(--fs-accent); opacity:.85;
}
.field-section:hover{ border-color: color-mix(in srgb, var(--fs-accent) 35%, var(--line)); }
.field-section:focus-within{
  border-color: var(--fs-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--fs-accent) 16%, transparent);
}
.field-section-title{
  display:flex; align-items:center; gap:8px;
  font-family: var(--font-display); font-weight:600; font-size:.76rem;
  text-transform:uppercase; letter-spacing:.05em; color: var(--fs-accent);
  margin:0 0 12px 2px;
}
.field-section-title .icon{ flex-shrink:0; opacity:.95; }
.field-section-body > .field:last-child,
.field-section-body > .grid-2:last-child,
.field-section-body > .grid-3:last-child,
.field-section-body > .bilingual-row:last-child,
.field-section-body > p.notice:last-child{ margin-bottom:0; }
.field-section-body .field{ margin-bottom:14px; }
.field-section-body > *:last-child{ margin-bottom:0; }
.field-section[data-accent="blue"]{ --fs-accent:#3b6fd6; }
.field-section[data-accent="green"]{ --fs-accent:#1f9d63; }
.field-section[data-accent="purple"]{ --fs-accent:#7c4fd6; }
.field-section[data-accent="amber"]{ --fs-accent:#c07a1e; }
.field-section[data-accent="red"]{ --fs-accent:#d6483f; }
.field-section[data-accent="teal"]{ --fs-accent:#0f9488; }
.field-section[data-accent="pink"]{ --fs-accent:#d1478a; }
.field-section[data-accent="slate"]{ --fs-accent:#5b6479; }
:root[data-mode="dark"] .field-section{ background: color-mix(in srgb, var(--fs-accent) 7%, var(--paper-dim)); }
:root[data-mode="dark"] .field-section[data-accent="blue"]{ --fs-accent:#7ea2f2; }
:root[data-mode="dark"] .field-section[data-accent="green"]{ --fs-accent:#4ade91; }
:root[data-mode="dark"] .field-section[data-accent="purple"]{ --fs-accent:#b39bfa; }
:root[data-mode="dark"] .field-section[data-accent="amber"]{ --fs-accent:#eab35c; }
:root[data-mode="dark"] .field-section[data-accent="red"]{ --fs-accent:#ff8a80; }
:root[data-mode="dark"] .field-section[data-accent="teal"]{ --fs-accent:#4fd8c9; }
:root[data-mode="dark"] .field-section[data-accent="pink"]{ --fs-accent:#f087b7; }
:root[data-mode="dark"] .field-section[data-accent="slate"]{ --fs-accent:#a7aec2; }

/* ---- Collapsible section header (click to fold/unfold a cụm) — pure UI
   state, never touches the underlying data, see toggleFieldSection() in
   admin.js. Chevron rotates; body height collapses to 0 with a smooth
   fade instead of an abrupt display:none jump. ---- */
.field-section-title{ cursor:pointer; user-select:none; }
.field-section-title:hover{ opacity:.82; }
.field-section-title .fs-chevron{ margin-left:auto; display:inline-flex; transition: transform .18s ease; opacity:.7; }
.field-section.collapsed .fs-chevron{ transform: rotate(-90deg); }
.field-section.collapsed .field-section-body{ display:none; }
.field-section.collapsed{ padding-bottom:14px; }
.field-section.collapsed .field-section-title{ margin-bottom:0; }

/* ---- Balanced auto-flow grid — for clusters made of several short,
   similarly-sized fields (stat chips, short path pickers, checkboxes):
   as many equal columns fit the available width as possible, wrapping
   into new rows automatically instead of one field stretching full-width
   for no reason. ---- */
.grid-auto{ display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:14px; }

/* ---- Read-only auto-computed stat tiles (replaces rows of <input
   disabled> — those look editable; a chip makes "đây là số liệu tự
   tính, không phải ô nhập" obvious at a glance) — see statChip()/
   statGrid() in admin.js. ---- */
.stat-grid{ display:grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap:10px; margin-bottom:10px; }
.stat-chip{
  border:1px solid var(--line); border-radius:12px; padding:10px 12px; background: var(--paper-dim);
  display:flex; flex-direction:column; gap:2px; transition: border-color .12s ease, transform .12s ease, box-shadow .12s ease;
}
.stat-chip:hover{ border-color: var(--brass); transform: translateY(-1px); box-shadow: 0 4px 10px rgba(13,20,36,.08); }
.stat-chip-value{ font-family: var(--font-display); font-weight:700; font-size:1.2rem; color: var(--ink); line-height:1.2; }
.stat-chip-label{ font-size:.66rem; color: var(--sage); text-transform:uppercase; letter-spacing:.03em; line-height:1.3; }
:root[data-mode="dark"] .stat-chip-value{ color: var(--text-dark); }
:root[data-mode="dark"] .stat-chip{ background: var(--ink-soft); }

/* ---------- Search ---------- */
.search-box{ position:relative; }
.search-box input{ width:100%; padding:10px 14px 10px 34px; border-radius:999px; border:1px solid var(--line); }
.search-box::before{ content:'🔎'; position:absolute; left:12px; top:9px; font-size:.85rem; }

/* =====================================================================
   VIEWER (index.html)
   ===================================================================== */
.hero{
  background:
    radial-gradient(circle at 15% 20%, rgba(185,134,58,.18), transparent 40%),
    linear-gradient(160deg, var(--ink), color-mix(in srgb, var(--brass-dark) 30%, var(--ink-soft)));
  color: var(--text-light);
  padding: 48px 24px 64px;
  text-align:center;
}
.hero h1{ color:#fff; font-size:2.1rem; }
.hero .lib-address{ opacity:.75; font-size:.9rem; margin-top:6px; }
.hero .social-links{ margin-top:16px; display:flex; gap:12px; justify-content:center; }
.hero .social-links a{ color: var(--brass); text-decoration:none; font-size:.85rem; border:1px solid var(--brass); padding:6px 12px; border-radius:999px; }
.hero .social-links a:hover{ background: var(--brass); color: var(--ink); }

.orgchart-section{ padding: 40px 24px; max-width:1200px; margin:0 auto; }
.orgchart-section h2{ text-align:center; }
.orgchart-section .lead{ text-align:center; color:var(--sage); max-width:620px; margin:0 auto 32px; font-size:.92rem; }

.top-row, .dept-row{
  display:grid; gap:18px; margin-bottom:22px;
}
.top-row{ grid-template-columns: repeat(3, 1fr); }
.dept-row{ grid-template-columns: repeat(3, 1fr); }
@media (max-width:900px){ .top-row,.dept-row{ grid-template-columns:1fr 1fr; } }
@media (max-width:560px){ .top-row,.dept-row{ grid-template-columns:1fr; } }

/* ---------- Skeleton loading placeholder (shown until the real org-chart
   cards replace it via innerHTML — see index.html initial markup) ------ */
.skeleton-card{
  height:118px; border-radius: var(--radius); border:1px solid var(--glass-border);
  background: linear-gradient(100deg, var(--paper-dim) 30%, color-mix(in srgb, var(--brass) 8%, var(--paper-dim)) 50%, var(--paper-dim) 70%);
  background-size: 220% 100%; animation: skeletonShimmer 1.6s ease-in-out infinite;
}
@keyframes skeletonShimmer{ 0%{ background-position: 120% 0; } 100%{ background-position: -20% 0; } }

/* ---------- Entrance animation — every re-render of the org chart /
   branch tree fades+lifts its cards in, instead of them just "appearing"
   flatly. Subtle, short, and respects prefers-reduced-motion via the
   global rule already in this file. ---------- */
@keyframes cardEnter{ from{ opacity:0; transform: translateY(10px) scale(.98); } to{ opacity:1; transform:none; } }
.node-card, .person-node{ animation: cardEnter .38s cubic-bezier(.22,1,.36,1) both; }

/* ---------- Site footer: người chịu trách nhiệm, liên hệ, bản quyền --- */
#siteFooter{
  background: linear-gradient(180deg, var(--ink), var(--ink-soft));
  color: rgba(255,255,255,.82); padding:44px 24px 22px; margin-top:56px;
}
.footer-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:32px; max-width:1200px; margin:0 auto; }
.footer-col h4{
  color: var(--glow); font-size:.76rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  margin:0 0 12px; font-family: var(--font-display);
}
.footer-col p{ margin:0 0 6px; font-size:.84rem; line-height:1.55; }
.footer-col a{ color: var(--brass); text-decoration:none; }
.footer-col a:hover{ text-decoration:underline; }
.footer-name{ font-weight:700; color:#fff; font-size:.95rem; }
.footer-role{ opacity:.72; font-size:.82rem; }
.footer-bottom{
  max-width:1200px; margin:30px auto 0; padding-top:18px; border-top:1px solid rgba(255,255,255,.12);
  text-align:center; font-size:.78rem; opacity:.65;
}
@media (max-width:700px){ #siteFooter{ padding:32px 16px 18px; margin-top:36px; } }

/* ---------- Floating "back to top" button ---------- */
.back-to-top{
  position:fixed; right:16px; bottom:88px; z-index:110;
  width:44px; height:44px; border-radius:50%; border:1px solid var(--glass-border);
  background: var(--glass-bg-2); backdrop-filter: blur(16px) saturate(150%); -webkit-backdrop-filter: blur(16px) saturate(150%);
  color: var(--ink); box-shadow: var(--glass-shadow-sm);
  display:flex; align-items:center; justify-content:center;
  opacity:0; visibility:hidden; transform: translateY(8px);
  transition: opacity .22s ease, transform .22s ease, visibility .22s, box-shadow .18s ease, border-color .18s ease;
}
.back-to-top.show{ opacity:1; visibility:visible; transform:none; }
.back-to-top:hover{ border-color: var(--brass); box-shadow: var(--glass-shadow); transform: translateY(-2px); }
:root[data-mode="dark"] .back-to-top{ color: var(--text-dark); }
@media (max-width:700px){ .back-to-top{ right:12px; bottom:80px; width:40px; height:40px; } }

.node-card{
  position:relative; text-align:center; cursor:pointer; border-radius: var(--radius);
  padding:20px 16px;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)) saturate(150%); -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-shadow-sm);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.node-card:hover{ z-index: 500; }
.node-card .holo-anchor{ position:relative; display:inline-block; }
.node-card:hover{ transform: translateY(-4px); box-shadow: var(--glass-shadow); border-color: color-mix(in srgb, var(--brass) 45%, var(--glass-border)); }
.node-card .icon{ font-size:1.8rem; margin-bottom:8px; }
.node-card h3{ font-size:1rem; margin:0 0 4px; }
.node-card .hint{ font-size:.72rem; color:var(--sage); }

/* ================= Holographic hover panel (shared overlay) ============
   A single #holoOverlay element (see index.html) is positioned via JS
   (position:fixed) next to whatever is hovered, flipping above/below and
   left/right to always stay on screen — see showHolo() in viewer.js.
   This also means it can never be clipped or covered by neighbouring
   cards, regardless of DOM order or ancestor overflow. */
/* --holo-blue / --holo-green / --holo-red now live in the main color-system :root above (theme-aware). */
/* ---- Tech-panel look (task: hover/click panels transparent, graph-paper
   diagonal grid, animated running-light border, no flat dark/gray/black
   fill) — shared by .holo-overlay and .modal via the .tech-panel class. */
/* ---- Task: bảng hover/modal — bỏ hẳn nền lưới caro, thay bằng kính mờ
   "trong như gương": nền trong suốt pha màu nhẹ, có vệt sáng chéo kiểu
   mặt kính (glossy sheen), đổ bóng nổi khối bên ngoài + bóng đổ dạng
   gương (inset) ở đáy để tạo chiều sâu. Viền vẫn có vệt sáng chạy quanh
   khung (::before, giữ từ trước) cho cảm giác công nghệ. */
/* ---- Task: bảng hover/modal — nền SÁNG, trong như kính (không tối như
   trước), lớp nội dung phía sau vẫn lờ mờ nhìn xuyên qua được một chút
   (backdrop-filter blur nhẹ hơn, nền dùng tông trắng pha thay vì --ink
   tối). Vệt sáng chéo kiểu mặt kính + đổ bóng nổi khối/đổ bóng đáy vẫn
   giữ để tạo chiều sâu "kiểu gương". Viền vẫn có vệt sáng chạy quanh
   khung (::before, giữ từ trước). */
/* ---- Task: bảng hover/modal — THẬT SỰ trong suốt (thấy lớp phía sau
   mờ mờ nhưng vẫn nhận ra được), không phải một khối trắng gần như đặc.
   Giảm hẳn độ mờ nền (opacity) và độ blur so với bản trước. Chữ bên
   trong dùng MÀU ĐỒNG NHẤT (không đổi theo vai trò xanh lá/xanh dương/
   tím nữa) và luôn đặt trên một dải nền tối vừa đủ riêng (không phải cả
   bảng) để đảm bảo đọc được dù nền ngoài sáng/trong đến đâu. */
.tech-panel{
  position:relative; isolation:isolate;
  background: linear-gradient(128deg, color-mix(in srgb, var(--glow) 8%, white 40%), color-mix(in srgb, var(--brass) 5%, white 44%) 55%, color-mix(in srgb, var(--glow) 4%, white 40%));
  background-color: color-mix(in srgb, white 10%, transparent);
  box-shadow:
    0 16px 36px rgba(13,20,36,.18),      /* nổi khối phía ngoài */
    inset 0 1px 0 rgba(255,255,255,.5),  /* mép sáng phía trên — cạnh kính */
    inset 0 -12px 22px -16px rgba(13,20,36,.14); /* bóng đổ hắt vào đáy, kiểu gương lõm nhẹ */
}
.tech-panel::after{
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:1;
  background: linear-gradient(115deg, rgba(255,255,255,.28) 0%, rgba(255,255,255,0) 22%, rgba(255,255,255,0) 62%, rgba(255,255,255,.10) 100%);
  mix-blend-mode: overlay;
}
.tech-panel::before{
  content:''; position:absolute; inset:0; border-radius:inherit; padding:1.5px; z-index:-1;
  background: conic-gradient(from var(--tp-angle,0deg), transparent 0 60deg, color-mix(in srgb, var(--holo-color, var(--glow)) 90%, white) 90deg, transparent 140deg 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  animation: tpBorderSpin 4.5s linear infinite;
}
@keyframes tpBorderSpin{ to{ --tp-angle: 360deg; } }
@property --tp-angle{ syntax:'<angle>'; inherits:false; initial-value:0deg; }

.holo-overlay{
  display:none; position:fixed; z-index:9000; width:260px; max-width:86vw;
  padding:14px 14px 12px; border-radius:14px; text-align:left; pointer-events:none;
  border:1px solid rgba(255,255,255,.16);
  box-shadow: 0 16px 34px rgba(13,20,36,.18), inset 0 1px 0 rgba(255,255,255,.10), 0 0 0 1px color-mix(in srgb, var(--holo-color, var(--holo-blue)) 35%, transparent);
  backdrop-filter: blur(5px) saturate(135%); -webkit-backdrop-filter: blur(5px) saturate(135%);
  opacity:0; transition: opacity .15s ease, transform .15s ease; transform: translateY(2px);
}
.holo-overlay.show{ display:block; }
.holo-overlay.visible{ opacity:1; transform: translateY(0); }
.holo-corner{ display:none; } /* HUD corner-brackets retired — kept in the DOM (viewer.js) for now but visually dropped */
.holo-head{ display:flex; align-items:center; gap:8px; margin-bottom:8px; background: rgba(12,42,82,.6); border-radius:9px; padding:6px 8px; }
.holo-icon3d{ width:34px; height:34px; flex-shrink:0; --poster-color: transparent; }
.holo-image{ width:100%; height:180px; object-fit:contain; object-position: center; border-radius:8px; opacity:.95; margin-bottom:8px; background: rgba(255,255,255,.06); }
.holo-logo{ width:26px; height:26px; object-fit:contain; border-radius:4px; flex-shrink:0; }
.holo-title{ font-size:.82rem; font-weight:700; color:#fff; }
.holo-sub{ font-size:.68rem; color: rgba(255,255,255,.82); }
.holo-readout{
  background: rgba(12,42,82,.56); border-radius:8px; padding:8px 9px; margin-top:6px;
}
.holo-line{
  font-family: var(--font-mono); font-size:.68rem; color:#f2fbff; line-height:1.5;
  white-space:normal; word-break:break-word;
  padding:2px 0; margin-bottom:3px; border-bottom:1px dashed rgba(255,255,255,.10);
}
.holo-line:last-child{ margin-bottom:0; border-bottom:none; }
.holo-line .holo-caret{ display:inline-block; width:2px; height:.9em; vertical-align:-2px; background:#f2fbff; animation: holoCaret .75s step-end infinite; }
/* Dòng Đảng viên/số lượng Đảng viên — nổi bật màu đặc trưng của Đảng
   (đỏ-vàng), tách khỏi các dòng thông tin khác bằng khoảng cách trên. */
.holo-line-party{
  background: linear-gradient(120deg,#7a1414,#a51d1d); color:#ffd76a !important; font-weight:700;
  border-radius:6px; padding:4px 8px; margin-top:6px; border-bottom:none;
}
.holo-line-party .holo-caret{ background:#ffd76a; }
@keyframes holoCaret{ 50%{ opacity:0; } }
.holo-close{
  position:absolute; top:6px; right:6px; width:22px; height:22px; border-radius:50%;
  background: rgba(255,255,255,.12); border:1px solid rgba(255,255,255,.2); color:#fff; font-size:.7rem;
  line-height:1; z-index:2; pointer-events:auto;
}

/* ---------- Minimal branch-header action row (replaces the old bulky
   "functions chip" preview — just one button, details live in the popup/
   modal instead of taking up space inline). ---------- */
.branch-info-bar{ display:flex; justify-content:center; margin-bottom:20px; }
.branch-info-bar .btn{ border-color: var(--glow); color: var(--ink); background: var(--paper-dim); }
.branch-info-bar .btn:hover{ background: var(--glow); }

/* ---------- Branch org chart (director -> deputies -> staff) --------- */
.branch-tree{ padding: 20px 6px 30px; overflow: visible; position:relative; }
/* ---- Task: sơ đồ tổng — cụm riêng cho từng Phòng để đường nối phản ánh
   đúng "Trưởng phòng quản lý Phó phòng của phòng mình" thay vì gộp phẳng
   Trưởng/Phó của cả 3 phòng vào chung 1 tầng. ---- */
.dept-cluster-row{ display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-top:6px; }
.dept-cluster{ border:1px solid var(--glass-border); border-radius:16px; padding:6px 8px 4px; background: color-mix(in srgb, var(--paper-dim) 55%, transparent); }
.dept-cluster-title{ text-align:center; font-weight:700; font-size:.82rem; color:var(--text-dark); padding:8px 4px 0; }
/* Task: khung hình gọn Phó Giám đốc phụ trách ở đầu mỗi cụm phòng —
   CHỈ hiện trên điện thoại (xem media query max-width:700px bên dưới);
   trên máy tính đã có hàng Phó Giám đốc dùng chung phía trên (đã sắp lại
   thứ tự cho khớp 3 cụm), không cần lặp lại. */
.dept-cluster-overseer{ display:none; }
@media (max-width:700px){
  .dept-cluster-overseer{ display:flex; justify-content:center; gap:10px; flex-wrap:wrap; padding:6px 4px 2px; }
  .mini-overseer-chip{
    display:flex; flex-direction:column; align-items:center; gap:2px; cursor:pointer; background: var(--glass-bg);
    border:1px solid var(--glass-border); border-radius:12px; padding:8px 10px 7px; min-width:84px;
  }
  .mini-overseer-avatar{
    width:30px; height:30px; border-radius:50%; overflow:hidden; flex-shrink:0; display:flex; align-items:center; justify-content:center;
    background: linear-gradient(145deg, var(--brass-dark), var(--ink)); color:var(--glow); font-size:.7rem; font-weight:700;
  }
  .mini-overseer-avatar img{ width:100%; height:100%; object-fit:cover; object-position: top center; }
  .mini-overseer-name{ font-size:.66rem; font-weight:700; color: var(--text-dark); text-align:center; line-height:1.25; }
  .mini-overseer-title{ font-size:.58rem; color: var(--sage); text-align:center; line-height:1.2; }
}
.dept-cluster .branch-tree{ padding:10px 2px 18px; }
@media (max-width:900px){ .dept-cluster-row{ grid-template-columns:1fr; } }
/* Vacant tier placeholder ("Khuyết Trưởng phòng") — dashed, muted, not
   clickable, so it never gets confused with a real person card. */
.person-node.vacant-node{ cursor:default; opacity:.7; border-style:dashed; background: transparent; box-shadow:none; }
.person-node.vacant-node .avatar{ background: transparent; border:1.5px dashed var(--sage); color: var(--sage); box-shadow:none; filter:none; }
.person-node.vacant-node .pname{ color: var(--sage); font-style: italic; font-weight:500; }
.branch-level{ display:flex; flex-wrap:wrap; justify-content:center; gap:16px; margin-bottom: 30px; position:relative; z-index:1; }
svg.branch-connectors{ position:absolute; left:0; top:0; pointer-events:none; z-index:0; }
/* ---- Task: đường nối sơ đồ cách điệu nổi 3D + ánh sáng chạy tủa nhánh
   theo phân cấp từ trên xuống. Base line = thân ống có bóng đổ nhẹ tạo
   cảm giác nổi khối; overlay line = vệt sáng chạy dọc theo dash-array,
   lặp vô hạn, tốc độ khác nhau theo độ dài mỗi đoạn (đặt qua stroke-dasharray
   động ở JS) để trông như tín hiệu toả nhánh từ cấp trên xuống cấp dưới. */
svg.branch-connectors .bc-base{ stroke-linecap:round; opacity:.6; }
/* Liên kết ngang giữa các Trưởng phòng / Phó phòng của 3 phòng — chân
   phương: nét đứt mảnh, không đổ bóng/hào quang, chỉ mang tính chỉ dẫn
   "cùng cấp bậc". */
svg.dept-peer-links{ overflow:visible; }
.dept-peer-line{ stroke: var(--sage); stroke-width:1.25; stroke-dasharray:4 5; opacity:.5; }
.dept-cluster{ position:relative; z-index:1; }
.tier-label{
  text-align:center; font-size:.7rem; letter-spacing:.06em; text-transform:uppercase; color: var(--sage);
  margin-bottom:8px; display:flex; align-items:center; gap:10px; justify-content:center; position:relative; z-index:1;
}
.tier-label::before, .tier-label::after{ content:''; flex:1; max-width:80px; height:1px; background: var(--line); }
.person-node{
  width:150px; border:1.5px solid var(--glass-border); border-radius:12px; padding:12px 10px;
  text-align:center; cursor:pointer; position:relative; transition: transform .15s, box-shadow .25s, opacity .3s, filter .3s, border-color .25s;
  background: var(--glass-bg);
  backdrop-filter: blur(14px) saturate(150%); -webkit-backdrop-filter: blur(14px) saturate(150%);
  box-shadow: var(--glass-shadow-sm), inset 0 0 0 1px color-mix(in srgb, var(--holo-color, var(--holo-blue)) 30%, transparent);
}
.person-node:hover{ transform: translateY(-3px); box-shadow: var(--glass-shadow), inset 0 0 0 1.5px var(--holo-color, var(--holo-blue)); z-index:600; }
.branch-tree.has-hover .person-node:not(.related):not(:hover){ opacity:.4; filter:saturate(.65); }
/* Related nodes (same dept / overseeing PGĐ): a static highlight ring —
   no infinite pulse — so it reads as an intentional, calm state change
   rather than constant background motion. */
.person-node.related{
  border-color: var(--holo-red);
  box-shadow: var(--glass-shadow-sm), 0 0 0 1.5px var(--holo-red);
}
.person-node .avatar{
  width:54px; height:54px; margin:0 auto 8px; background: linear-gradient(145deg, var(--brass-dark), var(--ink));
  display:flex; align-items:center; justify-content:center; font-family:var(--font-display); font-weight:700; color:var(--glow);
  overflow:hidden; clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%);
  filter: drop-shadow(0 0 5px var(--glow-soft)); position:relative;
}
.person-node .avatar img{ width:100%; height:100%; object-fit:cover; object-position: top center; }
.person-node .pname{ font-weight:700; font-size:.83rem; }
.person-node .prole{ font-size:.7rem; color:var(--brass-dark); }
.party-flag{
  position:absolute; top:-6px; right:calc(50% - 34px); width:20px; height:20px; border-radius:50%;
  background:#fff; padding:2px; box-shadow:0 0 6px rgba(0,0,0,.3); z-index:2;
}

/* ---------- Birthday today: the person's card gets a celebratory
   full-colour treatment for the day, instead of the usual holo blue/green
   border — easy to spot at a glance in the org chart. ---------- */
.person-node.birthday-today{
  background: linear-gradient(160deg, #fff8e6, #ffe9b3);
  border-color: #e8a838; animation: birthdayGlow 2.2s ease-in-out infinite;
}
.person-node.birthday-today .avatar{ background: linear-gradient(145deg, #e8a838, #b3891f); }
.person-node.birthday-today::after{
  content:'🎉'; position:absolute; top:-10px; left:-6px; font-size:1rem;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.3));
}
@keyframes birthdayGlow{
  0%,100%{ box-shadow:0 0 8px 0 rgba(232,168,56,.5); }
  50%{ box-shadow:0 0 20px 6px rgba(232,168,56,.75); }
}
:root[data-mode="dark"] .person-node.birthday-today{ background: linear-gradient(160deg, #3a2c0a, #5a4415); color: var(--text-dark); }

/* ---------- Speak-fab needs to sit above the holo overlay ---------- */
.speak-fab{ z-index:9100 !important; }

/* ---------- Detail modal ---------- */
.modal-overlay{
  position:fixed; inset:0; background: rgba(16,38,43,.55); display:none;
  align-items:flex-start; justify-content:center; padding: 40px 16px; z-index:2500; overflow-y:auto;
}
.modal-overlay.open{ display:flex; }
.modal{
  backdrop-filter: blur(6px) saturate(135%); -webkit-backdrop-filter: blur(6px) saturate(135%);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius); max-width:640px; width:100%;
  box-shadow: 0 20px 60px rgba(13,20,36,.30), inset 0 1px 0 rgba(255,255,255,.35); overflow:hidden;
}
.modal .modal-head{
  background: linear-gradient(120deg, color-mix(in srgb, var(--holo-color, var(--brass)) 55%, var(--ink) 45%), color-mix(in srgb, var(--brass) 40%, var(--ink-soft) 60%) 70%);
  color:#fff; padding:18px 22px;
  display:flex; align-items:flex-start; gap:12px; border-bottom:1px solid rgba(255,255,255,.1);
  position:relative; overflow:hidden;
}
.modal .modal-head::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:2px;
  background: linear-gradient(90deg, transparent, var(--glow), transparent); opacity:.7;
}
.modal .modal-head .avatar{
  width:68px; height:68px; background: linear-gradient(145deg, var(--glow), var(--brass)); flex-shrink:0; overflow:hidden;
  display:flex; align-items:center; justify-content:center; font-family:var(--font-display); font-weight:700; color:var(--ink);
  clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%);
  filter: drop-shadow(0 0 6px var(--glow-soft));
}
.modal .modal-head .avatar img{ width:100%; height:100%; object-fit:cover; object-position: top center; }
.modal .modal-head h3{ color:#fff; margin:0; }
.modal .modal-head .role{ opacity:.75; font-size:.85rem; }
.modal .modal-close{ margin-left:auto; background:none; border:none; color:#fff; font-size:1.3rem; }
.modal .modal-body{ padding:20px 22px; max-height:60vh; overflow-y:auto; background: color-mix(in srgb, var(--paper) 26%, transparent); color: var(--text-dark); }
:root[data-mode="dark"] .modal .modal-body{ background: color-mix(in srgb, var(--ink-soft) 22%, transparent); }
.modal .info-row{ display:flex; gap:8px; padding:6px 0; border-bottom:1px dashed var(--line); font-size:.85rem; }
.modal .info-row .k{ width:150px; flex-shrink:0; color:var(--sage); font-weight:600; font-family:var(--font-mono); font-size:.78em; letter-spacing:.02em; display:flex; align-items:center; gap:6px; }
.modal .info-row .k .k-icon{ display:inline-flex; align-items:center; justify-content:center; flex-shrink:0; font-size:1rem; line-height:1; }
.modal .info-row .k .k-icon img{ width:16px; height:16px; object-fit:contain; }
.modal .info-row .k .k-text{ display:inline; }
.modal .model3d-box{
  margin-top:14px; padding:14px; background: var(--paper-dim); border-radius:8px; font-size:.78rem; color:var(--sage);
}
.modal .listen-btn{ margin-top:12px; }
@media (max-width:700px){
  .modal .info-row{ align-items:center; }
  .modal .info-row .k{
    width:34px; gap:0; justify-content:center; cursor:pointer; position:relative;
  }
  .modal .info-row .k .k-text{
    display:none; position:absolute; left:0; top:100%; margin-top:4px; z-index:60;
    background: var(--ink); color:#fff; font-size:.68rem; font-weight:600; letter-spacing:normal;
    padding:4px 9px; border-radius:6px; white-space:nowrap; box-shadow: var(--shadow);
  }
  .modal .info-row .k.label-open .k-text{ display:block; }
  .modal .info-row .tts-stack{ position:static; }
  .modal .info-row > div:last-child{ flex:1; min-width:0; }
}

/* ---------- Duty speak buttons stacked vertically (🤖 robot / 🎙️ real
   recording) so having both doesn't eat horizontal space next to the
   label. ---------- */
.tts-stack{ display:flex; flex-direction:column; gap:3px; float:right; margin:0 0 6px 10px; }
.tts-stack .tts-inline{ display:inline-flex; }

/* ---------- 3D character viewer: soft radial glow instead of a hairline
   grid — Admin can still supply a real background image (model3dEnvPath)
   for actual scene composition. ---------- */
.model3d-scene{
  position:relative; width:100%; height:260px; margin-top:10px; border-radius:12px; overflow:hidden;
  background: var(--ink); /* fallback */
  background:
    radial-gradient(ellipse at 50% 85%, color-mix(in srgb, var(--glow) 20%, transparent), transparent 62%),
    linear-gradient(180deg, var(--ink) 0%, color-mix(in srgb, var(--brass-dark) 25%, var(--ink-soft)) 100%);
  border:1px solid rgba(255,255,255,.1);
}
.model3d-scene[style*="background-image"]{ background-blend-mode: normal; }
.model3d-scene model-viewer{ width:100%; height:100%; --poster-color: transparent; }

/* ---------- Role / login bar — glass, tier 2 ---------- */
.role-bar{
  position:fixed; bottom:16px; left:16px;
  background: var(--glass-bg-2); backdrop-filter: blur(16px) saturate(150%); -webkit-backdrop-filter: blur(16px) saturate(150%);
  border:1px solid var(--glass-border); border-radius:999px;
  box-shadow: var(--glass-shadow-sm); font-size:.78rem; display:flex; align-items:center; z-index:120; overflow:hidden;
}
.role-bar .dot{ width:8px; height:8px; border-radius:50%; background: var(--sage); flex-shrink:0; }
.role-bar-icon{
  width:38px; height:38px; border-radius:50%; border:none; background: var(--paper-dim); flex-shrink:0;
  font-size:1.1rem; overflow:hidden; display:flex; align-items:center; justify-content:center; margin:2px;
}
.role-bar-details{ display:flex; align-items:center; gap:8px; padding:0 14px 0 4px; }
@media (max-width:700px){
  .role-bar-details{ display:none; }
  .role-bar.expanded{
    position:fixed; bottom:16px; left:16px; right:16px; border-radius:16px;
  }
  .role-bar.expanded .role-bar-details{ display:flex; padding:0 14px 8px 10px; flex-wrap:wrap; }
}

/* ---------- AI assistant bubble — glass panel, tier 2 ---------- */
.assistant-bubble{
  position:fixed; bottom:16px; right:16px; z-index:130;
}
.assistant-toggle{
  width:56px; height:56px; border-radius:50%; background: var(--brass); border:none; font-size:1.4rem;
  box-shadow: var(--shadow); color: var(--ink); transition: transform .18s ease, box-shadow .18s ease;
}
.assistant-toggle:hover{ transform: translateY(-2px); box-shadow: 0 10px 22px rgba(0,0,0,.25); }
.assistant-panel{
  position:absolute; bottom:68px; right:0; width:290px; max-width: calc(100vw - 32px); max-height:380px;
  background: var(--glass-bg-2); backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%);
  border:1px solid var(--glass-border); border-radius: var(--radius); box-shadow: var(--glass-shadow); display:none;
  flex-direction:column; overflow:hidden;
}
.assistant-panel.open{ display:flex; }
.assistant-panel .ap-head{ background: var(--ink); color:#fff; padding:10px 14px; font-weight:600; font-size:.85rem; }
.assistant-panel .ap-body{ padding:12px 14px; font-size:.82rem; overflow-y:auto; flex:1; }
.assistant-panel .ap-body p{ margin:0 0 10px; }
.assistant-panel .ap-quick{ display:flex; flex-wrap:wrap; gap:6px; padding: 0 14px 12px; }
.assistant-panel .ap-quick button{
  border:1px solid var(--line); background: var(--paper); border-radius:999px; padding:5px 10px; font-size:.72rem;
}

/* ---------- Bilingual toggle ---------- */
.lang-toggle{
  display:flex; border:1px solid var(--brass); border-radius:999px; overflow:hidden;
}
.lang-toggle button{ border:none; background:none; color: var(--text-light); padding:6px 12px; font-size:.75rem; font-weight:600; }
.lang-toggle button.active{ background: var(--brass); color: var(--ink); }

/* ---------- Select on text -> speak hint (trigger + its own pause/stop,
   all pinned at the selection point — no separate bottom bar). ---------- */
.speak-fab{
  position:fixed; z-index:9100; display:none; align-items:center; gap:4px;
  background: var(--ink); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-radius:999px; padding:4px; box-shadow: var(--shadow);
}
.speak-fab.show{ display:flex; }
.speak-fab button{
  border:none; background: transparent; color:#fff; border-radius:999px; padding:6px 10px; font-size:.75rem;
  display:flex; align-items:center; gap:4px;
}
.speak-fab #speakFabPause, .speak-fab #speakFabStop{ padding:6px 9px; background: rgba(255,255,255,.12); }
.speak-fab #speakFabStop{ background: var(--clay); }

.hidden{ display:none !important; }
.notice{ background:#fff7e6; border:1px solid var(--brass); color:var(--brass-dark); padding:10px 14px; border-radius:8px; font-size:.8rem; margin-bottom:16px; }
.empty-state{ text-align:center; color: var(--sage); padding:40px 20px; font-size:.9rem; }

/* ---------- Leave/comp calendar picker (admin) ---------- */
.cal-month{ border:1px solid var(--line); border-radius:8px; padding:8px; }
.cal-month h4{ margin:0 0 6px; font-size:.82rem; text-align:center; }
.cal-days{ display:grid; grid-template-columns:repeat(7,1fr); gap:3px; }
.cal-dow{ font-size:.6rem; text-align:center; color:var(--sage); font-weight:700; }
.cal-day{ font-size:.68rem; text-align:center; padding:3px 0; border-radius:4px; cursor:pointer; background: var(--paper); }
.cal-day:hover{ background: var(--paper-dim); }
.cal-day.marked{ background: var(--clay); color:#fff; font-weight:700; }

/* ---------- Overview (whole-library) hero card ---------- */
.overview-card{
  grid-column: 1 / -1; color:#fff; border-color: rgba(255,255,255,.14);
  background: var(--ink); /* fallback */
  background: linear-gradient(135deg, color-mix(in srgb, var(--ink) 92%, transparent), color-mix(in srgb, var(--ink-soft) 86%, transparent));
}
.overview-card h3{ color:#fff; }
.overview-card .hint{ color: rgba(255,255,255,.7); }

/* ---------- Subtle "digital transformation" backdrop — theme-aware,
   uses the active palette's own accent colours instead of a fixed
   teal/gold wash that didn't shift with the palette picker. ---------- */
body{
  background-image:
    radial-gradient(circle at 85% 0%, color-mix(in srgb, var(--glow) 12%, transparent), transparent 45%),
    radial-gradient(circle at 0% 30%, color-mix(in srgb, var(--brass) 10%, transparent), transparent 40%);
  background-attachment: fixed;
}
.hero{
  background:
    radial-gradient(circle at 15% 20%, var(--glow-soft), transparent 35%),
    radial-gradient(circle at 85% 80%, rgba(185,134,58,.18), transparent 40%),
    linear-gradient(160deg, var(--ink), color-mix(in srgb, var(--brass-dark) 30%, var(--ink-soft)));
}

/* ---------- "Chức năng, nhiệm vụ" chip (replaces the old cluttered paragraph) --- */
.functions-chip{
  display:flex; align-items:flex-start; gap:12px; background: linear-gradient(135deg, var(--ink), color-mix(in srgb, var(--brass-dark) 30%, var(--ink-soft)));
  color:#fff; border-radius: var(--radius); padding:16px 18px; margin: 0 auto 24px; max-width:720px;
  border:1px solid var(--glow-soft); box-shadow: 0 8px 24px rgba(16,38,43,.2);
}
.fc-icon{ font-size:1.4rem; flex-shrink:0; }
.fc-text{ flex:1; font-size:.86rem; opacity:.9; }
.fc-actions{ display:flex; flex-direction:column; gap:6px; align-items:flex-end; flex-shrink:0; }
.functions-chip .btn{ border-color: var(--glow); color:#fff; background: rgba(255,255,255,.06); }
.functions-chip .btn:hover{ background: var(--glow); color: var(--ink); }
.functions-chip .speak-inline{ background: var(--glow); color: var(--ink); }

/* Rich text rendered output (viewer) — content authored via the admin rich editor */
.rich-render{ line-height:1.6; }
.rich-render b, .rich-render strong{ color: var(--ink); }

/* Small inline speaker icon next to Functions/Duties specifically */
.speak-inline{
  border:none; background: var(--glow-soft); color: var(--text-dark); border-radius:999px;
  width:26px; height:26px; font-size:.8rem; flex-shrink:0; line-height:1;
}
.speak-inline:hover{ background: var(--glow); }

/* ---------- Rich-text editor toolbar (admin) ---------- */
.rt-toolbar{ display:flex; gap:4px; margin-bottom:4px; }
.rt-toolbar button{
  border:1px solid var(--line); background:#fff; border-radius:5px; padding:3px 8px; font-size:.72rem; min-width:26px;
}
.rt-toolbar button:hover{ background: var(--paper-dim); }
.richtext{
  min-height:64px; max-height:70vh; padding:10px 12px; border:1px solid var(--line); border-radius:9px; background: var(--paper); transition: border-color .12s ease, box-shadow .12s ease;
  font-family:inherit; font-size:14px; line-height:1.5;
  resize: vertical; overflow:auto; /* task: kéo góc dưới-phải để phóng to/thu nhỏ ô (Nhiệm vụ, Chức năng-nhiệm vụ, Ghi chú...) */
}
.richtext:focus{ outline:none; border-color: var(--brass); box-shadow: 0 0 0 3px var(--brass-soft); }

/* ---------- Field validation error ---------- */
.field-error{ font-size:.7rem; color: var(--clay); min-height:0; }
.field-error:empty{ display:none; }

/* ---------- Portrait preview with a fixed, non-stretched aspect ratio (admin) --- */
.portrait-frame{
  width:110px; aspect-ratio: 3 / 4; border-radius:8px; overflow:hidden; margin-top:6px;
  border:1px solid var(--line); background: var(--paper-dim);
}
.portrait-frame img{ width:100%; height:100%; object-fit:cover; object-position: top center; }

/* ---------- Facility card collapse (admin) ---------- */
.facility-card .facility-body{ margin-top:14px; }
.facility-card.collapsed .facility-body{ display:none; }
.facility-card.collapsed h3 .chevron{ transform: rotate(-90deg); }
.facility-card h3 .chevron{ transition: transform .15s; display:inline-block; }

/* ---------- Site search (viewer topbar) ---------- */
.site-search{ min-width:220px; }
.site-search input{ background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.25); color:#fff; }
.site-search input::placeholder{ color: rgba(255,255,255,.6); }
.search-results{
  position:absolute; top:calc(100% + 6px); left:0; right:0; background:#fff; border:1px solid var(--line);
  border-radius:10px; box-shadow: var(--shadow); max-height:280px; overflow-y:auto; z-index:80;
}
.search-result-item{ padding:9px 12px; font-size:.8rem; border-bottom:1px solid var(--line); cursor:pointer; color: var(--text-dark); }
.search-result-item:last-child{ border-bottom:none; }
.search-result-item:hover{ background: var(--paper); }

/* ---------- Assistant search box ---------- */
.ap-search{ display:flex; flex-wrap:wrap; gap:6px; padding: 0 14px 10px; }
.ap-search input{ flex:1 1 100px; min-width:0; padding:7px 10px; border:1px solid var(--line); border-radius:8px; font-size:.78rem; }
.ap-search button{ flex-shrink:0; }
#assistantMicBtn.listening{ background: var(--clay); color:#fff; border-color: var(--clay); animation: micPulse 1s ease-in-out infinite; }
@keyframes micPulse{ 0%,100%{ box-shadow:0 0 0 0 rgba(239,84,104,.5); } 50%{ box-shadow:0 0 0 8px rgba(239,84,104,0); } }

/* ---------- Double-tap "related group" flash (mobile) — diagonal sweep -- */
.person-node.sweep{ position:relative; overflow:hidden; }
.person-node.sweep::after{
  content:''; position:absolute; inset:0; pointer-events:none; border-radius:6px;
  background: linear-gradient(135deg, transparent 42%, rgba(255,255,255,.95) 50%, transparent 58%);
  background-size: 260% 260%; background-position: -120% -120%;
  animation: diagSweep 1.1s ease-out 1.3s 1;
}
@keyframes diagSweep{ to{ background-position: 120% 120%; } }

/* ---------- Admin: colour-coded level badges (Giám đốc/Trưởng phòng...) - */
.meta-tag.level-giam_doc, .meta-tag.level-truong_phong{ background: var(--brass); color:#fff; }
.meta-tag.level-pho_giam_doc, .meta-tag.level-pho_truong_phong{ background: var(--glow); color: var(--ink); }
.meta-tag.level-vien_chuc{ background: var(--sage); color:#fff; }
.meta-tag.level-nguoi_lao_dong{ background: #9aa5bd; color:#fff; }

/* ---------- Branch section: collapse/hide button ---------- */
.branch-section-head{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; }

/* ---------- Assistant toggle as a small 3D character instead of an emoji  */
.assistant-toggle{
  width:64px; height:64px; border-radius:50%; background: radial-gradient(circle at 30% 30%, var(--glow), var(--brass));
  border:none; box-shadow: var(--shadow); overflow:hidden; padding:4px;
}
.assistant-toggle model-viewer{ width:100%; height:100%; --poster-color: transparent; pointer-events:none; }

/* ---------- Library "contact info" modal: QR code for Zalo OA ---------- */
.qr-box{ display:flex; align-items:center; gap:12px; margin-top:6px; }
.qr-box img{ width:90px; height:90px; object-fit:contain; border:1px solid var(--line); border-radius:8px; background:#fff; padding:4px; }
.gallery-box{ width:100%; height:220px; border-radius:8px; overflow:hidden; margin-top:10px; background: var(--paper-dim); }
.gallery-box img{ width:100%; height:100%; object-fit:cover; transition: opacity .3s ease; }

/* ---------- Drag handle for reordering people in Admin ---------- */
.drag-handle{ cursor:grab; padding:2px 6px; color: var(--sage); }
.person-card.dragging{ opacity:.4; }
.person-card.drag-over{ border-top:3px solid var(--glow); }

/* ---------- Collapsible "read more" block (long Chức năng/Nhiệm vụ text) --- */
.collapsible{ position:relative; }
.collapsible .collapsible-inner{ max-height:4.6em; overflow:hidden; position:relative; }
.collapsible.expanded .collapsible-inner{ max-height:none; }
.collapsible:not(.expanded) .collapsible-inner::after{
  content:''; position:absolute; left:0; right:0; bottom:0; height:1.6em;
  background: linear-gradient(transparent, #fff);
}
.collapsible-toggle{ margin-top:6px; }

/* ---------- Hamburger button + mobile nav drawer (reuses topbar-actions,
   just repositions it into a slide-in panel on small screens — no
   duplicated controls/IDs). ---------- */
.hamburger-btn{ display:none; }
.theme-picker{ position:relative; }
.theme-menu{
  position:absolute; top:calc(100% + 8px); right:0;
  background: var(--glass-bg-2); backdrop-filter: blur(18px) saturate(160%); -webkit-backdrop-filter: blur(18px) saturate(160%);
  border:1px solid var(--glass-border);
  border-radius:12px; box-shadow: var(--glass-shadow); overflow:hidden; z-index:1200; min-width:200px;
}
.theme-menu button{
  display:block; width:100%; text-align:left; padding:10px 14px; border:none; background:none;
  font-size:.82rem; color: var(--text-dark); border-bottom:1px solid var(--line);
}
.theme-menu button:last-child{ border-bottom:none; }
.theme-menu button:hover{ background: var(--paper-dim); }
.theme-menu button.active{ background: var(--glow-soft); font-weight:700; }
.mobile-nav-links{ display:none; }
.mobile-drawer-backdrop{ display:none; }
.drawer-close-mobile{ display:none; }
.pname-short{ display:none; }

@media (max-width:700px){
  /* Topbar: collapse the action row into a hamburger */
  .topbar{ padding:10px 14px; flex-wrap:nowrap; position:relative; }
  .topbar h1{ font-size:.8rem; line-height:1.25; }
  .topbar .subtitle{ display:none; }
  .topbar .crest{ width:32px; height:32px; font-size:.85rem; }
  /* Task: dropdown xổ DỌC XUỐNG ngay dưới header thay vì tấm trượt ngang
     phủ kín màn hình — panel neo tuyệt đối dưới thanh topbar, mặc định
     max-height:0 + ẩn overflow, mở ra bằng cách nới max-height (có
     transition mượt), full chiều rộng màn hình. */
  .topbar-actions{
    display:flex; flex-direction:column; align-items:stretch; gap:10px;
    position:absolute; top:100%; left:0; right:0; width:100%;
    background: linear-gradient(180deg, color-mix(in srgb, var(--ink) 96%, transparent), color-mix(in srgb, var(--ink-soft) 92%, transparent));
    padding:0 16px; z-index:2200; overflow:hidden; max-height:0; opacity:0;
    box-shadow: 0 16px 30px rgba(13,20,36,.30); border-bottom:1px solid rgba(255,255,255,.08);
    transition: max-height .32s ease, opacity .22s ease, padding .32s ease;
  }
  .hamburger-btn{
    display:flex; align-items:center; justify-content:center; width:38px; height:38px; border-radius:8px;
    background: rgba(255,255,255,.1); border:1px solid rgba(255,255,255,.2); color:#fff; font-size:1.1rem; flex-shrink:0;
  }
  body.drawer-open .topbar-actions{
    max-height:80vh; opacity:1; padding:14px 16px 18px; overflow-y:auto;
  }
  body.drawer-open .mobile-nav-links{ display:flex; flex-direction:column; gap:8px; }
  body.drawer-open .mobile-nav-links button{
    text-align:left; background: rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.15);
    color:#fff; padding:10px 12px; border-radius:8px; font-size:.85rem;
  }
  body.drawer-open .mobile-nav-links h4{ color: var(--brass); font-size:.72rem; text-transform:uppercase; letter-spacing:.05em; margin:6px 0 2px; }
  body.drawer-open .drawer-close-mobile{
    display:block; align-self:flex-end; background: rgba(255,255,255,.1);
    border:1px solid rgba(255,255,255,.2); color:#fff; padding:6px 10px; border-radius:8px; font-size:.85rem;
  }
  body.drawer-open .site-search{ min-width:0; }
  body.drawer-open .lang-toggle{ align-self:flex-start; }
  .mobile-drawer-backdrop{ display:none !important; } /* dropdown style no longer needs a full-screen scrim */

  .hero{ padding:28px 16px 40px; }
  .hero h1{ font-size:1.3rem; }
  .orgchart-section{ padding:24px 12px; }

  /* Person nodes: compact, abbreviated name only, no role/dept clutter,
     sized to fit 4 per row */
  .branch-level{ gap:6px; }
  .person-node{ width: calc(25% - 5px); min-width:0; padding:6px 2px; }
  .person-node .avatar{ width:32px; height:32px; margin-bottom:4px; }
  .person-node .pname-full{ display:none; }
  .person-node .pname-short{ display:block; }
  .person-node .pname{ font-size:.62rem; }
  .person-node .prole, .person-node > div[style]{ display:none; }
  .party-flag{ width:14px; height:14px; right:calc(50% - 20px); }

  /* Double-tap group highlight: the tapped card itself stays raised and
     visible (not dimmed), with a small relationship caption above it. */
  .person-node.self-active{ transform: translateY(-4px); box-shadow: 0 12px 26px rgba(0,0,0,.35); z-index:650; animation:none; }
  .branch-tree.has-hover .person-node.self-active{ opacity:1; filter:none; }
  .relation-caption{
    position:absolute; bottom:calc(100% + 6px); left:50%; transform:translateX(-50%); white-space:nowrap;
    background: var(--clay); color:#fff; font-size:.62rem; padding:3px 8px; border-radius:999px; z-index:660;
    box-shadow: 0 4px 10px rgba(0,0,0,.3);
  }
}
@media (max-width:360px){
  .person-node{ width: calc(33.333% - 5px); }
}

/* ---------- Admin login gate ---------- */
.login-gate{
  position:fixed; inset:0; z-index:2000; display:flex; align-items:center; justify-content:center;
  background:
    radial-gradient(circle at 20% 20%, var(--glow-soft), transparent 40%),
    radial-gradient(circle at 80% 80%, rgba(185,134,58,.18), transparent 40%),
    linear-gradient(160deg, var(--ink), color-mix(in srgb, var(--brass-dark) 30%, var(--ink-soft)));
  padding:20px;
}
.login-box{
  background:#fff; border-radius: var(--radius); padding:32px 30px; width:100%; max-width:380px;
  box-shadow: 0 0 0 1px var(--glow-soft), 0 24px 60px rgba(0,0,0,.4);
}
.login-box .crest{ width:56px; height:56px; font-size:1.3rem; }

/* ---------- Voice search hint (iOS unsupported / permission blocked) --- */
.mic-hint{
  font-size:.72rem; color: var(--clay); background: rgba(239,84,104,.08); border:1px solid rgba(239,84,104,.25);
  border-radius:8px; padding:6px 10px; margin: 0 14px 8px;
}

/* ---------- Party-activity-leave calendar (nghỉ sinh hoạt Đảng) -------- */
.cal-day.marked-reason{ background: var(--brass); color:#fff; font-weight:700; }
.cal-day.marked-noreason{ background: var(--clay); color:#fff; font-weight:700; }

/* ---------- Assistant toggle: natural (uncropped) shape once a real 3D
   model has loaded — circular robot mask/background only applies to the
   🤖 emoji fallback. ---------- */
.assistant-toggle.has-model3d{
  background: transparent; border-radius: 0; padding: 0; width:52px; height:64px;
  box-shadow: 0 6px 16px rgba(0,0,0,.25);
}
.assistant-toggle.has-model3d model-viewer{ width:100%; height:100%; --poster-color: transparent; pointer-events:none; }

/* ---------- Inline TTS pause/stop, sitting right next to the 🔊 that
   started it, instead of relying only on the shared floating bar. ------- */
.tts-inline{ display:inline-flex; align-items:center; gap:4px; vertical-align:middle; }
.tts-inline-btn{
  display:none; border:none; background: var(--ink); color:#fff; border-radius:50%;
  width:22px; height:22px; font-size:.62rem; align-items:center; justify-content:center; line-height:1; flex-shrink:0;
}
.tts-inline.playing .tts-inline-btn{ display:inline-flex; }

/* ---------- Birthday ticker: subtle, formal scrolling marquee ---------- */
.birthday-ticker{
  overflow:hidden; background: linear-gradient(90deg, var(--ink), color-mix(in srgb, var(--brass-dark) 25%, var(--ink-soft)) 60%, var(--ink));
  border-top:1px solid var(--glow-soft); border-bottom:1px solid var(--glow-soft); padding:7px 0;
}
.birthday-ticker-inner{
  display:inline-block; white-space:nowrap; padding-left:100%;
  color: var(--glow); font-family: var(--font-mono); font-size:.76rem; letter-spacing:.02em;
  animation: birthdayTickerScroll 26s linear infinite;
}
@keyframes birthdayTickerScroll{ from{ transform: translateX(0); } to{ transform: translateX(-100%); } }

/* =====================================================================
   PALETTE: "signal" (Indigo Signal) — modern indigo + cyan-as-status-only.
   Selectable via the palette picker; independent of light/dark mode
   (see the [data-mode="dark"] variant further down, next to the other
   3 dark palette overrides).
   ===================================================================== */
:root[data-palette="signal"]{
  --ink:        #12131a;
  --ink-soft:   #1c2030;
  --paper:      #f5f6fa;
  --paper-dim:  #e9ecf5;
  --brass:      #4f46e5;
  --brass-dark: #4338ca;
  --sage:       #565d70;
  --clay:       #e5484d;
  --line:       #dfe2ec;
  --text-dark:  #12131a;
  --text-light: #eef1f9;
  --glow:       #06b6d4;
  --glow-soft:  rgba(6,182,212,.26);
  --brass-soft: rgba(79,70,229,.20);
  --holo-blue:  var(--brass);
}

/* =====================================================================
   PALETTE: "slate" (Slate & Amber) — neutral-first, warm amber accent;
   deliberately avoids the generic "blue AI dashboard" look entirely.
   ===================================================================== */
:root[data-palette="slate"]{
  --ink:        #1c2128;
  --ink-soft:   #262c36;
  --paper:      #f4f5f7;
  --paper-dim:  #e7e9ed;
  --brass:      #3e4c6e;
  --brass-dark: #2c3752;
  --sage:       #656b78;
  --clay:       #c0392b;
  --line:       #dee1e6;
  --text-dark:  #1c2128;
  --text-light: #f4f5f7;
  --glow:       #d9a441;
  --glow-soft:  rgba(217,164,65,.26);
  --brass-soft: rgba(62,76,110,.20);
  --holo-blue:  var(--brass);
}

/* =====================================================================
   PALETTE: "violet" (Violet Pulse) — modern violet paired with a warm
   coral status accent (never blue/cyan, to avoid the overused
   "purple-to-blue gradient AI SaaS" cliché).
   ===================================================================== */
:root[data-palette="violet"]{
  --ink:        #161222;
  --ink-soft:   #201a33;
  --paper:      #f6f5fa;
  --paper-dim:  #ebe8f3;
  --brass:      #6d28d9;
  --brass-dark: #5b21b6;
  --sage:       #665f77;
  --clay:       #e5484d;
  --line:       #e1dcec;
  --text-dark:  #161222;
  --text-light: #f6f5fa;
  --glow:       #e8734a;
  --glow-soft:  rgba(232,115,74,.26);
  --brass-soft: rgba(109,40,217,.20);
  --holo-blue:  var(--brass);
}


/* =====================================================================
   ALTERNATE THEME: "Tối" (dark mode) — a neutral dark reskin of the
   default palette (keeps the same indigo/teal accent, just flips the
   light surfaces to dark ones) for visitors who prefer reading on a dark
   background at night. Cycled together with the gold theme via the 🎨
   button (default → gold → dark → default) — see js/viewer.js
   applyTheme/toggleTheme/initTheme. A few components set their surface
   colour directly as #fff instead of var(--paper) (.card/.modal/etc.),
   so those need explicit overrides here on top of the variable swap.
   ===================================================================== */
/* =====================================================================
   TASK BATCH: RBAC transfer button, active-person highlight, redesigned
   year cards, large evidence modal, evidence year tags (viewer), mobile
   assistant widget hardening, transparent assistant 3D background.
   ===================================================================== */

/* ---------- 1.4 Active person card (persists while collapsed) --------- */
.person-card.active-person{
  background: linear-gradient(180deg, var(--brass-soft), var(--paper-dim) 240%) !important;
  border-color: var(--brass) !important;
  box-shadow: 0 0 0 2px var(--brass-soft), var(--shadow) !important;
}
.person-card.active-person > .head{ background: rgba(91,127,255,.14); }
.person-card.active-person > .head .tab-index{ background: var(--brass); }

/* ---------- 1.2/1.4 Year cards redesign: soft neutral-blue stack ------ */
.achievement-year-grid{ display:flex; flex-direction:column; gap:10px; }
.achievement-year-card{
  border:1px solid #d7e3f5; border-radius:12px; overflow:hidden;
  background:#fff; box-shadow:0 1px 3px rgba(30,50,90,.06);
}
.achievement-year-head{
  background: linear-gradient(120deg,#eef3fc,#e4ecfa); color:var(--ink);
  padding:11px 14px;
}
.achievement-year-num{ color:var(--ink); }
.achievement-year-icon-btn{
  border:none; background: rgba(128,128,128,.16); color:var(--text-dark); border-radius:6px;
  width:24px; height:24px; font-size:.72rem; flex-shrink:0;
}
.achievement-year-icon-btn:hover{ background:rgba(13,20,36,.14); }
.achievement-year-icon-btn:disabled{ opacity:.3; cursor:not-allowed; }
.achievement-year-head .meta-tag{ background:var(--brass) !important; color:#fff; }
.achievement-year-body{ background:#f7f9fd; }
.achievement-item-card{ border-color:#e1e8f5; }
.achievement-item-head{ background:#fff; }

/* Task: đánh dấu minh chứng thuộc văn bản của Đảng — nền đỏ, chữ vàng, logo Đảng */
.achievement-item-card.party-doc{ border-color:#8f1d1d; }
.achievement-item-card.party-doc .achievement-item-head{
  background: linear-gradient(120deg,#7a1414,#a51d1d); color:#ffd76a;
}
.achievement-item-card.party-doc .achievement-item-head span{ color:#ffd76a; }
.party-doc-flag{ width:18px; height:18px; object-fit:contain; flex-shrink:0; border-radius:3px; background:#fff; padding:1px; }

/* ---------- 1.2 Large "table-style" evidence entry modal -------------- */
.evidence-modal .modal{ max-width: min(960px, 96vw); }
.evidence-modal .modal-body{ max-height:78vh; }
.evidence-table{ width:100%; border-collapse:collapse; font-size:.86rem; }
.evidence-table th{
  text-align:left; font-size:.72rem; text-transform:uppercase; letter-spacing:.03em;
  color:var(--sage); padding:8px 10px; border-bottom:2px solid var(--line); white-space:nowrap;
}
.evidence-table td{ padding:8px 10px; border-bottom:1px solid var(--line); vertical-align:top; overflow-wrap:anywhere; word-break:break-word; }
.evidence-table input, .evidence-table select{ width:100%; min-width:0; box-sizing:border-box; }
.evidence-table-wrap{ width:100%; overflow-x:auto; }
.evidence-modal-actions{ display:flex; justify-content:space-between; gap:10px; margin-top:14px; flex-wrap:wrap; }

/* ---------- 2.1 Evidence year tags + viewer table modal --------------- */
.evidence-year-tags{ display:flex; flex-wrap:wrap; gap:6px; margin-top:4px; }
.evidence-year-tag{
  border:1px solid var(--glow); background:var(--glow-soft); color:var(--text-dark);
  border-radius:999px; padding:4px 12px; font-size:.76rem; font-weight:600;
}
.evidence-year-tag:hover{ background:var(--glow); }
.evidence-view-table{ width:100%; border-collapse:collapse; font-size:.82rem; }
.evidence-view-table th{ text-align:left; font-size:.68rem; text-transform:uppercase; color:var(--sage); padding:6px 8px; border-bottom:2px solid var(--line); }
.evidence-view-table td{ padding:6px 8px; border-bottom:1px dashed var(--line); overflow-wrap:anywhere; }
/* Party-document rows in the public/viewer evidence table — same red/gold
   treatment as the Admin card, plus the Đảng flag logo in the first cell. */
.evidence-view-table tr.party-doc-row td{ background:#7a1414; color:#ffd76a; font-weight:600; }
.evidence-view-table tr.party-doc-row a{ color:#ffe08a; text-decoration:underline; }
.evidence-view-table .party-doc-title{ display:flex; align-items:center; gap:6px; }

/* ---------- 2.2 Mobile TTS/mic controls: never overlap the label text -
   Broadened to the app's usual phone breakpoint (700px, not 480px) since
   that's what every other mobile rule in this file uses. ---------------- */
@media (max-width:700px){
  .assistant-panel{ width: calc(100vw - 24px); right:-4px; }
  .ap-search{ flex-direction:column; align-items:stretch; }
  .ap-search input{ width:100%; }
  .ap-search button{ width:100%; justify-content:center; }
  .tts-stack{ flex-direction:column; float:none; display:inline-flex; margin:4px 0; }
  .speak-fab{ flex-direction:column; align-items:stretch; padding:6px; max-width:150px; }
  .speak-fab button{ justify-content:center; width:100%; }

  /* "Chức năng, nhiệm vụ" / "Nhiệm vụ" / "Thành tích" section headers use
     a plain text label + the TTS icon stack — they must NOT be squeezed
     into the icon-only 34px column meant for short data-field labels
     (.modal .info-row .k), or the label text and the 🤖/🎙️/⏸/⏹ icons
     overlap. `.section-row` opts a header row out of that squeeze. */
  .modal .info-row.section-row .k{
    width:auto; flex:1 1 100%; flex-direction:row; align-items:flex-start;
    flex-wrap:wrap; gap:8px; cursor:default; padding:0;
  }
  .modal .info-row.section-row .k .k-text{
    display:inline; position:static; background:none; color:var(--sage);
    font-size:.78rem; font-weight:600; padding:0; box-shadow:none; white-space:normal;
  }
  .modal .info-row.section-row{ flex-direction:column; }
  .modal .info-row.section-row > div:last-child{ width:100%; }
}

/* ---------- 2.3 Assistant 3D: guarantee transparent canvas ------------ */
.assistant-toggle model-viewer,
.assistant-toggle.has-model3d,
.assistant-toggle.has-model3d model-viewer{
  background: transparent !important; --poster-color: transparent;
}

/* ---------- Mobile brand line-break: "Thư viện Nguyễn Đình Chiểu" /
   "Vĩnh Long" reads better on 2 lines on phones; desktop keeps 1 line. --- */
.mobile-break{ display:none; }
@media (max-width:700px){ .mobile-break{ display:inline; } }

/* =====================================================================
   VIEW SWITCH — "Chính quyền" / "Đảng viên" segmented control at the top
   of the org-chart area (index.html #viewSwitch). Two equal pill buttons;
   the active one fills with a colour that hints at its destination (brass
   for Chính quyền, red for Đảng viên) so people orient before clicking.
   ===================================================================== */
.view-switch{
  display:flex; justify-content:center; gap:10px; max-width:560px; margin:22px auto 0; padding:0 16px;
}
.view-switch-btn{
  flex:1; display:flex; align-items:center; justify-content:center; gap:8px;
  padding:13px 18px; border-radius:999px; border:1.5px solid var(--glass-border);
  background: var(--glass-bg); backdrop-filter: blur(14px) saturate(150%); -webkit-backdrop-filter: blur(14px) saturate(150%);
  font-family: var(--font-display); font-weight:600; font-size:.86rem; color: var(--text-dark);
  cursor:pointer; transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease, background .16s ease, color .16s ease;
  box-shadow: var(--glass-shadow-sm);
}
.view-switch-btn:hover{ transform: translateY(-1px); border-color: var(--brass); }
.view-switch-btn.active{
  background: linear-gradient(135deg, var(--brass), var(--brass-dark)); color:#fff; border-color: var(--brass-dark);
  box-shadow: var(--glass-shadow);
}
.view-switch-btn[data-view="party"].active{
  background: linear-gradient(135deg, #d43c3c, #8e1616); border-color:#8e1616;
}
@media (max-width:480px){ .view-switch-btn span{ display:none; } .view-switch-btn{ padding:12px; } }

/* ---- Header (topbar + hero) chuyển chất Đảng khi đang xem mục Đảng
   viên (body.party-active, gán bởi switchMainView() trong viewer.js) —
   giữ nguyên bố cục/logic, chỉ đổi màu nền + logo (crest) tạm thời. ---- */
body.party-active .topbar{
  background: #7a1010 !important;
  background: linear-gradient(180deg, color-mix(in srgb, #7a1010 92%, transparent), color-mix(in srgb, #c62828 82%, transparent)) !important;
  box-shadow: 0 8px 24px rgba(122,16,16,.25), inset 0 -1px 0 rgba(255,255,255,.08) !important;
}
body.party-active .topbar .crest{
  background: radial-gradient(circle at 30% 30%, #e0b23a, #a97a1a) !important; color:#3a0d0d !important;
}
body.party-active .hero{
  background:
    radial-gradient(circle at 15% 20%, rgba(224,178,58,.20), transparent 35%),
    radial-gradient(circle at 85% 80%, rgba(255,255,255,.10), transparent 40%),
    linear-gradient(160deg, #7a1010, #c62828) !important;
}
/* Task: nút Website/Fanpage/Youtube/Zalo OA ở hero trước đây dùng màu
   xanh chàm (--brass) mặc định — trên nền đỏ mới rất khó đọc. Đổi sang
   viền/chữ vàng nhạt, nền trắng mờ khi hover, đúng tông đỏ-vàng-trắng. */
body.party-active .hero .social-links a{
  color:#f6e7c9; border-color: rgba(246,231,201,.55); background: rgba(0,0,0,.12);
}
body.party-active .hero .social-links a:hover{
  background:#e0b23a; border-color:#e0b23a; color:#3a0d0d;
}
body.party-active .hero .lib-address{ color: rgba(255,255,255,.82); }
body.party-active .btn.solid{
  background: linear-gradient(160deg, #e0b23a, #c69328) !important; color:#3a0d0d !important; border-color:#a97a1a !important;
}

/* =====================================================================
   ĐẢNG VIÊN CHI BỘ THEME — "đỏ vàng trắng" (red/gold/white), scoped to
   #partyView so it never leaks into the government (blue/indigo) chart.
   Deliberately a bright/cream base (not a dark panel like
   .former-leaders-theme) — reads as a flag-inspired identity, distinct
   at a glance from the rest of the site.
   ===================================================================== */
/* ---- Hover holo panel + click modal, đúng chất Đảng (đỏ-vàng) thay vì
   panel kính trong suốt trung tính dùng chung cho chính quyền — áp dụng
   khi spec.theme==='party' (showHolo) / showModal(...,'party'). ---- */
.holo-overlay.holo-party{
  background: linear-gradient(135deg, #c62828, #7a1010) !important;
  border-color: #e0b23a !important;
  box-shadow: 0 16px 34px rgba(122,16,16,.30), inset 0 1px 0 rgba(255,255,255,.12), 0 0 0 1px rgba(224,178,58,.45) !important;
}
.holo-overlay.holo-party .holo-head{ background: rgba(0,0,0,.22); }
.holo-overlay.holo-party .holo-title{ color:#e0b23a; }
.holo-overlay.holo-party .holo-sub{ color: rgba(255,255,255,.88); }
.holo-overlay.holo-party .holo-readout{ background: rgba(0,0,0,.22); }
.holo-overlay.holo-party .holo-line{ color:#fff4e0; border-bottom-color: rgba(255,255,255,.14); }
.holo-overlay.holo-party .holo-line .holo-caret{ background:#e0b23a; }
.holo-overlay.holo-party .holo-logo{ background:#fff; padding:2px; border-radius:6px; }

.modal.party-modal .modal-head{
  background: linear-gradient(120deg, #c62828, #7a1010) !important;
}
.modal.party-modal .modal-head h3{ color:#e0b23a; }
.modal.party-modal .modal-head .role{ color: rgba(255,255,255,.9); opacity:1; }
.modal.party-modal .modal-head .avatar{
  background: linear-gradient(145deg, #e0b23a, #7a1010) !important;
  filter: drop-shadow(0 0 6px rgba(224,178,58,.5));
}
.modal.party-modal .modal-body .info-row .k{ color:#8e1616; }
.modal.party-modal .modal-body{ background: linear-gradient(180deg, rgba(198,40,40,.045), transparent 200px) !important; }

.party-theme{
  --pt-red:#c62828; --pt-red-dark:#7a1010; --pt-gold:#e0b23a; --pt-gold-soft: rgba(224,178,58,.28);
  --pt-cream:#fffdf8;
  background:
    radial-gradient(circle at 10% 92%, rgba(198,40,40,.08), transparent 42%),
    radial-gradient(circle at 92% 10%, rgba(224,178,58,.14), transparent 46%),
    linear-gradient(180deg, var(--pt-cream) 0%, #fff6e0 55%, var(--pt-cream) 100%);
  border: 2px solid var(--pt-red);
  border-radius:26px; padding-bottom:10px; margin: 0 auto;
  box-shadow: 0 16px 40px rgba(122,16,16,.16);
  overflow:hidden;
}
.party-theme .orgchart-section{ padding-top:0; }
/* Task: tiêu đề + mô tả gộp thành 1 dải băng đỏ ở đầu khối — chữ tiêu đề
   VÀNG làm điểm nhấn, chữ mô tả TRẮNG (xen kẽ 2 màu như yêu cầu), thay vì
   chữ đỏ nằm trên nền trắng như bản trước (đối lập yếu, ít "chất Đảng"). */
.party-theme h2{
  color: var(--pt-gold); background: linear-gradient(120deg, var(--pt-red), var(--pt-red-dark));
  margin:0 -24px 0; padding:22px 24px 4px; text-shadow: 0 1px 3px rgba(0,0,0,.3);
  letter-spacing:.02em; border-radius:24px 24px 0 0;
}
.party-theme .lead{
  color: rgba(255,255,255,.92); background: linear-gradient(120deg, var(--pt-red), var(--pt-red-dark));
  margin:0 -24px 24px; padding:0 24px 20px; max-width:none;
}
.party-theme .tier-label{
  width:fit-content; margin:0 auto 16px; padding:8px 26px; border-radius:999px;
  background: linear-gradient(120deg, var(--pt-red), var(--pt-red-dark));
  color: var(--pt-gold); font-weight:700; letter-spacing:.05em; text-shadow: 0 1px 2px rgba(0,0,0,.25);
  box-shadow: 0 5px 14px rgba(122,16,16,.28);
}
.party-theme .tier-label::before, .party-theme .tier-label::after{ display:none; }
.party-theme .person-node{
  background:#fff; border:1.5px solid var(--pt-red);
  box-shadow: 0 6px 18px rgba(122,16,16,.12), inset 0 0 0 1px rgba(224,178,58,.18);
}
.party-theme .person-node:hover{
  border-color: var(--pt-gold); transform: translateY(-3px);
  box-shadow: 0 14px 28px rgba(122,16,16,.22), inset 0 0 0 2px var(--pt-gold);
}
.party-theme .person-node .avatar{
  background: linear-gradient(145deg, var(--pt-red), var(--pt-red-dark)); color: var(--pt-gold);
  filter: drop-shadow(0 0 5px rgba(224,178,58,.45));
}
.party-theme .person-node .pname{ color: var(--pt-red-dark); font-weight:700; }
.party-theme .person-node .prole{ color: var(--pt-red); font-weight:600; }
.party-theme .empty-state{ color:#8a5a12; padding:24px; }
.party-theme .branch-info-bar .btn{
  border-color: var(--pt-red); color: var(--pt-red); background:#fff;
}
.party-theme .branch-info-bar .btn:hover{ background: var(--pt-red); color:#fff; }
:root[data-mode="dark"] .party-theme{
  border-color:#ff6b60;
  background:
    radial-gradient(circle at 10% 92%, rgba(198,40,40,.20), transparent 42%),
    radial-gradient(circle at 92% 10%, rgba(224,178,58,.16), transparent 46%),
    linear-gradient(180deg, #1d1210 0%, #241512 55%, #1d1210 100%);
}
:root[data-mode="dark"] .party-theme .person-node{ background:#291815; border-color: rgba(224,178,58,.35); }
:root[data-mode="dark"] .party-theme .person-node .pname{ color:#f6e7c9; }
:root[data-mode="dark"] .party-theme .person-node .prole{ color:#ff8a80; }
:root[data-mode="dark"] .party-theme .empty-state{ color:#d8b978; }

/* ---- Admin: same red/gold identity for the "Đảng viên" data-entry tab
   (task: "màu chủ đạo là đỏ vàng trắng" applies to the input panel too,
   not just the public view) — a gradient top border on each card is
   enough to read as themed without needing to fork every field-section
   colour (those already reuse the shared red/amber accents). ---- */
.party-card{ border-top:4px solid #c62828; border-image: linear-gradient(90deg,#c62828,#e0b23a) 1; }
.party-card > .head{
  background: linear-gradient(120deg, #c62828, #7a1010) !important; color:#fff;
}
.party-card > .head .name{ color:#fff; }
.party-card > .head .chevron{ color:#fff; }
.party-card > .head .tab-index{ background:#e0b23a !important; }
.party-card > .head .drag-handle{ color: rgba(255,255,255,.75); }
.party-card > .head .btn.ghost-dark{ border-color: rgba(255,255,255,.45); color:#fff; }
.party-card > .head .btn.ghost-dark:hover{ background: rgba(255,255,255,.18); color:#fff; }
#panel-party .tab-panel-hint{ color:#8a6a1a; }

/* ---------- Mobile org-chart tiers: Thư viện (tầng 1, full) → Trụ sở/Cơ
   sở (tầng 2, compact 3-col) → Ban Giám đốc (tầng 3, full) → 3 Phòng
   (tầng 4). #topRow keeps 3 compact columns instead of collapsing to 1,
   matching the requested tier-2 layout; ID selector beats the shared
   .top-row/.dept-row breakpoint rules regardless of source order. ------- */
@media (max-width:900px){ #topRow, #deptRow{ grid-template-columns:repeat(3,1fr); } }
@media (max-width:700px){
  #topRow, #deptRow{ grid-template-columns:repeat(3,1fr); gap:8px; }
  #topRow .node-card, #deptRow .node-card{ padding:10px 4px; }
  #topRow .node-card .icon, #deptRow .node-card .icon{ font-size:1.25rem; margin-bottom:4px; }
  #topRow .node-card h3, #deptRow .node-card h3{ font-size:.66rem; line-height:1.25; margin:0 0 2px; }
  #topRow .node-card .hint, #deptRow .node-card .hint{ font-size:.56rem; }
  #bgdRow{ margin-bottom:16px; }
}
@media (max-width:560px){ #topRow, #deptRow{ grid-template-columns:repeat(3,1fr); } }

/* ---------- Admin dark mode (toggled via a small button in admin.html's
   topbar — reuses the same [data-mode="dark"] palette overrides already
   defined below in the shared "ALTERNATE THEME" section). --------------- */
.admin-theme-toggle{ margin-left:4px; }
.admin-theme-toggle.active-mode{ background: var(--brass) !important; color:#fff !important; border-color: var(--brass-dark) !important; }

:root[data-mode="dark"]{
  --ink:        #05070c;
  --ink-soft:   #0d1220;
  --paper:      #10141c;
  --paper-dim:  #171c28;
  --brass:      #5b7fff;
  --brass-dark: #4a6ae0;
  --sage:       #8b93a8;
  --clay:       #ff6b7a;
  --line:       #262d3d;
  --text-dark:  #e8ecf6;
  --text-light: #eef1f9;
  --glow:       #22d3ee;
  --glow-soft:  rgba(34,211,238,.30);
  --brass-soft: rgba(91,127,255,.24);
  --holo-blue:  var(--brass);
  --holo-green: #39ff8f;
  --holo-red:   #ff6b7a;
  --glass-bg:      rgba(255,255,255,.08); /* fallback */
  --glass-bg:      color-mix(in srgb, var(--brass) 12%, rgba(255,255,255,.07));
  --glass-bg-2:    color-mix(in srgb, var(--brass) 9%, rgba(255,255,255,.10));
  --glass-border:  color-mix(in srgb, var(--brass) 35%, rgba(255,255,255,.14));
  --glass-shadow:  0 12px 32px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.10);
  --glass-shadow-sm: 0 6px 18px rgba(0,0,0,.36), inset 0 1px 0 rgba(255,255,255,.08);
}
:root[data-palette="signal"][data-mode="dark"]{
  --ink:        #0a0b11; --ink-soft: #12141f; --paper: #13151f; --paper-dim: #1b1e2b;
  --brass:      #6c63f5; --brass-dark: #8078ff; --sage: #8d93a8; --clay: #ff6b72;
  --line:       #282c3c; --text-dark: #ebecf5; --text-light: #ffffff;
  --glow:       #2dd4e8; --glow-soft: rgba(45,212,232,.30); --brass-soft: rgba(108,99,245,.24);
  --holo-blue:  var(--brass);
}
:root[data-palette="slate"][data-mode="dark"]{
  --ink:        #101216; --ink-soft: #191c22; --paper: #191c22; --paper-dim: #22262e;
  --brass:      #8494b8; --brass-dark: #9eacd0; --sage: #9aa0ac; --clay: #e27461;
  --line:       #30343d; --text-dark: #f0f1f3; --text-light: #ffffff;
  --glow:       #e8b95e; --glow-soft: rgba(232,185,94,.30); --brass-soft: rgba(132,148,184,.24);
  --holo-blue:  var(--brass);
}
:root[data-palette="violet"][data-mode="dark"]{
  --ink:        #0d0a16; --ink-soft: #161129; --paper: #150f22; --paper-dim: #1f1830;
  --brass:      #a78bfa; --brass-dark: #c4b5fd; --sage: #a79bc0; --clay: #ff6b6b;
  --line:       #322847; --text-dark: #ede9f7; --text-light: #ffffff;
  --glow:       #f0916a; --glow-soft: rgba(240,145,106,.30); --brass-soft: rgba(167,139,250,.24);
  --holo-blue:  var(--brass);
}
:root[data-mode="dark"] .card,
:root[data-mode="dark"] .modal,
:root[data-mode="dark"] .assistant-panel,
:root[data-mode="dark"] .role-bar,
:root[data-mode="dark"] .search-results,
:root[data-mode="dark"] .node-card,
:root[data-mode="dark"] .login-box{
  background: var(--paper-dim); color: var(--text-dark);
}
:root[data-mode="dark"] .person-card{ background: linear-gradient(180deg, var(--paper-dim), var(--ink-soft) 240%); }
:root[data-mode="dark"] .field input,
:root[data-mode="dark"] .field select,
:root[data-mode="dark"] .field textarea,
:root[data-mode="dark"] .richtext{ background: var(--ink-soft); color: var(--text-dark); border-color: var(--line); }
:root[data-mode="dark"] .search-result-item{ color: var(--text-dark); border-color: var(--line); }
:root[data-mode="dark"] .search-result-item:hover{ background: var(--ink-soft); }
:root[data-mode="dark"] .role-bar-icon{ background: var(--ink-soft); }
:root[data-mode="dark"] .modal .info-row{ border-color: var(--line); }
:root[data-mode="dark"] .assistant-panel .ap-quick button{ background: var(--ink-soft); border-color: var(--line); color: var(--text-dark); }
/* Several components hard-code color:var(--ink) as text colour, assuming
   a light background behind them (true for the default + gold themes,
   where --ink is only ever used as a BACKGROUND). In dark mode --ink
   becomes the near-black page background itself, so re-using it as TEXT
   colour on top of that same dark background made it unreadable — these
   overrides restore contrast without touching the light/gold themes. */
:root[data-mode="dark"] h1,
:root[data-mode="dark"] h2,
:root[data-mode="dark"] h3,
:root[data-mode="dark"] h4,
:root[data-mode="dark"] .btn.ghost-dark,
:root[data-mode="dark"] .branch-info-bar .btn,
:root[data-mode="dark"] .rich-render b,
:root[data-mode="dark"] .rich-render strong{
  color: var(--text-dark);
}
:root[data-mode="dark"] .hero h1{ color:#fff; } /* hero keeps its own always-dark background in every theme */
:root[data-mode="dark"] .notice{ background: var(--paper-dim); border-color: var(--brass); color: var(--text-dark); }
:root[data-mode="dark"] .collapsible:not(.expanded) .collapsible-inner::after{
  background: linear-gradient(transparent, var(--paper-dim));
}
:root[data-mode="dark"] .field-error{ color: var(--clay); }
:root[data-mode="dark"] .person-node{ background: var(--paper-dim); }

/* ---------- Admin-specific dark-mode coverage (tabs, year cards, tables,
   login gate) — the block above was written for the viewer; these fill in
   the Admin-only components introduced later. ---------- */
:root[data-mode="dark"] .tabs{ border-color: var(--line); }
:root[data-mode="dark"] .tab{ color: var(--sage); }
:root[data-mode="dark"] .tab.active{ color: var(--text-dark); }
:root[data-mode="dark"] .achievement-year-card{ background: var(--paper-dim); border-color: var(--line); }
:root[data-mode="dark"] .achievement-year-head{ background: linear-gradient(120deg, var(--ink-soft), var(--paper-dim)); color: var(--text-dark); }
:root[data-mode="dark"] .achievement-year-num{ color: var(--text-dark); }
:root[data-mode="dark"] .achievement-year-body{ background: var(--ink-soft); }
:root[data-mode="dark"] .achievement-item-card{ border-color: var(--line); }
:root[data-mode="dark"] .achievement-item-head{ background: var(--paper-dim); }
:root[data-mode="dark"] .evidence-table th, :root[data-mode="dark"] .evidence-view-table th{ color: var(--sage); border-color: var(--line); }
:root[data-mode="dark"] .evidence-table td, :root[data-mode="dark"] .evidence-view-table td{ border-color: var(--line); }
:root[data-mode="dark"] .portrait-frame{ background: var(--ink-soft); border-color: var(--line); }
:root[data-mode="dark"] .login-box{ background: var(--paper-dim); color: var(--text-dark); }
:root[data-mode="dark"] .login-box h2{ color: var(--text-dark); }
:root[data-mode="dark"] .rt-toolbar button{ background: var(--ink-soft); border-color: var(--line); color: var(--text-dark); }
:root[data-mode="dark"] .facility-card, :root[data-mode="dark"] .person-card > .head{ background: var(--paper-dim); }
:root[data-mode="dark"] .person-card > .head{ border-color: var(--line); }
:root[data-mode="dark"] .theme-menu{ background: var(--paper-dim); border-color: var(--line); }
:root[data-mode="dark"] .theme-menu button{ color: var(--text-dark); border-color: var(--line); }

/* =====================================================================
   "LÃNH ĐẠO THƯ VIỆN QUA CÁC THỜI KỲ" — dark-green themed hall-of-fame
   chart, opened by clicking the library crest/logo in the header. Reuses
   .branch-tree/.person-node/.tier-label layout, just re-skinned via this
   scoping class so it never leaks into the normal (blue/navy) org chart.
   ===================================================================== */
.former-leaders-theme{
  --fl-deep:#062017; --fl-mid:#0c3626; --fl-accent:#3ddc84; --fl-accent-soft: rgba(61,220,132,.28);
  border-radius:22px; padding:28px 20px 34px; margin:0 auto 40px;
  background: linear-gradient(165deg, var(--fl-deep) 0%, var(--fl-mid) 55%, #0a2b1e 100%);
  box-shadow: 0 22px 50px rgba(4,20,13,.35), inset 0 1px 0 rgba(255,255,255,.06);
}
.former-leaders-theme h2, .former-leaders-theme .branch-section-head{ color:#eafff2; text-shadow:none; }
.former-leaders-theme .tier-label{ color: var(--fl-accent); }
.former-leaders-theme .tier-label::before, .former-leaders-theme .tier-label::after{ background: color-mix(in srgb, var(--fl-accent) 40%, transparent); }
.former-leaders-theme .person-node{
  background: color-mix(in srgb, var(--fl-mid) 55%, rgba(255,255,255,.05));
  border-color: var(--fl-accent-soft);
  box-shadow: 0 6px 18px rgba(4,20,13,.35), inset 0 0 0 1px var(--fl-accent-soft);
}
.former-leaders-theme .person-node:hover{ box-shadow: 0 10px 26px rgba(4,20,13,.4), inset 0 0 0 1.5px var(--fl-accent); }
.former-leaders-theme .person-node .pname,
.former-leaders-theme .person-node .prole{ color:#eafff2; }
.former-leaders-theme .person-node .avatar{ background: linear-gradient(145deg, var(--fl-accent), #0c3626); color:#04140c; }
.former-leaders-theme .fl-year-badge{
  display:inline-block; margin-top:4px; font-size:.66rem; font-weight:700; color:#04140c;
  background: var(--fl-accent); border-radius:999px; padding:2px 9px;
}
.former-leaders-theme .btn.ghost-dark{ border-color: var(--fl-accent-soft); color:#eafff2; }
.former-leaders-theme .btn.ghost-dark:hover{ background: var(--fl-accent); color:#04140c; }
.former-leaders-theme .empty-state{ color: rgba(234,255,242,.7); }

/* ---- Khung "Chi ủy Chi bộ" (node-card riêng, giống Ban Giám đốc bên
   chính quyền) khi nằm trong #partyView (.party-theme) — viền/nền đỏ,
   glow vàng khi hover, đúng nhận diện Đảng thay vì tông xanh dương mặc
   định của .node-card. Áp dụng luôn khi khung mở dưới dạng sơ đồ nhánh
   (#branchSection.party-theme) — xem openChiUyBranch() trong viewer.js. */
.party-theme .node-card, #branchSection.party-theme{
  background:#fff; border-color: var(--pt-red, #c62828);
  box-shadow: 0 6px 18px rgba(122,16,16,.12), inset 0 0 0 1px rgba(224,178,58,.18);
}
.party-theme .node-card:hover{
  border-color: var(--pt-gold, #e0b23a); box-shadow: 0 12px 26px rgba(122,16,16,.20), inset 0 0 0 1.5px var(--pt-gold, #e0b23a);
}
.party-theme .node-card h3{ color: var(--pt-red-dark, #7a1010); }
.party-theme .node-card .hint{ color: var(--pt-red, #c62828); }
#branchSection.party-theme{ border-radius:26px; padding:20px 20px 4px; margin-bottom:22px;
  background:
    radial-gradient(circle at 10% 8%, rgba(198,40,40,.08), transparent 42%),
    radial-gradient(circle at 90% 88%, rgba(212,160,23,.14), transparent 46%),
    linear-gradient(180deg, #fffdf8 0%, #fff6e0 55%, #fffdf8 100%);
  border:2px solid #c62828;
}
#branchSection.party-theme .branch-section-head h2,
#branchSection.party-theme #branchTitle{ color: var(--pt-red-dark, #7a1010); }
#branchSection.party-theme .tier-label{
  width:fit-content; margin:0 auto 16px; padding:8px 26px; border-radius:999px;
  background: linear-gradient(120deg, #c62828, #7a1010); color:#e0b23a; font-weight:700;
  letter-spacing:.05em; text-shadow:0 1px 2px rgba(0,0,0,.25); box-shadow:0 5px 14px rgba(122,16,16,.28);
}
#branchSection.party-theme .tier-label::before, #branchSection.party-theme .tier-label::after{ display:none; }
#branchSection.party-theme .branch-info-bar .btn{ border-color:#c62828; color:#c62828; background:#fff; }
#branchSection.party-theme .branch-info-bar .btn:hover{ background:#c62828; color:#fff; }
:root[data-mode="dark"] .party-theme .node-card{
  background:#291815; border-color: rgba(224,178,58,.35);
  box-shadow: 0 6px 18px rgba(0,0,0,.35), inset 0 0 0 1px rgba(224,178,58,.14);
}
:root[data-mode="dark"] .party-theme .node-card h3{ color:#f6e7c9; }
:root[data-mode="dark"] .party-theme .node-card .hint{ color:#ff8a80; }
:root[data-mode="dark"] #branchSection.party-theme{
  background:
    radial-gradient(circle at 10% 8%, rgba(198,40,40,.20), transparent 42%),
    radial-gradient(circle at 90% 88%, rgba(224,178,58,.16), transparent 46%),
    linear-gradient(180deg, #1d1210 0%, #241512 55%, #1d1210 100%);
}
:root[data-mode="dark"] #branchSection.party-theme .branch-section-head h2,
:root[data-mode="dark"] #branchSection.party-theme #branchTitle{ color:#ff8a80; }
:root[data-mode="dark"] #branchSection.party-theme .branch-info-bar .btn{ border-color:#e0b23a; color:#e0b23a; background:transparent; }
:root[data-mode="dark"] #branchSection.party-theme .branch-info-bar .btn:hover{ background:#c62828; color:#fff; }

/* =====================================================================
   ACCESSIBILITY: respect prefers-reduced-motion globally — every
   transition/animation in this stylesheet collapses to an instant state
   change for anyone who has this OS/browser preference set. ===================================================================== */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   THEME PICKER (palette + light/dark mode) — index.html topbar & the
   Admin topbar toggle both use this markup/classes.
   ===================================================================== */
.theme-menu .palette-swatch{
  display:inline-block; width:26px; height:26px; border-radius:50%; border:2px solid rgba(255,255,255,.5); cursor:pointer;
  flex-shrink:0; transition: transform .15s ease, border-color .15s ease; padding:0; margin:0; border-bottom-width:2px;
}
.theme-menu .palette-swatch:hover{ transform: scale(1.1); }
.theme-menu .palette-swatch.active{ border-color:#fff; box-shadow: 0 0 0 2px var(--brass); }
.theme-menu .palette-swatch[data-palette-swatch="control"]{ background: linear-gradient(135deg,#5b7fff,#22d3ee); }
.theme-menu .palette-swatch[data-palette-swatch="signal"]{ background: linear-gradient(135deg,#4f46e5,#06b6d4); }
.theme-menu .palette-swatch[data-palette-swatch="slate"]{ background: linear-gradient(135deg,#3e4c6e,#d9a441); }
.theme-menu .palette-swatch[data-palette-swatch="violet"]{ background: linear-gradient(135deg,#6d28d9,#e8734a); }
.theme-menu .palette-row{ display:flex; gap:8px; padding:12px 14px; border-bottom:1px solid var(--line); }
.theme-menu .mode-row{ display:flex; gap:6px; padding:10px 14px; }
.theme-menu .mode-btn{
  display:inline-block; flex:1; border:1px solid var(--line); background:var(--paper); border-radius:8px; padding:7px 0;
  font-size:.74rem; font-weight:600; color:var(--text-dark); text-align:center; width:auto; margin:0;
}
.theme-menu .mode-btn.active{ background: var(--brass); color:#fff; border-color: var(--brass); }

/* ---- Shared SVG icon system ---------------------------------------------
   Sized in em by default so icon() calls inherit the surrounding text's
   font-size automatically (button labels, headings, etc). */
.icon{ display:inline-block; vertical-align:-0.15em; flex-shrink:0; }
button .icon, .btn .icon{ vertical-align:-0.2em; margin-right:2px; }

/* ---- Admin topbar: grouped actions (task: reduce 9 same-weight
   buttons to a few clear groups — see design critique). ---- */
.topbar-divider{ width:1px; align-self:stretch; background: rgba(255,255,255,.14); margin: 2px 2px; }
.theme-menu-item{
  display:flex; align-items:center; gap:8px; width:100%; text-align:left; padding:10px 14px;
  border:none; background:none; font-size:.82rem; color: var(--text-dark); border-bottom:1px solid var(--line);
  cursor:pointer; text-decoration:none;
}
.theme-menu-item:last-child{ border-bottom:none; }
.theme-menu-item:hover{ background: var(--paper-dim); }
:root[data-mode="dark"] .theme-menu-item{ color: var(--text-dark); border-color: var(--line); }
:root[data-mode="dark"] .theme-menu-item:hover{ background: var(--ink-soft); }

/* ---- Guest "sign in to view" lock note — small, muted, never a big bold
   icon (this repeats up to 8x per guest profile view, so it must stay
   quiet, not alarming). ---- */
.lock-note{ display:inline-flex; align-items:center; gap:5px; color: var(--sage); font-style:italic; opacity:.85; }
.lock-note .icon{ opacity:.75; }

/* =====================================================================
   "2026 MODERNIZATION PASS" — cross-cutting polish additions only
   (custom scrollbars, consistent focus rings, richer empty states, a
   more premium login gate, assistant panel, search dropdown, and small
   typography/motion refinements). Everything below is additive/override
   — no existing selector is removed, no markup/JS structure required.
   ===================================================================== */

/* ---- Custom slim scrollbars everywhere content can overflow — a small
   but very "2026 SaaS" signal (Linear/Notion/Vercel all do this) versus
   the chunky default OS scrollbar. Falls back silently on browsers that
   don't support these properties (Firefox gets scrollbar-width/color). */
*{
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--brass) 45%, transparent) transparent;
}
::-webkit-scrollbar{ width:9px; height:9px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{
  background: color-mix(in srgb, var(--brass) 40%, transparent); border-radius:999px;
  border: 2px solid transparent; background-clip:content-box;
}
::-webkit-scrollbar-thumb:hover{ background: color-mix(in srgb, var(--brass) 65%, transparent); background-clip:content-box; }

/* ---- Consistent focus-visible ring app-wide — replaces whatever the
   browser's native default (often a harsh blue rectangle) would draw on
   buttons/links/cards, matching the palette in use instead of a fixed
   blue regardless of theme ("no default blue buttons" applies to focus
   states too, not just fills). Mouse/touch clicks never show this —
   only real keyboard focus does, so it never adds visual noise for the
   overwhelming majority of interactions. */
:focus:not(:focus-visible){ outline: none; }
:focus-visible{
  outline: 2.5px solid var(--brass); outline-offset: 2px; border-radius: 6px;
}
.btn:focus-visible, .view-switch-btn:focus-visible{ outline-offset: 3px; }
::selection{ background: var(--brass); color:#fff; }

/* ---- Richer empty states — small circular icon badge above the text
   instead of a bare line of muted copy, consistent radius/spacing with
   the rest of the app's card language. */
.empty-state{
  display:flex; flex-direction:column; align-items:center; gap:10px;
  padding:48px 20px; font-size:.88rem; line-height:1.6;
}
.empty-state::before{
  content:''; width:44px; height:44px; border-radius:50%; flex-shrink:0;
  background: color-mix(in srgb, var(--brass) 12%, var(--paper-dim));
  border:1px solid var(--line);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%235b6479' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:center;
}
:root[data-mode="dark"] .empty-state::before{
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='none' stroke='%238b93a8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
}

/* ---- Login gate — tighter radius/shadow rhythm matching the rest of the
   app's card language (var(--radius)) instead of a slightly mismatched
   bespoke value, plus a subtle glass edge and entrance motion. ---- */
.login-box{
  border-radius: calc(var(--radius) + 6px);
  box-shadow: 0 0 0 1px var(--glow-soft), 0 30px 70px rgba(0,0,0,.35);
  animation: cardEnter .42s cubic-bezier(.22,1,.36,1) both;
}
.login-box .field input{ font-size:.92rem; }
.login-box .btn.solid{ width:100%; padding:12px; font-size:.86rem; letter-spacing:.01em; }

/* ---- Assistant panel — opens with a soft pop instead of appearing
   instantly, matching the entrance motion used elsewhere. ---- */
@keyframes assistantPop{ from{ opacity:0; transform: translateY(8px) scale(.97); } to{ opacity:1; transform:none; } }
.assistant-panel.open{ animation: assistantPop .22s cubic-bezier(.22,1,.36,1) both; }
.assistant-toggle{ transition: transform .18s cubic-bezier(.22,1,.36,1), box-shadow .18s ease; }
.assistant-toggle:active{ transform: scale(.94); }

/* ---- Search results dropdown — slightly larger radius + softer shadow
   to match the rest of the "floating panel" language (glass shadow
   tokens) instead of the plain var(--shadow) it used before. ---- */
.search-results{
  border-radius: 14px; box-shadow: var(--glass-shadow);
  border-color: var(--glass-border);
  animation: cardEnter .18s ease both;
}
.search-result-item{ padding:11px 14px; transition: background .12s ease, padding-left .12s ease; }
.search-result-item:hover{ padding-left:17px; }

/* ---- Typography rhythm: tighten heading letter-spacing slightly for a
   more editorial/premium feel (Stripe/Linear-style headings read denser
   and more intentional than default browser tracking), and give buttons
   a touch more letter-spacing for a "designed" label feel. ---- */
h1,h2,h3,h4{ letter-spacing:-0.01em; }
.btn{ letter-spacing:.015em; }

/* ---- Card/table hover micro-interaction consistency: anything already
   using .card gets a very slight lift on hover ONLY when it is also
   interactive (has an onclick affordance) — cursor:pointer is already
   used as that signal throughout the codebase (node-card, person-node,
   facility-card headers), so scope the lift there rather than to every
   static .card (which would be noisy on data-entry forms). ---- */
h3[onclick]{ transition: opacity .12s ease; }
h3[onclick]:hover{ opacity:.75; }

/* ---- Buttons: slightly deeper press feedback + smoother easing curve
   app-wide, replacing the flatter linear-ish transition. ---- */
.btn{ transition: transform .14s cubic-bezier(.22,1,.36,1), box-shadow .14s cubic-bezier(.22,1,.36,1), background .15s ease, color .15s ease; }

@media (prefers-reduced-motion: reduce){
  .login-box, .assistant-panel.open, .search-results{ animation: none !important; }
}
