@empoweredvote/ev-ui 0.8.14 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -50,6 +50,7 @@ __export(index_exports, {
50
50
  JudicialScorecard: () => JudicialScorecard,
51
51
  LegislativeInlineSummary: () => LegislativeInlineSummary,
52
52
  LegislativeRecord: () => LegislativeRecord,
53
+ PlaceholderRadar: () => PlaceholderRadar,
53
54
  PoliticianCard: () => PoliticianCard,
54
55
  PoliticianProfile: () => PoliticianProfile,
55
56
  RadarChartCore: () => RadarChartCore,
@@ -69,6 +70,7 @@ __export(index_exports, {
69
70
  defaultNavItems: () => defaultNavItems,
70
71
  duration: () => duration,
71
72
  easing: () => easing,
73
+ evAppLinks: () => evAppLinks,
72
74
  evContext: () => evContext,
73
75
  focus: () => focus,
74
76
  fontSizes: () => fontSizes,
@@ -134,7 +136,8 @@ function RadarChartCore({
134
136
  labelFontSize = 18,
135
137
  padding = 80,
136
138
  labelOffset = 20,
137
- tightFit = false
139
+ tightFit = false,
140
+ maxLabelLines = 2
138
141
  }) {
139
142
  const { isDark } = useTheme();
140
143
  const radius = size / 2 - 40;
@@ -201,7 +204,7 @@ function RadarChartCore({
201
204
  const labelMeta = spokes.map(([shortTitle], i) => {
202
205
  const angle = 2 * Math.PI * i / numSpokes;
203
206
  const baseFSize = labelFontSize;
204
- const lines = wrapLabel(shortTitle, 12);
207
+ const lines = wrapLabel(shortTitle, 12, maxLabelLines);
205
208
  const longestLineLen = lines.reduce(
206
209
  (max, ln) => ln.length > max ? ln.length : max,
207
210
  0
@@ -244,7 +247,8 @@ function RadarChartCore({
244
247
  if (y < yMin) yMin = y;
245
248
  if (y > yMax) yMax = y;
246
249
  }
247
- const labelMargin = labelOffset + labelFontSize * 1.4 + labelFontSize * 1.1;
250
+ const effLabelFSize = adaptiveFontSize(12, labelFontSize);
251
+ const labelMargin = labelOffset + effLabelFSize * 1.1 * maxLabelLines;
248
252
  tightTop = yMin - labelMargin;
249
253
  tightHeight = yMax + labelMargin - tightTop;
250
254
  }
@@ -296,7 +300,7 @@ function RadarChartCore({
296
300
  const isTop = cosA > 0.5;
297
301
  const isBottom = cosA < -0.5;
298
302
  const baseFSize = labelFontSize;
299
- const lines = wrapLabel(shortTitle, 12);
303
+ const lines = wrapLabel(shortTitle, 12, maxLabelLines);
300
304
  const longestLine = lines.reduce(
301
305
  (max, ln) => ln.length > max ? ln.length : max,
302
306
  0
@@ -437,7 +441,7 @@ function RadarChartCore({
437
441
  function adaptiveFontSize(longestLineLen, baseFSize) {
438
442
  return Math.max(baseFSize, 10);
439
443
  }
440
- function wrapLabel(label, maxChars = 12) {
444
+ function wrapLabel(label, maxChars = 12, maxLines = 2) {
441
445
  const str = String(label);
442
446
  let rawWords;
443
447
  if (str.includes("/")) {
@@ -462,15 +466,15 @@ function wrapLabel(label, maxChars = 12) {
462
466
  }
463
467
  }
464
468
  if (line) lines.push(line);
465
- if (lines.length > 2) {
466
- const overflow = lines.splice(2).join(" ");
467
- lines[1] = lines[1] + " " + overflow;
469
+ if (lines.length > maxLines) {
470
+ const overflow = lines.splice(maxLines).join(" ");
471
+ lines[maxLines - 1] = lines[maxLines - 1] + " " + overflow;
468
472
  }
469
473
  return lines;
470
474
  }
471
475
 
472
- // src/Header.jsx
473
- var import_react5 = __toESM(require("react"));
476
+ // src/PlaceholderRadar.jsx
477
+ var import_react4 = __toESM(require("react"));
474
478
 
475
479
  // src/tokens.js
476
480
  var colorScales = {
@@ -865,14 +869,95 @@ var breakpoints = {
865
869
  xl: "1280px"
866
870
  };
867
871
 
872
+ // src/PlaceholderRadar.jsx
873
+ function PlaceholderRadar({ size = 250, name = "", darkMode = false }) {
874
+ const cx = size / 2;
875
+ const cy = size / 2;
876
+ const r = size / 2 * 0.65;
877
+ const n = 8;
878
+ const surface = darkMode ? "#1e2a3a" : colorScales.teal["050"];
879
+ const stroke = darkMode ? "rgba(255,255,255,0.22)" : colorScales.gray["200"];
880
+ const vertices = Array.from({ length: n }, (_, i) => {
881
+ const a = 2 * Math.PI * i / n;
882
+ return [cx + r * Math.sin(a), cy - r * Math.cos(a)];
883
+ });
884
+ const outerPts = vertices.map(([x, y]) => `${x},${y}`).join(" ");
885
+ const midPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.6},${cy + (y - cy) * 0.6}`).join(" ");
886
+ const innerPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.3},${cy + (y - cy) * 0.3}`).join(" ");
887
+ return /* @__PURE__ */ import_react4.default.createElement(
888
+ "svg",
889
+ {
890
+ width: size,
891
+ height: size,
892
+ viewBox: `0 0 ${size} ${size}`,
893
+ role: "img",
894
+ "aria-label": name ? `${name} \u2014 compass data unavailable` : "compass data unavailable",
895
+ style: {
896
+ backgroundColor: surface,
897
+ borderRadius: borderRadius.sm,
898
+ flexShrink: 0
899
+ }
900
+ },
901
+ vertices.map(([x, y], i) => /* @__PURE__ */ import_react4.default.createElement(
902
+ "line",
903
+ {
904
+ key: i,
905
+ x1: cx,
906
+ y1: cy,
907
+ x2: x,
908
+ y2: y,
909
+ stroke,
910
+ strokeWidth: "1",
911
+ strokeDasharray: "2 3",
912
+ opacity: "0.6"
913
+ }
914
+ )),
915
+ /* @__PURE__ */ import_react4.default.createElement(
916
+ "polygon",
917
+ {
918
+ points: innerPts,
919
+ fill: "none",
920
+ stroke,
921
+ strokeWidth: "1",
922
+ strokeDasharray: "2 3",
923
+ opacity: "0.5"
924
+ }
925
+ ),
926
+ /* @__PURE__ */ import_react4.default.createElement(
927
+ "polygon",
928
+ {
929
+ points: midPts,
930
+ fill: "none",
931
+ stroke,
932
+ strokeWidth: "1",
933
+ strokeDasharray: "3 3",
934
+ opacity: "0.6"
935
+ }
936
+ ),
937
+ /* @__PURE__ */ import_react4.default.createElement(
938
+ "polygon",
939
+ {
940
+ points: outerPts,
941
+ fill: "none",
942
+ stroke,
943
+ strokeWidth: "1.5",
944
+ strokeDasharray: "4 3"
945
+ }
946
+ )
947
+ );
948
+ }
949
+
950
+ // src/Header.jsx
951
+ var import_react6 = __toESM(require("react"));
952
+
868
953
  // src/useMediaQuery.js
869
- var import_react4 = require("react");
954
+ var import_react5 = require("react");
870
955
  function useMediaQuery(query) {
871
- const [matches, setMatches] = (0, import_react4.useState)(() => {
956
+ const [matches, setMatches] = (0, import_react5.useState)(() => {
872
957
  if (typeof window === "undefined") return false;
873
958
  return window.matchMedia(query).matches;
874
959
  });
875
- (0, import_react4.useEffect)(() => {
960
+ (0, import_react5.useEffect)(() => {
876
961
  if (typeof window === "undefined") return;
877
962
  const mql = window.matchMedia(query);
878
963
  const handler = (e) => setMatches(e.matches);
@@ -894,14 +979,16 @@ function Header({
894
979
  currentPath,
895
980
  onNavigate,
896
981
  profileMenu,
982
+ darkMode = false,
983
+ navCollapseBreakpoint = 1024,
897
984
  style = {}
898
985
  }) {
899
- const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react5.useState)(false);
900
- const [openDropdown, setOpenDropdown] = (0, import_react5.useState)(null);
901
- const [profileOpen, setProfileOpen] = (0, import_react5.useState)(false);
902
- const isMobile = useMediaQuery("(max-width: 768px)");
903
- const profileRef = (0, import_react5.useRef)(null);
904
- (0, import_react5.useEffect)(() => {
986
+ const [mobileMenuOpen, setMobileMenuOpen] = (0, import_react6.useState)(false);
987
+ const [openDropdown, setOpenDropdown] = (0, import_react6.useState)(null);
988
+ const [profileOpen, setProfileOpen] = (0, import_react6.useState)(false);
989
+ const isMobile = useMediaQuery(`(max-width: ${navCollapseBreakpoint}px)`);
990
+ const profileRef = (0, import_react6.useRef)(null);
991
+ (0, import_react6.useEffect)(() => {
905
992
  if (!profileOpen) return;
906
993
  const handleClickOutside = (e) => {
907
994
  if (profileRef.current && !profileRef.current.contains(e.target)) {
@@ -917,9 +1004,42 @@ function Header({
917
1004
  onNavigate(href);
918
1005
  }
919
1006
  };
1007
+ const t = darkMode ? {
1008
+ surface: semanticTokens.dark.layerBase.background,
1009
+ // #131416
1010
+ raised: semanticTokens.dark.layerOne.background,
1011
+ // #2F3237 (dropdowns)
1012
+ text: colors.evLightBlue,
1013
+ // #59B0C4 — AA on dark
1014
+ itemText: semanticTokens.dark.layerOne.text,
1015
+ // #D3D7DE (dropdown items)
1016
+ muted: semanticTokens.dark.layerBase.text,
1017
+ // #B3BBCC
1018
+ border: semanticTokens.dark.divider,
1019
+ // #41454E
1020
+ hoverBg: semanticTokens.dark.layerTwo.background,
1021
+ // #41454E
1022
+ ctaBg: semanticTokens.dark.buttonPrimary.background.default,
1023
+ // #005366
1024
+ ctaBgHover: semanticTokens.dark.buttonPrimary.background.hovered,
1025
+ ctaText: "#FFFFFF",
1026
+ shadow: "0 10px 40px rgba(0,0,0,0.5)"
1027
+ } : {
1028
+ surface: colors.bgWhite,
1029
+ raised: colors.bgWhite,
1030
+ text: colors.evTeal,
1031
+ itemText: colors.evTeal,
1032
+ muted: colors.textMuted,
1033
+ border: colors.borderLight,
1034
+ hoverBg: colors.bgLight,
1035
+ ctaBg: colors.evTeal,
1036
+ ctaBgHover: colors.evTealDark,
1037
+ ctaText: colors.textWhite,
1038
+ shadow: "0 10px 40px rgba(0,0,0,0.1)"
1039
+ };
920
1040
  const styles2 = {
921
1041
  header: {
922
- backgroundColor: colors.bgWhite,
1042
+ backgroundColor: t.surface,
923
1043
  position: "sticky",
924
1044
  top: 0,
925
1045
  zIndex: 50,
@@ -932,7 +1052,8 @@ function Header({
932
1052
  padding: isMobile ? `${spacing[3]} ${spacing[3]}` : `${spacing[4]} ${spacing[6]}`,
933
1053
  display: "flex",
934
1054
  alignItems: "center",
935
- justifyContent: "space-between"
1055
+ justifyContent: "space-between",
1056
+ gap: spacing[6]
936
1057
  },
937
1058
  logo: {
938
1059
  height: "43px",
@@ -940,20 +1061,24 @@ function Header({
940
1061
  },
941
1062
  nav: {
942
1063
  display: isMobile ? "none" : "flex",
1064
+ flex: "1 1 auto",
943
1065
  alignItems: "center",
944
- gap: spacing[10]
1066
+ justifyContent: "center",
1067
+ flexWrap: "nowrap",
1068
+ gap: spacing[8]
945
1069
  },
946
1070
  navItem: {
947
1071
  fontFamily: fonts.primary,
948
- fontWeight: fontWeights.bold,
949
- fontSize: fontSizes.xl,
950
- color: colors.evTeal,
1072
+ fontWeight: fontWeights.medium,
1073
+ fontSize: fontSizes.base,
1074
+ color: t.text,
951
1075
  textDecoration: "none",
952
1076
  cursor: "pointer",
953
1077
  display: "flex",
954
1078
  alignItems: "center",
955
1079
  gap: spacing[2],
956
- position: "relative"
1080
+ position: "relative",
1081
+ whiteSpace: "nowrap"
957
1082
  },
958
1083
  navItemActive: {
959
1084
  textDecoration: "underline"
@@ -970,9 +1095,9 @@ function Header({
970
1095
  zIndex: 100
971
1096
  },
972
1097
  dropdownInner: {
973
- backgroundColor: colors.bgWhite,
1098
+ backgroundColor: t.raised,
974
1099
  borderRadius: borderRadius.lg,
975
- boxShadow: "0 10px 40px rgba(0,0,0,0.1)",
1100
+ boxShadow: t.shadow,
976
1101
  minWidth: "200px",
977
1102
  padding: spacing[2]
978
1103
  },
@@ -982,14 +1107,14 @@ function Header({
982
1107
  fontFamily: fonts.primary,
983
1108
  fontWeight: fontWeights.medium,
984
1109
  fontSize: fontSizes.base,
985
- color: colors.evTeal,
1110
+ color: t.itemText,
986
1111
  textDecoration: "none",
987
1112
  borderRadius: borderRadius.md,
988
1113
  cursor: "pointer"
989
1114
  },
990
1115
  ctaButton: {
991
- backgroundColor: colors.evTeal,
992
- color: colors.textWhite,
1116
+ backgroundColor: t.ctaBg,
1117
+ color: t.ctaText,
993
1118
  fontFamily: fonts.primary,
994
1119
  fontWeight: fontWeights.bold,
995
1120
  fontSize: fontSizes.xl,
@@ -1004,13 +1129,13 @@ function Header({
1004
1129
  display: "inline-flex",
1005
1130
  alignItems: "center",
1006
1131
  backgroundColor: "transparent",
1007
- color: colors.evTeal,
1132
+ color: t.text,
1008
1133
  fontFamily: fonts.primary,
1009
1134
  fontWeight: fontWeights.bold,
1010
1135
  fontSize: fontSizes.base,
1011
1136
  padding: `${spacing[2]} ${spacing[5]}`,
1012
1137
  borderRadius: borderRadius.full || "999px",
1013
- border: `1.5px solid ${colors.evTeal}`,
1138
+ border: `1.5px solid ${t.text}`,
1014
1139
  cursor: "pointer",
1015
1140
  textDecoration: "none",
1016
1141
  lineHeight: 1.2,
@@ -1026,7 +1151,7 @@ function Header({
1026
1151
  hamburger: {
1027
1152
  width: "24px",
1028
1153
  height: "2px",
1029
- backgroundColor: colors.evTeal,
1154
+ backgroundColor: t.text,
1030
1155
  position: "relative"
1031
1156
  },
1032
1157
  mobileMenu: {
@@ -1036,25 +1161,25 @@ function Header({
1036
1161
  top: "100%",
1037
1162
  left: 0,
1038
1163
  right: 0,
1039
- backgroundColor: colors.bgWhite,
1164
+ backgroundColor: t.surface,
1040
1165
  padding: spacing[4],
1041
- boxShadow: "0 4px 20px rgba(0,0,0,0.1)"
1166
+ boxShadow: t.shadow
1042
1167
  },
1043
1168
  mobileNavItem: {
1044
1169
  fontFamily: fonts.primary,
1045
- fontWeight: fontWeights.bold,
1046
- fontSize: fontSizes.lg,
1047
- color: colors.evTeal,
1170
+ fontWeight: fontWeights.medium,
1171
+ fontSize: fontSizes.base,
1172
+ color: t.text,
1048
1173
  textDecoration: "none",
1049
1174
  padding: `${spacing[3]} 0`,
1050
- borderBottom: `1px solid ${colors.borderLight}`
1175
+ borderBottom: `1px solid ${t.border}`
1051
1176
  },
1052
1177
  profileButton: {
1053
1178
  width: "40px",
1054
1179
  height: "40px",
1055
1180
  borderRadius: borderRadius.full,
1056
- border: `2px solid ${colors.evTeal}`,
1057
- backgroundColor: colors.bgLight,
1181
+ border: `2px solid ${t.text}`,
1182
+ backgroundColor: darkMode ? t.raised : colors.bgLight,
1058
1183
  cursor: "pointer",
1059
1184
  display: "flex",
1060
1185
  alignItems: "center",
@@ -1069,9 +1194,9 @@ function Header({
1069
1194
  zIndex: 100
1070
1195
  },
1071
1196
  profileDropdownInner: {
1072
- backgroundColor: colors.bgWhite,
1197
+ backgroundColor: t.raised,
1073
1198
  borderRadius: borderRadius.lg,
1074
- boxShadow: "0 10px 40px rgba(0,0,0,0.1)",
1199
+ boxShadow: t.shadow,
1075
1200
  minWidth: "160px",
1076
1201
  padding: spacing[2]
1077
1202
  },
@@ -1082,7 +1207,7 @@ function Header({
1082
1207
  fontFamily: fonts.primary,
1083
1208
  fontWeight: fontWeights.medium,
1084
1209
  fontSize: fontSizes.base,
1085
- color: colors.evTeal,
1210
+ color: t.itemText,
1086
1211
  textDecoration: "none",
1087
1212
  borderRadius: borderRadius.md,
1088
1213
  cursor: "pointer",
@@ -1092,7 +1217,7 @@ function Header({
1092
1217
  },
1093
1218
  mobileDivider: {
1094
1219
  height: "1px",
1095
- backgroundColor: colors.borderLight,
1220
+ backgroundColor: t.border,
1096
1221
  margin: `${spacing[3]} 0`
1097
1222
  },
1098
1223
  profileLabel: {
@@ -1100,8 +1225,8 @@ function Header({
1100
1225
  fontFamily: fonts.primary,
1101
1226
  fontWeight: fontWeights.semibold,
1102
1227
  fontSize: fontSizes.sm,
1103
- color: colors.textMuted,
1104
- borderBottom: `1px solid ${colors.borderLight}`,
1228
+ color: t.muted,
1229
+ borderBottom: `1px solid ${t.border}`,
1105
1230
  marginBottom: spacing[1],
1106
1231
  overflow: "hidden",
1107
1232
  textOverflow: "ellipsis",
@@ -1109,17 +1234,23 @@ function Header({
1109
1234
  }
1110
1235
  };
1111
1236
  const NavLink = ({ item }) => {
1112
- const isActive = currentPath === item.href;
1237
+ const isActive = currentPath === item.href || typeof window !== "undefined" && /^https?:\/\//.test(item.href) && (() => {
1238
+ try {
1239
+ return new URL(item.href).hostname === window.location.hostname;
1240
+ } catch {
1241
+ return false;
1242
+ }
1243
+ })();
1113
1244
  const hasDropdown = item.dropdown && item.dropdown.length > 0;
1114
1245
  const isOpen = openDropdown === item.label;
1115
- return /* @__PURE__ */ import_react5.default.createElement(
1246
+ return /* @__PURE__ */ import_react6.default.createElement(
1116
1247
  "div",
1117
1248
  {
1118
1249
  style: { position: "relative" },
1119
1250
  onMouseEnter: () => hasDropdown && setOpenDropdown(item.label),
1120
1251
  onMouseLeave: () => hasDropdown && setOpenDropdown(null)
1121
1252
  },
1122
- /* @__PURE__ */ import_react5.default.createElement(
1253
+ /* @__PURE__ */ import_react6.default.createElement(
1123
1254
  "a",
1124
1255
  {
1125
1256
  href: item.href,
@@ -1130,7 +1261,7 @@ function Header({
1130
1261
  }
1131
1262
  },
1132
1263
  item.label,
1133
- hasDropdown && /* @__PURE__ */ import_react5.default.createElement(
1264
+ hasDropdown && /* @__PURE__ */ import_react6.default.createElement(
1134
1265
  "svg",
1135
1266
  {
1136
1267
  style: styles2.dropdownIcon,
@@ -1138,11 +1269,11 @@ function Header({
1138
1269
  fill: "none",
1139
1270
  xmlns: "http://www.w3.org/2000/svg"
1140
1271
  },
1141
- /* @__PURE__ */ import_react5.default.createElement(
1272
+ /* @__PURE__ */ import_react6.default.createElement(
1142
1273
  "path",
1143
1274
  {
1144
1275
  d: "M1 1L8 8L15 1",
1145
- stroke: colors.evTeal,
1276
+ stroke: t.text,
1146
1277
  strokeWidth: "2",
1147
1278
  strokeLinecap: "round",
1148
1279
  strokeLinejoin: "round"
@@ -1150,7 +1281,7 @@ function Header({
1150
1281
  )
1151
1282
  )
1152
1283
  ),
1153
- hasDropdown && isOpen && /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.dropdown }, /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.dropdownInner }, item.dropdown.map((dropdownItem, idx) => /* @__PURE__ */ import_react5.default.createElement(
1284
+ hasDropdown && isOpen && /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.dropdown }, /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.dropdownInner }, item.dropdown.map((dropdownItem, idx) => /* @__PURE__ */ import_react6.default.createElement(
1154
1285
  "a",
1155
1286
  {
1156
1287
  key: idx,
@@ -1158,7 +1289,7 @@ function Header({
1158
1289
  onClick: (e) => handleNavClick(e, dropdownItem.href),
1159
1290
  style: styles2.dropdownItem,
1160
1291
  onMouseEnter: (e) => {
1161
- e.target.style.backgroundColor = colors.bgLight;
1292
+ e.target.style.backgroundColor = t.hoverBg;
1162
1293
  },
1163
1294
  onMouseLeave: (e) => {
1164
1295
  e.target.style.backgroundColor = "transparent";
@@ -1168,26 +1299,26 @@ function Header({
1168
1299
  ))))
1169
1300
  );
1170
1301
  };
1171
- return /* @__PURE__ */ import_react5.default.createElement("header", { style: styles2.header }, /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.container }, /* @__PURE__ */ import_react5.default.createElement(
1302
+ return /* @__PURE__ */ import_react6.default.createElement("header", { style: styles2.header }, /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.container }, /* @__PURE__ */ import_react6.default.createElement(
1172
1303
  "a",
1173
1304
  {
1174
1305
  href: logoHref,
1175
1306
  onClick: (e) => handleNavClick(e, logoHref),
1176
- style: { display: "flex", alignItems: "center" }
1307
+ style: { display: "flex", alignItems: "center", flexShrink: 0 }
1177
1308
  },
1178
- logoSrc ? /* @__PURE__ */ import_react5.default.createElement("img", { src: logoSrc, alt: logoAlt, style: styles2.logo }) : /* @__PURE__ */ import_react5.default.createElement(
1309
+ logoSrc ? /* @__PURE__ */ import_react6.default.createElement("img", { src: logoSrc, alt: logoAlt, style: styles2.logo }) : /* @__PURE__ */ import_react6.default.createElement(
1179
1310
  "span",
1180
1311
  {
1181
1312
  style: {
1182
1313
  fontFamily: fonts.primary,
1183
1314
  fontWeight: fontWeights.bold,
1184
1315
  fontSize: fontSizes["2xl"],
1185
- color: colors.evTeal
1316
+ color: t.text
1186
1317
  }
1187
1318
  },
1188
1319
  "empowered.vote"
1189
1320
  )
1190
- ), /* @__PURE__ */ import_react5.default.createElement("nav", { style: styles2.nav, className: "ev-header-nav" }, navItems.map((item, idx) => /* @__PURE__ */ import_react5.default.createElement(NavLink, { key: idx, item }))), /* @__PURE__ */ import_react5.default.createElement("div", { style: { display: isMobile ? "none" : "flex", alignItems: "center", gap: spacing[3] } }, secondaryAction && import_react5.default.isValidElement(secondaryAction) && secondaryAction, secondaryAction && !import_react5.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react5.default.createElement(
1321
+ ), /* @__PURE__ */ import_react6.default.createElement("nav", { style: styles2.nav, className: "ev-header-nav" }, navItems.map((item, idx) => /* @__PURE__ */ import_react6.default.createElement(NavLink, { key: idx, item }))), /* @__PURE__ */ import_react6.default.createElement("div", { style: { display: isMobile ? "none" : "flex", alignItems: "center", gap: spacing[3], flexShrink: 0 } }, secondaryAction && import_react6.default.isValidElement(secondaryAction) && secondaryAction, secondaryAction && !import_react6.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react6.default.createElement(
1191
1322
  "a",
1192
1323
  {
1193
1324
  href: secondaryAction.href,
@@ -1201,16 +1332,16 @@ function Header({
1201
1332
  style: styles2.secondaryAction,
1202
1333
  className: "ev-header-secondary",
1203
1334
  onMouseEnter: (e) => {
1204
- e.currentTarget.style.backgroundColor = colors.evTeal;
1205
- e.currentTarget.style.color = colors.textWhite;
1335
+ e.currentTarget.style.backgroundColor = t.text;
1336
+ e.currentTarget.style.color = darkMode ? t.surface : colors.textWhite;
1206
1337
  },
1207
1338
  onMouseLeave: (e) => {
1208
1339
  e.currentTarget.style.backgroundColor = "transparent";
1209
- e.currentTarget.style.color = colors.evTeal;
1340
+ e.currentTarget.style.color = t.text;
1210
1341
  }
1211
1342
  },
1212
1343
  secondaryAction.label
1213
- ), ctaButton && /* @__PURE__ */ import_react5.default.createElement(
1344
+ ), ctaButton && /* @__PURE__ */ import_react6.default.createElement(
1214
1345
  "a",
1215
1346
  {
1216
1347
  href: ctaButton.href,
@@ -1218,14 +1349,14 @@ function Header({
1218
1349
  style: styles2.ctaButton,
1219
1350
  className: "ev-header-cta",
1220
1351
  onMouseEnter: (e) => {
1221
- e.target.style.backgroundColor = colors.evTealDark;
1352
+ e.target.style.backgroundColor = t.ctaBgHover;
1222
1353
  },
1223
1354
  onMouseLeave: (e) => {
1224
- e.target.style.backgroundColor = colors.evTeal;
1355
+ e.target.style.backgroundColor = t.ctaBg;
1225
1356
  }
1226
1357
  },
1227
1358
  ctaButton.label
1228
- ), profileMenu && /* @__PURE__ */ import_react5.default.createElement("div", { ref: profileRef, style: { position: "relative" } }, /* @__PURE__ */ import_react5.default.createElement(
1359
+ ), profileMenu && /* @__PURE__ */ import_react6.default.createElement("div", { ref: profileRef, style: { position: "relative" } }, /* @__PURE__ */ import_react6.default.createElement(
1229
1360
  "button",
1230
1361
  {
1231
1362
  style: styles2.profileButton,
@@ -1233,24 +1364,24 @@ function Header({
1233
1364
  "aria-label": "Profile menu",
1234
1365
  "aria-expanded": profileOpen
1235
1366
  },
1236
- /* @__PURE__ */ import_react5.default.createElement(
1367
+ /* @__PURE__ */ import_react6.default.createElement(
1237
1368
  "svg",
1238
1369
  {
1239
1370
  width: "20",
1240
1371
  height: "20",
1241
1372
  viewBox: "0 0 24 24",
1242
1373
  fill: "none",
1243
- stroke: colors.evTeal,
1374
+ stroke: t.text,
1244
1375
  strokeWidth: "2",
1245
1376
  strokeLinecap: "round",
1246
1377
  strokeLinejoin: "round"
1247
1378
  },
1248
- /* @__PURE__ */ import_react5.default.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1249
- /* @__PURE__ */ import_react5.default.createElement("circle", { cx: "12", cy: "7", r: "4" })
1379
+ /* @__PURE__ */ import_react6.default.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1380
+ /* @__PURE__ */ import_react6.default.createElement("circle", { cx: "12", cy: "7", r: "4" })
1250
1381
  )
1251
- ), profileOpen && /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.profileDropdown }, /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.profileDropdownInner }, profileMenu.label && /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.profileLabel }, profileMenu.label), profileMenu.items.map((item, idx) => {
1382
+ ), profileOpen && /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.profileDropdown }, /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.profileDropdownInner }, profileMenu.label && /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.profileLabel }, profileMenu.label), profileMenu.items.map((item, idx) => {
1252
1383
  if (item.href) {
1253
- return /* @__PURE__ */ import_react5.default.createElement(
1384
+ return /* @__PURE__ */ import_react6.default.createElement(
1254
1385
  "a",
1255
1386
  {
1256
1387
  key: idx,
@@ -1264,7 +1395,7 @@ function Header({
1264
1395
  },
1265
1396
  style: styles2.profileDropdownItem,
1266
1397
  onMouseEnter: (e) => {
1267
- e.target.style.backgroundColor = colors.bgLight;
1398
+ e.target.style.backgroundColor = t.hoverBg;
1268
1399
  },
1269
1400
  onMouseLeave: (e) => {
1270
1401
  e.target.style.backgroundColor = "transparent";
@@ -1273,7 +1404,7 @@ function Header({
1273
1404
  item.label
1274
1405
  );
1275
1406
  }
1276
- return /* @__PURE__ */ import_react5.default.createElement(
1407
+ return /* @__PURE__ */ import_react6.default.createElement(
1277
1408
  "button",
1278
1409
  {
1279
1410
  key: idx,
@@ -1284,7 +1415,7 @@ function Header({
1284
1415
  },
1285
1416
  style: styles2.profileDropdownItem,
1286
1417
  onMouseEnter: (e) => {
1287
- e.target.style.backgroundColor = colors.bgLight;
1418
+ e.target.style.backgroundColor = t.hoverBg;
1288
1419
  },
1289
1420
  onMouseLeave: (e) => {
1290
1421
  e.target.style.backgroundColor = "transparent";
@@ -1292,7 +1423,7 @@ function Header({
1292
1423
  },
1293
1424
  item.label
1294
1425
  );
1295
- }))))), /* @__PURE__ */ import_react5.default.createElement(
1426
+ }))))), /* @__PURE__ */ import_react6.default.createElement(
1296
1427
  "button",
1297
1428
  {
1298
1429
  style: styles2.mobileMenuButton,
@@ -1301,7 +1432,7 @@ function Header({
1301
1432
  "aria-label": "Toggle menu",
1302
1433
  "aria-expanded": mobileMenuOpen
1303
1434
  },
1304
- /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.hamburger }, /* @__PURE__ */ import_react5.default.createElement(
1435
+ /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.hamburger }, /* @__PURE__ */ import_react6.default.createElement(
1305
1436
  "span",
1306
1437
  {
1307
1438
  style: {
@@ -1310,10 +1441,10 @@ function Header({
1310
1441
  left: 0,
1311
1442
  width: "100%",
1312
1443
  height: "2px",
1313
- backgroundColor: colors.evTeal
1444
+ backgroundColor: t.text
1314
1445
  }
1315
1446
  }
1316
- ), /* @__PURE__ */ import_react5.default.createElement(
1447
+ ), /* @__PURE__ */ import_react6.default.createElement(
1317
1448
  "span",
1318
1449
  {
1319
1450
  style: {
@@ -1322,13 +1453,13 @@ function Header({
1322
1453
  left: 0,
1323
1454
  width: "100%",
1324
1455
  height: "2px",
1325
- backgroundColor: colors.evTeal
1456
+ backgroundColor: t.text
1326
1457
  }
1327
1458
  }
1328
1459
  ))
1329
- )), /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.mobileMenu, className: "ev-header-mobile-menu" }, navItems.map((item, idx) => {
1460
+ )), /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.mobileMenu, className: "ev-header-mobile-menu" }, navItems.map((item, idx) => {
1330
1461
  const hasDropdown = item.dropdown && item.dropdown.length > 0;
1331
- return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, { key: idx }, hasDropdown ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(
1462
+ return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, { key: idx }, hasDropdown ? /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(
1332
1463
  "span",
1333
1464
  {
1334
1465
  style: {
@@ -1338,7 +1469,7 @@ function Header({
1338
1469
  }
1339
1470
  },
1340
1471
  item.label
1341
- ), item.dropdown.map((sub, subIdx) => /* @__PURE__ */ import_react5.default.createElement(
1472
+ ), item.dropdown.map((sub, subIdx) => /* @__PURE__ */ import_react6.default.createElement(
1342
1473
  "a",
1343
1474
  {
1344
1475
  key: subIdx,
@@ -1355,7 +1486,7 @@ function Header({
1355
1486
  }
1356
1487
  },
1357
1488
  sub.label
1358
- ))) : /* @__PURE__ */ import_react5.default.createElement(
1489
+ ))) : /* @__PURE__ */ import_react6.default.createElement(
1359
1490
  "a",
1360
1491
  {
1361
1492
  href: item.href,
@@ -1367,7 +1498,7 @@ function Header({
1367
1498
  },
1368
1499
  item.label
1369
1500
  ));
1370
- }), secondaryAction && import_react5.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react5.default.createElement("div", { style: { marginTop: spacing[4], textAlign: "center" } }, secondaryAction), secondaryAction && !import_react5.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react5.default.createElement(
1501
+ }), secondaryAction && import_react6.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react6.default.createElement("div", { style: { marginTop: spacing[4], textAlign: "center" } }, secondaryAction), secondaryAction && !import_react6.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react6.default.createElement(
1371
1502
  "a",
1372
1503
  {
1373
1504
  href: secondaryAction.href,
@@ -1382,7 +1513,7 @@ function Header({
1382
1513
  style: { ...styles2.secondaryAction, marginTop: spacing[4], textAlign: "center", justifyContent: "center" }
1383
1514
  },
1384
1515
  secondaryAction.label
1385
- ), ctaButton && /* @__PURE__ */ import_react5.default.createElement(
1516
+ ), ctaButton && /* @__PURE__ */ import_react6.default.createElement(
1386
1517
  "a",
1387
1518
  {
1388
1519
  href: ctaButton.href,
@@ -1393,14 +1524,14 @@ function Header({
1393
1524
  style: { ...styles2.ctaButton, marginTop: spacing[4], textAlign: "center" }
1394
1525
  },
1395
1526
  ctaButton.label
1396
- ), profileMenu && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("div", { style: styles2.mobileDivider }), profileMenu.label && /* @__PURE__ */ import_react5.default.createElement(
1527
+ ), profileMenu && /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.mobileDivider }), profileMenu.label && /* @__PURE__ */ import_react6.default.createElement(
1397
1528
  "span",
1398
1529
  {
1399
1530
  style: {
1400
1531
  ...styles2.mobileNavItem,
1401
1532
  fontWeight: fontWeights.medium,
1402
1533
  fontSize: fontSizes.sm,
1403
- color: colors.textMuted,
1534
+ color: t.muted,
1404
1535
  cursor: "default",
1405
1536
  display: "block",
1406
1537
  borderBottom: "none"
@@ -1409,7 +1540,7 @@ function Header({
1409
1540
  profileMenu.label
1410
1541
  ), profileMenu.items.map((item, idx) => {
1411
1542
  if (item.href) {
1412
- return /* @__PURE__ */ import_react5.default.createElement(
1543
+ return /* @__PURE__ */ import_react6.default.createElement(
1413
1544
  "a",
1414
1545
  {
1415
1546
  key: idx,
@@ -1426,7 +1557,7 @@ function Header({
1426
1557
  item.label
1427
1558
  );
1428
1559
  }
1429
- return /* @__PURE__ */ import_react5.default.createElement(
1560
+ return /* @__PURE__ */ import_react6.default.createElement(
1430
1561
  "button",
1431
1562
  {
1432
1563
  key: idx,
@@ -1450,10 +1581,10 @@ function Header({
1450
1581
  }
1451
1582
 
1452
1583
  // src/SiteHeader.jsx
1453
- var import_react7 = __toESM(require("react"));
1584
+ var import_react8 = __toESM(require("react"));
1454
1585
 
1455
1586
  // src/FeedbackButton.jsx
1456
- var import_react6 = __toESM(require("react"));
1587
+ var import_react7 = __toESM(require("react"));
1457
1588
  var FEEDBACK_BASE_DEFAULT = "https://alpha.empowered.vote/feedback";
1458
1589
  var HOST_FEATURE_MAP = {
1459
1590
  "compass.empowered.vote": "compass",
@@ -1524,7 +1655,7 @@ function FeedbackButton({
1524
1655
  cursor: "pointer"
1525
1656
  };
1526
1657
  const baseStyle = variant === "link" ? linkStyle2 : pillStyle;
1527
- return /* @__PURE__ */ import_react6.default.createElement(
1658
+ return /* @__PURE__ */ import_react7.default.createElement(
1528
1659
  "a",
1529
1660
  {
1530
1661
  href,
@@ -1560,10 +1691,17 @@ var defaultNavItems = [
1560
1691
  { label: "Find Representatives", href: "https://essentials.empowered.vote" },
1561
1692
  { label: "Read & Rank", href: "https://readrank.empowered.vote" },
1562
1693
  { label: "Treasury Tracker", href: "https://treasurytracker.empowered.vote" },
1694
+ { label: "Civic Trivia", href: "https://ctc.empowered.vote" },
1563
1695
  { label: "Empowered Badges", href: "https://badges.empowered.vote" }
1564
1696
  ]
1565
1697
  }
1566
1698
  ];
1699
+ var evAppLinks = [
1700
+ { label: "Compass", href: "https://compass.empowered.vote" },
1701
+ { label: "Find Representatives", href: "https://essentials.empowered.vote" },
1702
+ { label: "Treasury Tracker", href: "https://treasurytracker.empowered.vote" },
1703
+ { label: "Civic Trivia", href: "https://ctc.empowered.vote" }
1704
+ ];
1567
1705
  var defaultCtaButton = {
1568
1706
  label: "Donate",
1569
1707
  href: "https://empowered.vote/donate"
@@ -1588,11 +1726,11 @@ function SiteHeader({
1588
1726
  if (secondaryAction === false) {
1589
1727
  resolvedSecondary = void 0;
1590
1728
  } else if (secondaryAction === void 0) {
1591
- resolvedSecondary = /* @__PURE__ */ import_react7.default.createElement(FeedbackButton, { feature: feedbackFeature });
1729
+ resolvedSecondary = /* @__PURE__ */ import_react8.default.createElement(FeedbackButton, { feature: feedbackFeature });
1592
1730
  } else {
1593
1731
  resolvedSecondary = secondaryAction;
1594
1732
  }
1595
- return /* @__PURE__ */ import_react7.default.createElement(
1733
+ return /* @__PURE__ */ import_react8.default.createElement(
1596
1734
  Header,
1597
1735
  {
1598
1736
  logoSrc,
@@ -1609,7 +1747,7 @@ function SiteHeader({
1609
1747
  }
1610
1748
 
1611
1749
  // src/FilterSidebar.jsx
1612
- var import_react8 = __toESM(require("react"));
1750
+ var import_react9 = __toESM(require("react"));
1613
1751
  function FilterSidebar({
1614
1752
  title = "Filter by",
1615
1753
  zipCode = "",
@@ -1763,14 +1901,14 @@ function FilterSidebar({
1763
1901
  fontSize: fontSizes.sm
1764
1902
  }
1765
1903
  };
1766
- return /* @__PURE__ */ import_react8.default.createElement("aside", { style: styles2.sidebar, className: "ev-filter-sidebar" }, !isMobile && /* @__PURE__ */ import_react8.default.createElement("h2", { style: styles2.title }, title), /* @__PURE__ */ import_react8.default.createElement("div", { style: isMobile ? void 0 : styles2.contentTop }, /* @__PURE__ */ import_react8.default.createElement("div", { style: isMobile ? { marginBottom: spacing[3] } : styles2.section }, !isMobile && /* @__PURE__ */ import_react8.default.createElement("label", { style: styles2.sectionLabel }, "Location"), autocompleteContainerRef ? /* @__PURE__ */ import_react8.default.createElement(
1904
+ return /* @__PURE__ */ import_react9.default.createElement("aside", { style: styles2.sidebar, className: "ev-filter-sidebar" }, !isMobile && /* @__PURE__ */ import_react9.default.createElement("h2", { style: styles2.title }, title), /* @__PURE__ */ import_react9.default.createElement("div", { style: isMobile ? void 0 : styles2.contentTop }, /* @__PURE__ */ import_react9.default.createElement("div", { style: isMobile ? { marginBottom: spacing[3] } : styles2.section }, !isMobile && /* @__PURE__ */ import_react9.default.createElement("label", { style: styles2.sectionLabel }, "Location"), autocompleteContainerRef ? /* @__PURE__ */ import_react9.default.createElement(
1767
1905
  "div",
1768
1906
  {
1769
1907
  ref: autocompleteContainerRef,
1770
1908
  style: styles2.zipInputWrapper,
1771
1909
  className: "ev-autocomplete-container"
1772
1910
  }
1773
- ) : /* @__PURE__ */ import_react8.default.createElement("div", { style: styles2.zipInputWrapper }, /* @__PURE__ */ import_react8.default.createElement(
1911
+ ) : /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.zipInputWrapper }, /* @__PURE__ */ import_react9.default.createElement(
1774
1912
  "input",
1775
1913
  {
1776
1914
  ref: zipInputRef,
@@ -1782,7 +1920,7 @@ function FilterSidebar({
1782
1920
  style: styles2.zipInput,
1783
1921
  "aria-label": "Search location"
1784
1922
  }
1785
- ), /* @__PURE__ */ import_react8.default.createElement(
1923
+ ), /* @__PURE__ */ import_react9.default.createElement(
1786
1924
  "button",
1787
1925
  {
1788
1926
  type: "button",
@@ -1791,7 +1929,7 @@ function FilterSidebar({
1791
1929
  "aria-label": "Clear ZIP code"
1792
1930
  },
1793
1931
  "\xD7"
1794
- ))), /* @__PURE__ */ import_react8.default.createElement("div", { style: isMobile ? {} : styles2.section }, !isMobile && /* @__PURE__ */ import_react8.default.createElement("label", { style: styles2.sectionLabel }, "Group"), /* @__PURE__ */ import_react8.default.createElement("div", { style: styles2.radioGroup, role: "radiogroup", "aria-label": "Filter by group" }, filterOptions.map((option) => /* @__PURE__ */ import_react8.default.createElement("label", { key: option.value, style: styles2.radioLabel }, /* @__PURE__ */ import_react8.default.createElement(
1932
+ ))), /* @__PURE__ */ import_react9.default.createElement("div", { style: isMobile ? {} : styles2.section }, !isMobile && /* @__PURE__ */ import_react9.default.createElement("label", { style: styles2.sectionLabel }, "Group"), /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.radioGroup, role: "radiogroup", "aria-label": "Filter by group" }, filterOptions.map((option) => /* @__PURE__ */ import_react9.default.createElement("label", { key: option.value, style: styles2.radioLabel }, /* @__PURE__ */ import_react9.default.createElement(
1795
1933
  "input",
1796
1934
  {
1797
1935
  type: "radio",
@@ -1801,18 +1939,18 @@ function FilterSidebar({
1801
1939
  onChange: () => onFilterChange == null ? void 0 : onFilterChange(option.value),
1802
1940
  style: styles2.radioInput
1803
1941
  }
1804
- ), option.label))))), !isMobile && /* @__PURE__ */ import_react8.default.createElement("div", { style: styles2.imageSection }, locationLabel && /* @__PURE__ */ import_react8.default.createElement("div", { style: styles2.locationLabel }, locationLabel), buildingImageSrc ? /* @__PURE__ */ import_react8.default.createElement(
1942
+ ), option.label))))), !isMobile && /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.imageSection }, locationLabel && /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.locationLabel }, locationLabel), buildingImageSrc ? /* @__PURE__ */ import_react9.default.createElement(
1805
1943
  "img",
1806
1944
  {
1807
1945
  src: buildingImageSrc,
1808
1946
  alt: `${selectedFilter} government building`,
1809
1947
  style: styles2.buildingImage
1810
1948
  }
1811
- ) : /* @__PURE__ */ import_react8.default.createElement("div", { style: styles2.buildingPlaceholder }, "No image")));
1949
+ ) : /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.buildingPlaceholder }, "No image")));
1812
1950
  }
1813
1951
 
1814
1952
  // src/PoliticianCard.jsx
1815
- var import_react9 = __toESM(require("react"));
1953
+ var import_react10 = __toESM(require("react"));
1816
1954
  function PoliticianCard({
1817
1955
  id,
1818
1956
  imageSrc,
@@ -1825,7 +1963,8 @@ function PoliticianCard({
1825
1963
  style = {},
1826
1964
  badge,
1827
1965
  imageFocalPoint,
1828
- footer
1966
+ footer,
1967
+ imageWidth = "90px"
1829
1968
  }) {
1830
1969
  const isHorizontal = variant === "horizontal";
1831
1970
  const handleCardClick = (e) => {
@@ -1853,20 +1992,25 @@ function PoliticianCard({
1853
1992
  ...style
1854
1993
  },
1855
1994
  imageWrapper: {
1856
- width: isHorizontal ? "90px" : "100%",
1995
+ // Horizontal: relative box whose height comes from the card (flex stretch),
1996
+ // so the photo fills the card height instead of dictating it. Absolutely
1997
+ // positioned children below mean a wider photo can't inflate the card.
1998
+ position: isHorizontal ? "relative" : void 0,
1999
+ width: isHorizontal ? imageWidth : "100%",
1857
2000
  height: isHorizontal ? "100%" : "auto",
1858
- maxHeight: isHorizontal ? "200px" : void 0,
1859
2001
  aspectRatio: isHorizontal ? void 0 : "4/5",
1860
2002
  flexShrink: 0,
1861
2003
  overflow: "hidden"
1862
2004
  },
1863
2005
  image: {
2006
+ ...isHorizontal ? { position: "absolute", top: 0, left: 0 } : {},
1864
2007
  width: "100%",
1865
2008
  height: "100%",
1866
2009
  objectFit: "cover",
1867
2010
  objectPosition: imageFocalPoint != null ? imageFocalPoint : "center 20%"
1868
2011
  },
1869
2012
  imagePlaceholder: {
2013
+ ...isHorizontal ? { position: "absolute", top: 0, left: 0 } : {},
1870
2014
  width: "100%",
1871
2015
  height: "100%",
1872
2016
  backgroundColor: colors.evTeal,
@@ -1964,7 +2108,7 @@ function PoliticianCard({
1964
2108
  textTransform: "uppercase"
1965
2109
  }
1966
2110
  };
1967
- const CompassIcon2 = () => /* @__PURE__ */ import_react9.default.createElement(
2111
+ const CompassIcon2 = () => /* @__PURE__ */ import_react10.default.createElement(
1968
2112
  "svg",
1969
2113
  {
1970
2114
  style: styles2.compassIcon,
@@ -1972,7 +2116,7 @@ function PoliticianCard({
1972
2116
  fill: "none",
1973
2117
  xmlns: "http://www.w3.org/2000/svg"
1974
2118
  },
1975
- /* @__PURE__ */ import_react9.default.createElement(
2119
+ /* @__PURE__ */ import_react10.default.createElement(
1976
2120
  "polygon",
1977
2121
  {
1978
2122
  points: "12,1 21.5,6.5 21.5,17.5 12,23 2.5,17.5 2.5,6.5",
@@ -1982,13 +2126,13 @@ function PoliticianCard({
1982
2126
  strokeLinejoin: "round"
1983
2127
  }
1984
2128
  ),
1985
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "1", stroke: "currentColor", strokeWidth: "1" }),
1986
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
1987
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
1988
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "23", stroke: "currentColor", strokeWidth: "1" }),
1989
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
1990
- /* @__PURE__ */ import_react9.default.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
1991
- /* @__PURE__ */ import_react9.default.createElement(
2129
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "1", stroke: "currentColor", strokeWidth: "1" }),
2130
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
2131
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
2132
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "23", stroke: "currentColor", strokeWidth: "1" }),
2133
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
2134
+ /* @__PURE__ */ import_react10.default.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
2135
+ /* @__PURE__ */ import_react10.default.createElement(
1992
2136
  "polygon",
1993
2137
  {
1994
2138
  points: "12,4 18,7.5 18,16 12,19.5 7,15 5,8",
@@ -1996,7 +2140,7 @@ function PoliticianCard({
1996
2140
  opacity: "0.35"
1997
2141
  }
1998
2142
  ),
1999
- /* @__PURE__ */ import_react9.default.createElement(
2143
+ /* @__PURE__ */ import_react10.default.createElement(
2000
2144
  "polygon",
2001
2145
  {
2002
2146
  points: "12,4 18,7.5 18,16 12,19.5 7,15 5,8",
@@ -2007,8 +2151,8 @@ function PoliticianCard({
2007
2151
  }
2008
2152
  )
2009
2153
  );
2010
- const [imgError, setImgError] = (0, import_react9.useState)(false);
2011
- (0, import_react9.useEffect)(() => {
2154
+ const [imgError, setImgError] = (0, import_react10.useState)(false);
2155
+ (0, import_react10.useEffect)(() => {
2012
2156
  setImgError(false);
2013
2157
  }, [imageSrc]);
2014
2158
  const getInitials = (n) => {
@@ -2017,7 +2161,7 @@ function PoliticianCard({
2017
2161
  const initials = parts.length >= 2 ? parts[0][0] + parts[parts.length - 1][0] : ((_a = parts[0]) == null ? void 0 : _a[0]) || "?";
2018
2162
  return initials.toUpperCase();
2019
2163
  };
2020
- return /* @__PURE__ */ import_react9.default.createElement(
2164
+ return /* @__PURE__ */ import_react10.default.createElement(
2021
2165
  "div",
2022
2166
  {
2023
2167
  style: styles2.card,
@@ -2042,8 +2186,8 @@ function PoliticianCard({
2042
2186
  }
2043
2187
  }
2044
2188
  },
2045
- badge && /* @__PURE__ */ import_react9.default.createElement("span", { style: styles2.badge }, badge),
2046
- /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.imageWrapper }, imageSrc && !imgError ? /* @__PURE__ */ import_react9.default.createElement(
2189
+ badge && /* @__PURE__ */ import_react10.default.createElement("span", { style: styles2.badge }, badge),
2190
+ /* @__PURE__ */ import_react10.default.createElement("div", { style: styles2.imageWrapper }, imageSrc && !imgError ? /* @__PURE__ */ import_react10.default.createElement(
2047
2191
  "img",
2048
2192
  {
2049
2193
  src: imageSrc,
@@ -2051,9 +2195,9 @@ function PoliticianCard({
2051
2195
  style: styles2.image,
2052
2196
  onError: () => setImgError(true)
2053
2197
  }
2054
- ) : /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.imagePlaceholder }, getInitials(name))),
2055
- /* @__PURE__ */ import_react9.default.createElement("div", { style: styles2.content }, /* @__PURE__ */ import_react9.default.createElement("h3", { style: styles2.name }, name), /* @__PURE__ */ import_react9.default.createElement("p", { style: styles2.title }, title), subtitle && /* @__PURE__ */ import_react9.default.createElement("p", { style: styles2.subtitle }, subtitle), footer && /* @__PURE__ */ import_react9.default.createElement("div", { style: { marginTop: "auto", marginLeft: "-5px" } }, footer)),
2056
- onCompassClick && /* @__PURE__ */ import_react9.default.createElement(
2198
+ ) : /* @__PURE__ */ import_react10.default.createElement("div", { style: styles2.imagePlaceholder }, getInitials(name))),
2199
+ /* @__PURE__ */ import_react10.default.createElement("div", { style: styles2.content }, /* @__PURE__ */ import_react10.default.createElement("h3", { style: styles2.name }, name), /* @__PURE__ */ import_react10.default.createElement("p", { style: styles2.title }, title), subtitle && /* @__PURE__ */ import_react10.default.createElement("p", { style: styles2.subtitle }, subtitle), footer && /* @__PURE__ */ import_react10.default.createElement("div", { style: { marginTop: "auto", marginLeft: "-5px" } }, footer)),
2200
+ onCompassClick && /* @__PURE__ */ import_react10.default.createElement(
2057
2201
  "button",
2058
2202
  {
2059
2203
  type: "button",
@@ -2068,7 +2212,7 @@ function PoliticianCard({
2068
2212
  },
2069
2213
  "aria-label": `View ${name}'s compass`
2070
2214
  },
2071
- /* @__PURE__ */ import_react9.default.createElement(CompassIcon2, null)
2215
+ /* @__PURE__ */ import_react10.default.createElement(CompassIcon2, null)
2072
2216
  )
2073
2217
  );
2074
2218
  }
@@ -2076,83 +2220,6 @@ function PoliticianCard({
2076
2220
  // src/CompassCardHorizontal.jsx
2077
2221
  var import_react15 = __toESM(require("react"));
2078
2222
 
2079
- // src/PlaceholderRadar.jsx
2080
- var import_react10 = __toESM(require("react"));
2081
- function PlaceholderRadar({ size = 250, name = "" }) {
2082
- const cx = size / 2;
2083
- const cy = size / 2;
2084
- const r = size / 2 * 0.65;
2085
- const n = 8;
2086
- const vertices = Array.from({ length: n }, (_, i) => {
2087
- const a = 2 * Math.PI * i / n;
2088
- return [cx + r * Math.sin(a), cy - r * Math.cos(a)];
2089
- });
2090
- const outerPts = vertices.map(([x, y]) => `${x},${y}`).join(" ");
2091
- const midPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.6},${cy + (y - cy) * 0.6}`).join(" ");
2092
- const innerPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.3},${cy + (y - cy) * 0.3}`).join(" ");
2093
- return /* @__PURE__ */ import_react10.default.createElement(
2094
- "svg",
2095
- {
2096
- width: size,
2097
- height: size,
2098
- viewBox: `0 0 ${size} ${size}`,
2099
- role: "img",
2100
- "aria-label": name ? `${name} \u2014 compass data unavailable` : "compass data unavailable",
2101
- style: {
2102
- backgroundColor: colorScales.teal["050"],
2103
- borderRadius: borderRadius.sm,
2104
- flexShrink: 0
2105
- }
2106
- },
2107
- vertices.map(([x, y], i) => /* @__PURE__ */ import_react10.default.createElement(
2108
- "line",
2109
- {
2110
- key: i,
2111
- x1: cx,
2112
- y1: cy,
2113
- x2: x,
2114
- y2: y,
2115
- stroke: colorScales.gray["200"],
2116
- strokeWidth: "1",
2117
- strokeDasharray: "2 3",
2118
- opacity: "0.6"
2119
- }
2120
- )),
2121
- /* @__PURE__ */ import_react10.default.createElement(
2122
- "polygon",
2123
- {
2124
- points: innerPts,
2125
- fill: "none",
2126
- stroke: colorScales.gray["200"],
2127
- strokeWidth: "1",
2128
- strokeDasharray: "2 3",
2129
- opacity: "0.5"
2130
- }
2131
- ),
2132
- /* @__PURE__ */ import_react10.default.createElement(
2133
- "polygon",
2134
- {
2135
- points: midPts,
2136
- fill: "none",
2137
- stroke: colorScales.gray["200"],
2138
- strokeWidth: "1",
2139
- strokeDasharray: "3 3",
2140
- opacity: "0.6"
2141
- }
2142
- ),
2143
- /* @__PURE__ */ import_react10.default.createElement(
2144
- "polygon",
2145
- {
2146
- points: outerPts,
2147
- fill: "none",
2148
- stroke: colorScales.gray["200"],
2149
- strokeWidth: "1.5",
2150
- strokeDasharray: "4 3"
2151
- }
2152
- )
2153
- );
2154
- }
2155
-
2156
2223
  // src/CompassCardHorizontalMeta.jsx
2157
2224
  var import_react14 = __toESM(require("react"));
2158
2225
 
@@ -6239,14 +6306,78 @@ function getDisplayUrl(url) {
6239
6306
  return url.length > 60 ? url.slice(0, 57) + "..." : url;
6240
6307
  }
6241
6308
  }
6309
+ var USER_DOT = "#7C6B9E";
6310
+ var POL_DOT_LIGHT = "#5A9A6E";
6311
+ var POL_DOT_DARK = "#6DD28C";
6312
+ function palette(darkMode) {
6313
+ return darkMode ? {
6314
+ rowBorder: "rgba(255,255,255,0.08)",
6315
+ rowHover: "#1e2a3a",
6316
+ // ev-navy-elevated
6317
+ title: "#f3f4f6",
6318
+ chipLabel: "#d1d5db",
6319
+ sectionLabel: "#9ca3af",
6320
+ // 6.24:1 on #1a2235 ✓ AA
6321
+ reasoning: "#d1d5db",
6322
+ chevron: "#9ca3af",
6323
+ // 6.24:1 — bumped from #6b7280 (3.28) for clarity
6324
+ pillActiveBg: "#1e2a3a",
6325
+ pillActiveBorder: "rgba(255,255,255,0.14)",
6326
+ pillIdleText: "#9ca3af",
6327
+ // 6.24:1 ✓ AA
6328
+ pillActiveText: "#f3f4f6",
6329
+ link: "#59b0c4",
6330
+ // 6.37:1 ✓ AA
6331
+ sourceText: "#9ca3af",
6332
+ quoteText: "#d1d5db",
6333
+ quoteBorder: "rgba(255,255,255,0.14)",
6334
+ emptyText: "#9ca3af",
6335
+ // 6.24:1 — bumped from #6b7280 (3.28, failed AA)
6336
+ spinnerTrack: "#374151",
6337
+ polDot: POL_DOT_DARK,
6338
+ agreedBg: "rgba(14,116,144,0.18)",
6339
+ agreedText: "#67e8f9",
6340
+ disagreedBg: "rgba(180,83,9,0.18)",
6341
+ disagreedText: "#fbbf24"
6342
+ } : {
6343
+ rowBorder: "#f1f1f1",
6344
+ rowHover: "#f9fafb",
6345
+ title: "#262626",
6346
+ chipLabel: "#525252",
6347
+ sectionLabel: "#6b7280",
6348
+ // 4.83:1 on white — bumped from #a3a3a3 (2.52, failed AA)
6349
+ reasoning: "#404040",
6350
+ chevron: "#6b7280",
6351
+ // 4.83:1 — bumped from #a3a3a3 (2.52, failed 3:1)
6352
+ pillActiveBg: "#fafafa",
6353
+ pillActiveBorder: "#e5e5e5",
6354
+ pillIdleText: "#737373",
6355
+ // 4.74:1 ✓ AA
6356
+ pillActiveText: "#171717",
6357
+ link: "#00657c",
6358
+ sourceText: "#737373",
6359
+ quoteText: "#374151",
6360
+ quoteBorder: "#e2e8f0",
6361
+ emptyText: "#6b7280",
6362
+ // 4.83:1 — bumped from #a3a3a3 (2.52, failed AA)
6363
+ spinnerTrack: "#e2e8f0",
6364
+ polDot: POL_DOT_LIGHT,
6365
+ agreedBg: "#ecfeff",
6366
+ agreedText: "#0e7490",
6367
+ disagreedBg: "#fffbeb",
6368
+ disagreedText: "#b45309"
6369
+ };
6370
+ }
6242
6371
  function StanceAccordion({
6243
6372
  topics,
6244
6373
  polAnswers,
6374
+ userAnswerMap = {},
6245
6375
  politicianId,
6246
6376
  allTopics,
6247
6377
  expandedTopics,
6378
+ darkMode = false,
6248
6379
  verdictsByTopic,
6249
- // Record<string, 'agreed' | 'disagreed'> | undefined — DEPRECATED, no longer rendered
6380
+ // DEPRECATED, no longer rendered
6250
6381
  verdictsByQuote,
6251
6382
  // Record<quote_id, 'agreed' | 'disagreed'> | undefined
6252
6383
  initialExpandedTopicId,
@@ -6258,6 +6389,7 @@ function StanceAccordion({
6258
6389
  const [showAll, setShowAll] = (0, import_react35.useState)(false);
6259
6390
  const contextCache = (0, import_react35.useRef)(/* @__PURE__ */ new Map());
6260
6391
  const quotesCache = (0, import_react35.useRef)(null);
6392
+ const c = palette(darkMode);
6261
6393
  const polAnswerMap = {};
6262
6394
  if (polAnswers) {
6263
6395
  polAnswers.forEach((a) => {
@@ -6349,201 +6481,314 @@ function StanceAccordion({
6349
6481
  visibleTopics = [pinned, ...baseTopics.filter((t) => String(t.id) !== String(initialExpandedTopicId))];
6350
6482
  }
6351
6483
  }
6484
+ const sectionLabelStyle = {
6485
+ fontSize: "11px",
6486
+ fontWeight: 600,
6487
+ color: c.sectionLabel,
6488
+ textTransform: "uppercase",
6489
+ letterSpacing: "0.06em"
6490
+ };
6352
6491
  return /* @__PURE__ */ import_react35.default.createElement(
6353
6492
  "div",
6354
6493
  {
6355
- className: "flex flex-col",
6494
+ className: "ev-stance-panel flex flex-col",
6356
6495
  style: { fontFamily: "'Manrope', sans-serif" }
6357
6496
  },
6358
- /* @__PURE__ */ import_react35.default.createElement(
6359
- "h3",
6360
- {
6361
- className: "text-sm font-semibold text-neutral-400 uppercase tracking-wider mb-2",
6362
- style: { fontSize: "12px" }
6363
- },
6364
- "Stance Breakdown"
6365
- ),
6497
+ /* @__PURE__ */ import_react35.default.createElement("h3", { style: { ...sectionLabelStyle, marginBottom: "8px" } }, "Stance Breakdown"),
6366
6498
  visibleTopics.map((topic) => {
6367
6499
  const topicId = String(topic.id);
6368
- const value = polAnswerMap[topicId];
6369
- const label = getStanceLabel(topicId, value);
6500
+ const polValue = polAnswerMap[topicId];
6501
+ const userValue = userAnswerMap[topicId];
6502
+ const label = getStanceLabel(topicId, polValue);
6370
6503
  const isExpanded = expandedTopicId === topicId;
6371
6504
  const isLoading = loadingId === topicId;
6372
6505
  const cached = contextCache.current.get(topicId);
6373
6506
  const fullTopic = topicById[topicId];
6374
6507
  const questionText = fullTopic == null ? void 0 : fullTopic.question_text;
6508
+ const titleText = questionText || topic.short_title;
6509
+ const stances = (fullTopic == null ? void 0 : fullTopic.stances) || topic.stances || [];
6375
6510
  const topicQuotes = quotesCache.current ? quotesCache.current.filter((q) => {
6376
6511
  if (!q.issue) return false;
6377
6512
  if (q.candidateId && q.candidateId !== politicianId) return false;
6378
6513
  if (topic.topic_key) return q.issue === topic.topic_key;
6379
6514
  return topic.short_title && q.issue.toLowerCase() === topic.short_title.toLowerCase();
6380
6515
  }) : [];
6381
- return /* @__PURE__ */ import_react35.default.createElement("div", { key: topicId, className: "border-b border-neutral-100" }, /* @__PURE__ */ import_react35.default.createElement(
6382
- "button",
6516
+ return /* @__PURE__ */ import_react35.default.createElement(
6517
+ "div",
6383
6518
  {
6384
- type: "button",
6385
- onClick: () => handleToggle(topicId),
6386
- className: "w-full flex items-center justify-between py-3 px-2 text-left cursor-pointer hover:bg-neutral-50 transition-colors"
6519
+ key: topicId,
6520
+ style: { borderBottom: `1px solid ${c.rowBorder}` }
6387
6521
  },
6388
- /* @__PURE__ */ import_react35.default.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "text-sm font-medium text-neutral-800 truncate" }, topic.short_title), questionText && /* @__PURE__ */ import_react35.default.createElement("span", { className: "text-xs text-neutral-400 mt-0.5" }, questionText), /* @__PURE__ */ import_react35.default.createElement("span", { className: "text-xs text-neutral-500 mt-0.5" }, label)),
6389
6522
  /* @__PURE__ */ import_react35.default.createElement(
6390
- "svg",
6523
+ "button",
6391
6524
  {
6392
- width: "16",
6393
- height: "16",
6394
- viewBox: "0 0 24 24",
6395
- fill: "none",
6396
- stroke: "currentColor",
6397
- strokeWidth: "2",
6398
- strokeLinecap: "round",
6399
- strokeLinejoin: "round",
6400
- className: "text-neutral-400 flex-shrink-0 ml-2",
6525
+ type: "button",
6526
+ onClick: () => handleToggle(topicId),
6527
+ className: "w-full flex items-start justify-between text-left cursor-pointer",
6401
6528
  style: {
6402
- transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
6403
- transition: "transform 0.2s ease"
6529
+ padding: "12px 8px",
6530
+ background: "transparent",
6531
+ border: "none",
6532
+ transition: "background 0.15s ease",
6533
+ borderRadius: "8px"
6534
+ },
6535
+ onMouseEnter: (e) => {
6536
+ e.currentTarget.style.background = c.rowHover;
6537
+ },
6538
+ onMouseLeave: (e) => {
6539
+ e.currentTarget.style.background = "transparent";
6404
6540
  }
6405
6541
  },
6406
- /* @__PURE__ */ import_react35.default.createElement("polyline", { points: "9 18 15 12 9 6" })
6407
- )
6408
- ), /* @__PURE__ */ import_react35.default.createElement(
6409
- "div",
6410
- {
6411
- style: {
6412
- display: "grid",
6413
- gridTemplateRows: isExpanded ? "1fr" : "0fr",
6414
- transition: "grid-template-rows 0.25s ease"
6415
- }
6416
- },
6417
- /* @__PURE__ */ import_react35.default.createElement("div", { style: { overflow: "hidden" } }, /* @__PURE__ */ import_react35.default.createElement("div", { className: "px-2 pb-4" }, isLoading && /* @__PURE__ */ import_react35.default.createElement("div", { className: "flex items-center py-3" }, /* @__PURE__ */ import_react35.default.createElement(
6418
- "div",
6419
- {
6420
- style: {
6421
- width: "20px",
6422
- height: "20px",
6423
- border: "2px solid #e2e8f0",
6424
- borderTopColor: "#00657c",
6425
- borderRadius: "50%",
6426
- animation: "ev-spin 0.8s linear infinite"
6542
+ /* @__PURE__ */ import_react35.default.createElement("div", { className: "flex flex-col min-w-0", style: { gap: "5px" } }, /* @__PURE__ */ import_react35.default.createElement(
6543
+ "span",
6544
+ {
6545
+ style: {
6546
+ fontSize: "14px",
6547
+ fontWeight: 600,
6548
+ color: c.title,
6549
+ lineHeight: 1.4
6550
+ }
6551
+ },
6552
+ titleText
6553
+ ), /* @__PURE__ */ import_react35.default.createElement("span", { style: { display: "flex", alignItems: "flex-start", gap: "8px" } }, /* @__PURE__ */ import_react35.default.createElement(
6554
+ "span",
6555
+ {
6556
+ style: {
6557
+ width: "8px",
6558
+ height: "8px",
6559
+ borderRadius: "50%",
6560
+ backgroundColor: c.polDot,
6561
+ flexShrink: 0,
6562
+ marginTop: "6px"
6563
+ }
6427
6564
  }
6428
- }
6429
- )), !isLoading && cached && /* @__PURE__ */ import_react35.default.createElement(import_react35.default.Fragment, null, cached.reasoning ? /* @__PURE__ */ import_react35.default.createElement(
6430
- "p",
6431
- {
6432
- className: "text-sm text-neutral-700 mb-3",
6433
- style: { whiteSpace: "pre-wrap", lineHeight: 1.6 }
6434
- },
6435
- cached.reasoning
6436
- ) : null, cached.sources && cached.sources.length > 0 && /* @__PURE__ */ import_react35.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ import_react35.default.createElement("p", { className: "text-xs font-semibold text-neutral-500 uppercase tracking-wider mb-1.5" }, "References"), /* @__PURE__ */ import_react35.default.createElement("ol", { className: "list-decimal list-inside space-y-1" }, cached.sources.map((src, i) => /* @__PURE__ */ import_react35.default.createElement("li", { key: i, className: "text-xs text-neutral-600" }, /* @__PURE__ */ import_react35.default.createElement(
6437
- "a",
6438
- {
6439
- href: src,
6440
- target: "_blank",
6441
- rel: "noreferrer",
6442
- className: "inline-flex items-center gap-1.5 hover:text-[#00657c] transition-colors"
6443
- },
6444
- /* @__PURE__ */ import_react35.default.createElement(Favicon, { url: src }),
6445
- /* @__PURE__ */ import_react35.default.createElement("span", { className: "underline underline-offset-2" }, getDisplayUrl(src))
6446
- ))))), topicQuotes.length > 0 && /* @__PURE__ */ import_react35.default.createElement("div", { style: { marginTop: "12px" } }, /* @__PURE__ */ import_react35.default.createElement(
6447
- "p",
6565
+ ), /* @__PURE__ */ import_react35.default.createElement(
6566
+ "span",
6567
+ {
6568
+ style: {
6569
+ fontSize: "13px",
6570
+ color: c.chipLabel,
6571
+ lineHeight: 1.45
6572
+ }
6573
+ },
6574
+ label
6575
+ ))),
6576
+ /* @__PURE__ */ import_react35.default.createElement(
6577
+ "svg",
6578
+ {
6579
+ width: "16",
6580
+ height: "16",
6581
+ viewBox: "0 0 24 24",
6582
+ fill: "none",
6583
+ stroke: c.chevron,
6584
+ strokeWidth: "2",
6585
+ strokeLinecap: "round",
6586
+ strokeLinejoin: "round",
6587
+ className: "flex-shrink-0 ml-2",
6588
+ style: {
6589
+ marginTop: "3px",
6590
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
6591
+ transition: "transform 0.2s ease"
6592
+ }
6593
+ },
6594
+ /* @__PURE__ */ import_react35.default.createElement("polyline", { points: "9 18 15 12 9 6" })
6595
+ )
6596
+ ),
6597
+ /* @__PURE__ */ import_react35.default.createElement(
6598
+ "div",
6448
6599
  {
6449
6600
  style: {
6450
- fontSize: "11px",
6451
- fontWeight: 600,
6452
- color: "#737373",
6453
- textTransform: "uppercase",
6454
- letterSpacing: "0.05em",
6455
- marginBottom: "8px"
6601
+ display: "grid",
6602
+ gridTemplateRows: isExpanded ? "1fr" : "0fr",
6603
+ transition: "grid-template-rows 0.25s ease"
6456
6604
  }
6457
6605
  },
6458
- "Quotes"
6459
- ), topicQuotes.map((quote) => {
6460
- const verdict = verdictsByQuote ? verdictsByQuote[quote.id] : void 0;
6461
- const borderColor = verdict === "agreed" ? "#0e7490" : verdict === "disagreed" ? "#b45309" : "#e2e8f0";
6462
- const sourceName = quote.source_name || quote.sourceName;
6463
- return /* @__PURE__ */ import_react35.default.createElement(
6606
+ /* @__PURE__ */ import_react35.default.createElement("div", { style: { overflow: "hidden" } }, /* @__PURE__ */ import_react35.default.createElement("div", { style: { padding: "4px 8px 16px" } }, stances.length > 0 && /* @__PURE__ */ import_react35.default.createElement(import_react35.default.Fragment, null, (userValue > 0 || polValue > 0) && /* @__PURE__ */ import_react35.default.createElement(
6464
6607
  "div",
6465
6608
  {
6466
- key: quote.id,
6467
6609
  style: {
6468
- borderLeft: `3px solid ${borderColor}`,
6469
- paddingLeft: "10px",
6470
- paddingTop: "6px",
6471
- paddingBottom: "6px",
6472
- marginBottom: "8px"
6610
+ display: "flex",
6611
+ alignItems: "center",
6612
+ gap: "14px",
6613
+ marginBottom: "8px",
6614
+ fontSize: "12px",
6615
+ color: c.sourceText
6473
6616
  }
6474
6617
  },
6475
- /* @__PURE__ */ import_react35.default.createElement(
6476
- "p",
6618
+ userValue > 0 && /* @__PURE__ */ import_react35.default.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" } }, /* @__PURE__ */ import_react35.default.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: USER_DOT } }), "You"),
6619
+ /* @__PURE__ */ import_react35.default.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" } }, /* @__PURE__ */ import_react35.default.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: c.polDot } }), "Their stance")
6620
+ ), /* @__PURE__ */ import_react35.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "6px", marginBottom: "14px" } }, stances.map((stance, i) => {
6621
+ const stanceNum = i + 1;
6622
+ const isUser = userValue === stanceNum;
6623
+ const isPol = polValue === stanceNum;
6624
+ const isActive = isUser || isPol;
6625
+ return /* @__PURE__ */ import_react35.default.createElement(
6626
+ "div",
6477
6627
  {
6628
+ key: i,
6478
6629
  style: {
6630
+ display: "flex",
6631
+ alignItems: "flex-start",
6632
+ gap: "10px",
6633
+ padding: "10px 12px",
6634
+ borderRadius: "12px",
6479
6635
  fontSize: "13px",
6480
- fontStyle: "italic",
6481
- color: "#374151",
6482
- margin: 0,
6483
- lineHeight: 1.5
6484
- }
6485
- },
6486
- quote.text
6487
- ),
6488
- verdict === "agreed" && /* @__PURE__ */ import_react35.default.createElement(
6489
- "span",
6490
- {
6491
- style: {
6492
- display: "inline-flex",
6493
- alignItems: "center",
6494
- gap: "4px",
6495
- backgroundColor: "#ecfeff",
6496
- color: "#0e7490",
6497
- padding: "2px 8px",
6498
- borderRadius: "9999px",
6499
- fontSize: "11px",
6500
- fontWeight: 500,
6501
- marginTop: "4px",
6502
- flexShrink: 0
6503
- }
6504
- },
6505
- /* @__PURE__ */ import_react35.default.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react35.default.createElement("path", { d: "M5 13l4 4L19 7" })),
6506
- "Agreed"
6507
- ),
6508
- verdict === "disagreed" && /* @__PURE__ */ import_react35.default.createElement(
6509
- "span",
6510
- {
6511
- style: {
6512
- display: "inline-flex",
6513
- alignItems: "center",
6514
- gap: "4px",
6515
- backgroundColor: "#fffbeb",
6516
- color: "#b45309",
6517
- padding: "2px 8px",
6518
- borderRadius: "9999px",
6519
- fontSize: "11px",
6520
- fontWeight: 500,
6521
- marginTop: "4px",
6522
- flexShrink: 0
6636
+ lineHeight: 1.4,
6637
+ border: `1px solid ${isActive ? c.pillActiveBorder : "transparent"}`,
6638
+ backgroundColor: isActive ? c.pillActiveBg : "transparent"
6523
6639
  }
6524
6640
  },
6525
- /* @__PURE__ */ import_react35.default.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react35.default.createElement("path", { d: "M6 18L18 6M6 6l12 12" })),
6526
- "Disagreed"
6527
- ),
6528
- sourceName && /* @__PURE__ */ import_react35.default.createElement(
6529
- "a",
6641
+ /* @__PURE__ */ import_react35.default.createElement(
6642
+ "span",
6643
+ {
6644
+ style: {
6645
+ flexShrink: 0,
6646
+ width: "30px",
6647
+ display: "flex",
6648
+ alignItems: "center",
6649
+ gap: "5px",
6650
+ paddingTop: "3px"
6651
+ }
6652
+ },
6653
+ isUser && /* @__PURE__ */ import_react35.default.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: USER_DOT, boxShadow: `0 0 0 3px ${USER_DOT}33` } }),
6654
+ isPol && /* @__PURE__ */ import_react35.default.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: c.polDot, boxShadow: `0 0 0 3px ${c.polDot}33` } })
6655
+ ),
6656
+ /* @__PURE__ */ import_react35.default.createElement(
6657
+ "span",
6658
+ {
6659
+ style: {
6660
+ flex: 1,
6661
+ color: isActive ? c.pillActiveText : c.pillIdleText,
6662
+ fontWeight: isActive ? 500 : 400
6663
+ }
6664
+ },
6665
+ stance.text
6666
+ )
6667
+ );
6668
+ }))), isLoading && /* @__PURE__ */ import_react35.default.createElement("div", { className: "flex items-center", style: { padding: "12px 0" } }, /* @__PURE__ */ import_react35.default.createElement(
6669
+ "div",
6670
+ {
6671
+ style: {
6672
+ width: "20px",
6673
+ height: "20px",
6674
+ border: `2px solid ${c.spinnerTrack}`,
6675
+ borderTopColor: "#00657c",
6676
+ borderRadius: "50%",
6677
+ animation: "ev-spin 0.8s linear infinite"
6678
+ }
6679
+ }
6680
+ )), !isLoading && cached && /* @__PURE__ */ import_react35.default.createElement(import_react35.default.Fragment, null, cached.reasoning ? /* @__PURE__ */ import_react35.default.createElement(
6681
+ "p",
6682
+ {
6683
+ style: {
6684
+ fontSize: "14px",
6685
+ color: c.reasoning,
6686
+ marginBottom: "12px",
6687
+ whiteSpace: "pre-wrap",
6688
+ lineHeight: 1.6
6689
+ }
6690
+ },
6691
+ cached.reasoning
6692
+ ) : null, cached.sources && cached.sources.length > 0 && /* @__PURE__ */ import_react35.default.createElement("div", { style: { marginTop: "8px" } }, /* @__PURE__ */ import_react35.default.createElement("p", { style: { ...sectionLabelStyle, marginBottom: "6px" } }, "References"), /* @__PURE__ */ import_react35.default.createElement("ol", { style: { listStyle: "decimal", listStylePosition: "inside", display: "flex", flexDirection: "column", gap: "4px" } }, cached.sources.map((src, i) => /* @__PURE__ */ import_react35.default.createElement("li", { key: i, style: { fontSize: "12px", color: c.sourceText } }, /* @__PURE__ */ import_react35.default.createElement(
6693
+ "a",
6694
+ {
6695
+ href: src,
6696
+ target: "_blank",
6697
+ rel: "noreferrer",
6698
+ className: "inline-flex items-center gap-1.5",
6699
+ style: { color: c.link }
6700
+ },
6701
+ /* @__PURE__ */ import_react35.default.createElement(Favicon, { url: src }),
6702
+ /* @__PURE__ */ import_react35.default.createElement("span", { style: { textDecoration: "underline", textUnderlineOffset: "2px" } }, getDisplayUrl(src))
6703
+ ))))), topicQuotes.length > 0 && /* @__PURE__ */ import_react35.default.createElement("div", { style: { marginTop: "14px" } }, /* @__PURE__ */ import_react35.default.createElement("p", { style: { ...sectionLabelStyle, marginBottom: "8px" } }, "Quotes"), topicQuotes.map((quote) => {
6704
+ const verdict = verdictsByQuote ? verdictsByQuote[quote.id] : void 0;
6705
+ const borderColor = verdict === "agreed" ? c.agreedText : verdict === "disagreed" ? c.disagreedText : c.quoteBorder;
6706
+ const sourceName = quote.source_name || quote.sourceName;
6707
+ return /* @__PURE__ */ import_react35.default.createElement(
6708
+ "div",
6530
6709
  {
6531
- href: quote.source_url || quote.sourceUrl,
6532
- target: "_blank",
6533
- rel: "noreferrer",
6710
+ key: quote.id,
6534
6711
  style: {
6535
- display: "block",
6536
- fontSize: "11px",
6537
- color: "#00657c",
6538
- marginTop: "3px",
6539
- textDecoration: "none"
6712
+ borderLeft: `3px solid ${borderColor}`,
6713
+ paddingLeft: "10px",
6714
+ paddingTop: "6px",
6715
+ paddingBottom: "6px",
6716
+ marginBottom: "8px"
6540
6717
  }
6541
6718
  },
6542
- sourceName
6543
- )
6544
- );
6545
- })), !cached.reasoning && (!cached.sources || cached.sources.length === 0) && topicQuotes.length === 0 && /* @__PURE__ */ import_react35.default.createElement("p", { className: "text-sm text-neutral-400 italic py-2" }, "No detailed reasoning available for this topic."))))
6546
- ));
6719
+ /* @__PURE__ */ import_react35.default.createElement(
6720
+ "p",
6721
+ {
6722
+ style: {
6723
+ fontSize: "13px",
6724
+ fontStyle: "italic",
6725
+ color: c.quoteText,
6726
+ margin: 0,
6727
+ lineHeight: 1.5
6728
+ }
6729
+ },
6730
+ quote.text
6731
+ ),
6732
+ verdict === "agreed" && /* @__PURE__ */ import_react35.default.createElement(
6733
+ "span",
6734
+ {
6735
+ style: {
6736
+ display: "inline-flex",
6737
+ alignItems: "center",
6738
+ gap: "4px",
6739
+ backgroundColor: c.agreedBg,
6740
+ color: c.agreedText,
6741
+ padding: "2px 8px",
6742
+ borderRadius: "9999px",
6743
+ fontSize: "11px",
6744
+ fontWeight: 500,
6745
+ marginTop: "4px",
6746
+ flexShrink: 0
6747
+ }
6748
+ },
6749
+ /* @__PURE__ */ import_react35.default.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react35.default.createElement("path", { d: "M5 13l4 4L19 7" })),
6750
+ "Agreed"
6751
+ ),
6752
+ verdict === "disagreed" && /* @__PURE__ */ import_react35.default.createElement(
6753
+ "span",
6754
+ {
6755
+ style: {
6756
+ display: "inline-flex",
6757
+ alignItems: "center",
6758
+ gap: "4px",
6759
+ backgroundColor: c.disagreedBg,
6760
+ color: c.disagreedText,
6761
+ padding: "2px 8px",
6762
+ borderRadius: "9999px",
6763
+ fontSize: "11px",
6764
+ fontWeight: 500,
6765
+ marginTop: "4px",
6766
+ flexShrink: 0
6767
+ }
6768
+ },
6769
+ /* @__PURE__ */ import_react35.default.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react35.default.createElement("path", { d: "M6 18L18 6M6 6l12 12" })),
6770
+ "Disagreed"
6771
+ ),
6772
+ sourceName && /* @__PURE__ */ import_react35.default.createElement(
6773
+ "a",
6774
+ {
6775
+ href: quote.source_url || quote.sourceUrl,
6776
+ target: "_blank",
6777
+ rel: "noreferrer",
6778
+ style: {
6779
+ display: "block",
6780
+ fontSize: "11px",
6781
+ color: c.link,
6782
+ marginTop: "3px",
6783
+ textDecoration: "none"
6784
+ }
6785
+ },
6786
+ sourceName
6787
+ )
6788
+ );
6789
+ })), !cached.reasoning && (!cached.sources || cached.sources.length === 0) && topicQuotes.length === 0 && /* @__PURE__ */ import_react35.default.createElement("p", { style: { fontSize: "14px", color: c.emptyText, fontStyle: "italic", padding: "8px 0" } }, "No detailed reasoning available for this topic."))))
6790
+ )
6791
+ );
6547
6792
  }),
6548
6793
  hasToggle && /* @__PURE__ */ import_react35.default.createElement(
6549
6794
  "button",
@@ -6551,7 +6796,7 @@ function StanceAccordion({
6551
6796
  type: "button",
6552
6797
  onClick: () => setShowAll((v) => !v),
6553
6798
  className: "text-sm font-medium mt-2 px-2 py-1 self-start cursor-pointer hover:underline",
6554
- style: { color: "#00657c" }
6799
+ style: { color: c.link }
6555
6800
  },
6556
6801
  showAll ? "Show fewer" : `Show all ${expandedTopics.length} topics`
6557
6802
  )
@@ -6580,6 +6825,7 @@ function StanceAccordion({
6580
6825
  JudicialScorecard,
6581
6826
  LegislativeInlineSummary,
6582
6827
  LegislativeRecord,
6828
+ PlaceholderRadar,
6583
6829
  PoliticianCard,
6584
6830
  PoliticianProfile,
6585
6831
  RadarChartCore,
@@ -6599,6 +6845,7 @@ function StanceAccordion({
6599
6845
  defaultNavItems,
6600
6846
  duration,
6601
6847
  easing,
6848
+ evAppLinks,
6602
6849
  evContext,
6603
6850
  focus,
6604
6851
  fontSizes,