Written by

in

<!DOCTYPE html>
<html lang="hi">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>मीणा समाज वंश-वृक्ष</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hind:wght@400;600&family=Yatra+One&display=swap">
<style>
:root{--bg:#E8EEE5;--panel:#F6F9F3;--ink:#1D2A22;--mute:#51604F;--line:#BCC9B8;--leafink:#fff;--sky1:#FBF3D2;--sky2:#CDE2D2;--b0:#3B4A9C;--b1:#A35F00;--b2:#B33A68;--b3:#2E7D4F;--btn:#1D2A22;--btnink:#F6F9F3;
box-sizing:border-box;padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#101A14;--panel:#18251D;--ink:#E6EEE3;--mute:#A3B2A0;--line:#2E4034;--leafink:#10190F;--sky1:#2B3F32;--sky2:#0F1913;--b0:#8E9BEA;--b1:#E3A64A;--b2:#E37AA3;--b3:#6CC18E;--btn:#E6EEE3;--btnink:#101A14}}
:root[data-theme="dark"]{--bg:#101A14;--panel:#18251D;--ink:#E6EEE3;--mute:#A3B2A0;--line:#2E4034;--leafink:#10190F;--sky1:#2B3F32;--sky2:#0F1913;--b0:#8E9BEA;--b1:#E3A64A;--b2:#E37AA3;--b3:#6CC18E;--btn:#E6EEE3;--btnink:#101A14}
html{scroll-padding-top:env(safe-area-inset-top,0px)}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font:400 17px/1.65 Hind,"Noto Sans Devanagari",sans-serif}
header{max-width:1180px;margin:0 auto;padding:26px 20px 6px}
h1{font:400 clamp(1.9rem,5vw,3rem)/1.2 "Yatra One",Hind,serif;margin:0 0 6px}
header p{margin:0;color:var(--mute);max-width:60ch}
#back{display:inline-block;margin-bottom:8px;color:var(--ink);font-weight:600}
.stats{display:flex;gap:22px;margin-top:12px;font-weight:600}
.wrap{max-width:1180px;margin:0 auto;padding:12px 20px 40px;display:grid;gap:20px}
@media(min-width:960px){.wrap{grid-template-columns:1.55fr 1fr;align-items:start}}
.card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px}
.stage{perspective:1000px;border-radius:12px;background:radial-gradient(ellipse at 50% 18%,var(--sky1),var(--sky2) 75%);overflow:hidden}
#tree{width:100%;height:auto;display:block;transition:transform .25s ease-out;transform-origin:50% 75%}
.lf{cursor:pointer}.lp{stroke:none;stroke-width:3}.lf:focus-visible .lp{stroke:var(--ink)}
.bl{cursor:pointer}.bl:hover .pill,.bl:focus-visible .pill{filter:brightness(1.2);stroke:var(--ink);stroke-width:2}.bl:focus{outline:none}
.crown{transform-origin:400px 428px;animation:cs 6s ease-in-out infinite alternate}
@keyframes cs{from{transform:rotate(-.8deg)}to{transform:rotate(.8deg)}}
.sw{animation:sw 4.5s ease-in-out infinite alternate}
@keyframes sw{from{transform:rotate(-4deg)}to{transform:rotate(4deg)}}
.grow,.sw{transform-box:fill-box;transform-origin:center}
.grow{animation:pop .8s cubic-bezier(.2,.9,.3,1.3) both;animation-delay:var(--d,0s)}
@keyframes pop{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}
.pl circle{fill:var(--b1);opacity:0;animation:rise 9s linear infinite}
@keyframes rise{0%{transform:translateY(0);opacity:0}15%{opacity:.75}100%{transform:translateY(-230px);opacity:0}}
@media(prefers-reduced-motion:reduce){.grow,.sw,.crown,.pl circle{animation:none}.pl circle{opacity:.5}}
#detail{margin-top:12px;min-height:3em}
#detail input{margin:8px 0}
.tw{overflow-x:auto;border:1px solid var(--line);border-radius:10px}
table.dt{width:100%;border-collapse:collapse;font-size:.95rem;min-width:680px}
table.dt th{text-align:left;font-weight:600;background:var(--hc,var(--ink));color:var(--leafink);padding:10px 12px;white-space:nowrap}
table.dt td{padding:9px 12px;border-bottom:1px solid var(--line);vertical-align:top}
table.dt tbody tr:nth-child(even){background:color-mix(in srgb,var(--hc) 9%,transparent)}
table.dt td.na{color:var(--mute)}table.dt td.nm{font-weight:600;white-space:nowrap}
table.dt a{color:var(--hc);font-weight:600}
.mb{display:flex;flex-wrap:wrap;gap:4px}.mb span{border:1px solid var(--hc);border-radius:999px;padding:0 9px;font-size:.85rem;white-space:nowrap}
.kd{display:inline-block;padding:2px 12px;border-radius:999px;border:1px solid var(--line);background:var(--bg);font-weight:600;font-size:.9rem}
#detail h2,.card h2{font:400 1.25rem/1.3 "Yatra One",Hind,serif;margin:0 0 8px}
.fam{border-top:1px solid var(--line);padding:8px 0}.fam small{display:block;color:var(--mute)}
label{display:block;font-weight:600;margin:12px 0 4px}
input,select,textarea{width:100%;font:inherit;color:var(--ink);background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:9px 10px}
input:focus-visible,select:focus-visible,textarea:focus-visible,button:focus-visible,#back:focus-visible{outline:3px solid var(--b0);outline-offset:1px}
.row{display:grid;grid-template-columns:9em 1fr auto;gap:8px;margin-bottom:8px}
button{font:inherit;font-weight:600;border:0;border-radius:8px;padding:10px 16px;cursor:pointer}
.main{background:var(--btn);color:var(--btnink);width:100%;margin-top:16px;font-size:1.05rem}
.ghost{background:transparent;color:var(--ink);border:1px dashed var(--mute)}
.x{background:transparent;color:var(--mute);padding:6px 10px}
.note{color:var(--mute);font-size:.9rem;margin:10px 0 0}
#status{min-height:1.5em;font-weight:600;margin:8px 0 0}
</style>
</head>
<body>
<header>
<a id="back" href="#" hidden>पूरे मीणा समाज पर लौटें</a>
<h1 id="h1">मीणा समाज वंश-वृक्ष</h1>
<p id="sub"></p>
<div class="stats" aria-live="polite"><span>परिवार: <span id="nf">0</span></span><span>गोत्र: <span id="ng">0</span></span></div>
</header>
<div class="wrap">
<section class="card" aria-label="वंश-वृक्ष">
<div class="stage" id="stage"><svg id="tree" viewBox="0 0 800 660" role="group" aria-label="वंश-वृक्ष"></svg></div>
<div id="detail"></div>
</section>
<section class="card" aria-label="परिवार जोड़ें">
<h2>अपना परिवार जोड़ें</h2>
<form id="f" autocomplete="off">
<label for="nm">आपका नाम</label><input id="nm" maxlength="60" required>
<label for="br">शाखा</label>
<select id="br" required><option value="">चुनें</option><option value="0">चौकीदार मीणा</option><option value="1">ज़मींदार मीणा</option><option value="2">उचला मीणा</option><option value="3">निचला वासी मीणा</option></select>
<label for="gs">गोत्र</label><select id="gs" required></select>
<input id="go" maxlength="40" list="gl" placeholder="अपना गोत्र लिखें" hidden aria-label="अपना गोत्र लिखें"><datalist id="gl"></datalist>
<label for="vl">गाँव (वैकल्पिक)</label><input id="vl" maxlength="60">
<label for="ut">आपके गोत्र की उत्पत्ति कहाँ से हुई (वैकल्पिक)</label><textarea id="ut" maxlength="400" rows="3"></textarea>
<label for="kd">आपकी कुलदेवी, अगर पता हो (वैकल्पिक)</label><input id="kd" maxlength="60">
<label>परिवार के सदस्य (वैकल्पिक)</label>
<div id="mem"></div>
<button type="button" class="ghost" id="add">सदस्य जोड़ें</button>
<button class="main" type="submit">मीणा समाज में जोड़ें</button>
<p id="status" role="status"></p>
</form>
<p class="note" id="mode"></p>
<p class="note">यह जानकारी परिवारों द्वारा स्वयं दी गई है, यह कोई सरकारी या प्रमाणित रिकॉर्ड नहीं है।</p>
</section>
</div>
<script>
const NS="http://www.w3.org/2000/svg",$=i=>document.getElementById(i),svg=$("tree");
const BR=[{n:"चौकीदार मीणा",s:"chaukidar",t:[140,300]},{n:"ज़मींदार मीणा",s:"zamindar",t:[290,205]},{n:"उचला मीणा",s:"uchla",t:[510,205]},{n:"निचला वासी मीणा",s:"nichla-vasi",t:[660,300]}];
const SEED=["मीमरोट"],REL=["परदादा","परदादी","दादा","दादी","पिताजी","माताजी","चाचा/ताऊ","चाची/ताई","बुआ","भाई","भाभी","बहन","बहनोई","पत्नी","पति","बेटा","बहू","बेटी","पोता","पोती"],LS="meena-vriksh-v1";
let shared=[],mine=[],db=null,sel=null,view=-1,fr=null;const seen=new Set();
try{mine=JSON.parse(localStorage.getItem(LS)||"[]")}catch(e){}
const norm=s=>String(s||"").normalize("NFC").replace(/\s+/g," ").trim();
function el(t,a,k,sv){const e=sv?document.createElementNS(NS,t):document.createElement(t);for(const x in a||{}){x==="text"?e.textContent=a[x]:e.setAttribute(x,a[x])}(k||[]).forEach(c=>e.append(c));return e}
const S=(t,a,k)=>el(t,a,k,1);
const all=()=>shared.concat(mine).filter(r=>r&&r.name&&r.gotra&&BR[r.branch]);
function groups(){const m=new Map();all().forEach(r=>{const k=r.branch+"|"+r.gotra;if(!m.has(k))m.set(k,{b:+r.branch,g:r.gotra,n:0,k});m.get(k).n++});return[...m.values()].sort((a,b)=>b.n-a.n||a.g.localeCompare(b.g,"hi"))}
const DEFS=`<defs><linearGradient id="bark" x1="0" x2="1"><stop offset="0" stop-color="#3a281a"/><stop offset=".42" stop-color="#8a6240"/><stop offset=".58" stop-color="#a97e55"/><stop offset="1" stop-color="#2f2017"/></linearGradient><radialGradient id="gnd"><stop offset="0" stop-color="#000" stop-opacity=".38"/><stop offset="1" stop-color="#000" stop-opacity="0"/></radialGradient><linearGradient id="hi" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#fff" stop-opacity=".5"/><stop offset=".6" stop-color="#fff" stop-opacity="0"/></linearGradient><filter id="ds" x="-20%" y="-30%" width="140%" height="170%"><feDropShadow dx="0" dy="3" stdDeviation="2.5" flood-opacity=".35"/></filter></defs><g class="pl">${[...Array(9)].map((_,i)=>`<circle cx="${70+i*85}" cy="${480+(i*53%100)}" r="${2+i%3}" style="animation-delay:-${i*1.1}s"/>`).join("")}</g>`;
function base(label){svg.setAttribute("viewBox","0 0 800 660");svg.replaceChildren();svg.insertAdjacentHTML("beforeend",DEFS);
 const st={fill:"none","stroke-linecap":"round"};
 svg.append(S("ellipse",{cx:400,cy:600,rx:270,ry:34,fill:"url(#gnd)"}));
 [[215,636],[325,652],[475,652],[585,636]].forEach(([x,y])=>{const d=`M400 560 C400 610 ${x} 604 ${x} ${y}`;svg.append(S("path",{d,...st,stroke:"#4a3322","stroke-width":9}),S("path",{d,...st,stroke:"#b88f63","stroke-width":3,opacity:.5,transform:"translate(-2 -1)"}))});
 svg.append(S("path",{d:"M312 606 C346 596 364 566 366 524 C368 486 358 452 364 412 C380 398 420 398 436 412 C442 452 432 486 434 524 C436 566 454 596 488 606 Z",fill:"url(#bark)"}));
 [[372,420,350,600],[386,410,380,560],[400,405,402,540],[414,408,422,570],[428,420,452,600],[379,440,372,520],[421,450,430,530]].forEach(([a,b,c,d],i)=>svg.append(S("path",{d:`M${a} ${b} C${a+(i%2?-7:7)} ${b+(d-b)*.35} ${c+(i%2?6:-6)} ${b+(d-b)*.7} ${c} ${d}`,...st,stroke:i%2?"#1f140c":"#c79d70","stroke-width":i%2?2.4:1.6,opacity:.32})));[[388,500,7,11],[415,455,6,9],[395,555,5,8]].forEach(([x,y,rx,ry])=>svg.append(S("ellipse",{cx:x,cy:y,rx,ry,fill:"#2a1c12",opacity:.45}),S("ellipse",{cx:x-1,cy:y-1,rx:rx*.55,ry:ry*.55,fill:"#6b4a30",opacity:.7})));
 const w=label.length*10+40;
 svg.append(S("rect",{x:400-w/2,y:612,width:w,height:34,rx:8,fill:"#F1E4C8",stroke:"#6b4a30","stroke-width":2}),S("text",{text:label,x:400,y:629,"text-anchor":"middle",dy:".35em",style:"font:400 16px 'Yatra One',Hind,serif;fill:#3a2a1a"}));
 const cr=S("g",{class:"crown"});svg.append(cr);return cr}
const qp=(t,a,c,b)=>(1-t)*(1-t)*a+2*(1-t)*t*c+t*t*b;
function taper(par,cx,cy,tx,ty,w0,w1,fill,op,ox,oy){const P=[],Q=[];for(let i=0;i<=14;i++){const t=i/14,x=qp(t,400,cx,tx),y=qp(t,428,cy,ty),dx=2*(1-t)*(cx-400)+2*t*(tx-cx),dy=2*(1-t)*(cy-428)+2*t*(ty-cy),l=Math.hypot(dx,dy)||1,w=(w0+(w1-w0)*t)/2;P.push((x-dy/l*w+ox).toFixed(1)+" "+(y+dx/l*w+oy).toFixed(1));Q.push((x+dy/l*w+ox).toFixed(1)+" "+(y-dx/l*w+oy).toFixed(1))}par.append(S("path",{d:"M"+P.join("L")+"L"+Q.reverse().join("L")+"Z",fill,opacity:op}))}
function limb(par,cx,cy,tx,ty,w){taper(par,cx,cy,tx,ty,w,w*.2,"#5b3f29",1,0,0);taper(par,cx,cy,tx,ty,w*.4,w*.06,"#b88f63",.55,-w*.1,-w*.08)}
function leaf(par,o){const d=`M${-o.rx} 0Q0 ${-o.h} ${o.rx} 0Q0 ${o.h} ${-o.rx} 0Z`,tr=`rotate(${o.rot})`;
 const k=[S("path",{class:"lp",d,transform:tr,style:`fill:var(--b${o.b});${o.bud?"opacity:.4":""}`}),S("path",{d,transform:tr,fill:"url(#hi)","pointer-events":"none"})];
 k.push(o.label?S("text",{text:o.label,"text-anchor":"middle",dy:".35em",style:"font:600 12px Hind,sans-serif;fill:var(--leafink);pointer-events:none"}):S("path",{d:`M${-o.rx+4} 0L${o.rx-4} 0`,transform:tr,stroke:"#fff","stroke-opacity":.35,fill:"none","pointer-events":"none"}));
 const g=S("g",{transform:`translate(${o.x} ${o.y})`,filter:"url(#ds)"},[S("g",{class:seen.has(o.k)?"":"grow",style:`--d:${(o.i*.05).toFixed(2)}s`},[S("g",{class:"sw",style:`animation-delay:-${(o.i*.9)%5}s`},k)])]);
 seen.add(o.k);par.append(g);return g}
function drawMain(){const cr=base("मीणा समाज की उत्पत्ति"),gr=groups();
 BR.forEach((b,i)=>{const L=gr.filter(o=>o.b===i),fs=L.reduce((a,o)=>a+o.n,0),[tx,ty]=b.t,cx=400+(tx-400)*.3,cy=ty+(428-ty)*.55,
  g=S("g",{class:"bl",tabindex:0,role:"link","aria-label":`${b.n}: शाखा खोलें`});
  limb(g,cx,cy,tx,ty,34);
  g.append(S("circle",{cx:tx,cy:ty-24,r:82,style:`fill:var(--b${i});opacity:.13`}),S("circle",{cx:tx,cy:ty-24,r:52,style:`fill:var(--b${i});opacity:.13`}));const pos=(j,s)=>{const a=j*2.4,r=s*Math.sqrt(j);return[Math.min(765,Math.max(35,tx+r*Math.cos(a)*1.35)),Math.max(30,ty-24+r*Math.sin(a)*.85)]};for(let j=0;j<18;j++){const[x,y]=pos(j,13);leaf(g,{x,y,rx:12,h:7.5,rot:(j*53%80)-40,b:i,k:`f${i}-${j}`,i:j})}
  L.slice(0,12).forEach((o,j)=>{const[x,y]=pos(j,18);leaf(g,{x,y,rx:17,h:11,rot:(j*47%60)-30,b:i,k:`m${i}-${j}`,i:j+18})});
  const px=tx,py=ty-122,w=Math.max(100,b.n.length*9+24);
  g.append(S("rect",{class:"pill",x:px-w/2,y:py-21,width:w,height:42,rx:21,style:`fill:var(--b${i})`}),S("text",{text:b.n,x:px,y:py-3,"text-anchor":"middle",style:"font:600 14px Hind,sans-serif;fill:var(--leafink);pointer-events:none"}),S("text",{text:`${L.length} गोत्र, ${fs} परिवार`,x:px,y:py+12,"text-anchor":"middle",style:"font:400 11px Hind,sans-serif;fill:var(--leafink);pointer-events:none"}));
  g.onclick=()=>{location.hash=b.s};g.onkeydown=e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();g.onclick()}};
  cr.append(g)})}
function drawSub(){const cr=base(BR[view].n),gr=groups().filter(o=>o.b===view),n=gr.length,B=Math.max(3,Math.min(7,Math.ceil(n/4))),L=Array.from({length:B},()=>[]);
 gr.forEach((o,i)=>L[i%B].push(o));
 L.forEach((list,j)=>{const th=(-70+140*j/(B-1))*Math.PI/180,R=230+(j%2)*70,tx=400+R*Math.sin(th)*1.3,ty=Math.max(80,410-R*Math.cos(th)*.95),cx=400+(tx-400)*.25,cy=ty+(428-ty)*.6;
  limb(cr,cx,cy,tx,ty,28);
  list.forEach((o,m)=>{const t=1-(m%6)*.15,px=qp(t,400,cx,tx),py=qp(t,428,cy,ty),dx=2*(1-t)*(cx-400)+2*t*(tx-cx),dy=2*(1-t)*(cy-428)+2*t*(ty-cy),ln=Math.hypot(dx,dy)||1,off=(24+26*Math.floor(m/6))*(m%2?1:-1);
   const g=leaf(cr,{x:Math.min(745,Math.max(55,px-dy/ln*off)),y:Math.min(430,Math.max(45,py+dx/ln*off)),rx:Math.max(26,o.g.length*4.8+14),h:15+Math.min(8,o.n),rot:(m*37%24)-12,b:o.b,label:o.g,k:o.k,i:j+m*B});
   g.dataset.k=o.k;g.setAttribute("class","lf");g.setAttribute("tabindex",0);g.setAttribute("role","button");g.setAttribute("aria-label",`${o.g}, ${o.n} परिवार`);
   g.onclick=()=>{sel=o.k;mark();detail()};g.onkeydown=e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();g.onclick()}}})});
 mark()}
const TI=[{p:["परदादा","परदादी"],e:[]},{p:["दादा","दादी"],e:[]},{p:["पिताजी","माताजी"],e:["चाचा/ताऊ","चाची/ताई","बुआ"]},{p:["आप","पत्नी|पति"],e:["भाई","भाभी","बहन","बहनोई"]},{p:null,e:["बेटा","बहू","बेटी"]},{p:null,e:["पोता","पोती"]}];
const fid=r=>String(r.id||"l"+r.at).replace(/[^A-Za-z0-9]/g,"");
function drawFam(){const r=fr,cr=base(`${r.name} का परिवार`),N={"आप":[r.name]};
 (r.members||[]).forEach(m=>{(N[m.rel]=N[m.rel]||[]).push(m.name)});
 const get=k=>k.split("|").flatMap(x=>N[x]||[]),lab=k=>k.replace("|","/");
 const tiers=TI.map(t=>{const L=t.p?get(t.p[0]):[],R=t.p?get(t.p[1]):[],ex=[];
  if(t.p){L.slice(1).forEach(n=>ex.push([n,lab(t.p[0])]));R.slice(1).forEach(n=>ex.push([n,lab(t.p[1])]))}
  t.e.forEach(k=>(N[k]||[]).forEach(n=>ex.push([n,k])));
  return{p:!!t.p,l:L[0]&&[L[0],lab(t.p[0])],r:R[0]&&[R[0],lab(t.p[1])],ex}}).filter(t=>t.l||t.r||t.ex.length),n=tiers.length,Y=k=>385-115*k,top=Math.min(0,Y(n-1)-110);
 svg.setAttribute("viewBox",`0 ${top} 800 ${660-top}`);
 const T=Y(n-1)-10,tw=(x1,y1,cx,cy,x2,y2)=>{const d=`M${x1} ${y1}Q${cx} ${cy} ${x2} ${y2}`,s={d,fill:"none","stroke-linecap":"round"};cr.append(S("path",{...s,stroke:"#5b3f29","stroke-width":13}),S("path",{...s,stroke:"#b88f63","stroke-width":4,opacity:.5,transform:"translate(-1 -2)"}))};
 cr.append(S("path",{d:`M364 420Q382 ${(420+T)/2} 390 ${T}L410 ${T}Q418 ${(420+T)/2} 436 420Z`,fill:"url(#bark)"}));
 let c=0;const node=(x,y,[nm,rel],k)=>{const g=leaf(cr,{x,y,rx:Math.max(30,nm.length*4.8+14),h:15,rot:(c*17%16)-8,b:+r.branch,label:nm,k:`n${k}-${c}`,i:k+c++});if(rel==="आप")g.querySelector(".lp").style.stroke="var(--ink)";if(rel)cr.append(S("text",{text:rel,x,y:y+28,"text-anchor":"middle",style:"font:400 11px Hind,sans-serif;fill:var(--ink)"}))};
 tiers.forEach((t,k)=>{const y=Y(k);cr.append(S("ellipse",{cx:400,cy:y+16,rx:15,ry:11,fill:"#5b3f29"}));
  if(t.l){tw(400,y+16,330,y+22,275,y-24);node(275,y-24,t.l,k)}
  if(t.r){tw(400,y+16,470,y+22,525,y-24);node(525,y-24,t.r,k)}
  t.ex.forEach((e,j)=>{const m=t.ex.length,x=t.p?400+(j%2?1:-1)*300:400+(j-(m-1)/2)*Math.min(150,620/m),yy=t.p?y-8+Math.floor(j/2)*40:y-30+(j%2?-26:10),xx=Math.min(745,Math.max(55,x));tw(400,y+22,(400+xx)/2,y+32,xx,yy);node(xx,yy,e,k)})})}
function famTable(fs,b){const wrap=el("div"),q=el("input",{type:"search",placeholder:"नाम या गाँव से खोजें","aria-label":"खोजें"}),box=el("div",{class:"tw",tabindex:0,role:"region","aria-label":"परिवारों की तालिका"}),note=el("p",{class:"note"}),H=["क्रम","परिवार का नाम","गाँव","कुलदेवी","गोत्र की उत्पत्ति","परिवार के सदस्य","वंश-वृक्ष"],td=(v,c)=>el("td",{class:v?c||"":"na",text:v||"—"});
 function fill(){const s=norm(q.value).toLowerCase(),rows=fs.filter(r=>!s||(r.name+" "+(r.village||"")).toLowerCase().includes(s));
  const tb=el("tbody",{},rows.slice(0,100).map((r,i)=>{const m=el("td",{},[el("div",{class:"mb"},(r.members||[]).map(x=>el("span",{text:`${x.rel}: ${x.name}`})))]);if(!(r.members||[]).length){m.className="na";m.textContent="—"}
   return el("tr",{},[td(String(i+1)),td(r.name,"nm"),td(r.village),td(r.kuldevi),td(r.origin),m,el("td",{},[el("a",{href:"#f-"+fid(r),text:"खोलें"})])])}));
  box.replaceChildren(el("table",{class:"dt",style:`--hc:var(--b${b})`},[el("thead",{},[el("tr",{},H.map(h=>el("th",{scope:"col",text:h})))]),tb]));
  note.textContent=rows.length>100?`पहले 100 दिख रहे हैं, कुल ${rows.length}। खोज से छाँटिए।`:`कुल ${rows.length}`}
 q.oninput=fill;wrap.append(q,box,note);fill();return wrap}
function mark(){svg.querySelectorAll("[data-k]").forEach(g=>g.querySelector(".lp").style.stroke=g.dataset.k===sel?"var(--ink)":"none")}
function detail(){const d=$("detail");d.replaceChildren();
 if(fr){const rows=[["गाँव",fr.village],["कुलदेवी",fr.kuldevi],["गोत्र की उत्पत्ति",fr.origin]].filter(x=>x[1]);d.append(el("h2",{text:`${fr.gotra} गोत्र`}),...rows.map(([k,v])=>el("p",{class:"note",text:`${k}: ${v}`})));return}
 if(!sel){d.append(el("p",{class:"note",text:view<0?"किसी शाखा के नाम पर क्लिक करें, मीणा समाज की वह शाखा और उसके गोत्र खुल जाएँगे।":groups().some(o=>o.b===view)?"किसी पत्ते पर क्लिक करें, उस गोत्र के परिवार यहाँ दिखेंगे।":"इस शाखा में अभी कोई गोत्र नहीं है। फॉर्म भरकर पहला पत्ता उगाइए।"}));return}
 const[b,...gp]=sel.split("|"),g=gp.join("|"),fs=all().filter(r=>r.branch==b&&r.gotra===g);
 d.append(el("h2",{text:`${g} (${BR[b].n}): ${fs.length} परिवार`}));
 const kd=[...new Set(fs.map(r=>r.kuldevi).filter(Boolean))];if(kd.length)d.append(el("span",{class:"kd",text:"कुलदेवी: "+kd.join("، ")}));
 d.append(famTable(fs,+b));
 }
function opts(){const s=$("gs"),v=s.value,set=[...new Set(SEED.concat(all().map(r=>r.gotra)))].sort((a,b)=>a.localeCompare(b,"hi"));
 s.replaceChildren(el("option",{value:"",text:"चुनें"}),...set.map(g=>el("option",{value:g,text:g})),el("option",{value:"__o",text:"अन्य (खुद लिखें)"}));
 s.value=set.includes(v)||v==="__o"?v:"";$("gl").replaceChildren(...set.map(g=>el("option",{value:g})))}
function render(){const hh=location.hash.slice(1);if(hh.startsWith("f-")&&!fr&&all().some(r=>fid(r)===hh.slice(2)))return route();const d=view<0?all():all().filter(r=>r.branch==view);
 $("nf").textContent=d.length;$("ng").textContent=new Set(d.map(r=>r.branch+"|"+r.gotra)).size;
 fr?drawFam():view<0?drawMain():drawSub();detail();opts()}
function route(){const h=location.hash.slice(1);fr=h.startsWith("f-")?all().find(r=>fid(r)===h.slice(2))||null:null;view=fr?+fr.branch:BR.findIndex(b=>b.s===h);sel=null;seen.clear();
 const t=fr?`${fr.name} का परिवार`:view<0?"मीणा समाज वंश-वृक्ष":BR[view].n;$("h1").textContent=t;document.title=t;
 $("sub").textContent=view<0?"अपना परिवार जोड़िए और मीणा समाज में अपने गोत्र का पत्ता उगता देखिए। यहाँ कोई रोक-टोक नहीं है, जो आप लिखेंगे वही दर्ज होगा।":"इस शाखा की जड़ें यहीं से फूटती हैं और हर पत्ता एक गोत्र है।";
 $("back").hidden=view<0;$("back").href="#"+(fr?BR[view].s:"");$("back").textContent=fr?"इस शाखा के गोत्रों पर लौटें":"पूरे मीणा समाज पर लौटें";if(fr)$("sub").textContent=`${BR[view].n}, ${fr.gotra} गोत्र${fr.village?", "+fr.village:""}`;if(view>=0)$("br").value=view;render();window.scrollTo(0,0)}
addEventListener("hashchange",route);
function row(){const r=el("div",{class:"row"},[el("select",{"aria-label":"रिश्ता"},REL.map(x=>el("option",{value:x,text:x}))),el("input",{maxlength:"60","aria-label":"सदस्य का नाम",placeholder:"नाम"}),el("button",{type:"button",class:"x",text:"हटाएँ"})]);r.lastChild.onclick=()=>r.remove();$("mem").append(r)}
$("add").onclick=row;
$("gs").onchange=()=>{const o=$("gs").value==="__o";$("go").hidden=!o;$("go").required=o;if(o)$("go").focus()};
$("f").onsubmit=async e=>{e.preventDefault();
 const g=$("gs").value==="__o"?norm($("go").value):$("gs").value,name=norm($("nm").value);
 if(!name||!g||$("br").value==="")return;
 const rec={name,branch:+$("br").value,gotra:g,village:norm($("vl").value),origin:norm($("ut").value),kuldevi:norm($("kd").value),at:Date.now(),members:[...$("mem").children].map(r=>({rel:r.firstChild.value,name:norm(r.children[1].value)})).filter(x=>x.name)};
 let ok=true;try{if(!db)throw 0;await db.collection("families").add(rec)}catch(x){ok=false;mine.push(rec);try{localStorage.setItem(LS,JSON.stringify(mine))}catch(y){}}
 sel=rec.branch+"|"+g;render();
 $("status").textContent=`${name} जी, आपका परिवार मीणा समाज के ${g} गोत्र में जुड़ गया`+(ok?"":" (सिर्फ़ आपके ब्राउज़र में)");
 $("f").reset();$("mem").replaceChildren();$("go").hidden=true;$("go").required=false;if(view>=0)$("br").value=view;opts()};
const stg=$("stage");
if(!matchMedia("(prefers-reduced-motion:reduce)").matches){stg.onpointermove=e=>{const r=stg.getBoundingClientRect(),x=(e.clientX-r.left)/r.width-.5,y=(e.clientY-r.top)/r.height-.5;svg.style.transform=`rotateY(${x*10}deg) rotateX(${-y*6}deg)`};stg.onpointerleave=()=>{svg.style.transform=""}}
route();
(async()=>{try{db=window.claude?await claude.use("db"):null}catch(e){db=null}
 if(db){$("mode").textContent="यहाँ मीणा समाज के जो परिवार जुड़ते हैं, सबको दिखते हैं।";
  db.collection("families").onSnapshot(sn=>{shared=sn.docs.map(d=>({id:d.id,...d.data()}));render()},()=>{})}
 else $("mode").textContent="अभी यह पेज जानकारी सिर्फ़ आपके ब्राउज़र में सहेजता है, दूसरों को नहीं दिखेगी।"})();
</script>
</body>
</html>

Comments

One response to “”

  1. A WordPress Commenter Avatar

    Hi, this is a comment.
    To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
    Commenter avatars come from Gravatar.

Leave a Reply

Your email address will not be published. Required fields are marked *

More posts