// Capability Rich Map — show all 8 domains + all skills at once. // No clicks, no modal. The whole picture at a glance, like a constellation. function CapabilityWheel() { const caps = window.CAPABILITIES; const N = caps.length; // 8 const SIZE = 1100; // SVG viewBox const cx = SIZE/2, cy = SIZE/2; const rCore = 110; // inner "Wealth Advisor" disc const rWedge = 230; // domain wedge outer const rSkillsIn = 295; // inner skill ring const rSkillsOut = 440; // outer skill ring const rArc = 510; // arc text label radius const sweep = 360 / N; // 45° const gap = 1.6; // wedge gap (deg) // Pre-flatten all skills with their absolute angle so we can assign a // strictly-alternating radius per global index. This guarantees adjacent // skills (within a wedge AND across wedge boundaries) never share a radius. const flatSkills = []; caps.forEach((c, i) => { const M = c.skills.length; const wedgeStart = i * sweep + gap/2 + 1.6; const wedgeEnd = (i+1) * sweep - gap/2 - 1.6; const range = wedgeEnd - wedgeStart; c.skills.forEach((s, k) => { const t = M === 1 ? 0.5 : (k + 0.5) / M; const ang = wedgeStart + t * range; flatSkills.push({ cap: c, skill: s, ang, idx: flatSkills.length }); }); }); function deg2xy(angDeg, r) { const a = (angDeg - 90) * Math.PI / 180; return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) }; } function wedgePath(startDeg, endDeg, rOut, rIn) { const p1 = deg2xy(startDeg, rOut); const p2 = deg2xy(endDeg, rOut); const p3 = deg2xy(endDeg, rIn); const p4 = deg2xy(startDeg, rIn); const large = (endDeg - startDeg) > 180 ? 1 : 0; return `M ${p1.x} ${p1.y} A ${rOut} ${rOut} 0 ${large} 1 ${p2.x} ${p2.y} L ${p3.x} ${p3.y} A ${rIn} ${rIn} 0 ${large} 0 ${p4.x} ${p4.y} Z`; } // path along an arc — for arc text labels function arcPath(startDeg, endDeg, r) { const p1 = deg2xy(startDeg, r); const p2 = deg2xy(endDeg, r); const large = (endDeg - startDeg) > 180 ? 1 : 0; return `M ${p1.x} ${p1.y} A ${r} ${r} 0 ${large} 1 ${p2.x} ${p2.y}`; } return (

05 · CAPABILITY MAP

One advisor. Eight domains.
Forty observable skills.

Each domain has its own competency anchors and rubric. Every skill is observable, coachable, and scored consistently across teams and regions.

{/* Background image-slot — faint, framed inside the wheel */}
{caps.map(c => ( ))} {/* faint guide rings — slow counter-rotation for depth */} {/* arc-text band labels — slow orbit, elegant rotation */} {[ { from: -22.5, to: 112.5, text: 'AMBIZ LADDER · AMBIZ LADDER ·' , id: 'arc-ladder' }, { from: 112.5, to: 247.5, text: 'SCALE & CONTROL · SCALE & CONTROL ·' , id: 'arc-scale' }, { from: 247.5, to: 337.5, text: 'STANDARD OF EXCELLENCE ·' , id: 'arc-standard' }, ].map(a => ( {a.text} ))} {/* 8 wedges — each capability */} {caps.map((c, i) => { const start = i * sweep + gap/2; const end = (i+1) * sweep - gap/2; const mid = (start + end) / 2; const labelR = (140 + rWedge) / 2 + 10; const lp = deg2xy(mid, labelR); // Multi-line title — short label up top, then a thin divider const lines = c.name.split(' '); // group words into 2 lines roughly const half = Math.ceil(lines.length / 2); const line1 = lines.slice(0, half).join(' '); const line2 = lines.slice(half).join(' '); return ( {/* tick line out toward skills */} {(() => { const a1 = deg2xy(mid, rWedge + 6); const a2 = deg2xy(mid, rSkillsIn - 50); return ; })()} {line1} {line2} ); })} {/* Core circle — gently breathing */} THE STANDARD Wealth Advisor {/* HTML skill labels — flat list with strictly-alternating radii by global index. Guarantees no two adjacent labels share a radius slot, eliminating wedge-boundary collisions. */} {flatSkills.map(({ cap: c, skill: s, ang, idx }) => { const r = (idx % 2 === 0) ? rSkillsIn : rSkillsOut; const pos = deg2xy(ang, r); const pctX = (pos.x / SIZE) * 100; const pctY = (pos.y / SIZE) * 100; const normalized = ((ang % 360) + 360) % 360; const leftHalf = normalized > 180; return (
{s}
); })}
{/* Legend strip — total at a glance */}
{caps.map((c, i) => (
0{i+1} {c.short} {c.skills.length} skills
))}
); } window.CapabilityWheel = CapabilityWheel;