@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.mjs CHANGED
@@ -43,7 +43,8 @@ function RadarChartCore({
43
43
  labelFontSize = 18,
44
44
  padding = 80,
45
45
  labelOffset = 20,
46
- tightFit = false
46
+ tightFit = false,
47
+ maxLabelLines = 2
47
48
  }) {
48
49
  const { isDark } = useTheme();
49
50
  const radius = size / 2 - 40;
@@ -110,7 +111,7 @@ function RadarChartCore({
110
111
  const labelMeta = spokes.map(([shortTitle], i) => {
111
112
  const angle = 2 * Math.PI * i / numSpokes;
112
113
  const baseFSize = labelFontSize;
113
- const lines = wrapLabel(shortTitle, 12);
114
+ const lines = wrapLabel(shortTitle, 12, maxLabelLines);
114
115
  const longestLineLen = lines.reduce(
115
116
  (max, ln) => ln.length > max ? ln.length : max,
116
117
  0
@@ -153,7 +154,8 @@ function RadarChartCore({
153
154
  if (y < yMin) yMin = y;
154
155
  if (y > yMax) yMax = y;
155
156
  }
156
- const labelMargin = labelOffset + labelFontSize * 1.4 + labelFontSize * 1.1;
157
+ const effLabelFSize = adaptiveFontSize(12, labelFontSize);
158
+ const labelMargin = labelOffset + effLabelFSize * 1.1 * maxLabelLines;
157
159
  tightTop = yMin - labelMargin;
158
160
  tightHeight = yMax + labelMargin - tightTop;
159
161
  }
@@ -205,7 +207,7 @@ function RadarChartCore({
205
207
  const isTop = cosA > 0.5;
206
208
  const isBottom = cosA < -0.5;
207
209
  const baseFSize = labelFontSize;
208
- const lines = wrapLabel(shortTitle, 12);
210
+ const lines = wrapLabel(shortTitle, 12, maxLabelLines);
209
211
  const longestLine = lines.reduce(
210
212
  (max, ln) => ln.length > max ? ln.length : max,
211
213
  0
@@ -346,7 +348,7 @@ function RadarChartCore({
346
348
  function adaptiveFontSize(longestLineLen, baseFSize) {
347
349
  return Math.max(baseFSize, 10);
348
350
  }
349
- function wrapLabel(label, maxChars = 12) {
351
+ function wrapLabel(label, maxChars = 12, maxLines = 2) {
350
352
  const str = String(label);
351
353
  let rawWords;
352
354
  if (str.includes("/")) {
@@ -371,15 +373,15 @@ function wrapLabel(label, maxChars = 12) {
371
373
  }
372
374
  }
373
375
  if (line) lines.push(line);
374
- if (lines.length > 2) {
375
- const overflow = lines.splice(2).join(" ");
376
- lines[1] = lines[1] + " " + overflow;
376
+ if (lines.length > maxLines) {
377
+ const overflow = lines.splice(maxLines).join(" ");
378
+ lines[maxLines - 1] = lines[maxLines - 1] + " " + overflow;
377
379
  }
378
380
  return lines;
379
381
  }
380
382
 
381
- // src/Header.jsx
382
- import React2, { useState as useState3, useRef as useRef2, useEffect as useEffect4 } from "react";
383
+ // src/PlaceholderRadar.jsx
384
+ import React2 from "react";
383
385
 
384
386
  // src/tokens.js
385
387
  var colorScales = {
@@ -774,6 +776,87 @@ var breakpoints = {
774
776
  xl: "1280px"
775
777
  };
776
778
 
779
+ // src/PlaceholderRadar.jsx
780
+ function PlaceholderRadar({ size = 250, name = "", darkMode = false }) {
781
+ const cx = size / 2;
782
+ const cy = size / 2;
783
+ const r = size / 2 * 0.65;
784
+ const n = 8;
785
+ const surface = darkMode ? "#1e2a3a" : colorScales.teal["050"];
786
+ const stroke = darkMode ? "rgba(255,255,255,0.22)" : colorScales.gray["200"];
787
+ const vertices = Array.from({ length: n }, (_, i) => {
788
+ const a = 2 * Math.PI * i / n;
789
+ return [cx + r * Math.sin(a), cy - r * Math.cos(a)];
790
+ });
791
+ const outerPts = vertices.map(([x, y]) => `${x},${y}`).join(" ");
792
+ const midPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.6},${cy + (y - cy) * 0.6}`).join(" ");
793
+ const innerPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.3},${cy + (y - cy) * 0.3}`).join(" ");
794
+ return /* @__PURE__ */ React2.createElement(
795
+ "svg",
796
+ {
797
+ width: size,
798
+ height: size,
799
+ viewBox: `0 0 ${size} ${size}`,
800
+ role: "img",
801
+ "aria-label": name ? `${name} \u2014 compass data unavailable` : "compass data unavailable",
802
+ style: {
803
+ backgroundColor: surface,
804
+ borderRadius: borderRadius.sm,
805
+ flexShrink: 0
806
+ }
807
+ },
808
+ vertices.map(([x, y], i) => /* @__PURE__ */ React2.createElement(
809
+ "line",
810
+ {
811
+ key: i,
812
+ x1: cx,
813
+ y1: cy,
814
+ x2: x,
815
+ y2: y,
816
+ stroke,
817
+ strokeWidth: "1",
818
+ strokeDasharray: "2 3",
819
+ opacity: "0.6"
820
+ }
821
+ )),
822
+ /* @__PURE__ */ React2.createElement(
823
+ "polygon",
824
+ {
825
+ points: innerPts,
826
+ fill: "none",
827
+ stroke,
828
+ strokeWidth: "1",
829
+ strokeDasharray: "2 3",
830
+ opacity: "0.5"
831
+ }
832
+ ),
833
+ /* @__PURE__ */ React2.createElement(
834
+ "polygon",
835
+ {
836
+ points: midPts,
837
+ fill: "none",
838
+ stroke,
839
+ strokeWidth: "1",
840
+ strokeDasharray: "3 3",
841
+ opacity: "0.6"
842
+ }
843
+ ),
844
+ /* @__PURE__ */ React2.createElement(
845
+ "polygon",
846
+ {
847
+ points: outerPts,
848
+ fill: "none",
849
+ stroke,
850
+ strokeWidth: "1.5",
851
+ strokeDasharray: "4 3"
852
+ }
853
+ )
854
+ );
855
+ }
856
+
857
+ // src/Header.jsx
858
+ import React3, { useState as useState3, useRef as useRef2, useEffect as useEffect4 } from "react";
859
+
777
860
  // src/useMediaQuery.js
778
861
  import { useState as useState2, useEffect as useEffect3 } from "react";
779
862
  function useMediaQuery(query) {
@@ -803,12 +886,14 @@ function Header({
803
886
  currentPath,
804
887
  onNavigate,
805
888
  profileMenu,
889
+ darkMode = false,
890
+ navCollapseBreakpoint = 1024,
806
891
  style = {}
807
892
  }) {
808
893
  const [mobileMenuOpen, setMobileMenuOpen] = useState3(false);
809
894
  const [openDropdown, setOpenDropdown] = useState3(null);
810
895
  const [profileOpen, setProfileOpen] = useState3(false);
811
- const isMobile = useMediaQuery("(max-width: 768px)");
896
+ const isMobile = useMediaQuery(`(max-width: ${navCollapseBreakpoint}px)`);
812
897
  const profileRef = useRef2(null);
813
898
  useEffect4(() => {
814
899
  if (!profileOpen) return;
@@ -826,9 +911,42 @@ function Header({
826
911
  onNavigate(href);
827
912
  }
828
913
  };
914
+ const t = darkMode ? {
915
+ surface: semanticTokens.dark.layerBase.background,
916
+ // #131416
917
+ raised: semanticTokens.dark.layerOne.background,
918
+ // #2F3237 (dropdowns)
919
+ text: colors.evLightBlue,
920
+ // #59B0C4 — AA on dark
921
+ itemText: semanticTokens.dark.layerOne.text,
922
+ // #D3D7DE (dropdown items)
923
+ muted: semanticTokens.dark.layerBase.text,
924
+ // #B3BBCC
925
+ border: semanticTokens.dark.divider,
926
+ // #41454E
927
+ hoverBg: semanticTokens.dark.layerTwo.background,
928
+ // #41454E
929
+ ctaBg: semanticTokens.dark.buttonPrimary.background.default,
930
+ // #005366
931
+ ctaBgHover: semanticTokens.dark.buttonPrimary.background.hovered,
932
+ ctaText: "#FFFFFF",
933
+ shadow: "0 10px 40px rgba(0,0,0,0.5)"
934
+ } : {
935
+ surface: colors.bgWhite,
936
+ raised: colors.bgWhite,
937
+ text: colors.evTeal,
938
+ itemText: colors.evTeal,
939
+ muted: colors.textMuted,
940
+ border: colors.borderLight,
941
+ hoverBg: colors.bgLight,
942
+ ctaBg: colors.evTeal,
943
+ ctaBgHover: colors.evTealDark,
944
+ ctaText: colors.textWhite,
945
+ shadow: "0 10px 40px rgba(0,0,0,0.1)"
946
+ };
829
947
  const styles2 = {
830
948
  header: {
831
- backgroundColor: colors.bgWhite,
949
+ backgroundColor: t.surface,
832
950
  position: "sticky",
833
951
  top: 0,
834
952
  zIndex: 50,
@@ -841,7 +959,8 @@ function Header({
841
959
  padding: isMobile ? `${spacing[3]} ${spacing[3]}` : `${spacing[4]} ${spacing[6]}`,
842
960
  display: "flex",
843
961
  alignItems: "center",
844
- justifyContent: "space-between"
962
+ justifyContent: "space-between",
963
+ gap: spacing[6]
845
964
  },
846
965
  logo: {
847
966
  height: "43px",
@@ -849,20 +968,24 @@ function Header({
849
968
  },
850
969
  nav: {
851
970
  display: isMobile ? "none" : "flex",
971
+ flex: "1 1 auto",
852
972
  alignItems: "center",
853
- gap: spacing[10]
973
+ justifyContent: "center",
974
+ flexWrap: "nowrap",
975
+ gap: spacing[8]
854
976
  },
855
977
  navItem: {
856
978
  fontFamily: fonts.primary,
857
- fontWeight: fontWeights.bold,
858
- fontSize: fontSizes.xl,
859
- color: colors.evTeal,
979
+ fontWeight: fontWeights.medium,
980
+ fontSize: fontSizes.base,
981
+ color: t.text,
860
982
  textDecoration: "none",
861
983
  cursor: "pointer",
862
984
  display: "flex",
863
985
  alignItems: "center",
864
986
  gap: spacing[2],
865
- position: "relative"
987
+ position: "relative",
988
+ whiteSpace: "nowrap"
866
989
  },
867
990
  navItemActive: {
868
991
  textDecoration: "underline"
@@ -879,9 +1002,9 @@ function Header({
879
1002
  zIndex: 100
880
1003
  },
881
1004
  dropdownInner: {
882
- backgroundColor: colors.bgWhite,
1005
+ backgroundColor: t.raised,
883
1006
  borderRadius: borderRadius.lg,
884
- boxShadow: "0 10px 40px rgba(0,0,0,0.1)",
1007
+ boxShadow: t.shadow,
885
1008
  minWidth: "200px",
886
1009
  padding: spacing[2]
887
1010
  },
@@ -891,14 +1014,14 @@ function Header({
891
1014
  fontFamily: fonts.primary,
892
1015
  fontWeight: fontWeights.medium,
893
1016
  fontSize: fontSizes.base,
894
- color: colors.evTeal,
1017
+ color: t.itemText,
895
1018
  textDecoration: "none",
896
1019
  borderRadius: borderRadius.md,
897
1020
  cursor: "pointer"
898
1021
  },
899
1022
  ctaButton: {
900
- backgroundColor: colors.evTeal,
901
- color: colors.textWhite,
1023
+ backgroundColor: t.ctaBg,
1024
+ color: t.ctaText,
902
1025
  fontFamily: fonts.primary,
903
1026
  fontWeight: fontWeights.bold,
904
1027
  fontSize: fontSizes.xl,
@@ -913,13 +1036,13 @@ function Header({
913
1036
  display: "inline-flex",
914
1037
  alignItems: "center",
915
1038
  backgroundColor: "transparent",
916
- color: colors.evTeal,
1039
+ color: t.text,
917
1040
  fontFamily: fonts.primary,
918
1041
  fontWeight: fontWeights.bold,
919
1042
  fontSize: fontSizes.base,
920
1043
  padding: `${spacing[2]} ${spacing[5]}`,
921
1044
  borderRadius: borderRadius.full || "999px",
922
- border: `1.5px solid ${colors.evTeal}`,
1045
+ border: `1.5px solid ${t.text}`,
923
1046
  cursor: "pointer",
924
1047
  textDecoration: "none",
925
1048
  lineHeight: 1.2,
@@ -935,7 +1058,7 @@ function Header({
935
1058
  hamburger: {
936
1059
  width: "24px",
937
1060
  height: "2px",
938
- backgroundColor: colors.evTeal,
1061
+ backgroundColor: t.text,
939
1062
  position: "relative"
940
1063
  },
941
1064
  mobileMenu: {
@@ -945,25 +1068,25 @@ function Header({
945
1068
  top: "100%",
946
1069
  left: 0,
947
1070
  right: 0,
948
- backgroundColor: colors.bgWhite,
1071
+ backgroundColor: t.surface,
949
1072
  padding: spacing[4],
950
- boxShadow: "0 4px 20px rgba(0,0,0,0.1)"
1073
+ boxShadow: t.shadow
951
1074
  },
952
1075
  mobileNavItem: {
953
1076
  fontFamily: fonts.primary,
954
- fontWeight: fontWeights.bold,
955
- fontSize: fontSizes.lg,
956
- color: colors.evTeal,
1077
+ fontWeight: fontWeights.medium,
1078
+ fontSize: fontSizes.base,
1079
+ color: t.text,
957
1080
  textDecoration: "none",
958
1081
  padding: `${spacing[3]} 0`,
959
- borderBottom: `1px solid ${colors.borderLight}`
1082
+ borderBottom: `1px solid ${t.border}`
960
1083
  },
961
1084
  profileButton: {
962
1085
  width: "40px",
963
1086
  height: "40px",
964
1087
  borderRadius: borderRadius.full,
965
- border: `2px solid ${colors.evTeal}`,
966
- backgroundColor: colors.bgLight,
1088
+ border: `2px solid ${t.text}`,
1089
+ backgroundColor: darkMode ? t.raised : colors.bgLight,
967
1090
  cursor: "pointer",
968
1091
  display: "flex",
969
1092
  alignItems: "center",
@@ -978,9 +1101,9 @@ function Header({
978
1101
  zIndex: 100
979
1102
  },
980
1103
  profileDropdownInner: {
981
- backgroundColor: colors.bgWhite,
1104
+ backgroundColor: t.raised,
982
1105
  borderRadius: borderRadius.lg,
983
- boxShadow: "0 10px 40px rgba(0,0,0,0.1)",
1106
+ boxShadow: t.shadow,
984
1107
  minWidth: "160px",
985
1108
  padding: spacing[2]
986
1109
  },
@@ -991,7 +1114,7 @@ function Header({
991
1114
  fontFamily: fonts.primary,
992
1115
  fontWeight: fontWeights.medium,
993
1116
  fontSize: fontSizes.base,
994
- color: colors.evTeal,
1117
+ color: t.itemText,
995
1118
  textDecoration: "none",
996
1119
  borderRadius: borderRadius.md,
997
1120
  cursor: "pointer",
@@ -1001,7 +1124,7 @@ function Header({
1001
1124
  },
1002
1125
  mobileDivider: {
1003
1126
  height: "1px",
1004
- backgroundColor: colors.borderLight,
1127
+ backgroundColor: t.border,
1005
1128
  margin: `${spacing[3]} 0`
1006
1129
  },
1007
1130
  profileLabel: {
@@ -1009,8 +1132,8 @@ function Header({
1009
1132
  fontFamily: fonts.primary,
1010
1133
  fontWeight: fontWeights.semibold,
1011
1134
  fontSize: fontSizes.sm,
1012
- color: colors.textMuted,
1013
- borderBottom: `1px solid ${colors.borderLight}`,
1135
+ color: t.muted,
1136
+ borderBottom: `1px solid ${t.border}`,
1014
1137
  marginBottom: spacing[1],
1015
1138
  overflow: "hidden",
1016
1139
  textOverflow: "ellipsis",
@@ -1018,17 +1141,23 @@ function Header({
1018
1141
  }
1019
1142
  };
1020
1143
  const NavLink = ({ item }) => {
1021
- const isActive = currentPath === item.href;
1144
+ const isActive = currentPath === item.href || typeof window !== "undefined" && /^https?:\/\//.test(item.href) && (() => {
1145
+ try {
1146
+ return new URL(item.href).hostname === window.location.hostname;
1147
+ } catch {
1148
+ return false;
1149
+ }
1150
+ })();
1022
1151
  const hasDropdown = item.dropdown && item.dropdown.length > 0;
1023
1152
  const isOpen = openDropdown === item.label;
1024
- return /* @__PURE__ */ React2.createElement(
1153
+ return /* @__PURE__ */ React3.createElement(
1025
1154
  "div",
1026
1155
  {
1027
1156
  style: { position: "relative" },
1028
1157
  onMouseEnter: () => hasDropdown && setOpenDropdown(item.label),
1029
1158
  onMouseLeave: () => hasDropdown && setOpenDropdown(null)
1030
1159
  },
1031
- /* @__PURE__ */ React2.createElement(
1160
+ /* @__PURE__ */ React3.createElement(
1032
1161
  "a",
1033
1162
  {
1034
1163
  href: item.href,
@@ -1039,7 +1168,7 @@ function Header({
1039
1168
  }
1040
1169
  },
1041
1170
  item.label,
1042
- hasDropdown && /* @__PURE__ */ React2.createElement(
1171
+ hasDropdown && /* @__PURE__ */ React3.createElement(
1043
1172
  "svg",
1044
1173
  {
1045
1174
  style: styles2.dropdownIcon,
@@ -1047,11 +1176,11 @@ function Header({
1047
1176
  fill: "none",
1048
1177
  xmlns: "http://www.w3.org/2000/svg"
1049
1178
  },
1050
- /* @__PURE__ */ React2.createElement(
1179
+ /* @__PURE__ */ React3.createElement(
1051
1180
  "path",
1052
1181
  {
1053
1182
  d: "M1 1L8 8L15 1",
1054
- stroke: colors.evTeal,
1183
+ stroke: t.text,
1055
1184
  strokeWidth: "2",
1056
1185
  strokeLinecap: "round",
1057
1186
  strokeLinejoin: "round"
@@ -1059,7 +1188,7 @@ function Header({
1059
1188
  )
1060
1189
  )
1061
1190
  ),
1062
- hasDropdown && isOpen && /* @__PURE__ */ React2.createElement("div", { style: styles2.dropdown }, /* @__PURE__ */ React2.createElement("div", { style: styles2.dropdownInner }, item.dropdown.map((dropdownItem, idx) => /* @__PURE__ */ React2.createElement(
1191
+ hasDropdown && isOpen && /* @__PURE__ */ React3.createElement("div", { style: styles2.dropdown }, /* @__PURE__ */ React3.createElement("div", { style: styles2.dropdownInner }, item.dropdown.map((dropdownItem, idx) => /* @__PURE__ */ React3.createElement(
1063
1192
  "a",
1064
1193
  {
1065
1194
  key: idx,
@@ -1067,7 +1196,7 @@ function Header({
1067
1196
  onClick: (e) => handleNavClick(e, dropdownItem.href),
1068
1197
  style: styles2.dropdownItem,
1069
1198
  onMouseEnter: (e) => {
1070
- e.target.style.backgroundColor = colors.bgLight;
1199
+ e.target.style.backgroundColor = t.hoverBg;
1071
1200
  },
1072
1201
  onMouseLeave: (e) => {
1073
1202
  e.target.style.backgroundColor = "transparent";
@@ -1077,26 +1206,26 @@ function Header({
1077
1206
  ))))
1078
1207
  );
1079
1208
  };
1080
- return /* @__PURE__ */ React2.createElement("header", { style: styles2.header }, /* @__PURE__ */ React2.createElement("div", { style: styles2.container }, /* @__PURE__ */ React2.createElement(
1209
+ return /* @__PURE__ */ React3.createElement("header", { style: styles2.header }, /* @__PURE__ */ React3.createElement("div", { style: styles2.container }, /* @__PURE__ */ React3.createElement(
1081
1210
  "a",
1082
1211
  {
1083
1212
  href: logoHref,
1084
1213
  onClick: (e) => handleNavClick(e, logoHref),
1085
- style: { display: "flex", alignItems: "center" }
1214
+ style: { display: "flex", alignItems: "center", flexShrink: 0 }
1086
1215
  },
1087
- logoSrc ? /* @__PURE__ */ React2.createElement("img", { src: logoSrc, alt: logoAlt, style: styles2.logo }) : /* @__PURE__ */ React2.createElement(
1216
+ logoSrc ? /* @__PURE__ */ React3.createElement("img", { src: logoSrc, alt: logoAlt, style: styles2.logo }) : /* @__PURE__ */ React3.createElement(
1088
1217
  "span",
1089
1218
  {
1090
1219
  style: {
1091
1220
  fontFamily: fonts.primary,
1092
1221
  fontWeight: fontWeights.bold,
1093
1222
  fontSize: fontSizes["2xl"],
1094
- color: colors.evTeal
1223
+ color: t.text
1095
1224
  }
1096
1225
  },
1097
1226
  "empowered.vote"
1098
1227
  )
1099
- ), /* @__PURE__ */ React2.createElement("nav", { style: styles2.nav, className: "ev-header-nav" }, navItems.map((item, idx) => /* @__PURE__ */ React2.createElement(NavLink, { key: idx, item }))), /* @__PURE__ */ React2.createElement("div", { style: { display: isMobile ? "none" : "flex", alignItems: "center", gap: spacing[3] } }, secondaryAction && React2.isValidElement(secondaryAction) && secondaryAction, secondaryAction && !React2.isValidElement(secondaryAction) && /* @__PURE__ */ React2.createElement(
1228
+ ), /* @__PURE__ */ React3.createElement("nav", { style: styles2.nav, className: "ev-header-nav" }, navItems.map((item, idx) => /* @__PURE__ */ React3.createElement(NavLink, { key: idx, item }))), /* @__PURE__ */ React3.createElement("div", { style: { display: isMobile ? "none" : "flex", alignItems: "center", gap: spacing[3], flexShrink: 0 } }, secondaryAction && React3.isValidElement(secondaryAction) && secondaryAction, secondaryAction && !React3.isValidElement(secondaryAction) && /* @__PURE__ */ React3.createElement(
1100
1229
  "a",
1101
1230
  {
1102
1231
  href: secondaryAction.href,
@@ -1110,16 +1239,16 @@ function Header({
1110
1239
  style: styles2.secondaryAction,
1111
1240
  className: "ev-header-secondary",
1112
1241
  onMouseEnter: (e) => {
1113
- e.currentTarget.style.backgroundColor = colors.evTeal;
1114
- e.currentTarget.style.color = colors.textWhite;
1242
+ e.currentTarget.style.backgroundColor = t.text;
1243
+ e.currentTarget.style.color = darkMode ? t.surface : colors.textWhite;
1115
1244
  },
1116
1245
  onMouseLeave: (e) => {
1117
1246
  e.currentTarget.style.backgroundColor = "transparent";
1118
- e.currentTarget.style.color = colors.evTeal;
1247
+ e.currentTarget.style.color = t.text;
1119
1248
  }
1120
1249
  },
1121
1250
  secondaryAction.label
1122
- ), ctaButton && /* @__PURE__ */ React2.createElement(
1251
+ ), ctaButton && /* @__PURE__ */ React3.createElement(
1123
1252
  "a",
1124
1253
  {
1125
1254
  href: ctaButton.href,
@@ -1127,14 +1256,14 @@ function Header({
1127
1256
  style: styles2.ctaButton,
1128
1257
  className: "ev-header-cta",
1129
1258
  onMouseEnter: (e) => {
1130
- e.target.style.backgroundColor = colors.evTealDark;
1259
+ e.target.style.backgroundColor = t.ctaBgHover;
1131
1260
  },
1132
1261
  onMouseLeave: (e) => {
1133
- e.target.style.backgroundColor = colors.evTeal;
1262
+ e.target.style.backgroundColor = t.ctaBg;
1134
1263
  }
1135
1264
  },
1136
1265
  ctaButton.label
1137
- ), profileMenu && /* @__PURE__ */ React2.createElement("div", { ref: profileRef, style: { position: "relative" } }, /* @__PURE__ */ React2.createElement(
1266
+ ), profileMenu && /* @__PURE__ */ React3.createElement("div", { ref: profileRef, style: { position: "relative" } }, /* @__PURE__ */ React3.createElement(
1138
1267
  "button",
1139
1268
  {
1140
1269
  style: styles2.profileButton,
@@ -1142,24 +1271,24 @@ function Header({
1142
1271
  "aria-label": "Profile menu",
1143
1272
  "aria-expanded": profileOpen
1144
1273
  },
1145
- /* @__PURE__ */ React2.createElement(
1274
+ /* @__PURE__ */ React3.createElement(
1146
1275
  "svg",
1147
1276
  {
1148
1277
  width: "20",
1149
1278
  height: "20",
1150
1279
  viewBox: "0 0 24 24",
1151
1280
  fill: "none",
1152
- stroke: colors.evTeal,
1281
+ stroke: t.text,
1153
1282
  strokeWidth: "2",
1154
1283
  strokeLinecap: "round",
1155
1284
  strokeLinejoin: "round"
1156
1285
  },
1157
- /* @__PURE__ */ React2.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1158
- /* @__PURE__ */ React2.createElement("circle", { cx: "12", cy: "7", r: "4" })
1286
+ /* @__PURE__ */ React3.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1287
+ /* @__PURE__ */ React3.createElement("circle", { cx: "12", cy: "7", r: "4" })
1159
1288
  )
1160
- ), profileOpen && /* @__PURE__ */ React2.createElement("div", { style: styles2.profileDropdown }, /* @__PURE__ */ React2.createElement("div", { style: styles2.profileDropdownInner }, profileMenu.label && /* @__PURE__ */ React2.createElement("div", { style: styles2.profileLabel }, profileMenu.label), profileMenu.items.map((item, idx) => {
1289
+ ), profileOpen && /* @__PURE__ */ React3.createElement("div", { style: styles2.profileDropdown }, /* @__PURE__ */ React3.createElement("div", { style: styles2.profileDropdownInner }, profileMenu.label && /* @__PURE__ */ React3.createElement("div", { style: styles2.profileLabel }, profileMenu.label), profileMenu.items.map((item, idx) => {
1161
1290
  if (item.href) {
1162
- return /* @__PURE__ */ React2.createElement(
1291
+ return /* @__PURE__ */ React3.createElement(
1163
1292
  "a",
1164
1293
  {
1165
1294
  key: idx,
@@ -1173,7 +1302,7 @@ function Header({
1173
1302
  },
1174
1303
  style: styles2.profileDropdownItem,
1175
1304
  onMouseEnter: (e) => {
1176
- e.target.style.backgroundColor = colors.bgLight;
1305
+ e.target.style.backgroundColor = t.hoverBg;
1177
1306
  },
1178
1307
  onMouseLeave: (e) => {
1179
1308
  e.target.style.backgroundColor = "transparent";
@@ -1182,7 +1311,7 @@ function Header({
1182
1311
  item.label
1183
1312
  );
1184
1313
  }
1185
- return /* @__PURE__ */ React2.createElement(
1314
+ return /* @__PURE__ */ React3.createElement(
1186
1315
  "button",
1187
1316
  {
1188
1317
  key: idx,
@@ -1193,7 +1322,7 @@ function Header({
1193
1322
  },
1194
1323
  style: styles2.profileDropdownItem,
1195
1324
  onMouseEnter: (e) => {
1196
- e.target.style.backgroundColor = colors.bgLight;
1325
+ e.target.style.backgroundColor = t.hoverBg;
1197
1326
  },
1198
1327
  onMouseLeave: (e) => {
1199
1328
  e.target.style.backgroundColor = "transparent";
@@ -1201,7 +1330,7 @@ function Header({
1201
1330
  },
1202
1331
  item.label
1203
1332
  );
1204
- }))))), /* @__PURE__ */ React2.createElement(
1333
+ }))))), /* @__PURE__ */ React3.createElement(
1205
1334
  "button",
1206
1335
  {
1207
1336
  style: styles2.mobileMenuButton,
@@ -1210,7 +1339,7 @@ function Header({
1210
1339
  "aria-label": "Toggle menu",
1211
1340
  "aria-expanded": mobileMenuOpen
1212
1341
  },
1213
- /* @__PURE__ */ React2.createElement("div", { style: styles2.hamburger }, /* @__PURE__ */ React2.createElement(
1342
+ /* @__PURE__ */ React3.createElement("div", { style: styles2.hamburger }, /* @__PURE__ */ React3.createElement(
1214
1343
  "span",
1215
1344
  {
1216
1345
  style: {
@@ -1219,10 +1348,10 @@ function Header({
1219
1348
  left: 0,
1220
1349
  width: "100%",
1221
1350
  height: "2px",
1222
- backgroundColor: colors.evTeal
1351
+ backgroundColor: t.text
1223
1352
  }
1224
1353
  }
1225
- ), /* @__PURE__ */ React2.createElement(
1354
+ ), /* @__PURE__ */ React3.createElement(
1226
1355
  "span",
1227
1356
  {
1228
1357
  style: {
@@ -1231,13 +1360,13 @@ function Header({
1231
1360
  left: 0,
1232
1361
  width: "100%",
1233
1362
  height: "2px",
1234
- backgroundColor: colors.evTeal
1363
+ backgroundColor: t.text
1235
1364
  }
1236
1365
  }
1237
1366
  ))
1238
- )), /* @__PURE__ */ React2.createElement("div", { style: styles2.mobileMenu, className: "ev-header-mobile-menu" }, navItems.map((item, idx) => {
1367
+ )), /* @__PURE__ */ React3.createElement("div", { style: styles2.mobileMenu, className: "ev-header-mobile-menu" }, navItems.map((item, idx) => {
1239
1368
  const hasDropdown = item.dropdown && item.dropdown.length > 0;
1240
- return /* @__PURE__ */ React2.createElement(React2.Fragment, { key: idx }, hasDropdown ? /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
1369
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, { key: idx }, hasDropdown ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
1241
1370
  "span",
1242
1371
  {
1243
1372
  style: {
@@ -1247,7 +1376,7 @@ function Header({
1247
1376
  }
1248
1377
  },
1249
1378
  item.label
1250
- ), item.dropdown.map((sub, subIdx) => /* @__PURE__ */ React2.createElement(
1379
+ ), item.dropdown.map((sub, subIdx) => /* @__PURE__ */ React3.createElement(
1251
1380
  "a",
1252
1381
  {
1253
1382
  key: subIdx,
@@ -1264,7 +1393,7 @@ function Header({
1264
1393
  }
1265
1394
  },
1266
1395
  sub.label
1267
- ))) : /* @__PURE__ */ React2.createElement(
1396
+ ))) : /* @__PURE__ */ React3.createElement(
1268
1397
  "a",
1269
1398
  {
1270
1399
  href: item.href,
@@ -1276,7 +1405,7 @@ function Header({
1276
1405
  },
1277
1406
  item.label
1278
1407
  ));
1279
- }), secondaryAction && React2.isValidElement(secondaryAction) && /* @__PURE__ */ React2.createElement("div", { style: { marginTop: spacing[4], textAlign: "center" } }, secondaryAction), secondaryAction && !React2.isValidElement(secondaryAction) && /* @__PURE__ */ React2.createElement(
1408
+ }), secondaryAction && React3.isValidElement(secondaryAction) && /* @__PURE__ */ React3.createElement("div", { style: { marginTop: spacing[4], textAlign: "center" } }, secondaryAction), secondaryAction && !React3.isValidElement(secondaryAction) && /* @__PURE__ */ React3.createElement(
1280
1409
  "a",
1281
1410
  {
1282
1411
  href: secondaryAction.href,
@@ -1291,7 +1420,7 @@ function Header({
1291
1420
  style: { ...styles2.secondaryAction, marginTop: spacing[4], textAlign: "center", justifyContent: "center" }
1292
1421
  },
1293
1422
  secondaryAction.label
1294
- ), ctaButton && /* @__PURE__ */ React2.createElement(
1423
+ ), ctaButton && /* @__PURE__ */ React3.createElement(
1295
1424
  "a",
1296
1425
  {
1297
1426
  href: ctaButton.href,
@@ -1302,14 +1431,14 @@ function Header({
1302
1431
  style: { ...styles2.ctaButton, marginTop: spacing[4], textAlign: "center" }
1303
1432
  },
1304
1433
  ctaButton.label
1305
- ), profileMenu && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("div", { style: styles2.mobileDivider }), profileMenu.label && /* @__PURE__ */ React2.createElement(
1434
+ ), profileMenu && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("div", { style: styles2.mobileDivider }), profileMenu.label && /* @__PURE__ */ React3.createElement(
1306
1435
  "span",
1307
1436
  {
1308
1437
  style: {
1309
1438
  ...styles2.mobileNavItem,
1310
1439
  fontWeight: fontWeights.medium,
1311
1440
  fontSize: fontSizes.sm,
1312
- color: colors.textMuted,
1441
+ color: t.muted,
1313
1442
  cursor: "default",
1314
1443
  display: "block",
1315
1444
  borderBottom: "none"
@@ -1318,7 +1447,7 @@ function Header({
1318
1447
  profileMenu.label
1319
1448
  ), profileMenu.items.map((item, idx) => {
1320
1449
  if (item.href) {
1321
- return /* @__PURE__ */ React2.createElement(
1450
+ return /* @__PURE__ */ React3.createElement(
1322
1451
  "a",
1323
1452
  {
1324
1453
  key: idx,
@@ -1335,7 +1464,7 @@ function Header({
1335
1464
  item.label
1336
1465
  );
1337
1466
  }
1338
- return /* @__PURE__ */ React2.createElement(
1467
+ return /* @__PURE__ */ React3.createElement(
1339
1468
  "button",
1340
1469
  {
1341
1470
  key: idx,
@@ -1359,10 +1488,10 @@ function Header({
1359
1488
  }
1360
1489
 
1361
1490
  // src/SiteHeader.jsx
1362
- import React4 from "react";
1491
+ import React5 from "react";
1363
1492
 
1364
1493
  // src/FeedbackButton.jsx
1365
- import React3 from "react";
1494
+ import React4 from "react";
1366
1495
  var FEEDBACK_BASE_DEFAULT = "https://alpha.empowered.vote/feedback";
1367
1496
  var HOST_FEATURE_MAP = {
1368
1497
  "compass.empowered.vote": "compass",
@@ -1433,7 +1562,7 @@ function FeedbackButton({
1433
1562
  cursor: "pointer"
1434
1563
  };
1435
1564
  const baseStyle = variant === "link" ? linkStyle2 : pillStyle;
1436
- return /* @__PURE__ */ React3.createElement(
1565
+ return /* @__PURE__ */ React4.createElement(
1437
1566
  "a",
1438
1567
  {
1439
1568
  href,
@@ -1469,10 +1598,17 @@ var defaultNavItems = [
1469
1598
  { label: "Find Representatives", href: "https://essentials.empowered.vote" },
1470
1599
  { label: "Read & Rank", href: "https://readrank.empowered.vote" },
1471
1600
  { label: "Treasury Tracker", href: "https://treasurytracker.empowered.vote" },
1601
+ { label: "Civic Trivia", href: "https://ctc.empowered.vote" },
1472
1602
  { label: "Empowered Badges", href: "https://badges.empowered.vote" }
1473
1603
  ]
1474
1604
  }
1475
1605
  ];
1606
+ var evAppLinks = [
1607
+ { label: "Compass", href: "https://compass.empowered.vote" },
1608
+ { label: "Find Representatives", href: "https://essentials.empowered.vote" },
1609
+ { label: "Treasury Tracker", href: "https://treasurytracker.empowered.vote" },
1610
+ { label: "Civic Trivia", href: "https://ctc.empowered.vote" }
1611
+ ];
1476
1612
  var defaultCtaButton = {
1477
1613
  label: "Donate",
1478
1614
  href: "https://empowered.vote/donate"
@@ -1497,11 +1633,11 @@ function SiteHeader({
1497
1633
  if (secondaryAction === false) {
1498
1634
  resolvedSecondary = void 0;
1499
1635
  } else if (secondaryAction === void 0) {
1500
- resolvedSecondary = /* @__PURE__ */ React4.createElement(FeedbackButton, { feature: feedbackFeature });
1636
+ resolvedSecondary = /* @__PURE__ */ React5.createElement(FeedbackButton, { feature: feedbackFeature });
1501
1637
  } else {
1502
1638
  resolvedSecondary = secondaryAction;
1503
1639
  }
1504
- return /* @__PURE__ */ React4.createElement(
1640
+ return /* @__PURE__ */ React5.createElement(
1505
1641
  Header,
1506
1642
  {
1507
1643
  logoSrc,
@@ -1518,7 +1654,7 @@ function SiteHeader({
1518
1654
  }
1519
1655
 
1520
1656
  // src/FilterSidebar.jsx
1521
- import React5 from "react";
1657
+ import React6 from "react";
1522
1658
  function FilterSidebar({
1523
1659
  title = "Filter by",
1524
1660
  zipCode = "",
@@ -1672,14 +1808,14 @@ function FilterSidebar({
1672
1808
  fontSize: fontSizes.sm
1673
1809
  }
1674
1810
  };
1675
- return /* @__PURE__ */ React5.createElement("aside", { style: styles2.sidebar, className: "ev-filter-sidebar" }, !isMobile && /* @__PURE__ */ React5.createElement("h2", { style: styles2.title }, title), /* @__PURE__ */ React5.createElement("div", { style: isMobile ? void 0 : styles2.contentTop }, /* @__PURE__ */ React5.createElement("div", { style: isMobile ? { marginBottom: spacing[3] } : styles2.section }, !isMobile && /* @__PURE__ */ React5.createElement("label", { style: styles2.sectionLabel }, "Location"), autocompleteContainerRef ? /* @__PURE__ */ React5.createElement(
1811
+ return /* @__PURE__ */ React6.createElement("aside", { style: styles2.sidebar, className: "ev-filter-sidebar" }, !isMobile && /* @__PURE__ */ React6.createElement("h2", { style: styles2.title }, title), /* @__PURE__ */ React6.createElement("div", { style: isMobile ? void 0 : styles2.contentTop }, /* @__PURE__ */ React6.createElement("div", { style: isMobile ? { marginBottom: spacing[3] } : styles2.section }, !isMobile && /* @__PURE__ */ React6.createElement("label", { style: styles2.sectionLabel }, "Location"), autocompleteContainerRef ? /* @__PURE__ */ React6.createElement(
1676
1812
  "div",
1677
1813
  {
1678
1814
  ref: autocompleteContainerRef,
1679
1815
  style: styles2.zipInputWrapper,
1680
1816
  className: "ev-autocomplete-container"
1681
1817
  }
1682
- ) : /* @__PURE__ */ React5.createElement("div", { style: styles2.zipInputWrapper }, /* @__PURE__ */ React5.createElement(
1818
+ ) : /* @__PURE__ */ React6.createElement("div", { style: styles2.zipInputWrapper }, /* @__PURE__ */ React6.createElement(
1683
1819
  "input",
1684
1820
  {
1685
1821
  ref: zipInputRef,
@@ -1691,7 +1827,7 @@ function FilterSidebar({
1691
1827
  style: styles2.zipInput,
1692
1828
  "aria-label": "Search location"
1693
1829
  }
1694
- ), /* @__PURE__ */ React5.createElement(
1830
+ ), /* @__PURE__ */ React6.createElement(
1695
1831
  "button",
1696
1832
  {
1697
1833
  type: "button",
@@ -1700,7 +1836,7 @@ function FilterSidebar({
1700
1836
  "aria-label": "Clear ZIP code"
1701
1837
  },
1702
1838
  "\xD7"
1703
- ))), /* @__PURE__ */ React5.createElement("div", { style: isMobile ? {} : styles2.section }, !isMobile && /* @__PURE__ */ React5.createElement("label", { style: styles2.sectionLabel }, "Group"), /* @__PURE__ */ React5.createElement("div", { style: styles2.radioGroup, role: "radiogroup", "aria-label": "Filter by group" }, filterOptions.map((option) => /* @__PURE__ */ React5.createElement("label", { key: option.value, style: styles2.radioLabel }, /* @__PURE__ */ React5.createElement(
1839
+ ))), /* @__PURE__ */ React6.createElement("div", { style: isMobile ? {} : styles2.section }, !isMobile && /* @__PURE__ */ React6.createElement("label", { style: styles2.sectionLabel }, "Group"), /* @__PURE__ */ React6.createElement("div", { style: styles2.radioGroup, role: "radiogroup", "aria-label": "Filter by group" }, filterOptions.map((option) => /* @__PURE__ */ React6.createElement("label", { key: option.value, style: styles2.radioLabel }, /* @__PURE__ */ React6.createElement(
1704
1840
  "input",
1705
1841
  {
1706
1842
  type: "radio",
@@ -1710,18 +1846,18 @@ function FilterSidebar({
1710
1846
  onChange: () => onFilterChange == null ? void 0 : onFilterChange(option.value),
1711
1847
  style: styles2.radioInput
1712
1848
  }
1713
- ), option.label))))), !isMobile && /* @__PURE__ */ React5.createElement("div", { style: styles2.imageSection }, locationLabel && /* @__PURE__ */ React5.createElement("div", { style: styles2.locationLabel }, locationLabel), buildingImageSrc ? /* @__PURE__ */ React5.createElement(
1849
+ ), option.label))))), !isMobile && /* @__PURE__ */ React6.createElement("div", { style: styles2.imageSection }, locationLabel && /* @__PURE__ */ React6.createElement("div", { style: styles2.locationLabel }, locationLabel), buildingImageSrc ? /* @__PURE__ */ React6.createElement(
1714
1850
  "img",
1715
1851
  {
1716
1852
  src: buildingImageSrc,
1717
1853
  alt: `${selectedFilter} government building`,
1718
1854
  style: styles2.buildingImage
1719
1855
  }
1720
- ) : /* @__PURE__ */ React5.createElement("div", { style: styles2.buildingPlaceholder }, "No image")));
1856
+ ) : /* @__PURE__ */ React6.createElement("div", { style: styles2.buildingPlaceholder }, "No image")));
1721
1857
  }
1722
1858
 
1723
1859
  // src/PoliticianCard.jsx
1724
- import React6, { useState as useState4, useEffect as useEffect5 } from "react";
1860
+ import React7, { useState as useState4, useEffect as useEffect5 } from "react";
1725
1861
  function PoliticianCard({
1726
1862
  id,
1727
1863
  imageSrc,
@@ -1734,7 +1870,8 @@ function PoliticianCard({
1734
1870
  style = {},
1735
1871
  badge,
1736
1872
  imageFocalPoint,
1737
- footer
1873
+ footer,
1874
+ imageWidth = "90px"
1738
1875
  }) {
1739
1876
  const isHorizontal = variant === "horizontal";
1740
1877
  const handleCardClick = (e) => {
@@ -1762,20 +1899,25 @@ function PoliticianCard({
1762
1899
  ...style
1763
1900
  },
1764
1901
  imageWrapper: {
1765
- width: isHorizontal ? "90px" : "100%",
1902
+ // Horizontal: relative box whose height comes from the card (flex stretch),
1903
+ // so the photo fills the card height instead of dictating it. Absolutely
1904
+ // positioned children below mean a wider photo can't inflate the card.
1905
+ position: isHorizontal ? "relative" : void 0,
1906
+ width: isHorizontal ? imageWidth : "100%",
1766
1907
  height: isHorizontal ? "100%" : "auto",
1767
- maxHeight: isHorizontal ? "200px" : void 0,
1768
1908
  aspectRatio: isHorizontal ? void 0 : "4/5",
1769
1909
  flexShrink: 0,
1770
1910
  overflow: "hidden"
1771
1911
  },
1772
1912
  image: {
1913
+ ...isHorizontal ? { position: "absolute", top: 0, left: 0 } : {},
1773
1914
  width: "100%",
1774
1915
  height: "100%",
1775
1916
  objectFit: "cover",
1776
1917
  objectPosition: imageFocalPoint != null ? imageFocalPoint : "center 20%"
1777
1918
  },
1778
1919
  imagePlaceholder: {
1920
+ ...isHorizontal ? { position: "absolute", top: 0, left: 0 } : {},
1779
1921
  width: "100%",
1780
1922
  height: "100%",
1781
1923
  backgroundColor: colors.evTeal,
@@ -1873,7 +2015,7 @@ function PoliticianCard({
1873
2015
  textTransform: "uppercase"
1874
2016
  }
1875
2017
  };
1876
- const CompassIcon2 = () => /* @__PURE__ */ React6.createElement(
2018
+ const CompassIcon2 = () => /* @__PURE__ */ React7.createElement(
1877
2019
  "svg",
1878
2020
  {
1879
2021
  style: styles2.compassIcon,
@@ -1881,7 +2023,7 @@ function PoliticianCard({
1881
2023
  fill: "none",
1882
2024
  xmlns: "http://www.w3.org/2000/svg"
1883
2025
  },
1884
- /* @__PURE__ */ React6.createElement(
2026
+ /* @__PURE__ */ React7.createElement(
1885
2027
  "polygon",
1886
2028
  {
1887
2029
  points: "12,1 21.5,6.5 21.5,17.5 12,23 2.5,17.5 2.5,6.5",
@@ -1891,13 +2033,13 @@ function PoliticianCard({
1891
2033
  strokeLinejoin: "round"
1892
2034
  }
1893
2035
  ),
1894
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "1", stroke: "currentColor", strokeWidth: "1" }),
1895
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
1896
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
1897
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "23", stroke: "currentColor", strokeWidth: "1" }),
1898
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
1899
- /* @__PURE__ */ React6.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
1900
- /* @__PURE__ */ React6.createElement(
2036
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "1", stroke: "currentColor", strokeWidth: "1" }),
2037
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
2038
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "21.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
2039
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "12", y2: "23", stroke: "currentColor", strokeWidth: "1" }),
2040
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "17.5", stroke: "currentColor", strokeWidth: "1" }),
2041
+ /* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "12", x2: "2.5", y2: "6.5", stroke: "currentColor", strokeWidth: "1" }),
2042
+ /* @__PURE__ */ React7.createElement(
1901
2043
  "polygon",
1902
2044
  {
1903
2045
  points: "12,4 18,7.5 18,16 12,19.5 7,15 5,8",
@@ -1905,7 +2047,7 @@ function PoliticianCard({
1905
2047
  opacity: "0.35"
1906
2048
  }
1907
2049
  ),
1908
- /* @__PURE__ */ React6.createElement(
2050
+ /* @__PURE__ */ React7.createElement(
1909
2051
  "polygon",
1910
2052
  {
1911
2053
  points: "12,4 18,7.5 18,16 12,19.5 7,15 5,8",
@@ -1926,7 +2068,7 @@ function PoliticianCard({
1926
2068
  const initials = parts.length >= 2 ? parts[0][0] + parts[parts.length - 1][0] : ((_a = parts[0]) == null ? void 0 : _a[0]) || "?";
1927
2069
  return initials.toUpperCase();
1928
2070
  };
1929
- return /* @__PURE__ */ React6.createElement(
2071
+ return /* @__PURE__ */ React7.createElement(
1930
2072
  "div",
1931
2073
  {
1932
2074
  style: styles2.card,
@@ -1951,8 +2093,8 @@ function PoliticianCard({
1951
2093
  }
1952
2094
  }
1953
2095
  },
1954
- badge && /* @__PURE__ */ React6.createElement("span", { style: styles2.badge }, badge),
1955
- /* @__PURE__ */ React6.createElement("div", { style: styles2.imageWrapper }, imageSrc && !imgError ? /* @__PURE__ */ React6.createElement(
2096
+ badge && /* @__PURE__ */ React7.createElement("span", { style: styles2.badge }, badge),
2097
+ /* @__PURE__ */ React7.createElement("div", { style: styles2.imageWrapper }, imageSrc && !imgError ? /* @__PURE__ */ React7.createElement(
1956
2098
  "img",
1957
2099
  {
1958
2100
  src: imageSrc,
@@ -1960,9 +2102,9 @@ function PoliticianCard({
1960
2102
  style: styles2.image,
1961
2103
  onError: () => setImgError(true)
1962
2104
  }
1963
- ) : /* @__PURE__ */ React6.createElement("div", { style: styles2.imagePlaceholder }, getInitials(name))),
1964
- /* @__PURE__ */ React6.createElement("div", { style: styles2.content }, /* @__PURE__ */ React6.createElement("h3", { style: styles2.name }, name), /* @__PURE__ */ React6.createElement("p", { style: styles2.title }, title), subtitle && /* @__PURE__ */ React6.createElement("p", { style: styles2.subtitle }, subtitle), footer && /* @__PURE__ */ React6.createElement("div", { style: { marginTop: "auto", marginLeft: "-5px" } }, footer)),
1965
- onCompassClick && /* @__PURE__ */ React6.createElement(
2105
+ ) : /* @__PURE__ */ React7.createElement("div", { style: styles2.imagePlaceholder }, getInitials(name))),
2106
+ /* @__PURE__ */ React7.createElement("div", { style: styles2.content }, /* @__PURE__ */ React7.createElement("h3", { style: styles2.name }, name), /* @__PURE__ */ React7.createElement("p", { style: styles2.title }, title), subtitle && /* @__PURE__ */ React7.createElement("p", { style: styles2.subtitle }, subtitle), footer && /* @__PURE__ */ React7.createElement("div", { style: { marginTop: "auto", marginLeft: "-5px" } }, footer)),
2107
+ onCompassClick && /* @__PURE__ */ React7.createElement(
1966
2108
  "button",
1967
2109
  {
1968
2110
  type: "button",
@@ -1977,7 +2119,7 @@ function PoliticianCard({
1977
2119
  },
1978
2120
  "aria-label": `View ${name}'s compass`
1979
2121
  },
1980
- /* @__PURE__ */ React6.createElement(CompassIcon2, null)
2122
+ /* @__PURE__ */ React7.createElement(CompassIcon2, null)
1981
2123
  )
1982
2124
  );
1983
2125
  }
@@ -1985,83 +2127,6 @@ function PoliticianCard({
1985
2127
  // src/CompassCardHorizontal.jsx
1986
2128
  import React11, { useState as useState6, useEffect as useEffect6 } from "react";
1987
2129
 
1988
- // src/PlaceholderRadar.jsx
1989
- import React7 from "react";
1990
- function PlaceholderRadar({ size = 250, name = "" }) {
1991
- const cx = size / 2;
1992
- const cy = size / 2;
1993
- const r = size / 2 * 0.65;
1994
- const n = 8;
1995
- const vertices = Array.from({ length: n }, (_, i) => {
1996
- const a = 2 * Math.PI * i / n;
1997
- return [cx + r * Math.sin(a), cy - r * Math.cos(a)];
1998
- });
1999
- const outerPts = vertices.map(([x, y]) => `${x},${y}`).join(" ");
2000
- const midPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.6},${cy + (y - cy) * 0.6}`).join(" ");
2001
- const innerPts = vertices.map(([x, y]) => `${cx + (x - cx) * 0.3},${cy + (y - cy) * 0.3}`).join(" ");
2002
- return /* @__PURE__ */ React7.createElement(
2003
- "svg",
2004
- {
2005
- width: size,
2006
- height: size,
2007
- viewBox: `0 0 ${size} ${size}`,
2008
- role: "img",
2009
- "aria-label": name ? `${name} \u2014 compass data unavailable` : "compass data unavailable",
2010
- style: {
2011
- backgroundColor: colorScales.teal["050"],
2012
- borderRadius: borderRadius.sm,
2013
- flexShrink: 0
2014
- }
2015
- },
2016
- vertices.map(([x, y], i) => /* @__PURE__ */ React7.createElement(
2017
- "line",
2018
- {
2019
- key: i,
2020
- x1: cx,
2021
- y1: cy,
2022
- x2: x,
2023
- y2: y,
2024
- stroke: colorScales.gray["200"],
2025
- strokeWidth: "1",
2026
- strokeDasharray: "2 3",
2027
- opacity: "0.6"
2028
- }
2029
- )),
2030
- /* @__PURE__ */ React7.createElement(
2031
- "polygon",
2032
- {
2033
- points: innerPts,
2034
- fill: "none",
2035
- stroke: colorScales.gray["200"],
2036
- strokeWidth: "1",
2037
- strokeDasharray: "2 3",
2038
- opacity: "0.5"
2039
- }
2040
- ),
2041
- /* @__PURE__ */ React7.createElement(
2042
- "polygon",
2043
- {
2044
- points: midPts,
2045
- fill: "none",
2046
- stroke: colorScales.gray["200"],
2047
- strokeWidth: "1",
2048
- strokeDasharray: "3 3",
2049
- opacity: "0.6"
2050
- }
2051
- ),
2052
- /* @__PURE__ */ React7.createElement(
2053
- "polygon",
2054
- {
2055
- points: outerPts,
2056
- fill: "none",
2057
- stroke: colorScales.gray["200"],
2058
- strokeWidth: "1.5",
2059
- strokeDasharray: "4 3"
2060
- }
2061
- )
2062
- );
2063
- }
2064
-
2065
2130
  // src/CompassCardHorizontalMeta.jsx
2066
2131
  import React10 from "react";
2067
2132
 
@@ -6160,14 +6225,78 @@ function getDisplayUrl(url) {
6160
6225
  return url.length > 60 ? url.slice(0, 57) + "..." : url;
6161
6226
  }
6162
6227
  }
6228
+ var USER_DOT = "#7C6B9E";
6229
+ var POL_DOT_LIGHT = "#5A9A6E";
6230
+ var POL_DOT_DARK = "#6DD28C";
6231
+ function palette(darkMode) {
6232
+ return darkMode ? {
6233
+ rowBorder: "rgba(255,255,255,0.08)",
6234
+ rowHover: "#1e2a3a",
6235
+ // ev-navy-elevated
6236
+ title: "#f3f4f6",
6237
+ chipLabel: "#d1d5db",
6238
+ sectionLabel: "#9ca3af",
6239
+ // 6.24:1 on #1a2235 ✓ AA
6240
+ reasoning: "#d1d5db",
6241
+ chevron: "#9ca3af",
6242
+ // 6.24:1 — bumped from #6b7280 (3.28) for clarity
6243
+ pillActiveBg: "#1e2a3a",
6244
+ pillActiveBorder: "rgba(255,255,255,0.14)",
6245
+ pillIdleText: "#9ca3af",
6246
+ // 6.24:1 ✓ AA
6247
+ pillActiveText: "#f3f4f6",
6248
+ link: "#59b0c4",
6249
+ // 6.37:1 ✓ AA
6250
+ sourceText: "#9ca3af",
6251
+ quoteText: "#d1d5db",
6252
+ quoteBorder: "rgba(255,255,255,0.14)",
6253
+ emptyText: "#9ca3af",
6254
+ // 6.24:1 — bumped from #6b7280 (3.28, failed AA)
6255
+ spinnerTrack: "#374151",
6256
+ polDot: POL_DOT_DARK,
6257
+ agreedBg: "rgba(14,116,144,0.18)",
6258
+ agreedText: "#67e8f9",
6259
+ disagreedBg: "rgba(180,83,9,0.18)",
6260
+ disagreedText: "#fbbf24"
6261
+ } : {
6262
+ rowBorder: "#f1f1f1",
6263
+ rowHover: "#f9fafb",
6264
+ title: "#262626",
6265
+ chipLabel: "#525252",
6266
+ sectionLabel: "#6b7280",
6267
+ // 4.83:1 on white — bumped from #a3a3a3 (2.52, failed AA)
6268
+ reasoning: "#404040",
6269
+ chevron: "#6b7280",
6270
+ // 4.83:1 — bumped from #a3a3a3 (2.52, failed 3:1)
6271
+ pillActiveBg: "#fafafa",
6272
+ pillActiveBorder: "#e5e5e5",
6273
+ pillIdleText: "#737373",
6274
+ // 4.74:1 ✓ AA
6275
+ pillActiveText: "#171717",
6276
+ link: "#00657c",
6277
+ sourceText: "#737373",
6278
+ quoteText: "#374151",
6279
+ quoteBorder: "#e2e8f0",
6280
+ emptyText: "#6b7280",
6281
+ // 4.83:1 — bumped from #a3a3a3 (2.52, failed AA)
6282
+ spinnerTrack: "#e2e8f0",
6283
+ polDot: POL_DOT_LIGHT,
6284
+ agreedBg: "#ecfeff",
6285
+ agreedText: "#0e7490",
6286
+ disagreedBg: "#fffbeb",
6287
+ disagreedText: "#b45309"
6288
+ };
6289
+ }
6163
6290
  function StanceAccordion({
6164
6291
  topics,
6165
6292
  polAnswers,
6293
+ userAnswerMap = {},
6166
6294
  politicianId,
6167
6295
  allTopics,
6168
6296
  expandedTopics,
6297
+ darkMode = false,
6169
6298
  verdictsByTopic,
6170
- // Record<string, 'agreed' | 'disagreed'> | undefined — DEPRECATED, no longer rendered
6299
+ // DEPRECATED, no longer rendered
6171
6300
  verdictsByQuote,
6172
6301
  // Record<quote_id, 'agreed' | 'disagreed'> | undefined
6173
6302
  initialExpandedTopicId,
@@ -6179,6 +6308,7 @@ function StanceAccordion({
6179
6308
  const [showAll, setShowAll] = useState17(false);
6180
6309
  const contextCache = useRef4(/* @__PURE__ */ new Map());
6181
6310
  const quotesCache = useRef4(null);
6311
+ const c = palette(darkMode);
6182
6312
  const polAnswerMap = {};
6183
6313
  if (polAnswers) {
6184
6314
  polAnswers.forEach((a) => {
@@ -6270,201 +6400,314 @@ function StanceAccordion({
6270
6400
  visibleTopics = [pinned, ...baseTopics.filter((t) => String(t.id) !== String(initialExpandedTopicId))];
6271
6401
  }
6272
6402
  }
6403
+ const sectionLabelStyle = {
6404
+ fontSize: "11px",
6405
+ fontWeight: 600,
6406
+ color: c.sectionLabel,
6407
+ textTransform: "uppercase",
6408
+ letterSpacing: "0.06em"
6409
+ };
6273
6410
  return /* @__PURE__ */ React30.createElement(
6274
6411
  "div",
6275
6412
  {
6276
- className: "flex flex-col",
6413
+ className: "ev-stance-panel flex flex-col",
6277
6414
  style: { fontFamily: "'Manrope', sans-serif" }
6278
6415
  },
6279
- /* @__PURE__ */ React30.createElement(
6280
- "h3",
6281
- {
6282
- className: "text-sm font-semibold text-neutral-400 uppercase tracking-wider mb-2",
6283
- style: { fontSize: "12px" }
6284
- },
6285
- "Stance Breakdown"
6286
- ),
6416
+ /* @__PURE__ */ React30.createElement("h3", { style: { ...sectionLabelStyle, marginBottom: "8px" } }, "Stance Breakdown"),
6287
6417
  visibleTopics.map((topic) => {
6288
6418
  const topicId = String(topic.id);
6289
- const value = polAnswerMap[topicId];
6290
- const label = getStanceLabel(topicId, value);
6419
+ const polValue = polAnswerMap[topicId];
6420
+ const userValue = userAnswerMap[topicId];
6421
+ const label = getStanceLabel(topicId, polValue);
6291
6422
  const isExpanded = expandedTopicId === topicId;
6292
6423
  const isLoading = loadingId === topicId;
6293
6424
  const cached = contextCache.current.get(topicId);
6294
6425
  const fullTopic = topicById[topicId];
6295
6426
  const questionText = fullTopic == null ? void 0 : fullTopic.question_text;
6427
+ const titleText = questionText || topic.short_title;
6428
+ const stances = (fullTopic == null ? void 0 : fullTopic.stances) || topic.stances || [];
6296
6429
  const topicQuotes = quotesCache.current ? quotesCache.current.filter((q) => {
6297
6430
  if (!q.issue) return false;
6298
6431
  if (q.candidateId && q.candidateId !== politicianId) return false;
6299
6432
  if (topic.topic_key) return q.issue === topic.topic_key;
6300
6433
  return topic.short_title && q.issue.toLowerCase() === topic.short_title.toLowerCase();
6301
6434
  }) : [];
6302
- return /* @__PURE__ */ React30.createElement("div", { key: topicId, className: "border-b border-neutral-100" }, /* @__PURE__ */ React30.createElement(
6303
- "button",
6435
+ return /* @__PURE__ */ React30.createElement(
6436
+ "div",
6304
6437
  {
6305
- type: "button",
6306
- onClick: () => handleToggle(topicId),
6307
- className: "w-full flex items-center justify-between py-3 px-2 text-left cursor-pointer hover:bg-neutral-50 transition-colors"
6438
+ key: topicId,
6439
+ style: { borderBottom: `1px solid ${c.rowBorder}` }
6308
6440
  },
6309
- /* @__PURE__ */ React30.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React30.createElement("span", { className: "text-sm font-medium text-neutral-800 truncate" }, topic.short_title), questionText && /* @__PURE__ */ React30.createElement("span", { className: "text-xs text-neutral-400 mt-0.5" }, questionText), /* @__PURE__ */ React30.createElement("span", { className: "text-xs text-neutral-500 mt-0.5" }, label)),
6310
6441
  /* @__PURE__ */ React30.createElement(
6311
- "svg",
6442
+ "button",
6312
6443
  {
6313
- width: "16",
6314
- height: "16",
6315
- viewBox: "0 0 24 24",
6316
- fill: "none",
6317
- stroke: "currentColor",
6318
- strokeWidth: "2",
6319
- strokeLinecap: "round",
6320
- strokeLinejoin: "round",
6321
- className: "text-neutral-400 flex-shrink-0 ml-2",
6444
+ type: "button",
6445
+ onClick: () => handleToggle(topicId),
6446
+ className: "w-full flex items-start justify-between text-left cursor-pointer",
6322
6447
  style: {
6323
- transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
6324
- transition: "transform 0.2s ease"
6448
+ padding: "12px 8px",
6449
+ background: "transparent",
6450
+ border: "none",
6451
+ transition: "background 0.15s ease",
6452
+ borderRadius: "8px"
6453
+ },
6454
+ onMouseEnter: (e) => {
6455
+ e.currentTarget.style.background = c.rowHover;
6456
+ },
6457
+ onMouseLeave: (e) => {
6458
+ e.currentTarget.style.background = "transparent";
6325
6459
  }
6326
6460
  },
6327
- /* @__PURE__ */ React30.createElement("polyline", { points: "9 18 15 12 9 6" })
6328
- )
6329
- ), /* @__PURE__ */ React30.createElement(
6330
- "div",
6331
- {
6332
- style: {
6333
- display: "grid",
6334
- gridTemplateRows: isExpanded ? "1fr" : "0fr",
6335
- transition: "grid-template-rows 0.25s ease"
6336
- }
6337
- },
6338
- /* @__PURE__ */ React30.createElement("div", { style: { overflow: "hidden" } }, /* @__PURE__ */ React30.createElement("div", { className: "px-2 pb-4" }, isLoading && /* @__PURE__ */ React30.createElement("div", { className: "flex items-center py-3" }, /* @__PURE__ */ React30.createElement(
6339
- "div",
6340
- {
6341
- style: {
6342
- width: "20px",
6343
- height: "20px",
6344
- border: "2px solid #e2e8f0",
6345
- borderTopColor: "#00657c",
6346
- borderRadius: "50%",
6347
- animation: "ev-spin 0.8s linear infinite"
6461
+ /* @__PURE__ */ React30.createElement("div", { className: "flex flex-col min-w-0", style: { gap: "5px" } }, /* @__PURE__ */ React30.createElement(
6462
+ "span",
6463
+ {
6464
+ style: {
6465
+ fontSize: "14px",
6466
+ fontWeight: 600,
6467
+ color: c.title,
6468
+ lineHeight: 1.4
6469
+ }
6470
+ },
6471
+ titleText
6472
+ ), /* @__PURE__ */ React30.createElement("span", { style: { display: "flex", alignItems: "flex-start", gap: "8px" } }, /* @__PURE__ */ React30.createElement(
6473
+ "span",
6474
+ {
6475
+ style: {
6476
+ width: "8px",
6477
+ height: "8px",
6478
+ borderRadius: "50%",
6479
+ backgroundColor: c.polDot,
6480
+ flexShrink: 0,
6481
+ marginTop: "6px"
6482
+ }
6348
6483
  }
6349
- }
6350
- )), !isLoading && cached && /* @__PURE__ */ React30.createElement(React30.Fragment, null, cached.reasoning ? /* @__PURE__ */ React30.createElement(
6351
- "p",
6352
- {
6353
- className: "text-sm text-neutral-700 mb-3",
6354
- style: { whiteSpace: "pre-wrap", lineHeight: 1.6 }
6355
- },
6356
- cached.reasoning
6357
- ) : null, cached.sources && cached.sources.length > 0 && /* @__PURE__ */ React30.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React30.createElement("p", { className: "text-xs font-semibold text-neutral-500 uppercase tracking-wider mb-1.5" }, "References"), /* @__PURE__ */ React30.createElement("ol", { className: "list-decimal list-inside space-y-1" }, cached.sources.map((src, i) => /* @__PURE__ */ React30.createElement("li", { key: i, className: "text-xs text-neutral-600" }, /* @__PURE__ */ React30.createElement(
6358
- "a",
6359
- {
6360
- href: src,
6361
- target: "_blank",
6362
- rel: "noreferrer",
6363
- className: "inline-flex items-center gap-1.5 hover:text-[#00657c] transition-colors"
6364
- },
6365
- /* @__PURE__ */ React30.createElement(Favicon, { url: src }),
6366
- /* @__PURE__ */ React30.createElement("span", { className: "underline underline-offset-2" }, getDisplayUrl(src))
6367
- ))))), topicQuotes.length > 0 && /* @__PURE__ */ React30.createElement("div", { style: { marginTop: "12px" } }, /* @__PURE__ */ React30.createElement(
6368
- "p",
6484
+ ), /* @__PURE__ */ React30.createElement(
6485
+ "span",
6486
+ {
6487
+ style: {
6488
+ fontSize: "13px",
6489
+ color: c.chipLabel,
6490
+ lineHeight: 1.45
6491
+ }
6492
+ },
6493
+ label
6494
+ ))),
6495
+ /* @__PURE__ */ React30.createElement(
6496
+ "svg",
6497
+ {
6498
+ width: "16",
6499
+ height: "16",
6500
+ viewBox: "0 0 24 24",
6501
+ fill: "none",
6502
+ stroke: c.chevron,
6503
+ strokeWidth: "2",
6504
+ strokeLinecap: "round",
6505
+ strokeLinejoin: "round",
6506
+ className: "flex-shrink-0 ml-2",
6507
+ style: {
6508
+ marginTop: "3px",
6509
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
6510
+ transition: "transform 0.2s ease"
6511
+ }
6512
+ },
6513
+ /* @__PURE__ */ React30.createElement("polyline", { points: "9 18 15 12 9 6" })
6514
+ )
6515
+ ),
6516
+ /* @__PURE__ */ React30.createElement(
6517
+ "div",
6369
6518
  {
6370
6519
  style: {
6371
- fontSize: "11px",
6372
- fontWeight: 600,
6373
- color: "#737373",
6374
- textTransform: "uppercase",
6375
- letterSpacing: "0.05em",
6376
- marginBottom: "8px"
6520
+ display: "grid",
6521
+ gridTemplateRows: isExpanded ? "1fr" : "0fr",
6522
+ transition: "grid-template-rows 0.25s ease"
6377
6523
  }
6378
6524
  },
6379
- "Quotes"
6380
- ), topicQuotes.map((quote) => {
6381
- const verdict = verdictsByQuote ? verdictsByQuote[quote.id] : void 0;
6382
- const borderColor = verdict === "agreed" ? "#0e7490" : verdict === "disagreed" ? "#b45309" : "#e2e8f0";
6383
- const sourceName = quote.source_name || quote.sourceName;
6384
- return /* @__PURE__ */ React30.createElement(
6525
+ /* @__PURE__ */ React30.createElement("div", { style: { overflow: "hidden" } }, /* @__PURE__ */ React30.createElement("div", { style: { padding: "4px 8px 16px" } }, stances.length > 0 && /* @__PURE__ */ React30.createElement(React30.Fragment, null, (userValue > 0 || polValue > 0) && /* @__PURE__ */ React30.createElement(
6385
6526
  "div",
6386
6527
  {
6387
- key: quote.id,
6388
6528
  style: {
6389
- borderLeft: `3px solid ${borderColor}`,
6390
- paddingLeft: "10px",
6391
- paddingTop: "6px",
6392
- paddingBottom: "6px",
6393
- marginBottom: "8px"
6529
+ display: "flex",
6530
+ alignItems: "center",
6531
+ gap: "14px",
6532
+ marginBottom: "8px",
6533
+ fontSize: "12px",
6534
+ color: c.sourceText
6394
6535
  }
6395
6536
  },
6396
- /* @__PURE__ */ React30.createElement(
6397
- "p",
6537
+ userValue > 0 && /* @__PURE__ */ React30.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" } }, /* @__PURE__ */ React30.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: USER_DOT } }), "You"),
6538
+ /* @__PURE__ */ React30.createElement("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" } }, /* @__PURE__ */ React30.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: c.polDot } }), "Their stance")
6539
+ ), /* @__PURE__ */ React30.createElement("div", { style: { display: "flex", flexDirection: "column", gap: "6px", marginBottom: "14px" } }, stances.map((stance, i) => {
6540
+ const stanceNum = i + 1;
6541
+ const isUser = userValue === stanceNum;
6542
+ const isPol = polValue === stanceNum;
6543
+ const isActive = isUser || isPol;
6544
+ return /* @__PURE__ */ React30.createElement(
6545
+ "div",
6398
6546
  {
6547
+ key: i,
6399
6548
  style: {
6549
+ display: "flex",
6550
+ alignItems: "flex-start",
6551
+ gap: "10px",
6552
+ padding: "10px 12px",
6553
+ borderRadius: "12px",
6400
6554
  fontSize: "13px",
6401
- fontStyle: "italic",
6402
- color: "#374151",
6403
- margin: 0,
6404
- lineHeight: 1.5
6405
- }
6406
- },
6407
- quote.text
6408
- ),
6409
- verdict === "agreed" && /* @__PURE__ */ React30.createElement(
6410
- "span",
6411
- {
6412
- style: {
6413
- display: "inline-flex",
6414
- alignItems: "center",
6415
- gap: "4px",
6416
- backgroundColor: "#ecfeff",
6417
- color: "#0e7490",
6418
- padding: "2px 8px",
6419
- borderRadius: "9999px",
6420
- fontSize: "11px",
6421
- fontWeight: 500,
6422
- marginTop: "4px",
6423
- flexShrink: 0
6424
- }
6425
- },
6426
- /* @__PURE__ */ React30.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React30.createElement("path", { d: "M5 13l4 4L19 7" })),
6427
- "Agreed"
6428
- ),
6429
- verdict === "disagreed" && /* @__PURE__ */ React30.createElement(
6430
- "span",
6431
- {
6432
- style: {
6433
- display: "inline-flex",
6434
- alignItems: "center",
6435
- gap: "4px",
6436
- backgroundColor: "#fffbeb",
6437
- color: "#b45309",
6438
- padding: "2px 8px",
6439
- borderRadius: "9999px",
6440
- fontSize: "11px",
6441
- fontWeight: 500,
6442
- marginTop: "4px",
6443
- flexShrink: 0
6555
+ lineHeight: 1.4,
6556
+ border: `1px solid ${isActive ? c.pillActiveBorder : "transparent"}`,
6557
+ backgroundColor: isActive ? c.pillActiveBg : "transparent"
6444
6558
  }
6445
6559
  },
6446
- /* @__PURE__ */ React30.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React30.createElement("path", { d: "M6 18L18 6M6 6l12 12" })),
6447
- "Disagreed"
6448
- ),
6449
- sourceName && /* @__PURE__ */ React30.createElement(
6450
- "a",
6560
+ /* @__PURE__ */ React30.createElement(
6561
+ "span",
6562
+ {
6563
+ style: {
6564
+ flexShrink: 0,
6565
+ width: "30px",
6566
+ display: "flex",
6567
+ alignItems: "center",
6568
+ gap: "5px",
6569
+ paddingTop: "3px"
6570
+ }
6571
+ },
6572
+ isUser && /* @__PURE__ */ React30.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: USER_DOT, boxShadow: `0 0 0 3px ${USER_DOT}33` } }),
6573
+ isPol && /* @__PURE__ */ React30.createElement("span", { style: { width: "9px", height: "9px", borderRadius: "50%", backgroundColor: c.polDot, boxShadow: `0 0 0 3px ${c.polDot}33` } })
6574
+ ),
6575
+ /* @__PURE__ */ React30.createElement(
6576
+ "span",
6577
+ {
6578
+ style: {
6579
+ flex: 1,
6580
+ color: isActive ? c.pillActiveText : c.pillIdleText,
6581
+ fontWeight: isActive ? 500 : 400
6582
+ }
6583
+ },
6584
+ stance.text
6585
+ )
6586
+ );
6587
+ }))), isLoading && /* @__PURE__ */ React30.createElement("div", { className: "flex items-center", style: { padding: "12px 0" } }, /* @__PURE__ */ React30.createElement(
6588
+ "div",
6589
+ {
6590
+ style: {
6591
+ width: "20px",
6592
+ height: "20px",
6593
+ border: `2px solid ${c.spinnerTrack}`,
6594
+ borderTopColor: "#00657c",
6595
+ borderRadius: "50%",
6596
+ animation: "ev-spin 0.8s linear infinite"
6597
+ }
6598
+ }
6599
+ )), !isLoading && cached && /* @__PURE__ */ React30.createElement(React30.Fragment, null, cached.reasoning ? /* @__PURE__ */ React30.createElement(
6600
+ "p",
6601
+ {
6602
+ style: {
6603
+ fontSize: "14px",
6604
+ color: c.reasoning,
6605
+ marginBottom: "12px",
6606
+ whiteSpace: "pre-wrap",
6607
+ lineHeight: 1.6
6608
+ }
6609
+ },
6610
+ cached.reasoning
6611
+ ) : null, cached.sources && cached.sources.length > 0 && /* @__PURE__ */ React30.createElement("div", { style: { marginTop: "8px" } }, /* @__PURE__ */ React30.createElement("p", { style: { ...sectionLabelStyle, marginBottom: "6px" } }, "References"), /* @__PURE__ */ React30.createElement("ol", { style: { listStyle: "decimal", listStylePosition: "inside", display: "flex", flexDirection: "column", gap: "4px" } }, cached.sources.map((src, i) => /* @__PURE__ */ React30.createElement("li", { key: i, style: { fontSize: "12px", color: c.sourceText } }, /* @__PURE__ */ React30.createElement(
6612
+ "a",
6613
+ {
6614
+ href: src,
6615
+ target: "_blank",
6616
+ rel: "noreferrer",
6617
+ className: "inline-flex items-center gap-1.5",
6618
+ style: { color: c.link }
6619
+ },
6620
+ /* @__PURE__ */ React30.createElement(Favicon, { url: src }),
6621
+ /* @__PURE__ */ React30.createElement("span", { style: { textDecoration: "underline", textUnderlineOffset: "2px" } }, getDisplayUrl(src))
6622
+ ))))), topicQuotes.length > 0 && /* @__PURE__ */ React30.createElement("div", { style: { marginTop: "14px" } }, /* @__PURE__ */ React30.createElement("p", { style: { ...sectionLabelStyle, marginBottom: "8px" } }, "Quotes"), topicQuotes.map((quote) => {
6623
+ const verdict = verdictsByQuote ? verdictsByQuote[quote.id] : void 0;
6624
+ const borderColor = verdict === "agreed" ? c.agreedText : verdict === "disagreed" ? c.disagreedText : c.quoteBorder;
6625
+ const sourceName = quote.source_name || quote.sourceName;
6626
+ return /* @__PURE__ */ React30.createElement(
6627
+ "div",
6451
6628
  {
6452
- href: quote.source_url || quote.sourceUrl,
6453
- target: "_blank",
6454
- rel: "noreferrer",
6629
+ key: quote.id,
6455
6630
  style: {
6456
- display: "block",
6457
- fontSize: "11px",
6458
- color: "#00657c",
6459
- marginTop: "3px",
6460
- textDecoration: "none"
6631
+ borderLeft: `3px solid ${borderColor}`,
6632
+ paddingLeft: "10px",
6633
+ paddingTop: "6px",
6634
+ paddingBottom: "6px",
6635
+ marginBottom: "8px"
6461
6636
  }
6462
6637
  },
6463
- sourceName
6464
- )
6465
- );
6466
- })), !cached.reasoning && (!cached.sources || cached.sources.length === 0) && topicQuotes.length === 0 && /* @__PURE__ */ React30.createElement("p", { className: "text-sm text-neutral-400 italic py-2" }, "No detailed reasoning available for this topic."))))
6467
- ));
6638
+ /* @__PURE__ */ React30.createElement(
6639
+ "p",
6640
+ {
6641
+ style: {
6642
+ fontSize: "13px",
6643
+ fontStyle: "italic",
6644
+ color: c.quoteText,
6645
+ margin: 0,
6646
+ lineHeight: 1.5
6647
+ }
6648
+ },
6649
+ quote.text
6650
+ ),
6651
+ verdict === "agreed" && /* @__PURE__ */ React30.createElement(
6652
+ "span",
6653
+ {
6654
+ style: {
6655
+ display: "inline-flex",
6656
+ alignItems: "center",
6657
+ gap: "4px",
6658
+ backgroundColor: c.agreedBg,
6659
+ color: c.agreedText,
6660
+ padding: "2px 8px",
6661
+ borderRadius: "9999px",
6662
+ fontSize: "11px",
6663
+ fontWeight: 500,
6664
+ marginTop: "4px",
6665
+ flexShrink: 0
6666
+ }
6667
+ },
6668
+ /* @__PURE__ */ React30.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React30.createElement("path", { d: "M5 13l4 4L19 7" })),
6669
+ "Agreed"
6670
+ ),
6671
+ verdict === "disagreed" && /* @__PURE__ */ React30.createElement(
6672
+ "span",
6673
+ {
6674
+ style: {
6675
+ display: "inline-flex",
6676
+ alignItems: "center",
6677
+ gap: "4px",
6678
+ backgroundColor: c.disagreedBg,
6679
+ color: c.disagreedText,
6680
+ padding: "2px 8px",
6681
+ borderRadius: "9999px",
6682
+ fontSize: "11px",
6683
+ fontWeight: 500,
6684
+ marginTop: "4px",
6685
+ flexShrink: 0
6686
+ }
6687
+ },
6688
+ /* @__PURE__ */ React30.createElement("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React30.createElement("path", { d: "M6 18L18 6M6 6l12 12" })),
6689
+ "Disagreed"
6690
+ ),
6691
+ sourceName && /* @__PURE__ */ React30.createElement(
6692
+ "a",
6693
+ {
6694
+ href: quote.source_url || quote.sourceUrl,
6695
+ target: "_blank",
6696
+ rel: "noreferrer",
6697
+ style: {
6698
+ display: "block",
6699
+ fontSize: "11px",
6700
+ color: c.link,
6701
+ marginTop: "3px",
6702
+ textDecoration: "none"
6703
+ }
6704
+ },
6705
+ sourceName
6706
+ )
6707
+ );
6708
+ })), !cached.reasoning && (!cached.sources || cached.sources.length === 0) && topicQuotes.length === 0 && /* @__PURE__ */ React30.createElement("p", { style: { fontSize: "14px", color: c.emptyText, fontStyle: "italic", padding: "8px 0" } }, "No detailed reasoning available for this topic."))))
6709
+ )
6710
+ );
6468
6711
  }),
6469
6712
  hasToggle && /* @__PURE__ */ React30.createElement(
6470
6713
  "button",
@@ -6472,7 +6715,7 @@ function StanceAccordion({
6472
6715
  type: "button",
6473
6716
  onClick: () => setShowAll((v) => !v),
6474
6717
  className: "text-sm font-medium mt-2 px-2 py-1 self-start cursor-pointer hover:underline",
6475
- style: { color: "#00657c" }
6718
+ style: { color: c.link }
6476
6719
  },
6477
6720
  showAll ? "Show fewer" : `Show all ${expandedTopics.length} topics`
6478
6721
  )
@@ -6500,6 +6743,7 @@ export {
6500
6743
  JudicialScorecard,
6501
6744
  LegislativeInlineSummary,
6502
6745
  LegislativeRecord,
6746
+ PlaceholderRadar,
6503
6747
  PoliticianCard,
6504
6748
  PoliticianProfile,
6505
6749
  RadarChartCore,
@@ -6519,6 +6763,7 @@ export {
6519
6763
  defaultNavItems,
6520
6764
  duration,
6521
6765
  easing,
6766
+ evAppLinks,
6522
6767
  evContext,
6523
6768
  focus,
6524
6769
  fontSizes,