--- a/src/chart.js
+++ b/src/chart.js
@@ -12,8 +12,10 @@
 const svg = d3.select("#incident-chart");
 const chartContainer = document.getElementById("chart-container");
 const legendContainer = document.getElementById("legend");
+const tooltip = d3.select("#tooltip");
 
 let rawData = [];
+let activeSeverities = new Set(SEVERITY_ORDER);
 
 init();
 
@@ -24,9 +26,11 @@
   renderLegend(SEVERITY_ORDER);
   renderChart(rawData);
 
-  // TODO: add ResizeObserver for responsive redraw.
-  // TODO: add legend click toggles that filter active severities.
-  // TODO: add bar-level tooltip interaction.
+  // Responsive resize observer
+  const resizeObserver = new ResizeObserver(() => {
+    renderChart(rawData);
+  });
+  resizeObserver.observe(chartContainer);
 }
 
 function renderLegend(severities) {
@@ -35,14 +39,33 @@
     const chip = document.createElement("button");
     chip.type = "button";
     chip.textContent = severity;
-    chip.title = "Legend toggle not wired yet";
+    chip.className = activeSeverities.has(severity) ? "active" : "";
+    chip.title = `Toggle ${severity} severity`;
+    chip.setAttribute("aria-pressed", activeSeverities.has(severity));
     chip.style.borderColor = SEVERITY_COLORS[severity];
-    chip.style.boxShadow = `inset 0 0 0 1px ${SEVERITY_COLORS[severity]}33`;
+    chip.style.backgroundColor = activeSeverities.has(severity)
+      ? SEVERITY_COLORS[severity]
+      : "transparent";
+    chip.style.color = activeSeverities.has(severity) ? "#fff" : SEVERITY_COLORS[severity];
+
+    chip.addEventListener("click", () => {
+      if (activeSeverities.has(severity)) {
+        if (activeSeverities.size > 1) activeSeverities.delete(severity);
+      } else {
+        activeSeverities.add(severity);
+      }
+      renderLegend(SEVERITY_ORDER);
+      renderChart(rawData);
+    });
+
     legendContainer.appendChild(chip);
   });
 }
 
 function renderChart(data) {
+  const filtered = data.filter((d) => activeSeverities.has(d.severity));
+  const activeSevOrder = SEVERITY_ORDER.filter((s) => activeSeverities.has(s));
+
   const width = chartContainer.clientWidth;
   const height = 420;
   const innerWidth = width - margin.left - margin.right;
@@ -56,20 +79,29 @@
     .attr("transform", `translate(${margin.left},${margin.top})`);
 
   const months = [...new Set(data.map((d) => d.month))];
-  const grouped = d3.groups(data, (d) => d.month);
+  const grouped = d3.groups(filtered, (d) => d.month);
 
   const xMonth = d3.scaleBand().domain(months).range([0, innerWidth]).padding(0.22);
   const xSeverity = d3
     .scaleBand()
-    .domain(SEVERITY_ORDER)
+    .domain(activeSevOrder)
     .range([0, xMonth.bandwidth()])
     .padding(0.12);
 
   const y = d3
     .scaleLinear()
-    .domain([0, d3.max(data, (d) => d.count)])
+    .domain([0, d3.max(filtered, (d) => d.count) || 1])
     .nice()
     .range([innerHeight, 0]);
+
+  // Grid lines
+  g.append("g")
+    .attr("class", "grid")
+    .call(d3.axisLeft(y).tickSize(-innerWidth).tickFormat(""))
+    .selectAll("line")
+    .attr("stroke", "#e2e8f0")
+    .attr("stroke-dasharray", "2,3");
+  g.select(".grid .domain").remove();
 
   g.append("g")
     .attr("transform", `translate(0,${innerHeight})`)
@@ -95,8 +127,17 @@
     .attr("y", (d) => y(d.count))
     .attr("width", xSeverity.bandwidth())
     .attr("height", (d) => innerHeight - y(d.count))
+    .attr("rx", 2)
     .attr("fill", (d) => SEVERITY_COLORS[d.severity] || "#64748b")
-    .attr("opacity", 0.9);
+    .attr("opacity", 0.9)
+    .attr("tabindex", 0)
+    .attr("role", "img")
+    .attr("aria-label", (d) => `${d.month} ${d.severity}: ${d.count} incidents`)
+    .on("pointerenter", showTooltip)
+    .on("pointermove", moveTooltip)
+    .on("pointerleave", hideTooltip)
+    .on("focus", showTooltip)
+    .on("blur", hideTooltip);
 
   g.append("text")
     .attr("class", "axis-label")
@@ -113,3 +154,31 @@
     .attr("text-anchor", "middle")
     .text("Incident count");
 }
+
+/* ---- Tooltip helpers ---- */
+
+function showTooltip(event, d) {
+  const datum = d.severity ? d : event.target.__data__;
+  tooltip
+    .classed("visible", true)
+    .html(
+      `<strong>${datum.month}</strong><br/>` +
+      `<span class="swatch" style="background:${SEVERITY_COLORS[datum.severity]}"></span> ` +
+      `${datum.severity}: <strong>${datum.count}</strong> incidents`
+    );
+  moveTooltip(event);
+}
+
+function moveTooltip(event) {
+  const rect = chartContainer.getBoundingClientRect();
+  let x = event.clientX - rect.left + 14;
+  let y = event.clientY - rect.top - 10;
+  // Keep tooltip inside container
+  const tw = 180;
+  if (x + tw > rect.width) x = x - tw - 28;
+  tooltip.style("left", x + "px").style("top", y + "px");
+}
+
+function hideTooltip() {
+  tooltip.classed("visible", false);
+}
