PageSourceSearch

https://loothing.xyz/assets/RosterGuide-C3-id2yQ.js

js loothing.xyz collected 2026-10-02 02:13:52 UTC 79,894 bytes, 1 lines download raw bytes

1import{j as e,r as a}from"./react-vendor-BR2bEzcq.js";import{G as t}from"./GuideCallout-DdHDiUqN.js";import{G as s}from"./GuideDemoFrame-CPlrz0dx.js";import{d as r,g as l,a as i,c as o,b as n,M as c,e as d,f as m,h as x}from"./MobileDemo-Dezr2koG.js";import{G as h}from"./GuideLayout-BmQS_pv4.js";import{a as p,c as g}from"./upgradeGuideShared-FP4HrArE.js";import{E as u}from"./eye-tKxUxQQk.js";import{C as b}from"./circle-plus-oZUi8o53.js";import{U as y,R as v,ay as j,T as f,D as N,m as w,Q as S,M as k,v as C,a0 as D,i as T,A as M,S as P}from"./index-CpSDEIFT.js";import{C as L}from"./chart-column-DlZj1Pa2.js";import{A as H}from"./archive-in_8UCG_.js";import{S as R}from"./shield-check-Bgl2CPxg.js";import{T as A}from"./trophy-B30ncVk3.js";import{S as E}from"./sparkles-BkZALuyM.js";import{S as F}from"./Guide-BEVoqyzV.js";import{H as V}from"./heart-Df9HZ-_i.js";import{U as $}from"./user-x-BK2uieEl.js";import{S as G}from"./shuffle-DPacWZQ3.js";import{C as W}from"./circle-check-REcAsX_P.js";import{F as I}from"./flame-CoLFKpzk.js";import{T as q}from"./trash-2-CefGdBnP.js";import{B as O}from"./box-Dw6AFY8G.js";import{L as B}from"./lock-s08R_Cx5.js";import"./GuideStep-w0KIOkRN.js";import"./share-2-BlQHCczL.js";import"./axios-ClGXtqae.js";import"./layout-grid-BTk_CvLf.js";import"./building-2-BhdniG9k.js";import"./upload-Bfj5LvPA.js";import"./hammer-CUtrhFi4.js";import"./calendar-OSP8Zfeh.js";import"./package-CwoWoNvZ.js";import"./user-CGSJLesu.js";import"./git-branch-B7yKhDpX.js";import"./message-square-CUDp72-o.js";import"./send-Oz9vOn7S.js";import"./bell-S7NzOLmU.js";import"./copy-8tRFsKvC.js";import"./pen-line-D_j69fhG.js";import"./type-B7YUSxPR.js";import"./layers-MVHMmIBS.js";import"./palette-BeobZT6s.js";import"./cpu-Cmd8LMsD.js";import"./image-DZCp_FKW.js";import"./wrench-D8nRrVN1.js";import"./brain-DjxFfTbU.js";import"./clock-7p0Hl2bb.js";import"./bot-Byfuftfk.js";import"./radio-TlwUtTDC.js";import"./user-check-CynCp8qd.js";import"./panels-top-left-DGVbvuPj.js";import"./funnel-DDgrh7CG.js";import"./wifi-DhHqG1lh.js";import"./award-VeMRr7dO.js";import"./flask-conical-B4JjR3ly.js";import"./database-fKN-p4vL.js";import"./shield-alert-gOWkfPRp.js";import"./vote-BSWsIZzN.js";import"./hash-IAqmTeC5.js";import"./arrow-left-BrJfR4cx.js";const U={Tank:"#3b82f6",Healer:"#22c55e",DPS:"#ef4444",Flex:"#a855f7"},z={Tank:S,Healer:V,DPS:k,Flex:G},K={Warrior:"#C79C6E",Paladin:"#F58CBA",Hunter:"#ABD473",Rogue:"#FFF569",Priest:"#FFFFFF","Death Knight":"#C41F3B",Shaman:"#0070DE",Mage:"#69CCF0",Warlock:"#9482C9",Monk:"#00FF96","Demon Hunter":"#A330C9",Druid:"#FF7D0A",Evoker:"#33937F"},Y=[{id:"1",name:"Main Roster",rosterType:"main",isDefault:!0,isActive:!0,seasonId:"mn-s1",archivedAt:null,memberCount:22,composition:{total:22,byRole:{Tank:2,Healer:4,DPS:14,Flex:2},averageItemLevel:271}},{id:"2",name:"Alt Roster",rosterType:"alt",isDefault:!1,isActive:!0,seasonId:"mn-s1",archivedAt:null,memberCount:15,composition:{total:15,byRole:{Tank:2,Healer:3,DPS:9,Flex:1},averageItemLevel:258}},{id:"3",name:"Trial Team",rosterType:"trial",isDefault:!1,isActive:!0,seasonId:"mn-s1",archivedAt:null,memberCount:6,composition:{total:6,byRole:{Tank:0,Healer:1,DPS:5,Flex:0},averageItemLevel:262}}],Q={id:"4",name:"Main Roster",rosterType:"main",isDefault:!1,isActive:!0,seasonId:"tww-s3",archivedAt:"2026-03-16T00:00:00Z",memberCount:20,composition:{total:20,byRole:{Tank:2,Healer:4,DPS:12,Flex:2},averageItemLevel:249}},X=[{id:"m1",role:"Tank",status:"active",assignedSpec:"Protection",primaryCharacter:{characterName:"Kragnok",class:"Warrior",spec:"Protection",server:"Illidan",itemLevel:275},playerAccount:{displayName:"Krag"}},{id:"m2",role:"Tank",status:"active",assignedSpec:"Vengeance",primaryCharacter:{characterName:"Vexmoon",class:"Demon Hunter",spec:"Vengeance",server:"Illidan",itemLevel:273},playerAccount:{displayName:"Vex"}},{id:"m3",role:"Healer",status:"active",assignedSpec:"Holy",primaryCharacter:{characterName:"Altheria",class:"Paladin",spec:"Holy",server:"Illidan",itemLevel:271},playerAccount:{displayName:"Alth"}},{id:"m4",role:"Healer",status:"active",assignedSpec:"Restoration",primaryCharacter:{characterName:"Leafwhisper",class:"Druid",spec:"Restoration",server:"Area 52",itemLevel:270},playerAccount:{displayName:"Leaf"}},{id:"m5",role:"Healer",status:"active",assignedSpec:"Preservation",primaryCharacter:{characterName:"Draconis",class:"Evoker",spec:"Preservation",server:"Illidan",itemLevel:268},playerAccount:{displayName:"Drac"}},{id:"m6",role:"Healer",status:"trial",assignedSpec:"Discipline",primaryCharacter:{characterName:"Lightweave",class:"Priest",spec:"Discipline",server:"Stormrage",itemLevel:265},playerAccount:{displayName:"Light"}},{id:"m7",role:"DPS",status:"active",assignedSpec:"Frost",primaryCharacter:{characterName:"Sylvara",class:"Mage",spec:"Frost",server:"Illidan",itemLevel:274},playerAccount:{displayName:"Sylv"}},{id:"m8",role:"DPS",status:"active",assignedSpec:"Affliction",primaryCharacter:{characterName:"Darkflame",class:"Warlock",spec:"Affliction",server:"Illidan",itemLevel:272},playerAccount:{displayName:"Dark"}},{id:"m9",role:"DPS",status:"active",assignedSpec:"Assassination",primaryCharacter:{characterName:"Shadowsong",class:"Rogue",spec:"Assassination",server:"Area 52",itemLevel:270},playerAccount:{displayName:"Shadow"}},{id:"m10",role:"DPS",status:"active",assignedSpec:"Beast Mastery",primaryCharacter:{characterName:"Hawkstrike",class:"Hunter",spec:"Beast Mastery",server:"Illidan",itemLevel:269},playerAccount:{displayName:"Hawk"}},{id:"m11",role:"Flex",status:"active",assignedSpec:"Windwalker",primaryCharacter:{characterName:"Zenkai",class:"Monk",spec:"Windwalker",server:"Illidan",itemLevel:267},playerAccount:{displayName:"Zen"}},{id:"m12",role:"DPS",status:"departed",assignedSpec:"Shadow",primaryCharacter:{characterName:"Voidshroud",class:"Priest",spec:"Shadow",server:"Illidan",itemLevel:263},playerAccount:{displayName:"Void"}}
1],Z=[{characterId:"c1",characterName:"Kragnok",class:"Warrior",server:"Illidan",role:"Tank",itemLevel:275,mythicPlusData:{rating:2680,weeklyRuns:8},greatVault:{totalSlots:9,maxPossibleSlots:9,categories:{mythicPlus:{slots:3},raid:{slots:3},world:{slots:3}}},tierSet:{equippedCount:4,slots:{HEAD:!0,SHOULDER:!0,CHEST:!0,HANDS:!0,LEGS:!1}},enchants:{count:8,missingSlots:[]},gems:{count:3,missingSlots:[]}},{characterId:"c2",characterName:"Altheria",class:"Paladin",server:"Illidan",role:"Healer",itemLevel:271,mythicPlusData:{rating:2450,weeklyRuns:6},greatVault:{totalSlots:7,maxPossibleSlots:9,categories:{mythicPlus:{slots:3},raid:{slots:2},world:{slots:2}}},tierSet:{equippedCount:3,slots:{HEAD:!0,SHOULDER:!0,CHEST:!0,HANDS:!1,LEGS:!1}},enchants:{count:5,missingSlots:["FEET"]},gems:{count:3,missingSlots:[]}},{characterId:"c3",characterName:"Sylvara",class:"Mage",server:"Illidan",role:"DPS",itemLevel:274,mythicPlusData:{rating:2810,weeklyRuns:10},greatVault:{totalSlots:9,maxPossibleSlots:9,categories:{mythicPlus:{slots:3},raid:{slots:3},world:{slots:3}}},tierSet:{equippedCount:5,slots:{HEAD:!0,SHOULDER:!0,CHEST:!0,HANDS:!0,LEGS:!0}},enchants:{count:8,missingSlots:[]},gems:{count:4,missingSlots:[]}},{characterId:"c4",characterName:"Darkflame",class:"Warlock",server:"Illidan",role:"DPS",itemLevel:272,mythicPlusData:{rating:2200,weeklyRuns:4},greatVault:{totalSlots:5,maxPossibleSlots:9,categories:{mythicPlus:{slots:3},raid:{slots:2},world:{slots:0}}},tierSet:{equippedCount:2,slots:{HEAD:!1,SHOULDER:!0,CHEST:!1,HANDS:!1,LEGS:!0}},enchants:{count:4,missingSlots:["CHEST","LEGS"]},gems:{count:2,missingSlots:["NECK"]}},{characterId:"c5",characterName:"Leafwhisper",class:"Druid",server:"Area 52",role:"Healer",itemLevel:270,mythicPlusData:{rating:2550,weeklyRuns:7},greatVault:{totalSlots:8,maxPossibleSlots:9,categories:{mythicPlus:{slots:3},raid:{slots:3},world:{slots:2}}},tierSet:{equippedCount:4,slots:{HEAD:!0,SHOULDER:!0,CHEST:!0,HANDS:!0,LEGS:!1}},enchants:{count:8,missingSlots:[]},gems:{count:3,missingSlots:[]}}],J={characterCount:22,itemLevel:271,itemLevelRange:{min:258,max:275},averageMythicPlusRating:2438,fullVaultCount:8,tierSetStats:{fourPiece:10,twoPiece:6,partial:4,none:2},enchantStats:{fullyEnchanted:15,partiallyEnchanted:5,noEnchants:2},gemStats:{fullyGemmed:16,partiallyGemmed:4,noGems:2}},_=[{weekStartDate:"2026-02-28",itemLevel:264,fullVaultCount:5,characterCount:20,tierSetStats:{fourPiece:4,twoPiece:6,partial:6,none:4},mythicPlusRuns:82,avgMythicPlusKey:8.2},{weekStartDate:"2026-03-07",itemLevel:267,fullVaultCount:6,characterCount:21,tierSetStats:{fourPiece:7,twoPiece:6,partial:5,none:3},mythicPlusRuns:95,avgMythicPlusKey:9.1},{weekStartDate:"2026-03-14",itemLevel:269,fullVaultCount:7,characterCount:22,tierSetStats:{fourPiece:9,twoPiece:6,partial:4,none:3},mythicPlusRuns:108,avgMythicPlusKey:9.8},{weekStartDate:"2026-03-21",itemLevel:271,fullVaultCount:8,characterCount:22,tierSetStats:{fourPiece:10,twoPiece:6,partial:4,none:2},mythicPlusRuns:115,avgMythicPlusKey:10.3}],ee=({role:a})=>{const t=z[a];return e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-sm text-[11px] font-medium border",style:{color:U[a],borderColor:`${U[a]}40`,backgroundColor:`${U[a]}15`},children:[t&&e.jsx(t,{className:"h-3 w-3"}),a]})},ae=({status:a})=>e.jsx("span",{className:`w-2 h-2 rounded-full ${{active:"bg-green-500",trial:"bg-yellow-500",bench:"bg-gray-500",inactive:"bg-red-500",departed:"bg-orange-500"}[a]||"bg-gray-500"}`}),te=({value:a,max:t,color:s="var(--theme-primary-color,#6366f1)"})=>e.jsx("div",{className:"h-1.5 bg-gray-700 rounded-full overflow-hidden w-full",children:e.jsx("div",{className:"h-full rounded-full transition-all duration-500",style:{width:`${Math.min(a/t*100,100)}%`,backgroundColor:s}})}),se=({perm:a})=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-1.5 py-0.5 rounded-sm text-[10px] font-medium bg-amber-900/30 text-amber-400 border border-amber-700/40",children:[e.jsx(B,{className:"h-2.5 w-2.5"}),a]}),re=[{title:"Roster Page Overview",shortTitle:"Overview",icon:u,description:"The /raid-roster page shows your guild's raid rosters in a sidebar + detail panel layout. Each roster has a type (main, alt, trial, bench, custom), difficulty, and 4 detail tabs: Members (role groups), Composition (charts), History (member change log), and Stats (buff/debuff coverage, raid progression tiles). Star any roster to set it as your default.",tip:"Set your main roster as default — it auto-selects when you open the page, saving a click every visit.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Roster Page Layout",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(r,{stats:[{label:"Total Members",value:22,color:"text-gray-100"},{label:"Avg iLvl",value:271,color:"text-yellow-400"},{label:"Tanks",value:2,color:"text-blue-400"},{label:"Healers",value:4,color:"text-green-400"},{label:"DPS",value:14,color:"text-red-400"},{label:"Flex",value:2,color:"text-purple-400"}]}),e.jsx(l,{tabs:[{label:"Members"},{label:"Composition"},{label:"History"},{label:"Stats"}],activeIndex:0}),e.jsx(i,{items:[{label:"Main Roster",desc:"22 members · main",badge:"Default",badgeColor:"bg-yellow-800/40 text-yellow-400"},{label:"Alt Roster",desc:"15 members · alt",badge:"Active",badgeColor:"bg-gray-700/60 text-gray-400"},{label:"Trial Team",desc:"6 members · trial",badge:"Active",badgeColor:"bg-gray-700/60 text-gray-400"}]})]}),children:e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3 min-h-[260px]",children:[e.jsxs("div",{className:"w-full sm:w-40 shrink-0 border-b sm:border-b-0 sm:border-r border-gray-700/50 pb-3 sm:pb-0 sm:pr-3 space-y-1.5",children:[e.jsx("div",{className:"text-[10px] text-gray-500 uppercase tracking-wider mb-2 font-semibold",children:"Rosters"}),Y.map(a=>e.jsxs(w.div,{initial:{opacity:0,x:-8}
1,animate:{opacity:1,x:0},transition:{delay:.08*Number(a.id)},className:"flex items-center gap-2 px-2 py-1.5 rounded-lg cursor-pointer text-xs sm:text-sm transition-colors "+(a.isDefault?"bg-(--theme-primary-color,#6366f1)/15 text-gray-100 border border-(--theme-primary-color,#6366f1)/30":"text-gray-400 hover:text-gray-200 hover:bg-gray-800/50"),children:[a.isDefault&&e.jsx("span",{className:"text-yellow-400 text-xs",children:"★"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"font-medium truncate",children:a.name}),e.jsxs("div",{className:"text-[10px] text-gray-500",children:[a.memberCount," members"]})]}),e.jsx("span",{className:"text-[10px] px-1.5 py-px rounded-sm bg-gray-800 text-gray-400 capitalize",children:a.rosterType})]},a.id))]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-3",children:[e.jsx("h3",{className:"text-sm sm:text-base font-bold text-gray-100",children:"Main Roster"}),e.jsx("span",{className:"text-xs text-gray-500",children:"Heroic"})]}),e.jsx("div",{className:"flex flex-wrap gap-2 mb-4",children:[{label:"Total",value:22,icon:y},{label:"Tanks",value:2,icon:S},{label:"Healers",value:4,icon:V},{label:"DPS",value:14,icon:k},{label:"Avg iLvl",value:271,icon:E}].map(({label:a,value:t,icon:s})=>e.jsxs("span",{className:"inline-flex items-center gap-1.5 px-2.5 py-1 bg-gray-800/60 border border-gray-700/50 rounded-lg text-xs",children:[e.jsx(s,{className:"h-3 w-3 text-gray-400"}),e.jsx("span",{className:"text-gray-400",children:a}),e.jsx("span",{className:"text-gray-200 font-medium",children:t})]},a))}),e.jsx("div",{className:"flex gap-1 border-b border-gray-700/50 mb-3 overflow-x-auto",children:["Members","Composition","History","Stats"].map((a,t)=>e.jsx("div",{className:"px-2 sm:px-3 py-1.5 text-xs font-medium rounded-t-lg whitespace-nowrap "+(0===t?"bg-gray-800 text-gray-100 border-b-2 border-(--theme-primary-color,#6366f1)":"text-gray-500"),children:a},a))}),e.jsx("div",{className:"text-xs text-gray-500 italic",children:"Member list, composition charts, history log, or statistics shown here"})]})]})}),e.jsxs(t,{type:"info",children:["The roster page is at ",e.jsx("strong",{children:"/raid-roster"}),". The left sidebar shows all your rosters — click the star icon next to any roster to set it as your default (auto-selected on page load)."]})]})},{title:"Creating & Configuring Rosters",shortTitle:"Create",icon:b,description:"Create rosters with a name, type, and difficulty setting. Configure composition targets (min tanks, min healers, max size) so the system can alert you when roles are under or over-filled. You can have multiple rosters — a main team, an alt roster, a trial group, and more.",tip:'Roster types organize your teams — "main" for your primary raid group, "trial" for new recruits, "bench" for reserves. Members within each roster have independent statuses (active, bench, trial).',component:()=>e.jsx(e.Fragment,{children:e.jsx(s,{label:"Create Roster Dialog",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(o,{pairs:[{label:"Name",value:"Main Raid Team"},{label:"Type",value:"Main"},{label:"Difficulty",value:"Heroic"},{label:"Min Tanks",value:"2"},{label:"Min Healers",value:"4"},{label:"Max Size",value:"25"}]}),e.jsx(n,{badges:[{label:"main"},{label:"alt"},{label:"trial"},{label:"bench"},{label:"custom"}]})]}),children:e.jsxs("div",{className:"max-w-md mx-auto bg-gray-900/70 border border-gray-700/50 rounded-xl p-3 sm:p-5 space-y-4",children:[e.jsx("h3",{className:"text-sm font-bold text-gray-100",children:"Create Roster"}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] text-gray-400 uppercase tracking-wider font-semibold block mb-1",children:"Name"}),e.jsx("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg px-3 py-2 text-sm text-gray-200",children:"Main Raid Team"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] text-gray-400 uppercase tracking-wider font-semibold block mb-1",children:"Type"}),e.jsx("div",{className:"bg-gray-800/60 border border-(--theme-primary-color,#6366f1)/40 rounded-lg px-3 py-2 text-sm text-gray-200",children:"Main"}),e.jsx("div",{className:"flex flex-wrap gap-1 mt-1.5",children:["main","alt","trial","bench","custom"].map(a=>e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-sm capitalize "+("main"===a?"bg-(--theme-primary-color,#6366f1)/2
10 text-(--theme-primary-color,#6366f1)":"text-gray-500 bg-gray-800"),children:a},a))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] text-gray-400 uppercase tracking-wider font-semibold block mb-1",children:"Difficulty"}),e.jsx("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg px-3 py-2 text-sm text-gray-200",children:"Heroic"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] text-gray-400 uppercase tracking-wider font-semibold block mb-1",children:"Composition Targets"}),e.jsx("div",{className:"grid grid-cols-3 gap-2",children:[{label:"Min Tanks",value:2},{label:"Min Healers",value:4},{label:"Max Size",value:25}].map(({label:a,value:t})=>e.jsxs("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg px-2 py-1.5 text-center",children:[e.jsx("div",{className:"text-xs sm:text-sm font-semibold text-gray-200",children:t}),e.jsx("div",{className:"text-[10px] text-gray-500",children:a})]},a))})]})]})})})},{title:"Managing Roster Members",shortTitle:"Members",icon:y,description:"Members are displayed in grid (cards) or list (table) view, grouped by role: Tank, Healer, DPS, and Flex. Each member card shows class-colored top bar, spec, item level, and a status dot (green = active, yellow = trial, gray = bench, red = inactive, orange = departed). Drag and drop members between role groups to reassign. Right-click for edit, bench, trial, or remove actions.",tip:'Members are unique per account — one player per roster, but each member can have multiple allowed characters via the allowedCharacterIds system. The primary character is shown by default. The "Departed" status is set automatically when a character leaves the WoW guild or their Discord account leaves the server.',component:()=>{const[r,l]=a.useState("grid"),i={Tank:[],Healer:[],DPS:[],Flex:[]};return X.forEach(e=>{i[e.role]&&i[e.role].push(e)}),e.jsxs(e.Fragment,{children:[e.jsxs(s,{label:"Member Management",interactive:!0,mobileContent:e.jsx(c,{items:X.filter(e=>"departed"!==e.status).slice(0,8).map(e=>({title:e.primaryCharacter.characterName,subtitle:`${e.primaryCharacter.spec} ${e.primaryCharacter.class} · ${e.primaryCharacter.server}`,meta:`${e.primaryCharacter.itemLevel} iLvl`,badges:[{label:e.role,color:"Tank"===e.role?"bg-blue-900/40 text-blue-400":"Healer"===e.role?"bg-green-900/40 text-green-400":"DPS"===e.role?"bg-red-900/40 text-red-400":"bg-purple-900/40 text-purple-400"},{label:e.status,color:"active"===e.status?"bg-green-900/30 text-green-400":"trial"===e.status?"bg-yellow-900/30 text-yellow-400":"bg-gray-700/60 text-gray-400"}]}))}),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-4",children:[e.jsx("button",{onClick:()=>l("grid"),className:"px-2.5 py-1 text-xs rounded-lg transition-colors "+("grid"===r?"bg-(--theme-primary-color,#6366f1)/20 text-(--theme-primary-color,#6366f1)":"text-gray-500 hover:text-gray-300"),children:"Grid"}),e.jsx("button",{onClick:()=>l("list"),className:"px-2.5 py-1 text-xs rounded-lg transition-colors "+("list"===r?"bg-(--theme-primary-color,#6366f1)/20 text-(--theme-primary-color,#6366f1)":"text-gray-500 hover:text-gray-300"),children:"List"})]}),"grid"===r?e.jsx("div",{className:"space-y-4",children:Object.entries(i).filter(([,e])=>e.length>0).map(([a,t])=>e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(ee,{role:a}),e.jsxs("span",{className:"text-xs text-gray-500",children:[t.length,"/","Tank"===a?2:"Healer"===a?4:"DPS"===a?14:5]})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2",children:t.map((a,t)=>{const s=a.primaryCharacter;return e.jsxs(w.div,{initial:{opacity:0,y:6},animate:{opacity:1,y:0},transition:{delay:.04*t},className:"bg-gray-800/60 border border-gray-700/50 rounded-lg p-2.5 relative overflow-hidden hover:border-gray-600 transition-colors",children:[e.jsx("div",{className:"absolute top-0 left-0 w-full h-0.5",style:{backgroundColor:K[s.class]||"#666"}}),e.jsx("div",{className:"text-sm font-medium",style:{color:K[s.class]},children:s.characterName}),e.jsxs("div",{className:"text-[10px] text-gray-500",children:[s.spec," ",s.class]}),e.jsxs("div",{className:"flex items-center justify-between mt-1.5",children:[e.jsxs("span",{className:"text-xs text-(--theme-primary-color,#6366f1) font-medium",children:[s.itemLevel," iLvl"]}),e.jsx(ae,{status:a.status})]})]},a.id)})})]},a))}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"border-b border-gray-700/50",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left py-2 px-2 text-gray-400 font-semibold",children:"Character"}),e.jsx("th",{className:"text-center py-2 px-2 text-gray-400 font-semibold",children:"Role"}),e.jsx("th",{className:"text-center py-2 px-2 text-gray-400 font-semibold",children:"Spec"}),e.jsx("th",{className:"text-center py-2 px-2 text-gray-400 font-semibold",children:"iLvl"}),e.jsx("th",{className:"text-center py-2 px-2 text-gray-400 font-semibold",children:"Status"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-700/30",children:X.map(a=>{const t=a.primaryCharacter;return e.jsxs("tr",{className:"hover:bg-gray-700/20",children:[e.jsx("td",{className:"py-2 px-2 font-medium",style:{color:K[t.class]},children:t.characterName}),e.jsx("td",{className:"py-2 px-2 text-center",children:e.jsx(ee,{role:a.role})}),e.jsx("td",{className:"py-2 px-2 text-center text-gray-300",children:t.spec}),e.jsx("td",{className:"py-2 px-2 text-center text-(--theme-primary-color,#6366f1)",children:t.itemLevel}),e.jsx("td",{className:"py-2 px-2 text-center",children:e.jsxs("div",{className:"flex items-center justify-center gap-1",children:[e.jsx(ae,{status:a.status}),e.jsx("span",{className:"text-gray-400 capitalize",children:a.status})]})})]},a.id)})})]})})]}),e.jsx(t,{type:"tip",children:"Drag and drop members between role groups to reassign them. Right-click any member to access the context menu for editing role, spec, status, benching, or removal."}),e.jsx(t,{type:"info",children:e.jsxs("div",{className:"flex flex-col sm:flex-row items-start gap-2",children:[e.jsxs("span",{className:"inline-flex items-center gap-1.5 shrink-0",children:[e.jsx($,{className:"h-3.5 w-3.5 text-orange-400"}),e.jsx("span",{className:"font-semibold text-orange-400",children:"Departed"})]}),e.jsx("span",{children:"Characters are automatically flagged as Departed when they leave the WoW guild or their Discord account leaves the server. The orange dot distinguishes them from manually inactive members."})]})}),e.jsx(t,{type:"info",children:e.jsxs("div",{className:"flex flex-col sm:flex-row items-start gap-2",children:[e.jsx("span",{className:"inline-flex items-center gap-1.5 shrink-0",children:e.jsx("span",{className:"px-1.5 py-0.5 rounded-sm text-[10px] font-semibold bg-gray-700 text-gray-200",children:"Unlinked"})}),e.jsxs("span",{children:[e.jsx("strong",{children:"Adding characters whose owner hasn't linked Discord:"})," ","The Add Member dialog now lists every character imported from Battle.net or WarcraftLogs, not just ones with a linked Discord account. Unlinked characters get a grey ",e.jsx("em",{children:"Unlinked"}
1)," badge so you know what you're adding. They will appear in the roster, count toward composition, and be auto-filled into event signups — but they will ",e.jsx("strong",{children:"not"})," receive Discord DM reminders or auto-confirmations until the player links their Discord account. Once they link, the existing record automatically merges."]})]})})]})}},{title:"Composition Analysis",shortTitle:"Composition",icon:L,description:"The Composition tab shows 6 analysis sections: role distribution doughnut, DPS melee vs ranged split (derived from class/spec classification), Mythic ideal comparison (2T/4H/14D), class distribution bar chart, spec breakdown with mismatch flags, and coverage gap alerts for missing classes or under-filled roles.",tip:"The Mythic Ideal bars highlight under-filled roles in red and over-filled roles in yellow. Green means you hit the 2/4/14 target exactly.",component:()=>{const a=Y[0].composition.byRole,l={Tank:2,Healer:4,DPS:14,Flex:0},i=Object.entries({Warrior:2,Paladin:2,"Demon Hunter":1,Druid:2,Evoker:1,Priest:1,Mage:3,Warlock:2,Rogue:2,Hunter:2,Monk:1,Shaman:1,"Death Knight":2}).sort((e,a)=>a[1]-e[1]);return e.jsxs(e.Fragment,{children:[e.jsxs(s,{label:"Composition Tab",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(r,{stats:[{label:"Tanks",value:`${a.Tank}/2`,color:a.Tank>=l.Tank?"text-green-400":"text-red-400"},{label:"Healers",value:`${a.Healer}/4`,color:a.Healer>=l.Healer?"text-green-400":"text-red-400"},{label:"DPS",value:`${a.DPS}/14`,color:a.DPS>=l.DPS?"text-green-400":"text-yellow-400"},{label:"Melee / Ranged",value:"8 / 6",color:"text-orange-400"}]}),e.jsx(d,{items:i.slice(0,8).map(([e,a])=>({label:e,value:String(a),color:"text-gray-100"})),cols:2})]}),children:[e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-3 gap-3",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Role Distribution"}),e.jsx("div",{className:"flex items-center justify-center h-28",children:e.jsxs("div",{className:"relative w-24 h-24",children:[e.jsx("svg",{viewBox:"0 0 100 100",className:"w-full h-full -rotate-90",children:(()=>{const t=Object.values(a).reduce((e,a)=>e+a,0);let s=0;return Object.entries(a).filter(([,e])=>e>0).map(([a,r])=>{const l=r/t*100,i=`${2.51*l} ${251.2-2.51*l}`,o=e.jsx("circle",{cx:"50",cy:"50",r:"40",fill:"none",stroke:U[a],strokeWidth:"12",strokeDasharray:i,strokeDashoffset:2.512*-s},a);return s+=l,o})})()}),e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"text-lg font-bold text-gray-100",children:"22"}),e.jsx("div",{className:"text-[9px] text-gray-500",children:"members"})]})})]})}),e.jsx("div",{className:"grid grid-cols-2 gap-1 mt-2",children:Object.entries(a).map(([a,t])=>{const s=z[a];return e.jsxs("div",{className:"flex items-center gap-1 text-[11px]",children:[e.jsx(s,{className:"h-3 w-3",style:{color:U[a]}}),e.jsx("span",{className:"text-gray-400",children:a}),e.jsx("span",{className:"text-gray-200 font-medium ml-auto",children:t})]},a)})})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"DPS Breakdown"}),e.jsxs("div",{className:"flex items-center justify-center h-20 gap-4",children:[e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"text-xl font-bold text-orange-400",children:"8"}),e.jsx("div",{className:"text-[10px] text-gray-500",children:"Melee"})]}),e.jsx("div",{className:"w-px h-10 bg-gray-700"}),e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"text-xl font-bold text-violet-400",children:"6"}),e.jsx("div",{className:"text-[10px] text-gray-500",children:"Ranged"})]})]}),e.jsxs("div",{className:"flex gap-1 mt-2",children:[e.jsx("div",{className:"h-2 rounded-full bg-orange-500 transition-all",style:{width:8/14*100+"%"}}),e.jsx("div",{className:"h-2 rounded-full bg-violet-500 transition-all",style:{width:6/14*100+"%"}})]})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Mythic Ideal (20-man)"}),e.jsx("div",{className:"space-y-2.5",children:Object.entries(l).filter(([,e])=>e>0).map(([t,s])=>{const r=a[t]||0,l=r-s,i=z[t];return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between text-[11px] mb-0.5",children:[e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(i,{className:"h-3 w-3",style:{color:U[t]}}),e.jsx("span",{className:"text-gray-300",children:t})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"text-gray-200 font-medium",children:r}),e.jsx("span",{className:"text-gray-600",children:"/"}),e.jsx("span",{className:"text-gray-500",children:s}),0===l&&e.jsx(W,{className:"h-3 w-3 text-green-500"}),l<0&&e.jsxs("span",{className:"text-red-400 text-[10px]",children:["(",l,")"]}),l>0&&e.jsxs("span",{className:"text-yellow-400 text-[10px]",children:["(+",l,")"]})]})]}),e.jsx(te,{value:r,max:s,color:0===l?"#22c55e":l<0?"#ef4444":U[t]})]},t)})})]})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3 mt-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Class Distribution"}),e.jsx("div",{className:"space-y-1.5",children:i.map(([a,t],s)=>e.jsxs(w.div,{initial:{opacity:0,x:-10}
1,animate:{opacity:1,x:0},transition:{delay:.03*s},className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[11px] text-gray-300 w-24 truncate",children:a}),e.jsx("div",{className:"flex-1 h-4 bg-gray-800 rounded-sm overflow-hidden",children:e.jsx(w.div,{initial:{width:0},animate:{width:t/3*100+"%"},transition:{duration:.4,delay:.03*s},className:"h-full rounded-sm",style:{backgroundColor:K[a]||"#666"}})}),e.jsx("span",{className:"text-[11px] text-gray-400 w-4 text-right",children:t})]},a))})]})]}),e.jsx(t,{type:"tip",children:"The Mythic Ideal bars compare your roster against the standard 20-man composition: 2 Tanks, 4 Healers, 14 DPS. Red bars indicate under-filled roles, green means you hit the target."})]})}},{title:"Syncing from External Sources",shortTitle:"Sync",icon:v,description:"Enrich your existing roster members with live data from 3 external sources: Battle.net (item levels and armory data), Raider.io (M+ scores and runs), and WarcraftLogs (parse percentiles and performance ratings). Use Manual entry to add new members. Sync does not add or remove roster members. Requires the players.import permission.",tip:"WarcraftLogs sync updates parse data for members who appear in recent guild raid reports. Add members to your roster first, then sync to enrich their data.",component:()=>e.jsxs(e.Fragment,{children:[e.jsxs(s,{label:"Sync Sources",children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 max-w-lg mx-auto",children:[{name:"Battle.net",desc:"Enrich with armory data",icon:S,color:"text-blue-400",bg:"bg-blue-900/20",border:"border-blue-700/40"},{name:"Raider.io",desc:"Enrich with M+ ratings",icon:I,color:"text-orange-400",bg:"bg-orange-900/20",border:"border-orange-700/40"},{name:"WarcraftLogs",desc:"Enrich with parse data",icon:L,color:"text-purple-400",bg:"bg-purple-900/20",border:"border-purple-700/40"},{name:"Manual",desc:"Search and add characters",icon:b,color:"text-green-400",bg:"bg-green-900/20",border:"border-green-700/40"}].map(({name:a,desc:t,icon:s,color:r,bg:l,border:i},o)=>e.jsxs(w.div,{initial:{opacity:0,scale:.95},animate:{opacity:1,scale:1},transition:{delay:.08*o},className:`${l} border ${i} rounded-lg p-3 text-center`,children:[e.jsx(s,{className:`h-6 w-6 ${r} mx-auto mb-1.5`}),e.jsx("div",{className:"text-sm font-medium text-gray-200",children:a}),e.jsx("div",{className:"text-[10px] text-gray-500 mt-0.5",children:t})]},a))}),e.jsxs("div",{className:"mt-4 flex items-center justify-center gap-2",children:[e.jsx(se,{perm:"players.import"}),e.jsx("span",{className:"text-[10px] text-gray-500",children:"Required to sync from external sources"})]})]}),e.jsx(t,{type:"info",children:"Sync enriches your existing roster members with live data — it does not add or remove members. WarcraftLogs updates parse percentiles, Battle.net refreshes item levels, and Raider.io updates M+ scores. Add members manually or via the Manual sync option."})]})},{title:"Seasons, Archiving & Carry Forward",shortTitle:"Seasons",icon:H,description:"Every roster is tied to a WoW season (shown as a badge in the sidebar). When a new season is detected — automatically, via Battle.net and Raider.io — a banner prompts you to carry each roster forward or archive it. Carry forward copies the roster and its members into the new season with attendance, performance ratings, and character-switch history reset, and archives the old roster in the same step. Archived rosters are hidden from the sidebar, event roster pickers, wishlist pickers, and form exports, and skip background syncing — but their history, audit data, and loot records stay fully viewable.",tip:'Use the "Show archived" toggle in the sidebar to browse past seasons\' rosters. Archiving is reversible — the roster menu has an Unarchive action. New rosters are bound to the current season automatically.',component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Season Rollover Banner",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(c,{cards:[{title:"New season — MN-S2",desc:"Main Roster is still on MN-S1",badge:"Banner",badgeColor:"bg-blue-800/40 text-blue-300"}]}),e.jsx(i,{items:[{label:"Main Roster",desc:"22 members · MN-S2",badge:"Default",badgeColor:"bg-yellow-800/40 text-yellow-400"},{label:"Main Roster",desc:"20 members · TWW-S3",badge:"Archived",badgeColor:"bg-gray-700/60 text-gray-400"}]}),e.jsx(m,{steps:[{label:"New season detected"},{label:"Carry roster forward"},{label:"Old roster archived"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-3 px-3 py-2.5 rounded-lg bg-blue-900/30 border border-blue-700/50 text-blue-100",children:[e.jsx(C,{className:"h-4 w-4 shrink-0 text-blue-300"}),e.jsxs("div",{className:"flex-1 text-xs sm:text-sm",children:[e.jsx("span",{className:"font-semibold",children:"New season — MN-S2."})," ",e.jsx("span",{className:"font-medium",children:"Main Roster"})," is still on MN-S1."]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"px-2.5 py-1 rounded-lg bg-(--theme-primary-color,#6366f1) text-white text-xs font-medium",children:"Carry forward"}),e.jsx("span",{className:"px-2.5 py-1 rounded-lg bg-gray-700 text-gray-200 text-xs font-medium",children:"Archive"}),e.jsx("span",{className:"px-1.5 py-1 text-gray-400 text-xs",children:"Dismiss"})]})]}),e.jsx("div",{className:"space-y-1.5",children:[{...Y[0],seasonId:"mn-s2"},Q].map(a=>e.jsxs("div",{className:"flex items-center gap-2 px-2 py-2 rounded-lg text-xs sm:text-sm border "+(a.archivedAt?"border-gray-700/50 text-gray-500 opacity-60":"border-(--theme-primary-color,#6366f1)/30 bg-(--theme-primary-color,#6366f1)/10 text-gray-100"),children:[a.archivedAt?e.jsx(H,{className:"h-4 w-4 shrink-0"}):e.jsx("span",{className:"text-yellow-400",children:"★"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"font-medium truncate",children:a.name}),e.jsxs("div",{className:"text-[10px] text-gray-500",children:[a.memberCount," members"]})]}),e.jsx("span",{className:"text-[10px] px-1.5 py-px rounded-full border border-blue-500/40 text-blue-300 uppercase",children:a.seasonId}),a.archivedAt&&e.jsx("span",{className:"text-[10px] px-1.5 py-px rounded-full bg-gray-700 text-gray-300",children:"Archived"})]},a.id))}),e.jsx("div",{className:"text-[11px] text-gray-500 italic",children:"Carrying forward copies members and settings into the new season; attendance, performance ratings, and character-switch history start fresh. The archived roster keeps all of its history, audit data, and loot records."})]})}),e.jsxs(t,{type:"info",children:["A new season is detected automatically from Battle.net and Raider.io data — the banner appears on the roster page as soon as a roster is still bound to a previous season. Archived rosters disappear from pickers (events, wishlists, form exports
1) and background syncing, but stay fully viewable via ",e.jsx("strong",{children:"Show archived"})," in the sidebar, and can be unarchived at any time."]})]})},{title:"Audit Dashboard Overview",shortTitle:"Audit",icon:R,description:"The /roster-audit page has a toolbar with 10 action buttons (roster selector, tier override, refresh, armory sync, clear cache, vault guide, upgrade guide, config, snapshot, export), summary stat cards, tier/enchant/gem coverage, and a sortable character table with 10 columns. Data is aggregated from Battle.net, Raider.io, and WarcraftLogs.",tip:'Three different refresh actions: "Refresh" re-fetches audit data from the 1-hour server cache. "Refresh Armory" triggers a background Battle.net sync (shows live X/Y progress). "Clear Cache" wipes the Raider.io and Battle.net caches entirely.',component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Audit Dashboard",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(r,{stats:[{label:"Characters",value:J.characterCount,color:"text-purple-400"},{label:"Avg iLvl",value:J.itemLevel,color:"text-yellow-400"},{label:"Avg M+ Rating",value:J.averageMythicPlusRating,color:"text-orange-400"},{label:"Full Vault",value:`${J.fullVaultCount}/${J.characterCount}`,color:"text-green-400"}]}),e.jsx(d,{items:[{label:"4-Piece",value:String(J.tierSetStats.fourPiece),color:"text-purple-400",desc:"tier set"},{label:"2-Piece",value:String(J.tierSetStats.twoPiece),color:"text-blue-400",desc:"tier set"},{label:"Enchanted",value:String(J.enchantStats.fullyEnchanted),color:"text-cyan-400",desc:"fully"},{label:"Gemmed",value:String(J.gemStats.fullyGemmed),color:"text-pink-400",desc:"fully"}],cols:2}),e.jsx(c,{items:Z.slice(0,4).map(e=>({title:e.characterName,subtitle:`${e.class} · ${e.role}`,meta:`${e.itemLevel} iLvl`,badges:[{label:`M+ ${e.mythicPlusData.rating}`,color:"bg-orange-900/30 text-orange-400"},{label:`Vault ${e.greatVault.totalSlots}/9`,color:e.greatVault.totalSlots>=6?"bg-green-900/30 text-green-400":"bg-yellow-900/30 text-yellow-400"},{label:`Tier ${e.tierSet.equippedCount}/5`,color:e.tierSet.equippedCount>=4?"bg-purple-900/30 text-purple-400":"bg-blue-900/30 text-blue-400"}]}))})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"bg-gray-800/40 border border-gray-700/40 rounded-lg px-3 py-2 flex flex-wrap items-center gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5 bg-gray-700/50 rounded-lg px-2.5 py-1.5 text-xs text-gray-200 border border-gray-600/50",children:["Main Roster ",e.jsx(D,{className:"h-3 w-3 text-gray-400"})]}),e.jsxs("div",{className:"flex items-center gap-1.5 bg-gray-700/50 rounded-lg px-2.5 py-1.5 text-xs text-gray-400 border border-gray-600/50",children:["Midnight S2 ",e.jsx("span",{className:"text-gray-500",children:"(auto)"})," ",e.jsx(D,{className:"h-3 w-3"})]}),e.jsx("div",{className:"w-px h-5 bg-gray-700 hidden sm:block"}),[{icon:v,label:"Refresh",cls:""},{icon:v,label:"Armory",cls:"text-blue-400"},{icon:q,label:"Cache",cls:"text-red-400"}].map(({icon:a,label:t,cls:s})=>e.jsxs("div",{className:`flex items-center gap-1 px-2 py-1 rounded-sm text-[10px] bg-gray-700/30 border border-gray-600/30 ${s||"text-gray-400"}`,children:[e.jsx(a,{className:"h-3 w-3"}),t]},t)),e.jsx("div",{className:"w-px h-5 bg-gray-700 hidden sm:block"}),[{icon:A,label:"Vault Guide"},{icon:f,label:"Upgrade Guide"},{icon:F,label:"Config"},{icon:j,label:"Snapshot"},{icon:N,label:"Export"}].map(({icon:a,label:t})=>e.jsxs("div",{className:"flex items-center gap-1 px-2 py-1 rounded-sm text-[10px] text-gray-400 bg-gray-700/30 border border-gray-600/30",children:[e.jsx(a,{className:"h-3 w-3"}),t]},t))]}),e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-2",children:[{title:"Characters",value:J.characterCount,icon:y,iconColor:"text-purple-400"},{title:"Avg Item Level",value:J.itemLevel,sub:`${J.itemLevelRange.min} – ${J.itemLevelRange.max}`,icon:E,iconColor:"text-yellow-400"},{title:"Avg M+ Rating",value:J.averageMythicPlusRating,icon:I,iconColor:"text-orange-400"},{title:"Full Vault",value:J.fullVaultCount,sub:`${Math.round(J.fullVaultCount/J.characterCount*100)}% of roster`,icon:A,iconColor:"text-green-400"}].map(({title:a,value:t,sub:s,icon:r,iconColor:l},i)=>e.jsxs(w.div,{initial:{opacity:0,y:8}
1,animate:{opacity:1,y:0},transition:{delay:.06*i},className:"bg-gray-800/60 border border-gray-700/50 rounded-lg p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx(r,{className:`h-4 w-4 ${l}`}),e.jsx("span",{className:"text-[10px] text-gray-500 uppercase tracking-wider font-semibold",children:a})]}),e.jsx("div",{className:"text-xl font-bold text-gray-100",children:t}),s&&e.jsx("div",{className:"text-[10px] text-gray-500 mt-0.5",children:s})]},a))}),e.jsxs("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(R,{className:"h-4 w-4 text-purple-400"}),e.jsx("span",{className:"text-sm font-semibold text-gray-100",children:"Tier Set Progress"})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2 sm:gap-3 text-center",children:[{label:"4-Piece",value:J.tierSetStats.fourPiece,cls:"text-purple-400"},{label:"2-Piece",value:J.tierSetStats.twoPiece,cls:"text-blue-400"},{label:"Partial",value:J.tierSetStats.partial,cls:"text-yellow-400"},{label:"None",value:J.tierSetStats.none,cls:"text-gray-400"}].map(({label:a,value:t,cls:s})=>e.jsxs("div",{children:[e.jsx("div",{className:`text-xl sm:text-2xl font-bold ${s}`,children:t}),e.jsx("div",{className:"text-[10px] text-gray-500",children:a})]},a))})]}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:[{title:"Enchant Coverage",icon:E,iconCls:"text-cyan-400",stats:[{label:"Fully Enchanted",value:J.enchantStats.fullyEnchanted,cls:"text-green-400"},{label:"Partially",value:J.enchantStats.partiallyEnchanted,cls:"text-yellow-400"},{label:"Missing",value:J.enchantStats.noEnchants,cls:"text-red-400"}]},{title:"Gem Coverage",icon:O,iconCls:"text-pink-400",stats:[{label:"Fully Gemmed",value:J.gemStats.fullyGemmed,cls:"text-green-400"},{label:"Partially",value:J.gemStats.partiallyGemmed,cls:"text-yellow-400"},{label:"Missing",value:J.gemStats.noGems,cls:"text-red-400"}]}].map(({title:a,icon:t,iconCls:s,stats:r})=>e.jsxs("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg p-3",children:[e.jsxs("div",{className:"flex items-center gap-1.5 mb-2",children:[e.jsx(t,{className:`h-4 w-4 ${s}`}),e.jsx("span",{className:"text-xs font-semibold text-gray-200",children:a})]}),e.jsx("div",{className:"space-y-1",children:r.map(({label:a,value:t,cls:s})=>e.jsxs("div",{className:"flex justify-between text-[11px]",children:[e.jsx("span",{className:"text-gray-400",children:a}),e.jsx("span",{className:`font-medium ${s}`,children:t})]},a))})]},a))}),e.jsxs("div",{className:"bg-gray-800/60 border border-gray-700/50 rounded-lg overflow-hidden",children:[e.jsxs("div",{className:"px-3 py-2 border-b border-gray-700/50 flex items-center gap-2",children:[e.jsx(L,{className:"h-4 w-4 text-(--theme-primary-color,#6366f1)"}),e.jsx("span",{className:"text-xs font-semibold text-gray-100",children:"Character Details"}),e.jsx("span",{className:"text-[10px] text-gray-500",children:"22"})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-[11px]",children:[e.jsx("thead",{className:"bg-gray-900/50 border-b border-gray-700/40",children:e.jsx("tr",{children:["Character","Role","iLvl","M+","Vault","Tier","Ench","Gems"].map(a=>e.jsx("th",{className:"px-2 py-1.5 text-gray-400 font-semibold text-center first:text-left",children:a},a))})}),e.jsx("tbody",{className:"divide-y divide-gray-700/20",children:Z.slice(0,4).map(a=>e.jsxs("tr",{className:"hover:bg-gray-700/20",children:[e.jsx("td",{className:"px-2 py-1.5 font-medium",style:{color:K[a.class]},children:a.characterName}),e.jsx("td",{className:"px-2 py-1.5 text-center",children:e.jsx(ee,{role:a.role})}),e.jsx("td",{className:"px-2 py-1.5 text-center text-(--theme-primary-color,#6366f1) font-medium",children:a.itemLevel}),e.jsx("td",{className:"px-2 py-1.5 text-center text-gray-300",children:a.mythicPlusData.rating}),e.jsx("td",{className:"px-2 py-1.5 text-center",children:e.jsxs("span",{className:a.greatVault.totalSlots>=6?"text-green-400":a.greatVault.totalSlots>=3?"text-yellow-400":"text-gray-400",children:[a.greatVault.totalSlots,"/9"]})}),e.jsx("td",{className:"px-2 py-1.5 text-center",children:e.jsxs("span",{className:a.tierSet.equippedCount>=4?"text-purple-400":a.tierSet.equippedCount>=2?"text-blue-400":"text-gray-400",children:[a.tierSet.equippedCount,"/5"]})}),e.jsx("td",{className:"px-2 py-1.5 text-center",children:0===a.enchants.missingSlots.length?e.jsx(W,{className:"h-3.5 w-3.5 text-green-400 mx-auto"}):e.jsx(T,{className:"h-3.5 w-3.5 text-yellow-400 mx-auto"})}),e.jsx("td",{className:"px-2 py-1.5 text-center",children:0===a.gems.missingSlots.length?e.jsx(W,{className:"h-3.5 w-3.5 text-green-400 mx-auto"}):e.jsx(T,{className:"h-3.5 w-3.5 text-yellow-400 mx-auto"})})]},a.characterId))})]})})]})]})}),e.jsxs(t,{type:"info",children:["The Roster Audit page is at ",e.jsx("strong",{children:"/roster-audit"})," — a separate page from the roster manager. It aggregates data from Battle.net, Raider.io, and WarcraftLogs to evaluate raid readiness. Requires ",e.jsx("strong",{children:"players.view"})," permission."]})]})},{title:"Character Detail Analysis",shortTitle:"Details",icon:j,description:"Click any character in the audit table to open a 6-tab detail modal: Overview (quick enchant/gem/profession check), Mythic+ (rating, weekly runs with timed indicator, upgrade track badges), Great Vault (M+/Raid slot progress with predicted reward ilvls — World is coming soon), Tier Set (X/5 with per-slot breakdown), Enchants/Gems (slot-by-slot detail), and History (ilvl/M+/vault progression charts over weeks). The quick-stats header also surfaces a Loot (Season) tile — total items the character has received since the current season started; hover to see the Need / Off·Greed / TMog / Unknown / Personal breakdown.",tip:"The Overview tab gives you an instant pass/fail readiness check — green checkmarks for complete enchants/gems, yellow warnings for missing slots. Use /loot roster roster:<name>
1 in Discord to compare loot counts across the full roster.",component:()=>{const[r,i]=a.useState(0),n=Z[1];return e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Character Detail Modal",interactive:!0,mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(l,{tabs:[{label:"Overview"},{label:"Mythic+"},{label:"Great Vault"},{label:"Tier Set"},{label:"Enchants/Gems"},{label:"History"}],activeIndex:r}),e.jsx(o,{pairs:[{label:"Character",value:n.characterName},{label:"Class",value:n.class},{label:"Server",value:n.server},{label:"Item Level",value:String(n.itemLevel),color:"text-(--theme-primary-color,#6366f1)"},{label:"M+ Rating",value:String(n.mythicPlusData.rating),color:"text-orange-400"},{label:"Vault Slots",value:`${n.greatVault.totalSlots}/9`,color:n.greatVault.totalSlots>=6?"text-green-400":"text-yellow-400"},{label:"Tier Pieces",value:`${n.tierSet.equippedCount}/5`,color:n.tierSet.equippedCount>=4?"text-purple-400":"text-blue-400"}]})]}),children:e.jsxs("div",{className:"bg-gray-900/70 border border-gray-700/50 rounded-xl overflow-hidden max-w-lg mx-auto",children:[e.jsxs("div",{className:"p-3 sm:p-4 border-b border-gray-700/50",children:[e.jsxs("div",{className:"flex items-center gap-2 sm:gap-3 flex-wrap",children:[e.jsx("div",{className:"w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold shrink-0",style:{backgroundColor:`${K[n.class]}25`,color:K[n.class]},children:n.characterName[0]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"font-bold",style:{color:K[n.class]},children:n.characterName}),e.jsxs("div",{className:"text-[10px] text-gray-500",children:[n.class," · ",n.server]})]}),e.jsx(ee,{role:n.role})]}),e.jsx("div",{className:"grid grid-cols-5 gap-1 mt-3",children:[{label:"iLvl",value:n.itemLevel,cls:"text-(--theme-primary-color,#6366f1)"},{label:"M+",value:n.mythicPlusData.rating,cls:"text-orange-400"},{label:"Raid",value:"7/9 H",cls:"text-pink-400"},{label:"Vault",value:`${n.greatVault.totalSlots}/9`,cls:n.greatVault.totalSlots>=6?"text-green-400":"text-yellow-400"},{label:"Tier",value:`${n.tierSet.equippedCount}/5`,cls:n.tierSet.equippedCount>=4?"text-purple-400":"text-blue-400"}].map(({label:a,value:t,cls:s})=>e.jsxs("div",{className:"text-center min-w-0",children:[e.jsx("div",{className:`text-xs sm:text-sm font-bold ${s} truncate`,children:t}),e.jsx("div",{className:"text-[9px] text-gray-500",children:a})]},a))})]}),e.jsx("div",{className:"flex border-b border-gray-700/50 overflow-x-auto",children:["Overview","Mythic+","Great Vault","Tier Set","Enchants/Gems","History"].map((a,t)=>e.jsx("button",{onClick:()=>i(t),className:"px-3 py-2 text-[11px] font-medium whitespace-nowrap transition-colors "+(t===r?"text-(--theme-primary-color,#6366f1) border-b-2 border-(--theme-primary-color,#6366f1)":"text-gray-500 hover:text-gray-300"),children:a},a))}),e.jsx("div",{className:"p-3 sm:p-4",children:e.jsx(M,{mode:"wait",children:e.jsxs(w.div,{initial:{opacity:0,y:4},animate:{opacity:1,y:0},exit:{opacity:0},transition:{duration:.1},children:[0===r&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"Quick readiness check across enchants, gems, and professions."}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"bg-gray-800/50 rounded-sm p-2",children:[e.jsx("div",{className:"text-[10px] text-gray-500 mb-1",children:"Enchants"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(T,{className:"h-3.5 w-3.5 text-yellow-400"}),e.jsx("span",{className:"text-xs text-yellow-400",children:"1 missing (Wrist)"})]})]}),e.jsxs("div",{className:"bg-gray-800/50 rounded-sm p-2",children:[e.jsx("div",{className:"text-[10px] text-gray-500 mb-1",children:"Gems"}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx(W,{className:"h-3.5 w-3.5 text-green-400"}),e.jsx("span",{className:"text-xs text-green-400",children:"All gemmed"})]})]})]})]}),2===r&&e.jsxs("div",{className:"space-y-3",children:[e.jsx("div",{className:"text-xs text-gray-400",children:"Great Vault slot progress across M+, Raids, and World content."}),e.jsx("div",{className:"grid grid-cols-3 gap-2",children:[{cat:"Mythic+",slots:3,thresholds:[1,4,8],color:"text-orange-400"},{cat:"Raids",slots:2,thresholds:[2,4,6],color:"text-purple-400"},{cat:"World",slots:0,thresholds:[],color:"text-gray-500",locked:!0}].map(({cat:a,slots:t,thresholds:s,color:r,locked:l})=>e.jsxs("div",{className:"bg-gray-800/50 rounded-sm p-2 text-center",children:[e.jsx("div",{className:`text-xs font-semibold ${r} mb-2`,children:a}),l?e.jsx("div",{className:"text-[10px] text-gray-500 italic py-1",children:"Coming Soon"}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex justify-center gap-1.5",children:s.map((a,s)=>e.jsx("div",{className:"w-5 h-5 rounded-full border-2 flex items-center justify-center text-[9px] font-bold "+(s<t?"border-green-500 bg-green-500/20 text-green-400":"border-gray-600 text-gray-600"),children:s+1},s))}),e.jsxs("div",{className:"text-[10px] text-gray-500 mt-1.5",children:[t,"/3 slots"]})]})]},a))})]}),3===r&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("span",{className:"text-sm font-semibold text-gray-100",children:[n.tierSet.equippedCount,"/5 Pieces"]}),e.jsxs("div",{className:"flex gap-1",children:[e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded-sm font-medium "+(n.tier
1Set.equippedCount>=2?"bg-blue-900/30 text-blue-400":"bg-gray-800 text-gray-500"),children:["2pc ",n.tierSet.equippedCount>=2?"✓":"—"]}),e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded-sm font-medium "+(n.tierSet.equippedCount>=4?"bg-purple-900/30 text-purple-400":"bg-gray-800 text-gray-500"),children:["4pc ",n.tierSet.equippedCount>=4?"✓":"—"]})]})]}),e.jsx("div",{className:"space-y-1.5",children:[{name:"Head",key:"HEAD"},{name:"Shoulder",key:"SHOULDER"},{name:"Chest",key:"CHEST"},{name:"Hands",key:"HANDS"},{name:"Legs",key:"LEGS"}].map(({name:a,key:t})=>{const s=n.tierSet.slots[t];return e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 rounded-sm "+(s?"bg-green-900/15 border border-green-800/30":"bg-gray-800/40 border border-gray-700/30"),children:[s?e.jsx(W,{className:"h-3.5 w-3.5 text-green-400"}):e.jsx(T,{className:"h-3.5 w-3.5 text-gray-500"}),e.jsx("span",{className:"text-xs "+(s?"text-green-300":"text-gray-500"),children:a}),e.jsx("span",{className:"text-[10px] ml-auto "+(s?"text-green-400":"text-gray-600"),children:s?"Equipped":"Missing"})]},t)})})]}),0!==r&&2!==r&&3!==r&&e.jsx("div",{className:"text-center py-4",children:e.jsxs("div",{className:"text-xs text-gray-500",children:[1===r&&"M+ rating breakdown, weekly runs with timing status, and upgrade track badges.",4===r&&"Slot-by-slot enchant names and gem details for the character.",5===r&&"Item level, M+ rating, and vault score progression charts over recent weeks."]})})]},r)})})]})}),e.jsx(t,{type:"tip",children:"Click any character row in the audit table to open this 6-tab detail modal. The Overview tab gives you a quick pass/fail readiness check at a glance."})]})}},{title:"The Great Vault & Vault Score",shortTitle:"Vault",icon:A,description:"The Great Vault offers up to 9 weekly reward slots across Mythic+ (1/4/8 runs), Raids (2/4/6 bosses), and World content (coming soon). Each unlocked slot has a predicted reward item level based on key level or raid difficulty. The Vault Score is a 0–100 normalized composite: slot count (max 45 points) plus reward quality (max 55 points).",tip:"Focus on 8 M+ runs per week for the maximum 3 dungeon vault slots — that is the highest-impact single activity. The Vault Guide modal (toolbar button) shows exact reward item levels per key level.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Vault Progress",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(r,{stats:[{label:"Mythic+ Slots",value:"3/3",color:"text-orange-400"},{label:"Raid Slots",value:"2/3",color:"text-purple-400"},{label:"World Slots",value:"Soon",color:"text-gray-500"},{label:"Total Vault",value:"5/9",color:"text-green-400"}]}),e.jsx(o,{pairs:[{label:"M+ threshold 1",value:"1 run"},{label:"M+ threshold 2",value:"4 runs"},{label:"M+ threshold 3",value:"8 runs"},{label:"Raid threshold 1",value:"2 bosses"},{label:"Raid threshold 2",value:"4 bosses"},{label:"Raid threshold 3",value:"6 bosses"},{label:"Vault Score",value:"0 – 100",color:"text-(--theme-primary-color,#6366f1)"}]})]}),children:e.jsxs("div",{className:"space-y-4 max-w-lg mx-auto",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-200 mb-3",children:"Great Vault Slots"}),e.jsx("div",{className:"grid grid-cols-3 gap-2 sm:gap-3",children:[{cat:"Mythic+",thresholds:[1,4,8],slots:3,icon:I,hex:"#f97316",hexLight:"#fb923c"},{cat:"Raids",thresholds:[2,4,6],slots:2,icon:k,hex:"#a855f7",hexLight:"#c084fc"},{cat:"World",thresholds:[3,6,9],slots:0,icon:A,hex:"#22c55e",hexLight:"#4ade80",locked:!0}].map(({cat:a,thresholds:t,slots:s,icon:r,hex:l,hexLight:i,locked:o})=>e.jsxs("div",{className:"text-center",children:[e.jsx(r,{className:"h-5 w-5 mx-auto mb-1",style:{color:i}}),e.jsx("div",{className:"text-xs font-medium",style:{color:i},children:a}),o?e.jsx("div",{className:"mt-2 text-[10px] text-gray-500 italic py-2",children:"Coming Soon"}):e.jsx("div",{className:"flex justify-center gap-1 sm:gap-2 mt-2",children:t.map((a,t)=>e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-6 h-6 sm:w-7 sm:h-7 rounded-lg border-2 flex items-center justify-center text-[9px] sm:text-[10px] font-bold mb-0.5",style:{borderColor:t<s?l:"#4b5563",backgroundColor:t<s?`${l}
125`:void 0,color:t<s?i:"#4b5563"},children:t<s?"✓":a}),e.jsx("div",{className:"text-[9px] text-gray-500",children:a})]},t))})]},a))}),e.jsxs("div",{className:"mt-4 pt-3 border-t border-gray-700/50 flex items-center justify-between",children:[e.jsx("span",{className:"text-xs text-gray-400",children:"Total vault slots:"}),e.jsx("span",{className:"text-lg font-bold text-green-400",children:"5/9"})]})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-200 mb-2",children:"Vault Score"}),e.jsx("div",{className:"text-xs text-gray-400 mb-3",children:"Normalized 0–100 composite score combining slot count and reward quality."}),e.jsxs("div",{className:"bg-gray-800/60 rounded-lg p-3 font-mono text-[11px] sm:text-xs text-gray-300 space-y-1 wrap-break-word overflow-x-auto",children:[e.jsxs("div",{children:["Slot Score  = min(slots × 5, 45) ",e.jsx("span",{className:"text-gray-500",children:"// max 45"})]}),e.jsxs("div",{children:["Quality Score = (avg vault iLvl, normalized) ",e.jsx("span",{className:"text-gray-500",children:"// max 55"})]}),e.jsxs("div",{className:"pt-1 border-t border-gray-700/50 text-(--theme-primary-color,#6366f1) font-semibold",children:["Vault Score = Slot Score + Quality Score ",e.jsx("span",{className:"text-gray-500",children:"// 0–100"})]})]})]})]})}),e.jsx(t,{type:"tip",children:"Focus on getting 8 M+ runs per week for the maximum 3 vault slots from dungeons — that is the highest-impact single activity for vault rewards. The Vault Guide modal (toolbar button) shows exact reward item levels per key level and difficulty."})]})},{title:"Tier Set Detection",shortTitle:"Tier Set",icon:R,description:"The audit tracks equipped tier set pieces across 5 slots (Head, Shoulder, Chest, Hands, Legs) and reports 2-piece and 4-piece bonus status. The dashboard shows guild-wide distribution — how many characters have 4pc, 2pc, partial, or none. Detection uses Battle.net Item Set data with Raider.io as a fallback.",tip:"When looking at a character's tier tab, the per-slot breakdown tells you exactly which pieces they still need — focus loot priority on characters close to their next set bonus.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Tier Set Tracking",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(r,{stats:[{label:"4-Piece",value:String(J.tierSetStats.fourPiece),color:"text-purple-400"},{label:"2-Piece",value:String(J.tierSetStats.twoPiece),color:"text-blue-400"},{label:"Partial",value:String(J.tierSetStats.partial),color:"text-yellow-400"},{label:"None",value:String(J.tierSetStats.none),color:"text-gray-400"}]}),e.jsx(i,{items:[{label:"Head",badge:"Equipped",badgeColor:"bg-green-900/30 text-green-400"},{label:"Shoulder",badge:"Equipped",badgeColor:"bg-green-900/30 text-green-400"},{label:"Chest",badge:"Equipped",badgeColor:"bg-green-900/30 text-green-400"},{label:"Hands",badge:"Missing",badgeColor:"bg-gray-700/60 text-gray-400"},{label:"Legs",badge:"Missing",badgeColor:"bg-gray-700/60 text-gray-400"}]})]}),children:e.jsxs("div",{className:"max-w-md mx-auto space-y-3",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx(R,{className:"h-5 w-5 text-purple-400"}),e.jsx("h4",{className:"text-sm font-semibold text-gray-200",children:"Guild Tier Set Distribution"})]}),e.jsx("div",{className:"flex gap-1 mb-3 h-6 rounded-sm overflow-hidden",children:[{label:"4pc",pct:45,cls:"bg-purple-500"},{label:"2pc",pct:27,cls:"bg-blue-500"},{label:"Partial",pct:18,cls:"bg-yellow-500"},{label:"None",pct:10,cls:"bg-gray-600"}].map(({label:a,pct:t,cls:s})=>e.jsx(w.div,{initial:{width:0},animate:{width:`${t}%`},transition:{duration:.5},className:`${s} flex items-center justify-center text-[10px] font-bold text-gray-900`,title:`${a}: ${t}%`,children:t>=10?`${t}%`:""},a))}),e.jsx("div",{className:"flex flex-wrap gap-2",children:[{label:"4-Piece",value:10,cls:"text-purple-400",bg:"bg-purple-500"},{label:"2-Piece",value:6,cls:"text-blue-400",bg:"bg-blue-500"},{label:"Partial",value:4,cls:"text-yellow-400",bg:"bg-yellow-500"},{label:"None",value:2,cls:"text-gray-400",bg:"bg-gray-500"}].map(({label:a,value:t,cls:s,bg:r})=>e.jsxs("span",{className:`inline-flex items-center gap-1.5 text-[11px] ${s}`,children:[e.jsx("span",{className:`w-2 h-2 rounded-xs ${r}`}),a,": ",t]},a))})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-3",children:[e.jsx("div",{className:"w-1 h-4 rounded-full",style:{backgroundColor:K.Paladin}}),e.jsx("span",{className:"text-sm font-medium",style:{color:K.Paladin},children:"Altheria"}),e.jsx("span",{className:"text-xs text-gray-500",children:"Holy Paladin"}),e.jsx("span",{className:"text-xs font-semibold text-blue-400 ml-auto",children:"3/5"})]}),e.jsxs("div",{className:"flex gap-1.5 mb-2",children:[e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-sm bg-blue-900/30 text-blue-400 font-medium",children:"2pc ✓"}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-sm bg-gray-800 text-gray-500 font-medium",children:"4pc —"})]}),e.jsx("div",{className:"space-y-1",children:["Head","Shoulder","Chest","Hands","Legs"].map((a,t)=>{const s=t<3;return e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1 rounded-sm text-xs "+(s?"bg-green-900/15 border border-green-800/30":"bg-gray-800/30 border border-gray-700/30"),children:[s?e.jsx(W,{className:"h-3 w-3 text-green-400"}):e.jsx(T,{className:"h-3 w-3 text-gray-500"}),e.jsx("span",{className:s?"text-green-300":"text-gray-500",children:a})]},a)})})]})]})}),e.jsx(t,{type:"info",children:"Tier set detection uses Battle.net Item Set data with Raider.io as a fallback. The system automatically tracks the current season's tier set across all 5 slots: Head, Shoulder, Chest, Hands, Legs."})]})},{title:"Enchant & Gem Compliance",shortTitle:"Enchants",icon:E,description:"The audit checks enchants on configurable slots (8 of 12 enforced by default) and gems in 3 modes: all sockets, none, or custom. Dashboard cards show distribution (fully enchanted/gemmed, partial, missing). Character detail shows slot-by-slot enchant names and gem info 
1with pass/fail indicators.",tip:"Customize enforced enchant slots in the Config panel — not all 12 possible slots have relevant enchants every season. The defaults (Chest, Legs, Wrist, Feet, Rings, Weapon, Back) cover the most common slots.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Enchant & Gem Compliance",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(i,{items:[{label:"Chest",badge:"Crystalline Radiance",badgeColor:"bg-green-900/30 text-green-400"},{label:"Legs",badge:"Stormbound Armor Kit",badgeColor:"bg-green-900/30 text-green-400"},{label:"Wrist",badge:"Missing",badgeColor:"bg-red-900/30 text-red-400"},{label:"Feet",badge:"Defender's March",badgeColor:"bg-green-900/30 text-green-400"},{label:"Finger 1",badge:"Radiant Haste",badgeColor:"bg-green-900/30 text-green-400"},{label:"Finger 2",badge:"Radiant Mastery",badgeColor:"bg-green-900/30 text-green-400"},{label:"Main Hand",badge:"Authority of Storms",badgeColor:"bg-green-900/30 text-green-400"},{label:"Back",badge:"Missing",badgeColor:"bg-red-900/30 text-red-400"}]}),e.jsx(x,{items:[{label:"Gem mode: Check All Sockets",enabled:!0},{label:"Enforce current tier only",enabled:!0}]})]}),children:e.jsxs("div",{className:"max-w-md mx-auto space-y-3",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-200 mb-3",children:"Enchant Check — Darkflame"}),e.jsx("div",{className:"space-y-1.5",children:[{slot:"Chest",enchant:"Crystalline Radiance",ok:!0},{slot:"Legs",enchant:"Stormbound Armor Kit",ok:!0},{slot:"Wrist",enchant:null,ok:!1},{slot:"Feet",enchant:"Defender's March",ok:!0},{slot:"Finger 1",enchant:"Radiant Haste",ok:!0},{slot:"Finger 2",enchant:"Radiant Mastery",ok:!0},{slot:"Main Hand",enchant:"Authority of Storms",ok:!0},{slot:"Back",enchant:null,ok:!1}].map(({slot:a,enchant:t,ok:s})=>e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 rounded-sm text-xs "+(s?"bg-gray-800/40":"bg-red-900/15 border border-red-800/30"),children:[s?e.jsx(W,{className:"h-3 w-3 shrink-0 text-green-400"}):e.jsx(T,{className:"h-3 w-3 shrink-0 text-red-400"}),e.jsx("span",{className:"text-gray-300 w-14 shrink-0",children:a}),e.jsx("span",{className:"min-w-0 wrap-break-word "+(s?"text-gray-400":"text-red-400 font-medium"),children:t||"Missing"})]},a))})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsx(P,{className:"h-4 w-4 text-gray-400"}),e.jsx("h4",{className:"text-xs font-semibold text-gray-200",children:"Configurable Enforcement"})]}),e.jsxs("div",{className:"text-[11px] text-gray-400 space-y-1",children:[e.jsx("div",{children:"Default enforced: Chest, Legs, Wrist, Feet, Finger ×2, Main Hand, Back"}),e.jsx("div",{children:"Gem modes: Check All Sockets • Skip All • Custom Slots"}),e.jsx("div",{className:"text-gray-500 italic",children:"Adjustable via the Audit Config panel"})]})]})]})}),e.jsx(t,{type:"tip",children:"Customize which enchant slots are enforced in the Config panel (gear icon in the toolbar). Not all slots have relevant enchants every season — adjust the 12 available checkboxes to match current expectations."})]})},{title:"Historical Trends & Snapshots",shortTitle:"Trends",icon:f,description:"Weekly snapshots capture item level, M+ rating, vault slots, tier pieces, enchants, and gems per character. Enable historical trends to see 4 charts: average item level bars, vault completion rates, tier set stacked progress, and M+ activity with average key levels. Adjust the weeks slider (1–12) to control how far back the charts look.",tip:"Snapshots are created on demand via the toolbar Snapshot button — they are NOT automatic. Take one at the same time each week (e.g., before your first raid) for consistent trend tracking.",component:()=>{const a=Math.max(..._.map(e=>e.itemLevel)),l=Math.min(..._.map(e=>e.itemLevel)),i=a-l||1;return e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Historical Trends",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(o,{pairs:_.map((e,a)=>{const t="string"==typeof e.weekStartDate?e.weekStartDate.slice(0,10):"",[,s,r]=t.split("-");return{label:s&&r?`Week ${a+1} (${parseInt(s,10)}/${parseInt(r,10)})`:`Week ${a+1}`,value:`${e.itemLevel} iLvl`,color:"text-(--theme-primary-color,#6366f1)"}})}),e.jsx(r,{stats:[{label:"M+ Runs (latest)",value:String(_[_.length-1].mythicPlusRuns),color:"text-orange-400"},{label:"Avg Key Level",value:String(_[_.length-1].avgMythicPlusKey),color:"text-orange-400"},{label:"Full Vault (latest)",value:String(_[_.length-1].fullVaultCount),color:"text-green-400"},{label:"4-Piece (latest)",value:String(_[_.length-1].tierSetStats.fourPiece),color:"text-purple-400"}]})]}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Average Item Level"}),e.jsx("div",{className:"h-28 flex items-stretch gap-2",children:_.map((a,t)=>{const s=(a.itemLevel-l)/i*100,r="string"==typeof a.weekStartDate?a.weekStartDate.slice(0,10):"",[,o,n]=r.split("-"),c=o&&n?`${parseInt(o,10)}/${parseInt(n,10)}`:"";return e.jsxs(w.div,{className:"flex-1 flex flex-col items-center gap-1",initial:{opacity:0,scaleY:0}
1,animate:{opacity:1,scaleY:1},transition:{delay:.1*t,duration:.3},style:{transformOrigin:"bottom"},children:[e.jsx("div",{className:"text-[9px] text-gray-400 font-medium",children:a.itemLevel}),e.jsx("div",{className:"flex-1 w-full relative",children:e.jsx("div",{className:"absolute inset-x-0 bottom-0 bg-(--theme-primary-color,#6366f1) rounded-xs opacity-80",style:{height:`${Math.max(s,15)}%`}})}),e.jsx("div",{className:"text-[9px] text-gray-500",children:c})]},t)})})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Tier Set Progress Over Time"}),e.jsx("div",{className:"space-y-1.5",children:_.map((a,t)=>{const s=a.tierSetStats,r=Object.values(s).reduce((e,a)=>e+a,0)||1;return e.jsxs("div",{children:[e.jsxs("div",{className:"text-[10px] text-gray-400 mb-0.5",children:["Week ",t+1]}),e.jsx("div",{className:"flex gap-0.5 h-5 rounded-sm overflow-hidden",children:[{value:s.fourPiece,cls:"bg-purple-500"},{value:s.twoPiece,cls:"bg-blue-500"},{value:s.partial,cls:"bg-yellow-500"},{value:s.none,cls:"bg-gray-600"}].map(({value:a,cls:s},l)=>e.jsx(w.div,{className:s,initial:{width:0},animate:{width:a/r*100+"%"},transition:{delay:.08*t,duration:.3},style:{minWidth:a>0?"8px":"0"}},l))})]},t)})})]})]})}),e.jsxs(t,{type:"info",children:["Weekly snapshots are captured ",e.jsx("strong",{children:"automatically"})," every day at 18:00 UTC for every active roster. You can also take a manual snapshot at any time via the Snapshot button in the toolbar (useful for capturing pre-raid state). Historical trends follow each character regardless of which roster they're in, so two rosters that share players will see the same history. The weeks slider (1–12) controls how far back the charts look."]})]})}},{title:"Upgrade Tracks & Crest Sources",shortTitle:"Upgrades",icon:f,description:"The Upgrade Guide modal shows two parallel upgrade columns: Veteran→Hero and Champion→Myth, each with 6 steps requiring specific crests. Additional tabs cover Crest Sources (where to earn each type), Crafting (spark costs and quality tiers), and Raid Loot (boss-by-boss item levels per difficulty for all 3 current raids).",tip:"These are two parallel paths, not sequential. Veteran→Hero tracks Heroic-tier gear, Champion→Myth tracks higher-tier sources. Check the Crest Sources tab to plan your weekly crest farming.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Upgrade Guide",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(m,{steps:[{label:"Veteran 1/6 — 259 iLvl",status:"done"},{label:"Veteran 4/6 — 262 iLvl",status:"done"},{label:"Champion 1/6 — 268 iLvl",status:"active"},{label:"Hero 1/6 — 272 iLvl"},{label:"Hero 4/6 — 276 iLvl"}]}),e.jsx(m,{steps:[{label:"Champion 1/6 — 246 iLvl",status:"done"},{label:"Champion 4/6 — 249 iLvl",status:"done"},{label:"Hero 1/6 — 255 iLvl",status:"done"},{label:"Myth 1/6 — 259 iLvl",status:"active"},{label:"Myth 4/6 — 263 iLvl"}]})]}),children:e.jsxs("div",{className:"space-y-4 max-w-lg mx-auto",children:[e.jsx(p,{}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Veteran → Hero"}),e.jsx("div",{className:"space-y-1",children:[{track:"veteran",ilvl:259,step:"1/6"},{track:"veteran",ilvl:262,step:"4/6"},{track:"champion",ilvl:268,step:"1/6"},{track:"hero",ilvl:272,step:"1/6"},{track:"hero",ilvl:276,step:"4/6"}].map(({track:a,ilvl:t,step:s},r)=>e.jsxs(w.div,{initial:{opacity:0,x:-6},animate:{opacity:1,x:0},transition:{delay:.04*r},className:"flex items-center gap-2 text-[11px]",children:[e.jsx(g,{track:a,size:"xs"}),e.jsx("span",{className:"text-gray-300 font-medium",children:t}),e.jsx("span",{className:"text-gray-500 ml-auto",children:s})]},r))})]}),e.jsxs("div",{className:"bg-gray-900/50 border border-gray-700/50 rounded-lg p-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-200 mb-2",children:"Champion → Myth"}),e.jsx("div",{className:"space-y-1",children:[{track:"champion",ilvl:246,step:"1/6"},{track:"champion",ilvl:249,step:"4/6"},{track:"hero",ilvl:255,step:"1/6"},{track:"myth",ilvl:259,step:"1/6"},{track:"myth",ilvl:263,step:"4/6"}].map(({track:a,ilvl:t,step:s},r)=>e.jsxs(w.div,{initial:{opacity:0,x:-6}
1,animate:{opacity:1,x:0},transition:{delay:.04*r},className:"flex items-center gap-2 text-[11px]",children:[e.jsx(g,{track:a,size:"xs"}),e.jsx("span",{className:"text-gray-300 font-medium",children:t}),e.jsx("span",{className:"text-gray-500 ml-auto",children:s})]},r))})]})]}),e.jsx("div",{className:"text-[10px] text-gray-500 text-center",children:"The Upgrade Guide modal (toolbar button) has 4 tabs: Upgrade Tracks, Crest Sources, Crafting, and Raid Loot with exact item levels for every source."})]})}),e.jsxs(t,{type:"info",children:["These are ",e.jsx("strong",{children:"two parallel upgrade columns"}),", not a single linear path. Veteran→Hero tracks gear from Heroic-level sources, while Champion→Myth tracks gear from higher-tier sources like Mythic raids. Each track has 6 upgrade steps requiring specific crests."]})]})},{title:"Audit Configuration",shortTitle:"Config",icon:F,description:"The Audit Config panel lets you customize what the audit enforces: 12 possible enchant slots (8 default), gem mode (all sockets, skip, or custom), and current-tier-only toggle for tier set validation. Config is saved per-roster. Requires the players.manage permission.",tip:"Review your audit config at the start of each season — enchant slot requirements and gem expectations change with new gear.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Audit Configuration",mobileContent:e.jsxs("div",{className:"space-y-3",children:[e.jsx(x,{items:[{label:"Chest",desc:"Enchant required",enabled:!0},{label:"Legs",desc:"Enchant required",enabled:!0},{label:"Wrist",desc:"Enchant required",enabled:!0},{label:"Feet",desc:"Enchant required",enabled:!0},{label:"Finger 1",desc:"Enchant required",enabled:!0},{label:"Finger 2",desc:"Enchant required",enabled:!0},{label:"Main Hand",desc:"Enchant required",enabled:!0},{label:"Back",desc:"Enchant required",enabled:!0},{label:"Head",desc:"Not enforced",enabled:!1},{label:"Shoulder",desc:"Not enforced",enabled:!1},{label:"Enforce current tier only",desc:"Tier set detection",enabled:!0}]}),e.jsx(o,{pairs:[{label:"Gem Mode",value:"Check All Sockets"},{label:"Permission",value:"players.manage",color:"text-amber-400"}]})]}),children:e.jsxs("div",{className:"max-w-md mx-auto bg-gray-900/70 border border-gray-700/50 rounded-xl p-3 sm:p-5 space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-1",children:[e.jsx(F,{className:"h-5 w-5 text-gray-400"}),e.jsx("h3",{className:"text-sm font-bold text-gray-100",children:"Audit Config"}),e.jsx(se,{perm:"players.manage"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[10px] text-gray-400 uppercase tracking-wider font-semibold block mb-2",children:"Enchant Requirements (8 of 12 enforced)"}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 gap-1.5",children:[{slot:"Chest",on:!0},{slot:"Legs",on:!0},{slot:"Wrist",on:!0},{slot:"Feet",on:!0},{slot:"Finger 1",on:!0},{slot:"Finger 2",on:!0},{slot:"Main Hand",on:!0},{slot:"Back",on:!0},{slot:"Head",on:!1},{slot:"Shoulder",on:!1},{slot:"Hands",on:!1},{slot:"Off Hand",on:!1}].map(({slot:a,on:t})=>e.jsxs("div",{className:"flex items-center gap-1.5 px-2 py-1 rounded-sm text-[11px] "+(t?"bg-green-900/15 text-green-400 border border-green-800/30":"bg-gray-800/40 text-gray-500 border border-gray-700/30"),children:[e.jsx("div",{className:"w-3 h-3 shrink-0 rounded-sm border "+(t?"bg-green-500 border-green-500":"border-gray-600"),children:t&&e.jsx(W,{className:"h-3 w-3 text-gray-900"})}),e.jsx("span",{className:"truncate",children:a})]},a))})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[10px] text-gray-400 uppercase tracking-wider font-semibold block mb-2",children:"Gem Enforcement"}),e.jsx("div",{className:"space-y-1",children:["Check All Sockets","Skip All","Custom Slots"].map((a,t)=>e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 rounded-sm text-xs "+(0===t?"bg-(--theme-primary-color,#6366f1)/10 text-(--theme-primary-color,#6366f1) border border-(--theme-primary-color,#6366f1)/30":"text-gray-400 border border-gray-700/30"),children:[e.jsx("div",{className:"w-3 h-3 rounded-full border-2 "+(0===t?"border-(--theme-primary-color,#6366f1) bg-(--theme-primary-color,#6366f1)":"border-gray-600")}),a]},a))})]}),e.jsxs("div",{className:"flex items-center justify-between py-1",children:[e.jsx("span",{className:"text-xs text-gray-300",children:"Enforce 
1current tier only"}),e.jsx("div",{className:"w-8 h-4 rounded-full bg-green-500/30 flex items-center px-0.5",children:e.jsx("div",{className:"w-3 h-3 rounded-full bg-green-400 ml-auto"})})]})]})}),e.jsx(t,{type:"info",children:"Config is saved per-roster in the roster settings. Changes affect what the audit flags as “missing” — a character with no wrist enchant won't be flagged if you uncheck the Wrist slot."})]})},{title:"Export & Sharing",shortTitle:"Export",icon:N,description:"Export audit data in 3 formats: CSV spreadsheet (all metrics per character), JSON (machine-readable for tools), or Discord embed (formatted summary copied to clipboard). Exports can optionally include historical snapshot data with a configurable weeks-back range (1–24 weeks).",tip:"Use the Discord embed export to share a formatted raid readiness summary with your raiders — it includes top characters by item level, averages, and vault completion.",component:()=>e.jsxs(e.Fragment,{children:[e.jsx(s,{label:"Export Options",children:e.jsxs("div",{className:"max-w-sm mx-auto space-y-3",children:[[{format:"CSV Spreadsheet",desc:"Full audit data with all metrics per character",icon:N,color:"text-green-400",bg:"bg-green-900/20"},{format:"JSON Data",desc:"Machine-readable export for external tools",icon:O,color:"text-blue-400",bg:"bg-blue-900/20"},{format:"Discord Embed",desc:"Formatted summary copied to clipboard for Discord",icon:u,color:"text-purple-400",bg:"bg-purple-900/20"}].map(({format:a,desc:t,icon:s,color:r,bg:l},i)=>e.jsxs(w.div,{initial:{opacity:0,x:-8},animate:{opacity:1,x:0},transition:{delay:.08*i},className:`flex items-center gap-3 p-3 rounded-lg ${l} border border-gray-700/30`,children:[e.jsx(s,{className:`h-5 w-5 ${r} shrink-0`}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-gray-200",children:a}),e.jsx("div",{className:"text-[10px] text-gray-500",children:t})]})]},a)),e.jsxs("div",{className:"bg-gray-800/40 border border-gray-700/30 rounded-lg p-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(P,{className:"h-4 w-4 text-gray-400"}),e.jsx("span",{className:"text-xs font-medium text-gray-200",children:"Export Options"})]}),e.jsxs("div",{className:"space-y-1.5 text-[11px] text-gray-400",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-3 h-3 rounded-sm border bg-green-500 border-green-500",children:e.jsx(W,{className:"h-3 w-3 text-gray-900"})}),"Include historical data"]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{children:"Weeks back:"}),e.jsx("span",{className:"bg-gray-700 rounded-sm px-1.5 py-0.5 text-gray-200 font-medium",children:"4"})]})]})]})]})}),e.jsx(t,{type:"tip",children:"Use the Discord embed export to share a formatted raid readiness summary directly in your server. It includes top characters by item level, overall averages, and vault completion rates."})]})}];function le({onDone:a,initialStep:t=0,guideId:s}){return e.jsx(h,{steps:re,onDone:a,initialStep:t,guideId:s})}export{le as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.