/* Gia phả — bảng màu giấy dó / son / đồng, sáng + tối */
/* ============================================================ TOKENS */
:root{
  --paper:#F6F1E7; --paper-2:#FFFCF6; --paper-3:#EDE4D3; --paper-4:#E3D7C1;
  --ink:#241C14; --ink-2:#6E6152; --ink-3:#968A79;
  --line:#DFD4BF; --line-2:#C8B99C;
  --son:#A6321F; --son-2:#C1462F; --son-tint:#F5E1DA;
  --dong:#8E6A22; --dong-tint:#F3E8CF;
  --luc:#2C6A4E; --luc-tint:#DCEAE1;
  --lam:#2A5C87; --lam-tint:#DBE7F1;
  --tim:#63498A; --tim-tint:#E6DEF2;
  /* Sáu sắc chia NHÓM con cùng một cha trên sơ đồ theo đời — dải ghi tên cha,
     vạch đầu thẻ và đường nối xuống đều lấy chung một sắc, nên lần theo màu là
     lần lên được đời trên. Cố ý tách khỏi bộ son/đồng/lam/tím/lục: mấy màu ấy
     đã có nghĩa cố định là vai vế (xem DESIGN.md §1), mượn sang đây thì cùng
     một màu hoá hai nghĩa. Sáu là số nhóm cạnh nhau nhiều nhất mà mắt còn tách
     bạch được; quá sáu thì quay vòng, lúc ấy hai nhóm trùng sắc đã cách nhau
     đủ xa. */
  --nhom-1:#A6321F; --nhom-2:#8E6A22; --nhom-3:#2C6A4E;
  --nhom-4:#1F6474; --nhom-5:#2A5C87; --nhom-6:#63498A;
  --nhom-chu:#FDF6E2;        /* chữ trên dải nhóm */
  --noi-vien:#F6F1E7;        /* nét viền dưới đường nối, để đường cắt nhau vẫn tách bạch */
  --shadow-1:0 1px 2px rgba(60,44,24,.07), 0 1px 1px rgba(60,44,24,.05);
  --shadow-2:0 4px 14px rgba(60,44,24,.10), 0 1px 3px rgba(60,44,24,.07);
  --shadow-3:0 16px 44px rgba(45,32,16,.20), 0 2px 8px rgba(45,32,16,.10);
  --r-s:7px; --r-m:11px; --r-l:16px; --r-xl:22px;
  --serif:'Iowan Old Style','Palatino Linotype',Palatino,'Book Antiqua','Noto Serif',Georgia,serif;
  --sans:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,'SF Mono',Menlo,Consolas,monospace;
  --topbar-h:58px; --tabs-h:44px; --side-w:262px; --drawer-w:396px;
  --bando-h:180px;      /* chiều cao dải bản đồ toàn phả; xem #banDo */
}
[data-theme="toi"]{
  --paper:#141210; --paper-2:#1D1A16; --paper-3:#26221C; --paper-4:#332D25;
  --ink:#F0E8D9; --ink-2:#A3957F; --ink-3:#7B6F5E;
  --line:#332D25; --line-2:#463E32;
  --son:#E67A61; --son-2:#F09077; --son-tint:#3A211B;
  --dong:#D3A552; --dong-tint:#332A17;
  --luc:#66BE93; --luc-tint:#172C22;
  --lam:#7DB2DE; --lam-tint:#152430;
  --tim:#A78BD0; --tim-tint:#241C33;
  --nhom-1:#E67A61; --nhom-2:#D3A552; --nhom-3:#66BE93;
  --nhom-4:#5FA8BC; --nhom-5:#7DB2DE; --nhom-6:#A78BD0;
  --nhom-chu:#141210;        /* nền tối thì dải sáng, chữ trên dải phải đậm lại */
  --noi-vien:#141210;
  --shadow-1:0 1px 2px rgba(0,0,0,.4);
  --shadow-2:0 4px 14px rgba(0,0,0,.45);
  --shadow-3:0 16px 44px rgba(0,0,0,.6);
}
*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; font-family:var(--sans); background:var(--paper); color:var(--ink);
  font-size:14px; line-height:1.5; -webkit-font-smoothing:antialiased;
  overscroll-behavior:none;
}
body::before{
  content:''; position:fixed; inset:0; pointer-events:none; z-index:-1; opacity:.5;
  background:
    radial-gradient(1100px 620px at 15% -10%, var(--dong-tint), transparent 62%),
    radial-gradient(900px 520px at 92% 6%, var(--son-tint), transparent 60%);
}
[data-theme="toi"] body::before{opacity:.42}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:none;padding:0}
a{color:var(--son);text-decoration:none}
h1,h2,h3,h4{font-family:var(--serif);font-weight:600;margin:0;letter-spacing:.1px}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:8px;border:3px solid transparent;background-clip:content-box}
::-webkit-scrollbar-track{background:transparent}
:focus-visible{outline:2px solid var(--son);outline-offset:2px;border-radius:4px}

/* ============================================================ APP SHELL */
#app{position:relative;height:100%;display:flex;flex-direction:column}

.topbar{
  height:var(--topbar-h);flex:none;display:flex;align-items:center;gap:12px;
  padding:0 14px;background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 88%,transparent);
  -webkit-backdrop-filter:saturate(1.4) blur(14px);backdrop-filter:saturate(1.4) blur(14px);border-bottom:1px solid var(--line);
  position:relative;z-index:60;
}
.brand{display:flex;align-items:center;gap:10px;min-width:0}
.brand-mark{
  width:34px;height:34px;flex:none;border-radius:10px;display:grid;place-items:center;
  background:linear-gradient(150deg,var(--son),#7d2417);color:#fff;
  font-family:var(--serif);font-size:17px;font-weight:700;
  box-shadow:var(--shadow-1);
}
[data-theme="toi"] .brand-mark{background:linear-gradient(150deg,#8f2c1c,#5d1b11)}
.brand-title{font-family:var(--serif);font-size:15.5px;font-weight:700;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brand-sub{font-size:11px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.search-wrap{position:relative;flex:1;max-width:430px;margin-left:auto}
.search-box{display:flex;align-items:center;gap:7px;background:var(--paper);border:1px solid var(--line);
  border-radius:999px;padding:0 12px;height:36px;transition:border-color .15s,box-shadow .15s}
.search-box:focus-within{border-color:var(--son);box-shadow:0 0 0 3px var(--son-tint)}
.search-box svg{flex:none;opacity:.5}
.search-box input{flex:1;min-width:0;border:none;background:none;outline:none;font-size:13.5px}
.q-results{
  position:absolute;top:44px;left:0;right:0;background:var(--paper-2);border:1px solid var(--line);
  border-radius:var(--r-m);box-shadow:var(--shadow-3);max-height:min(60vh,420px);overflow:auto;
  display:none;padding:5px;z-index:80;
}
.q-results.on{display:block}
.q-item{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:var(--r-s);cursor:pointer}
.q-item:hover,.q-item.sel{background:var(--paper-3)}
.q-item .qi-name{font-weight:600;font-size:13.5px}
.q-item .qi-sub{font-size:11.5px;color:var(--ink-3)}
.q-empty{padding:16px;text-align:center;color:var(--ink-3);font-size:13px}

/* Ô chọn người có tìm kiếm (tab Xưng hô): dùng lại nguyên bộ .q-results/.q-item
   của ô tìm kiếm trên thanh trên, chỉ đổi chỗ neo cho hợp ô nhập. `.pick-mo` là
   dòng ghi rõ người đang chọn, để đóng danh sách rồi vẫn biết mình chọn ai. */
.pick{position:relative}
.pick .q-results{top:calc(100% + 6px)}
.pick-mo{font-size:11.5px;color:var(--ink-3);line-height:1.35;margin-top:5px;min-height:15px}

.top-actions{display:flex;gap:4px;flex:none}
.icon-btn{
  width:36px;height:36px;border-radius:10px;display:grid;place-items:center;
  color:var(--ink-2);transition:background .14s,color .14s;
}
.icon-btn:hover{background:var(--paper-3);color:var(--ink)}
.icon-btn.on{background:var(--son-tint);color:var(--son)}
/* Nút đóng của tấm trượt: to, có viền, thấy ngay là bấm được — người lớn tuổi
   không đoán ra rằng bấm ra ngoài hay vuốt xuống cũng đóng được. */
.icon-btn.lg{width:42px;height:42px;border:1px solid var(--line-2);background:var(--paper-2);color:var(--ink-2)}
.icon-btn.lg:hover{background:var(--paper-3);border-color:var(--ink-3);color:var(--ink)}
#btnMenu{display:none}
/* Vùng nắm để vuốt đóng — không nhường cử chỉ cho trình duyệt cuộn trang,
   và không để cú kéo biến thành thao tác bôi đen chữ trên dải tiêu đề */
[data-vuot]{touch-action:none;-webkit-user-select:none;user-select:none}

/* ---- tabs (desktop) */
.tabs{
  height:var(--tabs-h);flex:none;display:flex;align-items:center;gap:2px;padding:0 12px;
  border-bottom:1px solid var(--line);background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 60%,transparent);
  overflow-x:auto;scrollbar-width:none;
}
.tabs::-webkit-scrollbar{display:none}
.tab{
  display:flex;align-items:center;gap:7px;padding:7px 13px;border-radius:9px;white-space:nowrap;
  font-size:13.5px;font-weight:500;color:var(--ink-2);transition:.14s;
}
.tab:hover{background:var(--paper-3);color:var(--ink)}
.tab.on{background:var(--son);color:#fff;box-shadow:var(--shadow-1)}
[data-theme="toi"] .tab.on{background:var(--son);color:#241009}
.tab svg{opacity:.9}

.main{flex:1;display:flex;min-height:0;position:relative}
.sidebar{
  width:var(--side-w);flex:none;border-right:1px solid var(--line);
  display:flex;flex-direction:column;min-height:0;
  background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 45%,transparent);
}
.side-body{flex:1;min-height:0;overflow-y:auto;padding:14px 14px 40px}
/* Dải tiêu đề của tấm trượt — chỉ có ở khổ hẹp, nơi bộ lọc trượt đè lên cây.
   Ở màn rộng bộ lọc là một cột cố định nên không cần tiêu đề lẫn nút đóng. */
.sheet-h{display:none}
.sheet-t{font-family:var(--serif);font-size:15px;font-weight:700;flex:1;min-width:0}
.stage{flex:1;min-width:0;position:relative;overflow:hidden}
.panel{position:absolute;inset:0;display:none;overflow:auto}
.panel.on{display:block}
.panel.flat{padding:22px 26px 60px}

/* ============================================================ CONTROLS */
.grp{margin-bottom:20px}
.grp-h{
  font-size:10.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 8px 2px;display:flex;align-items:center;gap:6px;
}
.seg{display:flex;flex-direction:column;gap:3px}
.seg-i{
  display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:9px;font-size:13.5px;
  color:var(--ink-2);transition:.13s;text-align:left;width:100%;border:1px solid transparent;
}
.seg-i:hover{background:var(--paper-3);color:var(--ink)}
.seg-i.on{background:var(--paper-2);border-color:var(--line-2);color:var(--ink);font-weight:600;box-shadow:var(--shadow-1)}
.seg-i .dot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--line-2)}
.seg-i.on .dot{background:var(--son)}
.seg-i .sub{font-size:11px;color:var(--ink-3);font-weight:400;display:block}
/* Hai lựa chọn loại trừ nhau, đặt cạnh nhau cho thấy ngay là chọn một trong hai */
.seg.ngang{flex-direction:row;gap:8px}
.seg.ngang .seg-i{flex:1;align-items:flex-start}
.seg.ngang .seg-i:not(.on){border-color:var(--line)}
.seg.ngang .dot{margin-top:4px}

.chips{display:flex;flex-wrap:wrap;gap:6px}
.chip{
  padding:5px 11px;border-radius:999px;border:1px solid var(--line-2);font-size:12.5px;
  color:var(--ink-2);background:var(--paper-2);transition:.13s;
}
.chip:hover{border-color:var(--ink-3);color:var(--ink)}
.chip.on{background:var(--son);border-color:var(--son);color:#fff;font-weight:600}
[data-theme="toi"] .chip.on{color:#241009}
.chip.c-dong.on{background:var(--dong);border-color:var(--dong)}
.chip.c-lam.on{background:var(--lam);border-color:var(--lam)}
.chip.c-luc.on{background:var(--luc);border-color:var(--luc)}

.sw{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 2px;font-size:13.5px;color:var(--ink-2)}
.sw input{display:none}
.sw .track{width:38px;height:22px;border-radius:999px;background:var(--paper-4);position:relative;transition:.18s;flex:none;cursor:pointer}
.sw .track::after{content:'';position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--paper-2);box-shadow:var(--shadow-1);transition:.18s}
.sw input:checked + .track{background:var(--son)}
.sw input:checked + .track::after{transform:translateX(16px)}

.stepper{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink-2)}
.stepper button[data-depth]{
  width:26px;height:26px;border-radius:8px;border:1px solid var(--line-2);background:var(--paper-2);
  font-size:15px;font-weight:700;line-height:1;color:var(--ink-2);display:grid;place-items:center;transition:.13s;
}
.stepper button[data-depth]:hover{background:var(--son);color:#fff;border-color:var(--son)}
.stepper b{min-width:44px;text-align:center;color:var(--ink);font-variant-numeric:tabular-nums}
.rng{width:100%;accent-color:var(--son);margin:4px 0}
.rng-lbl{display:flex;justify-content:space-between;font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums}

.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:8px 14px;border-radius:9px;
  border:1px solid var(--line-2);background:var(--paper-2);font-size:13.5px;font-weight:500;
  color:var(--ink);transition:.14s;box-shadow:var(--shadow-1);
}
.btn:hover{border-color:var(--ink-3);transform:translateY(-1px);box-shadow:var(--shadow-2)}
.btn:active{transform:none}
.btn.primary{background:var(--son);border-color:var(--son);color:#fff}
[data-theme="toi"] .btn.primary{color:#2a0f08}
.btn.primary:hover{background:var(--son-2)}
.btn.ghost{background:none;box-shadow:none;border-color:transparent;color:var(--ink-2)}
.btn.ghost:hover{background:var(--paper-3);border-color:transparent}
.btn.sm{padding:5px 10px;font-size:12.5px;border-radius:7px}
.btn.danger{color:var(--son);border-color:var(--son-tint)}
.btn.block{width:100%}

.inp,select.sel,.ta{
  width:100%;padding:8px 11px;border-radius:9px;border:1px solid var(--line);
  background:var(--paper-2);font-size:13.5px;outline:none;transition:.14s;
}
.inp:focus,select.sel:focus,.ta:focus{border-color:var(--son);box-shadow:0 0 0 3px var(--son-tint)}
.ta{resize:vertical;min-height:76px;font-family:inherit}
.fld{margin-bottom:12px}
.fld > label{display:block;font-size:11.5px;font-weight:600;color:var(--ink-2);margin-bottom:5px;letter-spacing:.02em}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px}
.fld-note{font-size:11.5px;line-height:1.55;color:var(--ink-3);margin:6px 0 0}
.fld-note b{color:var(--ink-2)}
/* Ô đã suy ra từ quan hệ nên không cho gõ tay — xem formNguoi() trong admin.js.
   Viền đứt + nền chìm để phân biệt ngay với ô nhập được, không phải bấm vào
   mới biết. `.o-suy` là chỗ chỉ hiện kết quả, không có ô nhập nào cả. */
.inp[readonly],select.sel:disabled{
  background:var(--paper-3);color:var(--ink-2);-webkit-text-fill-color:var(--ink-2);
  opacity:1;border-style:dashed;cursor:default;
}
.inp[readonly]:focus{border-color:var(--line);box-shadow:none}
.o-suy{
  padding:8px 11px;border-radius:9px;border:1px dashed var(--line-2);
  background:var(--paper-3);font-size:13.5px;color:var(--ink-2);
}
.lnk{background:none;border:0;padding:0;font:inherit;color:var(--son);cursor:pointer;
  text-decoration:underline;text-underline-offset:2px}

.badge{
  display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:999px;
  font-size:11px;font-weight:600;background:var(--paper-3);color:var(--ink-2);white-space:nowrap;
}
.badge.son{background:var(--son-tint);color:var(--son)}
.badge.dong{background:var(--dong-tint);color:var(--dong)}
.badge.lam{background:var(--lam-tint);color:var(--lam)}
.badge.luc{background:var(--luc-tint);color:var(--luc)}
.badge.tim{background:var(--tim-tint);color:var(--tim)}

.card{background:var(--paper-2);border:1px solid var(--line);border-radius:var(--r-l);padding:18px;box-shadow:var(--shadow-1)}
.card + .card{margin-top:14px}
.card-h{font-family:var(--serif);font-size:16px;font-weight:700;margin:0 0 4px}
.card-sub{font-size:12.5px;color:var(--ink-3);margin:0 0 14px}

.empty{padding:56px 20px;text-align:center;color:var(--ink-3)}
.empty .big{font-size:34px;opacity:.35;margin-bottom:10px}

/* ============================================================ TREE CANVAS */
.canvas{position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden;cursor:grab;touch-action:none;
  transition:bottom .24s cubic-bezier(.32,.72,0,1);
  background-image:radial-gradient(circle at 1px 1px, var(--line) 1px, transparent 0);
  background-size:26px 26px;}
[data-theme="toi"] .canvas{background-image:radial-gradient(circle at 1px 1px, #2b251d 1px, transparent 0)}
.canvas.drag{cursor:grabbing}
.world{position:absolute;top:0;left:0;transform-origin:0 0;will-change:transform}
.links{position:absolute;top:0;left:0;overflow:visible;pointer-events:none}
.links path{fill:none;stroke-width:1.6px}
/* Lượt viền chạy dưới, dày hơn, mang màu giấy: chỗ hai đường cắt nhau vẫn tách
   bạch được đường nào đi đâu, khỏi phải chừa khoảng trống to giữa hai đời. */
.links .noi-vien path{stroke:var(--noi-vien);stroke-width:4.5px;stroke-linecap:round}
/* Màu nhóm ghi thẳng vào style của <path> — nên đường trực hệ tới người đang
   chọn phải !important mới đè nổi lên màu nhóm. */
.links path.hl{stroke:var(--son)!important;stroke-width:2.4px}

/* ---- Dải màu ghi tên cha, nằm ngay trên đầu (hoặc bên trái) nhóm anh em ruột.
   Đây là thứ thay cho khoảng trống của lối toả nhánh cũ: hàng xếp khít thì
   không còn nhìn hình dáng mà đoán ra ai con ai, phải ghi thẳng tên cha ra. */
.gr-bar{
  position:absolute;border-radius:2px;display:flex;align-items:center;justify-content:center;
  overflow:hidden;font-family:var(--sans);font-size:8.5px;font-weight:700;letter-spacing:.07em;
  white-space:nowrap;color:var(--nhom-chu);background:var(--mau,var(--line-2));z-index:1;
}
.gr-bar.doc{writing-mode:vertical-rl;transform:rotate(180deg)}

/* Một thẻ = một gia đình. Khối trên là người mang họ, dưới là các ô phối ngẫu,
   ghi đủ tên và ngày giỗ như nhau. Bề rộng VÀ chiều cao đều do JS đặt theo chữ
   thật đo được (xem doThe() trong tree.js), nên ở đây không khoá cái nào — và
   cũng không cắt ba chấm ở đâu cả: thẻ đã được nới cho vừa nội dung rồi. */
.node{
  position:absolute;border-radius:2px;background:var(--paper-2);
  border:1px solid var(--line-2);box-shadow:var(--shadow-1);
  display:flex;overflow:visible;z-index:2;
  transition:box-shadow .15s,border-color .15s,transform .15s;cursor:pointer;
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
}
.node:not(.hz){flex-direction:column}
.node.hz{flex-direction:row}
/* Vạch sắc nhóm: nằm đầu thẻ khi cha trên con dưới, dựng bên trái khi xem ngang */
.node-vach{flex:none;background:var(--mau,var(--line-2))}
.node:not(.hz) .node-vach{height:3px}
.node.hz .node-vach{width:3px}
.node-than{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column}
.node-chinh{
  flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;
  text-align:center;padding:2px 4px;line-height:1.22;font-family:var(--serif);
}
.node-name{font-weight:700;letter-spacing:.02em;text-transform:uppercase;text-wrap:pretty}
.node-meta{font-weight:400;font-size:.86em;color:var(--ink-2);font-family:var(--sans);font-variant-numeric:tabular-nums}
/* Ô phối ngẫu: một gạch kẻ chia ô đúng lối phả in cũ ghi "chính thất" ngay
   dưới tên ông. Vẫn bấm được để mở hồ sơ riêng của bà ấy. */
.node-vc{
  flex:none;border-top:1px solid var(--line-2);padding:2px 4px;text-align:center;
  line-height:1.22;font-family:var(--serif);color:var(--ink);
  background:color-mix(in srgb,var(--paper-3) 55%,transparent);
}
.node-vc .vc-meta{font-size:.9em;color:var(--ink-2);font-family:var(--sans);font-variant-numeric:tabular-nums}
.node-vc:hover{background:var(--son-tint);color:var(--ink)}
.node-vc.on{background:var(--son);color:#fff}
.node-vc.on .vc-meta{color:#fff}
.node:hover{border-color:var(--son);box-shadow:var(--shadow-2);z-index:5}
.node.he-dau,.node.he-re{background:color-mix(in srgb,var(--paper-2) 55%,transparent);border-style:dashed}
.node.sel{border-color:var(--son);box-shadow:0 0 0 3px var(--son-tint),var(--shadow-2);z-index:6}
/* Tì tay lên thẻ một lúc = muốn đẩy cây đi chứ không phải mở thẻ. Thẻ nhấc lên
   để báo "giờ kéo được rồi, thả tay ra sẽ không mở gì cả". */
.node.giu{transform:scale(1.05);box-shadow:var(--shadow-3);border-color:var(--son);z-index:8;cursor:grabbing}
.node.path{border-color:var(--son)}
.node.dim{opacity:.34}
/* Huy hiệu vai trò chiếm hẳn một dòng cuối thẻ (doThe() đã cộng 12px cho nó)
   chứ không treo ra ngoài mép: mép trên đã là dải nhóm, mép dưới là nút thu
   nhánh — treo ra chỗ nào cũng đè lên một thứ khác. */
.node-vai{flex:none;display:flex;justify-content:flex-end;padding:0 3px 2px}
.node-tag{font-size:8px;font-weight:700;padding:1px 5px;border-radius:2px;background:var(--dong);color:#fff;letter-spacing:.03em;white-space:nowrap}
.node-tag.tt{background:var(--dong)}
.node-tag.to{background:var(--son)}
/* Chấm "còn sống" nằm ngay trên vạch sắc nhóm, ngoài luồng chữ — thẻ nào cũng
   khít chữ nên không còn góc trống nào để đặt nó mà không đè lên tên. */
.node-live{position:absolute;left:-1px;top:-1px;width:6px;height:6px;border-radius:50%;background:var(--luc);box-shadow:0 0 0 2px var(--paper-2);z-index:3}
.node.hz .node-live{left:-2px;top:2px}
.node-toggle{
  position:absolute;left:50%;bottom:-24px;transform:translateX(-50%);
  min-width:22px;height:22px;padding:0 6px;border-radius:999px;background:var(--paper-2);
  border:1px solid var(--line-2);font-size:10.5px;font-weight:700;color:var(--ink-2);
  display:grid;place-items:center;box-shadow:var(--shadow-1);z-index:4;transition:.13s;
}
/* Nút chỉ 22px, nhưng ngón tay cần chừng 44px mới bấm trúng — nới vùng chạm
   ra bằng một lớp trong suốt, không đụng gì tới hình dáng nút. */
.node-toggle::after{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:44px;height:40px}
.node-toggle:hover{background:var(--son);color:#fff;border-color:var(--son)}
/* Xem ngang thì neo bằng MÉP TRÁI của nút, không phải `right`: chiều dài nút
   thay đổi theo nhãn ("−" hẹp, "+12" rộng) và trên điện thoại min-width còn
   nới lên 34px, nên mọi giá trị `right` cố định đều có lúc để nút thụt lại
   vào trong thẻ mà đè lên tên. Neo mép trái thì nút bắt đầu ngay ngoài mép
   thẻ, rộng bao nhiêu cũng nằm ngoài. Sơ đồ dọc không cần vậy vì bề CAO của
   nút cố định, `bottom` âm là đủ. */
.node.hz .node-toggle{left:calc(100% + 2px);right:auto;bottom:auto;top:50%;transform:translateY(-50%)}

/* ============================================================ CÂY THỤT LỀ
   Bề ngang bám bề ngang màn, chỉ cuộn dọc. Không thu phóng, nên cỡ chữ ở đây
   luôn là cỡ chữ thật — thứ mà sơ đồ toả nhánh không giữ nổi khi họ đông. */
#thutLe{
  position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;display:none;
  touch-action:pan-y;-webkit-overflow-scrolling:touch;
}
.canvas.la-thutle{cursor:default;touch-action:auto;background-image:none}
.canvas.la-thutle #world,
.canvas.la-thutle #genRail{display:none}
.canvas.la-thutle #thutLe{display:block}
/* ============================================================ BẢN ĐỒ TOÀN PHẢ */
#banDo{
  position:absolute;left:0;right:0;bottom:0;z-index:22;
  height:calc(var(--bando-h) + env(safe-area-inset-bottom));
  padding:0 10px calc(6px + env(safe-area-inset-bottom));
  background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 94%,transparent);
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  border-top:1px solid var(--line);box-shadow:0 -6px 22px rgba(60,44,24,.10);
  transform:translateY(101%);transition:transform .24s cubic-bezier(.32,.72,0,1);
  overflow:hidden;
}
#banDo.on{transform:none}
.bd-h{display:flex;align-items:center;gap:8px;height:30px;font-size:11.5px;color:var(--ink-3)}
.bd-h b{font-size:12.5px;color:var(--ink);font-family:var(--serif)}
.bd-h span{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bd-h .icon-btn{width:26px;height:26px;border-radius:7px;flex:none}
/* chỉ tấm bản đồ mới trải hết bề ngang — không vơ cả biểu tượng ✕ trong dải
   tiêu đề, vốn cũng là một <svg> do paintIcons() chèn vào */
#banDo > svg{display:block;width:100%}
.bd-o rect{opacity:.30;transition:opacity .12s}
.bd-o text{font-size:9.5px;fill:var(--ink);text-anchor:middle;pointer-events:none;opacity:.62}
.bd-o.xem rect{opacity:.82}                 /* phần đang hiện trên khung nhìn */
.bd-o.xem text{opacity:1;fill:#fff;font-weight:600}
.bd-o.sel rect{opacity:1;stroke:var(--ink);stroke-width:1.5}
.bd-o:hover rect{opacity:.95}
.bd-o{cursor:pointer}
/* nhường chỗ cho bản đồ, kẻo nó đè lên thanh thông tin và cụm nút */
/* Mở bản đồ thì khung cây co lên đúng bấy nhiêu — cây tự canh lại vào phần
   còn thấy được, thay vì để một phần ba nằm khuất dưới dải bản đồ. */
.canvas.co-bando{bottom:calc(var(--bando-h) + env(safe-area-inset-bottom))}
.canvas.co-bando ~ .canvas-info,
.canvas.co-bando ~ .canvas-tools{bottom:calc(var(--bando-h) + 14px + env(safe-area-inset-bottom))}

.zoom-grp{display:flex;flex-direction:column;gap:5px}
/* thu phóng vô nghĩa khi không có gì để phóng */
.canvas.la-thutle ~ .canvas-tools .zoom-grp{display:none}
.tl-cuon{padding:2px 12px calc(84px + env(safe-area-inset-bottom))}
/* Bố cục thụt lề có dải đếm dính ở đầu danh sách, nên hai lớp nổi của sơ đồ
   theo đời phải tắt đi — nếu không chúng đè lên chữ ở mép trái. */
.canvas.la-thutle ~ .legend,
.canvas.la-thutle ~ .canvas-info{display:none}
.tl-dau{
  position:sticky;top:0;z-index:5;display:flex;gap:6px;flex-wrap:wrap;
  padding:9px 12px;border-bottom:1px solid var(--line);
  background:var(--paper);background:color-mix(in srgb,var(--paper) 92%,transparent);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.tl-dau .pill{backdrop-filter:none;-webkit-backdrop-filter:none}

.tl-dong{
  position:relative;display:flex;align-items:center;gap:8px;min-height:46px;
  padding:5px 10px 5px 4px;border-radius:9px;cursor:pointer;
}
.tl-dong:hover{background:var(--paper-3);background:color-mix(in srgb,var(--paper-3) 60%,transparent)}
.tl-dong.sel{background:var(--son-tint);box-shadow:inset 0 0 0 1px var(--son)}
.tl-dong.path{box-shadow:inset 2px 0 0 var(--son)}
.tl-dong.dim{opacity:.42}
/* nét dẫn dọc của các đời trên còn anh em phía dưới */
.tl-ray,.tl-moc{position:absolute;pointer-events:none;border-color:var(--line-2)}
.tl-ray{top:0;bottom:0;width:0;border-left:1px solid var(--line-2)}
.tl-moc{top:0;height:23px;width:9px;border-left:1px solid var(--line-2);border-bottom:1px solid var(--line-2);border-radius:0 0 0 5px}

.tl-mo{
  flex:none;width:24px;height:24px;border-radius:7px;border:1px solid var(--line-2);
  background:var(--paper-2);color:var(--ink-2);font-size:11px;font-weight:700;
  display:grid;place-items:center;position:relative;z-index:1;
}
.tl-mo:hover{background:var(--son);border-color:var(--son);color:#fff}
.tl-la{flex:none;width:24px;height:24px;position:relative;z-index:1}
.tl-la::after{content:'';position:absolute;left:9px;top:11px;width:6px;height:2px;border-radius:2px;background:var(--line-2)}

.tl-noi{flex:1;min-width:0}
.tl-ten{
  font-family:var(--serif);font-size:14px;font-weight:650;line-height:1.25;
  display:flex;align-items:center;gap:5px;flex-wrap:wrap;
}
.tl-meta{font-size:11.5px;color:var(--ink-3);font-variant-numeric:tabular-nums;margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Vạch màu ở đây chỉ GIỚI TÍNH / HỆ — khác với sơ đồ theo đời, nơi vạch chỉ
   NHÓM con cùng cha. Danh sách thụt lề đã thụt lề ra quan hệ cha con rồi nên
   vạch được rảnh tay làm việc khác; chú giải màu đổi theo bố cục (views.js). */
.tl-dong.g-nam .tl-noi{box-shadow:inset 2px 0 0 var(--son);padding-left:8px}
.tl-dong.g-nu .tl-noi{box-shadow:inset 2px 0 0 var(--dong);padding-left:8px}
.tl-dong.he-ngoai .tl-noi{box-shadow:inset 2px 0 0 var(--lam)}
.tl-dong.he-re .tl-noi{box-shadow:inset 2px 0 0 var(--tim)}

.tl-vcs{flex:none;display:flex;flex-direction:column;gap:2px;align-items:flex-end;max-width:38%}
.tl-vc{
  font-size:11px;color:var(--ink-2);background:var(--paper-3);border:1px solid var(--line);
  border-radius:999px;padding:2px 9px;max-width:100%;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tl-vc:hover{background:var(--son-tint);border-color:var(--son);color:var(--son)}
.tl-vc.on{background:var(--son);border-color:var(--son);color:#fff}
.grp-note{font-size:11.5px;color:var(--ink-3);line-height:1.45;margin-top:7px}

.canvas-tools{
  position:absolute;right:14px;bottom:14px;display:flex;flex-direction:column;gap:5px;
  background:var(--paper-2);border:1px solid var(--line);border-radius:12px;padding:5px;
  box-shadow:var(--shadow-2);z-index:20;
}
.canvas-tools .icon-btn{width:32px;height:32px;border-radius:8px}
.canvas-info{
  position:absolute;left:14px;bottom:14px;display:flex;gap:6px;flex-wrap:wrap;z-index:20;
  max-width:calc(100% - 90px);
}
/* Dải trạng thái neo dưới thanh tiêu đề — chỉ dựng ở khổ hẹp (xem khối KHỔ HẸP);
   màn rộng vẫn dùng .canvas-info nổi trên mặt cây. */
.cay-trangthai{display:none}
.pill{
  background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 92%,transparent);border:1px solid var(--line);
  border-radius:999px;padding:4px 11px;font-size:11.5px;color:var(--ink-2);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);box-shadow:var(--shadow-1);white-space:nowrap;
}
#legendSide{display:none}
.la-thutle-app #legendSide{display:block}
/* Khổ hẹp giấu dải chú giải nổi trên cây (chiếm mất mặt cây) — đưa nó vào
   trong bộ lọc. Điều kiện phải trùng khối "KHỔ HẸP" bên dưới, không thì màn
   ngang mất cả hai. */
@media (max-width:900px), (max-height:560px) and (max-width:1180px){#legendSide{display:block}}
.legend{position:absolute;left:14px;top:14px;z-index:20;display:flex;gap:5px;flex-wrap:wrap;max-width:calc(100% - 28px)}
.lg{display:inline-flex;align-items:center;gap:5px;background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 92%,transparent);
  border:1px solid var(--line);border-radius:999px;padding:3px 10px;font-size:11px;color:var(--ink-2);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.lg i{width:8px;height:8px;border-radius:2px;display:inline-block}

/* ============================================================ DRAWER */
.scrim{position:fixed;inset:0;background:rgba(30,20,10,.42);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:90;opacity:0;pointer-events:none;transition:opacity .22s}
.scrim.on{opacity:1;pointer-events:auto}
.drawer{
  position:fixed;top:0;right:0;bottom:0;width:var(--drawer-w);max-width:100vw;z-index:100;
  background:var(--paper-2);border-left:1px solid var(--line);box-shadow:var(--shadow-3);
  transform:translateX(100%);transition:transform .26s cubic-bezier(.32,.72,0,1);
  display:flex;flex-direction:column;
}
.drawer.on{transform:none}
.drawer-h{flex:none;padding:14px 16px;border-bottom:1px solid var(--line);display:flex;align-items:flex-start;gap:10px}
.drawer-b{flex:1;overflow-y:auto;padding:16px;-webkit-overflow-scrolling:touch}
.drawer-f{flex:none;padding:10px 16px;border-top:1px solid var(--line);display:flex;gap:8px;flex-wrap:wrap}

.avatar{
  width:52px;height:52px;border-radius:14px;flex:none;display:grid;place-items:center;
  font-family:var(--serif);font-size:20px;font-weight:700;color:#fff;
  background:linear-gradient(150deg,var(--son),#7d2417);box-shadow:var(--shadow-1);
}
.avatar.nu{background:linear-gradient(150deg,var(--dong),#6d4f14)}
.avatar.ngoai{background:linear-gradient(150deg,var(--lam),#1b3f5e)}
.avatar.lg{width:64px;height:64px;font-size:25px;border-radius:18px}

.kv{display:grid;grid-template-columns:104px 1fr;gap:7px 12px;font-size:13px}
.kv dt{color:var(--ink-3);font-size:12px}
.kv dd{margin:0}
.sec-t{font-size:10.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);margin:20px 0 9px;display:flex;align-items:center;gap:8px}
.sec-t::after{content:'';flex:1;height:1px;background:var(--line)}
.rel-list{display:flex;flex-direction:column;gap:4px}
.rel{display:flex;align-items:center;gap:9px;padding:7px 9px;border-radius:9px;transition:.13s;cursor:pointer;text-align:left;width:100%}
.rel:hover{background:var(--paper-3)}
.rel .av{width:30px;height:30px;border-radius:9px;flex:none;display:grid;place-items:center;font-size:12px;font-weight:700;color:#fff;background:linear-gradient(150deg,var(--son),#7d2417);font-family:var(--serif)}
.rel .av.nu{background:linear-gradient(150deg,var(--dong),#6d4f14)}
.rel .av.ngoai{background:linear-gradient(150deg,var(--lam),#1b3f5e)}
.rel .t{flex:1;min-width:0;display:block}
.rel .n{display:block;font-size:13px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rel .s{display:block;font-size:11px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.breadcrumb{display:flex;flex-wrap:wrap;gap:4px;align-items:center;font-size:12px}
.breadcrumb button{color:var(--son);font-size:12px}
.breadcrumb span{color:var(--ink-3)}
.bio{font-size:13.5px;line-height:1.65;color:var(--ink-2);font-family:var(--serif)}
.ghi-chu{
  display:flex;gap:8px;align-items:flex-start;margin:0 0 14px;padding:9px 11px;
  border-radius:var(--r-s);background:var(--dong-tint);border:1px solid var(--line-2);
  font-size:12.5px;line-height:1.55;color:var(--ink-2);
}
.ghi-chu svg{flex:none;color:var(--dong);margin-top:1px}
.cd-doi{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:10px}
.cd-doi p{
  margin:0;padding:14px 16px;border-radius:var(--r-s);text-align:center;
  background:linear-gradient(180deg,#9E1710,#7C1109);color:#EFDFA0;
  font-family:var(--serif);font-size:15px;font-weight:600;line-height:1.5;
  border:1px solid var(--dong);box-shadow:var(--shadow-1);
}
@media (max-width:560px){.cd-doi{grid-template-columns:1fr}}

/* ============================================================ HỘP THOẠI */
.modal-box{
  position:fixed;z-index:160;left:50%;top:50%;transform:translate(-50%,-50%);
  width:min(720px,94vw);max-height:90vh;background:var(--paper-2);border:1px solid var(--line);
  border-radius:var(--r-l);box-shadow:var(--shadow-3);display:flex;flex-direction:column;
}
.modal-h{flex:none;padding:14px 18px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px}
.modal-h h3{font-size:17px;flex:1;min-width:0}
.modal-b{flex:1;min-height:0;overflow:auto;padding:18px;-webkit-overflow-scrolling:touch}
.modal-f{flex:none;padding:12px 18px;border-top:1px solid var(--line);display:flex;gap:8px;justify-content:flex-end;flex-wrap:wrap}
.modal-box .sheet-handle{margin:8px auto 2px}

/* ============================================================ TABLES / LISTS */
.tbl-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:var(--r-m);background:var(--paper-2)}
table.tbl{width:100%;border-collapse:collapse;font-size:13px;min-width:640px}
table.tbl th{
  text-align:left;font-size:10.5px;letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);
  padding:10px 12px;border-bottom:1px solid var(--line);white-space:nowrap;position:sticky;top:0;
  background:var(--paper-3);z-index:2;font-weight:700;
}
table.tbl td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:middle}
table.tbl tbody tr:hover{background:var(--paper-3)}
table.tbl tbody tr{cursor:pointer}
table.tbl tbody tr:last-child td{border-bottom:none}
.nowrap{white-space:nowrap}
.num{font-variant-numeric:tabular-nums}

.gen-block{margin-bottom:26px}
.gen-h{display:flex;align-items:baseline;gap:10px;margin-bottom:10px;position:sticky;top:0;background:var(--paper);padding:8px 0;z-index:3}
.gen-h h3{font-size:17px}
.gen-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(228px,1fr));gap:9px}
.pcard{
  display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:11px;
  border:1px solid var(--line);background:var(--paper-2);text-align:left;transition:.14s;box-shadow:var(--shadow-1);
}
.pcard:hover{border-color:var(--ink-3);transform:translateY(-1px);box-shadow:var(--shadow-2)}
.pcard .t{min-width:0;flex:1;display:block}
.pcard .n{display:block;font-size:13.5px;font-weight:650;font-family:var(--serif);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pcard .s{display:block;font-size:11.5px;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ============================================================ STATS */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:16px}
.stat{background:var(--paper-2);border:1px solid var(--line);border-radius:var(--r-m);padding:14px 16px;box-shadow:var(--shadow-1)}
.stat .v{font-family:var(--serif);font-size:27px;font-weight:700;line-height:1.05;font-variant-numeric:tabular-nums}
.stat .l{font-size:11.5px;color:var(--ink-3);margin-top:3px}
.stat .p{font-size:10.5px;color:var(--ink-3);margin-top:5px;opacity:.85;line-height:1.35}
/* Ô số bấm được thì phải trông ra là bấm được — người lớn tuổi không rê chuột
   quanh trang để dò xem chỗ nào ăn. Mũi tên góc phải là dấu hiệu tĩnh, thấy
   ngay cả khi không có con trỏ (điện thoại). */
.stat.bam,.bar-row.bam{text-align:left;width:100%;position:relative;transition:.14s}
.stat.bam{padding-right:26px}
.stat.bam::after{
  content:'›';position:absolute;right:11px;top:11px;font-size:17px;line-height:1;
  color:var(--ink-3);opacity:.55;font-family:var(--serif);
}
.stat.bam:hover{border-color:var(--son);box-shadow:var(--shadow-2);transform:translateY(-1px)}
.stat.bam:hover::after{color:var(--son);opacity:1}
/* Cột nhãn 96px chứ không phải 88px: "Tháng Mười một" vừa đúng hết chỗ ấy, hẹp
   hơn là cắt thành "Tháng Mười …" — mà cắt ở đấy thì mười, mười một hay chạp
   đều đọc ra như nhau. */
.bar-row{display:grid;grid-template-columns:96px 1fr 62px;gap:10px;align-items:center;margin-bottom:7px;font-size:12.5px}
.bar-row.bam{margin-left:-6px;margin-right:-6px;padding:3px 6px;border-radius:8px}
.bar-row.bam:hover{background:var(--paper-3)}
.bar-l{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink-2)}
.bar-row .num{text-align:right;color:var(--ink-2);font-weight:600;font-variant-numeric:tabular-nums}
.bar-row .num small{display:block;font-size:10px;font-weight:400;color:var(--ink-3)}
.bar{height:16px;border-radius:5px;background:var(--paper-3);overflow:hidden}
.bar i{display:block;height:100%;border-radius:5px;background:var(--son);min-width:2px}
.bar i.dong{background:var(--dong)} .bar i.lam{background:var(--lam)}
.bar i.luc{background:var(--luc)} .bar i.tim{background:var(--tim)}

/* ---------- dải bộ lọc riêng của tab Thống kê ---------- */
.tk-loc{margin-bottom:18px;padding:14px 16px}
/* Dòng đầu luôn thấy: đang tính trên bao nhiêu người, lọc theo gì, và nút mở
   bộ lọc. Sáu hàng chip bên dưới chỉ bày ra khi .mo — xem TK_MO_LOC. */
.tk-dau{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.tk-tom{flex:1;min-width:190px;font-size:12.5px;color:var(--ink-2)}
.tk-nut{display:flex;gap:6px;flex-wrap:wrap}
.tk-hangs{display:none;margin-top:12px;border-top:1px solid var(--line)}
.tk-loc.mo .tk-hangs{display:block}
.tk-hang{display:flex;align-items:flex-start;gap:12px;padding:5px 0}
.tk-hang + .tk-hang{border-top:1px solid var(--line)}
.tk-nhan{
  flex:none;width:86px;padding-top:7px;font-size:10.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-3);
}
.tk-muc{
  font-family:var(--serif);font-size:17px;font-weight:700;margin:26px 0 12px;
  display:flex;align-items:center;gap:10px;
}
.tk-muc::after{content:'';flex:1;height:1px;background:var(--line)}
.tk-luoi{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:14px;align-items:start}
.tk-luoi > .card + .card{margin-top:0}
.tk-them{margin-top:10px}
.tk-luuy{margin:0;padding-left:18px;font-size:13px;line-height:1.65;color:var(--ink-2)}
.tk-luuy li + li{margin-top:10px}
.tk-luuy b{color:var(--ink)}

/* ============================================================ TIMELINE */
.tl{position:relative;padding-left:26px}
.tl::before{content:'';position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:var(--line)}
.tl-i{position:relative;margin-bottom:18px}
.tl-i::before{content:'';position:absolute;left:-23px;top:5px;width:10px;height:10px;border-radius:50%;background:var(--son);box-shadow:0 0 0 3px var(--paper)}
.tl-y{font-family:var(--serif);font-weight:700;color:var(--son);font-size:13px}

/* ============================================================ KHỔ HẸP
   "Hẹp" không chỉ là màn dọc. Điện thoại xoay ngang rộng 844–956px, lọt qua
   mốc 900px cũ nên rơi vào bố cục màn rộng: cột bộ lọc dựng cứng bên trái,
   ăn mất một phần ba bề ngang trong khi màn chỉ cao ~390px. Nên xét cả chiều
   cao. Mốc cao 560px bắt trọn mọi điện thoại nằm ngang; kèm mốc rộng 1180px
   để cửa sổ desktop thấp và rộng không bị kéo theo.
   ⚠ Đổi bộ điều kiện này thì đổi cả MQ_HEP/MQ_NGANG trong core.js cho khớp. */
.bottomnav{display:none}
.sheet-handle{display:none}
@media (max-width:900px), (max-height:560px) and (max-width:1180px){
  :root{--drawer-w:100vw}
  #btnMenu{display:grid}
  .brand-sub{display:none}
  .tabs{display:none}
  .sidebar{
    position:fixed;left:0;right:0;bottom:0;top:auto;width:100%;max-height:82vh;z-index:95;
    border-right:none;border-top:1px solid var(--line);background:var(--paper-2);
    border-radius:var(--r-xl) var(--r-xl) 0 0;box-shadow:var(--shadow-3);
    transform:translateY(102%);transition:transform .26s cubic-bezier(.32,.72,0,1);
    padding:0;
  }
  .sidebar.on{transform:none}
  .side-body{padding:12px 16px calc(28px + env(safe-area-inset-bottom))}
  .sheet-handle{display:block;width:44px;height:5px;border-radius:99px;background:var(--line-2);margin:9px auto 4px}
  .sheet-h{
    display:flex;align-items:center;gap:10px;flex:none;
    padding:4px 12px 10px 16px;border-bottom:1px solid var(--line);
  }
  .main{padding-bottom:calc(60px + env(safe-area-inset-bottom))}
  .panel.flat{padding:16px 14px 40px}
  .topbar{padding-left:calc(14px + env(safe-area-inset-left));padding-right:calc(14px + env(safe-area-inset-right))}
  .bottomnav{
    display:flex;position:fixed;left:0;right:0;bottom:0;z-index:70;height:calc(60px + env(safe-area-inset-bottom));
    padding:0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    background:var(--paper-2);background:color-mix(in srgb,var(--paper-2) 94%,transparent);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
    border-top:1px solid var(--line);
  }
  .bn{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    font-size:10.5px;color:var(--ink-3);transition:.13s;padding-top:6px}
  .bn.on{color:var(--son)}
  .bn svg{width:21px;height:21px}
  .drawer{border-left:none;border-radius:var(--r-xl) var(--r-xl) 0 0;top:auto;height:88vh;
    transform:translateY(102%);}
  .drawer.on{transform:none}
  .legend{display:none}
  .tl-cuon{padding:2px 10px calc(96px + env(safe-area-inset-bottom))}
  .tl-vcs{max-width:44%}
  .search-wrap{position:fixed;top:8px;left:12px;right:12px;max-width:none;z-index:75;display:none}
  .search-wrap.on{display:block}
  .search-box{height:42px}
  .kv{grid-template-columns:92px 1fr}
  .row3{grid-template-columns:1fr 1fr}
  .gen-grid{grid-template-columns:1fr 1fr}

  /* Vùng chạm rộng tay hơn — trang này dành cho cả người nhiều tuổi, ngón tay
     to và mắt kém, nên các nút nhỏ xíu kiểu desktop không dùng được. */
  .icon-btn{width:42px;height:42px}
  .chip{padding:9px 15px;font-size:13.5px}
  .sw{padding:11px 2px;font-size:14px}
  .sw .track{width:46px;height:28px}
  .sw .track::after{width:22px;height:22px}
  .sw input:checked + .track::after{transform:translateX(18px)}
  .seg-i{padding:11px 12px;font-size:14px}
  .stepper button[data-depth]{width:38px;height:38px;font-size:19px;border-radius:10px}
  .stepper b{min-width:56px;font-size:14px}
  .rng{height:30px}
  .btn{padding:11px 16px;font-size:14px}
  .btn.sm{padding:9px 13px;font-size:13px}
  .rel{padding:10px 9px}
  .q-item{padding:11px 10px}
  .grp-h{font-size:11.5px}

  /* Hộp thoại thành tấm trượt lên từ đáy: vuốt xuống đóng được, và ngón cái
     với tới nút bấm mà không phải đổi tay. */
  .modal-box{
    left:0;right:0;bottom:0;top:auto;width:auto;transform:none;
    max-height:88vh;border-radius:var(--r-xl) var(--r-xl) 0 0;border-bottom:none;
  }
  .modal-box .sheet-handle{display:block}
  .modal-h{padding:2px 12px 12px 18px}
  .modal-f{padding:12px 18px calc(12px + env(safe-area-inset-bottom))}

  /* ─────────────────────────── THẺ NGƯỜI TRÊN ĐIỆN THOẠI
     Không còn bộ thẻ riêng cho khổ hẹp. Thẻ nay tự nới theo chữ thật nên cỡ
     chữ trên điện thoại đúng bằng cỡ chữ trên màn rộng — cùng một tấm, cùng
     một cỡ, khổ hẹp chỉ là khung nhìn hẹp hơn kéo trên tấm ấy. Chỉ còn nới
     riêng nút thu/mở nhánh cho vừa đầu ngón tay. */
  .node-toggle{min-width:34px;height:26px;border-radius:13px;font-size:12px;bottom:-28px;
    border-color:var(--son);color:var(--son)}

  /* ─────────────────────────── HAI DẢI NEO THAY CHO LỚP NỔI
     .canvas-info và .canvas-tools vốn nổi trên mặt cây, che đúng hai góc dưới
     — chỗ hay có thẻ nhất khi kéo. Trên khổ hẹp chúng thành hai dải neo: trạng
     thái 34px trên, điều khiển 48px dưới. Cây mất 82px chiều cao nhưng được
     lại toàn bộ bề mặt, và nút nào cũng nằm trong tầm ngón cái. */
  .cay-trangthai{
    position:absolute;left:0;right:0;top:0;height:34px;z-index:21;
    display:flex;align-items:center;gap:8px;padding:0 14px;
    background:var(--paper-3);border-bottom:1px solid var(--line);
    font-size:12.5px;color:var(--ink-2);overflow:hidden;white-space:nowrap;
  }
  /* Mấy mục đầu là số liệu ngắn, phải hiện đủ; chỉ mục cuối (tên người đang
     làm tiêu điểm) mới được co lại và cắt ba chấm. */
  .cay-trangthai .pill{background:none;border:none;box-shadow:none;padding:0;font-size:12.5px;
    -webkit-backdrop-filter:none;backdrop-filter:none;flex:none}
  .cay-trangthai .pill:last-child{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}
  .cay-trangthai .pill:first-child{color:var(--son);font-weight:700}
  .cay-trangthai .pill + .pill{border-left:1px solid var(--line-2);border-radius:0;padding-left:8px}
  .la-thutle-app .cay-trangthai{display:none}

  .canvas{top:34px;bottom:48px}
  .canvas.co-bando{bottom:calc(48px + var(--bando-h) + env(safe-area-inset-bottom))}
  .canvas.la-thutle{top:0;left:0}
  .canvas-info{display:none}
  .canvas-tools{
    left:0;right:0;bottom:0;top:auto;flex-direction:row;align-items:center;gap:6px;
    height:48px;padding:0 10px;border-radius:0;border:none;border-top:1px solid var(--line);
    background:var(--paper-2);box-shadow:none;
  }
  .canvas.co-bando ~ .canvas-tools{bottom:calc(var(--bando-h) + env(safe-area-inset-bottom))}
  .canvas-tools .zoom-grp{flex-direction:row;gap:2px;border:1px solid var(--line-2);
    border-radius:10px;background:var(--paper-3);overflow:hidden}
  .canvas-tools .zoom-grp .icon-btn{border:none;border-radius:0;background:none}
  .canvas-tools .zoom-grp .icon-btn + .icon-btn{box-shadow:-1px 0 0 var(--line)}
  .canvas-tools .icon-btn{width:44px;height:36px;border-radius:10px;
    border:1px solid var(--line-2);background:var(--paper-3)}
  /* paintIcons() chỉ vẽ được biểu tượng, nên nhãn của nút chính đặt bằng CSS */
  #zTo{flex:1;width:auto;gap:7px;font-size:13px;font-weight:600;color:var(--son)}
  #zTo::after{content:'Về Thuỷ tổ'}

  /* ─────────────────────────── MÁNG ĐỜI RIÊNG
     Nhãn "ĐỜI N" rời khỏi tấm phả, sang một máng 22px bên trái khung nhìn:
     không đè lên thẻ nào, mà kéo ngang tới đâu vẫn đọc được đời. Lớp
     .mang-rieng do treoMangDoi() bật/tắt — sơ đồ nằm ngang vẫn dùng máng cũ
     nằm trong tấm. */
  html.mang-rieng .canvas{left:22px}
  html.mang-rieng .canvas.la-thutle{left:0;top:0}   /* thụt lề không có máng đời */
  html.mang-rieng #genRail{
    inset:auto;left:0;top:34px;bottom:48px;width:22px;z-index:21;
    background:var(--paper-3);border-right:1px solid var(--line);overflow:hidden;
  }
  html.mang-rieng .canvas.co-bando ~ #genRail{bottom:calc(48px + var(--bando-h) + env(safe-area-inset-bottom))}
  /* overflow:hidden vì nhãn dựng đứng dài hơn ô hàng khi thu nhỏ hết cỡ —
     thà cắt cụt còn hơn để nhãn các đời chồng lên nhau. */
  html.mang-rieng .gen-rail-i{
    left:0;width:22px;justify-content:center;text-shadow:none;overflow:hidden;
    writing-mode:vertical-rl;text-orientation:mixed;font-size:12.5px;letter-spacing:.06em;
  }
  html.mang-rieng .gen-rail-i::after{display:none}
  /* máng đã ra ngoài .canvas nên luật `.canvas.la-thutle #genRail` không với tới */
  .la-thutle-app #genRail{display:none}
}
@media (max-width:560px){
  .gen-grid{grid-template-columns:1fr}
  .stat-grid{grid-template-columns:1fr 1fr}
  .brand-title{font-size:14px}
  /* Hai ô cạnh nhau trên màn 375px chỉ còn 150px mỗi ô: tên người xuống ba
     dòng, danh sách chọn người bóp lại không đọc nổi. Dồn về một cột. */
  .row2,.row3{grid-template-columns:1fr}
  .seg.ngang{flex-direction:column}
  /* Nhãn bộ lọc thống kê chiếm 86px thì hàng chip "Đời" còn chưa tới 240px,
     tám con số xuống bốn dòng. Cho nhãn lên trên, chip ăn hết bề ngang. */
  .tk-hang{flex-direction:column;gap:4px;padding:8px 0}
  .tk-nhan{width:auto;padding-top:0}
  .bar-row{grid-template-columns:96px 1fr 54px;gap:8px}
}

/* ---------------------------------------------- ĐIỆN THOẠI NẰM NGANG
   Nằm ngang thì thứ quý nhất là chiều cao. Tấm trượt lên từ đáy sẽ nuốt gần
   hết màn, nên cho chúng trượt vào từ cạnh bên; thanh điều hướng dưới cũng
   dẹp lại, chữ nằm cạnh biểu tượng thay vì xuống dòng. */
@media (max-height:560px) and (min-width:561px) and (max-width:1180px){
  /* nằm ngang thì chiều cao là thứ quý nhất — bản đồ dẹp lại còn hơn nửa */
  :root{--topbar-h:48px; --bando-h:122px}
  .brand-mark{width:30px;height:30px;font-size:15px}
  .sidebar{
    top:0;bottom:0;left:0;right:auto;height:100%;max-height:none;
    width:min(340px,58vw);
    border-top:none;border-right:1px solid var(--line);
    border-radius:0 var(--r-xl) var(--r-xl) 0;
    transform:translateX(-102%);
  }
  .sidebar.on{transform:none}
  .side-body{padding:10px 14px calc(16px + env(safe-area-inset-bottom)) calc(14px + env(safe-area-inset-left))}
  .drawer{
    top:0;height:100%;width:min(430px,60vw);max-width:none;
    border-radius:var(--r-xl) 0 0 var(--r-xl);
    transform:translateX(102%);
  }
  .drawer.on{transform:none}
  /* Thanh nắm dựng đứng ở cạnh trong — hướng nắm chỉ luôn hướng vuốt để đóng */
  .sheet-handle{position:absolute;top:50%;width:5px;height:46px;margin:0;transform:translateY(-50%);z-index:3}
  .drawer .sheet-handle{left:8px}
  .sidebar .sheet-handle{right:8px}
  /* Thanh cuộn vẽ sẵn của trình duyệt đứng đúng chỗ thanh nắm, hai vạch dọc
     cạnh nhau trông như một. Màn cảm ứng vốn không cần thanh cuộn cố định. */
  .side-body,.drawer-b{scrollbar-width:none}
  .side-body::-webkit-scrollbar,.drawer-b::-webkit-scrollbar{display:none}
  .side-body{padding-right:24px}
  .sheet-h{padding:10px 12px 10px calc(16px + env(safe-area-inset-left))}
  /* Tấm chi tiết nằm sát mép phải, nơi máy xoay ngang hay có tai thỏ hoặc
     vạch cảm ứng — chừa thêm chỗ để chữ không chui xuống dưới chúng. */
  .drawer-h{padding:12px calc(16px + env(safe-area-inset-right)) 12px 26px}
  .drawer-b{padding:14px calc(16px + env(safe-area-inset-right)) 14px 26px}
  .drawer-f{padding:8px calc(16px + env(safe-area-inset-right)) calc(8px + env(safe-area-inset-bottom))}
  .bottomnav{height:calc(46px + env(safe-area-inset-bottom))}
  .bn{flex-direction:row;gap:7px;padding-top:0;font-size:12px}
  .bn svg{width:19px;height:19px}
  .main{padding-bottom:calc(46px + env(safe-area-inset-bottom))}
  /* Hai dải neo dẹp lại: nằm ngang thì mỗi pixel chiều cao đều quý. */
  .cay-trangthai{height:30px;padding:0 calc(12px + env(safe-area-inset-right)) 0 calc(12px + env(safe-area-inset-left))}
  .canvas{top:30px;bottom:42px}
  .canvas.co-bando{bottom:calc(42px + var(--bando-h) + env(safe-area-inset-bottom))}
  .canvas-tools{height:42px;padding:0 calc(10px + env(safe-area-inset-right)) 0 calc(10px + env(safe-area-inset-left))}
  .canvas-tools .icon-btn{height:32px}
  html.mang-rieng #genRail{top:30px;bottom:42px}
  html.mang-rieng .canvas.co-bando ~ #genRail{bottom:calc(42px + var(--bando-h) + env(safe-area-inset-bottom))}
  .panel.flat{padding:14px calc(16px + env(safe-area-inset-right)) 30px calc(16px + env(safe-area-inset-left))}
  .modal-box{
    left:50%;right:auto;top:50%;bottom:auto;transform:translate(-50%,-50%);
    width:min(680px,90vw);max-height:92vh;border-radius:var(--r-l);border-bottom:1px solid var(--line);
  }
  .modal-box .sheet-handle{display:none}
  .modal-h{padding:12px 14px 12px 18px}
  .modal-b{padding:14px 18px}
}
@media print{
  .topbar,.tabs,.sidebar,.bottomnav,.canvas-tools,.canvas-info,.cay-trangthai,.drawer,.scrim,.legend,
  #banDo,.tl-dau{display:none!important}
  .canvas{position:static;overflow:visible;background:none;bottom:auto}
  /* bản thụt lề in ra thành một bản phả ký liền mạch, không cắt ngang tên ai */
  #thutLe{position:static;overflow:visible;height:auto}
  .tl-dong{break-inside:avoid}
  body{background:#fff}
}
.boot-err{position:fixed;left:10px;right:10px;top:10px;z-index:9999;background:#A6321F;color:#fff;
  padding:11px 14px;border-radius:11px;font-size:13px;line-height:1.5;display:none;
  box-shadow:0 8px 28px rgba(0,0,0,.3);word-break:break-word}
.boot-err b{display:block;margin-bottom:3px}
#booting{position:absolute;left:50%;top:38%;transform:translate(-50%,-50%);text-align:center;
  color:var(--ink-3);font-size:14px;line-height:1.7;width:min(420px,88vw)}
.hide{display:none!important}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.toast{
  position:fixed;left:50%;bottom:26px;transform:translate(-50%,16px);z-index:200;
  background:var(--ink);color:var(--paper);padding:10px 18px;border-radius:999px;font-size:13px;
  box-shadow:var(--shadow-3);opacity:0;pointer-events:none;transition:.22s;max-width:90vw;text-align:center;
}
.toast.on{opacity:1;transform:translate(-50%,0)}
@media (max-width:900px), (max-height:560px) and (max-width:1180px){
  .toast{bottom:calc(74px + env(safe-area-inset-bottom))}
}
@media (max-height:560px) and (min-width:561px) and (max-width:1180px){
  .toast{bottom:calc(58px + env(safe-area-inset-bottom));font-size:12.5px;padding:8px 16px}
}
