{
const cleaned = latestYearData
.filter(d =>
d["Occupational Category"] &&
!isNaN(+d["Men Median Pa"]) &&
!isNaN(+d["Women Median Pay"]) &&
!isNaN(+d["%women workers"])
)
.map(d => ({
Occupation: d["Occupational Category"],
Men_Earnings: +d["Men Median Pa"],
Women_Earnings: +d["Women Median Pay"],
AverageIncome: (+d["Men Median Pa"] + +d["Women Median Pay"]) / 2,
FemalePct: +d["%women workers"],
MalePct: 100 - +d["%women workers"]
}));
const sorted = cleaned.sort((a, b) => a.AverageIncome - b.AverageIncome);
const width = 900;
const height = 550;
const margin = { top: 60, right: 20, bottom: 180, left: 80 };
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
const x = d3.scaleBand()
.domain(sorted.map(d => d.Occupation))
.range([margin.left, width - margin.right])
.padding(0.2);
const y = d3.scaleLinear()
.domain([0, d3.max(sorted, d => d.AverageIncome)]).nice()
.range([height - margin.bottom, margin.top + 40]);
const color = d3.scaleSequential()
.domain([0, 100])
.interpolator(d3.interpolateRgb("#fce4ec", "#880e4f"));
// Title
svg.append("text")
.attr("x", width / 2)
.attr("y", margin.top - 30)
.attr("text-anchor", "middle")
.style("font-size", "18px")
.style("font-weight", "bold")
.text("Average Income by Occupation");
// Axis
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(6).tickFormat(d3.format("$.0f")));
// Bars
const bars = svg.selectAll("rect")
.data(sorted)
.join("rect")
.attr("x", d => x(d.Occupation))
.attr("y", d => y(d.AverageIncome))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.AverageIncome))
.attr("fill", d => color(d.FemalePct))
.style("opacity", 0.9)
.style("cursor", "pointer");
// Labels under bars
svg.selectAll("text.label")
.data(sorted)
.join("text")
.attr("class", "label")
.attr("x", d => x(d.Occupation) + x.bandwidth() / 2)
.attr("y", height - margin.bottom + 10)
.attr("transform", d => `rotate(-60, ${x(d.Occupation) + x.bandwidth() / 2}, ${height - margin.bottom + 10})`)
.attr("text-anchor", "end")
.attr("font-size", 10)
.text(d => d.Occupation);
// Gradient Legend
const legendWidth = 200;
const legendHeight = 12;
const legendX = width / 2 - legendWidth / 2;
const legendY = margin.top;
const defs = svg.append("defs");
const gradient = defs.append("linearGradient")
.attr("id", "female-gradient")
.attr("x1", "0%")
.attr("x2", "100%");
gradient.append("stop").attr("offset", "0%").attr("stop-color", "#fce4ec");
gradient.append("stop").attr("offset", "100%").attr("stop-color", "#880e4f");
const legendGroup = svg.append("g").attr("transform", `translate(${legendX}, ${legendY})`);
legendGroup.append("rect")
.attr("width", legendWidth)
.attr("height", legendHeight)
.attr("fill", "url(#female-gradient)")
.attr("stroke", "gray")
.attr("stroke-width", 0.5);
legendGroup.append("text")
.attr("x", 0)
.attr("y", -4)
.attr("text-anchor", "start")
.style("font-size", "10px")
.text("0% women");
legendGroup.append("text")
.attr("x", legendWidth)
.attr("y", -4)
.attr("text-anchor", "end")
.style("font-size", "10px")
.text("100% women");
// Tooltip with Font Awesome icons
const tooltip = html`<div style="
position: absolute;
pointer-events: none;
background: white;
border: 1px solid #ccc;
padding: 6px 10px;
border-radius: 4px;
font-size: 13px;
box-shadow: 0 1px 5px rgba(0,0,0,0.15);
display: none;
line-height: 1.6;
white-space: nowrap;
"></div>`;
document.body.appendChild(tooltip);
const container = html`<div style="position: relative; width: ${width}px; height: ${height}px;"></div>`;
container.appendChild(svg.node());
bars
.on("mouseover", function (event, d) {
d3.select(this).style("opacity", 1.8);
tooltip.innerHTML = `
<i class="fa-solid fa-person-dress" style="color: #d1006f;"></i> ${d.FemalePct.toFixed(1)}% women<br>
<i class="fa-solid fa-person" style="color: #1f77b4;"></i> ${d.MalePct.toFixed(1)}% men<br>
💰 Women earn: $${d.Women_Earnings.toLocaleString()}<br>
💰 Men earn: $${d.Men_Earnings.toLocaleString()}
`;
tooltip.style.display = "block";
})
.on("mousemove", function (event) {
tooltip.style.left = event.pageX + 12 + "px";
tooltip.style.top = event.pageY - 28 + "px";
})
.on("mouseout", function () {
tooltip.style.display = "none";
bars.style("opacity", 0.9);
});
return container;
}