app.css 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /* Base reset scoped to root */
  2. #polisci-root, #polisci-root *, #polisci-root *::before, #polisci-root *::after {
  3. box-sizing: border-box;
  4. }
  5. #polisci-root {
  6. --ps-party-r: #d9534f;
  7. --ps-party-d: #337ab7;
  8. --ps-party-i: #5cb85c;
  9. --ps-accent: #2c3e50;
  10. --ps-bg: #f5f7fa;
  11. --ps-surface: #ffffff;
  12. --ps-text: #1f2933;
  13. --ps-text-muted: #5b6471;
  14. --ps-border: #d8dde4;
  15. --ps-row-alt: #f9fafc;
  16. --ps-hover: #eef3f9;
  17. --ps-radius: 6px;
  18. --ps-shadow: 0 1px 2px rgba(0,0,0,0.04);
  19. font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  20. font-size: 15px;
  21. line-height: 1.45;
  22. color: var(--ps-text);
  23. background: var(--ps-bg);
  24. padding: 16px;
  25. max-width: 1400px;
  26. margin: 0 auto;
  27. }
  28. #polisci-root .is-hidden { display: none !important; }
  29. #polisci-root .visually-hidden {
  30. position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  31. overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
  32. }
  33. /* Header */
  34. #polisci-root .ps-header { margin-bottom: 16px; }
  35. #polisci-root .ps-header h1 { font-size: 1.6rem; margin: 0 0 4px; color: var(--ps-accent); }
  36. #polisci-root .ps-subtitle { margin: 0; color: var(--ps-text-muted); font-size: 0.95rem; }
  37. #polisci-root .member-note {
  38. margin-top: 10px;
  39. padding: 10px 14px;
  40. background: #fff8e1;
  41. border: 1px solid #f0d97a;
  42. border-radius: var(--ps-radius);
  43. font-size: 0.92rem;
  44. }
  45. /* Layout */
  46. #polisci-root .ps-layout {
  47. display: grid;
  48. grid-template-columns: 240px 1fr;
  49. gap: 20px;
  50. align-items: start;
  51. }
  52. /* Sidebar */
  53. #polisci-root .sidebar {
  54. background: var(--ps-surface);
  55. border: 1px solid var(--ps-border);
  56. border-radius: var(--ps-radius);
  57. padding: 14px;
  58. box-shadow: var(--ps-shadow);
  59. position: sticky;
  60. top: 12px;
  61. }
  62. #polisci-root .sidebar-toggle {
  63. display: none;
  64. width: 100%;
  65. padding: 8px 12px;
  66. background: var(--ps-accent);
  67. color: #fff;
  68. border: none;
  69. border-radius: var(--ps-radius);
  70. font-size: 0.95rem;
  71. cursor: pointer;
  72. }
  73. #polisci-root .filter-group {
  74. border: none;
  75. padding: 0;
  76. margin: 0 0 14px;
  77. }
  78. #polisci-root .filter-group legend {
  79. font-weight: 600;
  80. font-size: 0.85rem;
  81. text-transform: uppercase;
  82. letter-spacing: 0.04em;
  83. color: var(--ps-text-muted);
  84. margin-bottom: 6px;
  85. padding: 0;
  86. }
  87. #polisci-root .filter-group label {
  88. display: block;
  89. padding: 3px 0;
  90. font-size: 0.93rem;
  91. cursor: pointer;
  92. }
  93. #polisci-root .filter-group input[type="checkbox"] { margin-right: 6px; }
  94. #polisci-root #filter-state-select {
  95. width: 100%;
  96. font-size: 0.9rem;
  97. border: 1px solid var(--ps-border);
  98. border-radius: var(--ps-radius);
  99. padding: 4px;
  100. }
  101. #polisci-root .btn-reset {
  102. width: 100%;
  103. padding: 7px 10px;
  104. background: var(--ps-surface);
  105. color: var(--ps-text);
  106. border: 1px solid var(--ps-border);
  107. border-radius: var(--ps-radius);
  108. cursor: pointer;
  109. font-size: 0.9rem;
  110. }
  111. #polisci-root .btn-reset:hover { background: var(--ps-hover); }
  112. #polisci-root .hint {
  113. margin: 10px 0 0;
  114. font-size: 0.82rem;
  115. color: var(--ps-text-muted);
  116. }
  117. /* Main */
  118. #polisci-root .ps-main { min-width: 0; }
  119. /* Search */
  120. #polisci-root .search-wrap {
  121. position: relative;
  122. margin-bottom: 16px;
  123. }
  124. #polisci-root #member-search {
  125. width: 100%;
  126. padding: 10px 14px;
  127. font-size: 1rem;
  128. border: 1px solid var(--ps-border);
  129. border-radius: var(--ps-radius);
  130. background: var(--ps-surface);
  131. }
  132. #polisci-root #member-search:focus {
  133. outline: 2px solid var(--ps-party-d);
  134. outline-offset: -1px;
  135. }
  136. #polisci-root .member-results {
  137. position: absolute;
  138. top: 100%;
  139. left: 0;
  140. right: 0;
  141. margin: 4px 0 0;
  142. padding: 0;
  143. list-style: none;
  144. background: var(--ps-surface);
  145. border: 1px solid var(--ps-border);
  146. border-radius: var(--ps-radius);
  147. box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  148. max-height: 320px;
  149. overflow-y: auto;
  150. z-index: 20;
  151. }
  152. #polisci-root .member-results li {
  153. padding: 8px 12px;
  154. cursor: pointer;
  155. font-size: 0.94rem;
  156. border-bottom: 1px solid var(--ps-border);
  157. }
  158. #polisci-root .member-results li:last-child { border-bottom: none; }
  159. #polisci-root .member-results li:hover,
  160. #polisci-root .member-results li[aria-selected="true"] {
  161. background: var(--ps-hover);
  162. }
  163. /* Member summary */
  164. #polisci-root .member-summary {
  165. background: var(--ps-surface);
  166. border: 1px solid var(--ps-border);
  167. border-radius: var(--ps-radius);
  168. padding: 14px;
  169. margin-bottom: 16px;
  170. min-height: 60px;
  171. box-shadow: var(--ps-shadow);
  172. }
  173. #polisci-root .member-summary:empty { display: none; }
  174. /* KPI cards */
  175. #polisci-root .kpi-cards {
  176. display: grid;
  177. grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  178. gap: 12px;
  179. margin-bottom: 20px;
  180. }
  181. #polisci-root .kpi-card {
  182. background: var(--ps-surface);
  183. border: 1px solid var(--ps-border);
  184. border-radius: var(--ps-radius);
  185. padding: 12px 14px;
  186. box-shadow: var(--ps-shadow);
  187. }
  188. #polisci-root .kpi-label {
  189. font-size: 0.78rem;
  190. text-transform: uppercase;
  191. letter-spacing: 0.04em;
  192. color: var(--ps-text-muted);
  193. margin-bottom: 4px;
  194. }
  195. #polisci-root .kpi-value {
  196. font-size: 1.6rem;
  197. font-weight: 600;
  198. color: var(--ps-accent);
  199. font-variant-numeric: tabular-nums;
  200. }
  201. /* Charts grid */
  202. #polisci-root .charts-grid {
  203. display: grid;
  204. grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  205. gap: 16px;
  206. margin-bottom: 24px;
  207. }
  208. #polisci-root .chart-frame {
  209. background: var(--ps-surface);
  210. border: 1px solid var(--ps-border);
  211. border-radius: var(--ps-radius);
  212. padding: 16px;
  213. margin: 0;
  214. height: 340px;
  215. box-shadow: var(--ps-shadow);
  216. display: flex;
  217. flex-direction: column;
  218. }
  219. #polisci-root .chart-frame figcaption {
  220. font-size: 0.95rem;
  221. font-weight: 600;
  222. color: var(--ps-accent);
  223. margin-bottom: 10px;
  224. flex: 0 0 auto;
  225. }
  226. #polisci-root .chart-canvas-wrap {
  227. position: relative;
  228. flex: 1 1 auto;
  229. min-height: 0;
  230. width: 100%;
  231. }
  232. #polisci-root .chart-frame canvas {
  233. position: absolute;
  234. top: 0; left: 0;
  235. width: 100% !important;
  236. height: 100% !important;
  237. }
  238. #polisci-root .chart-wide { grid-column: 1 / -1; }
  239. /* Vote table */
  240. #polisci-root .vote-table-section {
  241. background: var(--ps-surface);
  242. border: 1px solid var(--ps-border);
  243. border-radius: var(--ps-radius);
  244. padding: 14px;
  245. box-shadow: var(--ps-shadow);
  246. margin-bottom: 20px;
  247. }
  248. #polisci-root .vote-table-section h2 {
  249. font-size: 1.1rem;
  250. margin: 0 0 12px;
  251. color: var(--ps-accent);
  252. }
  253. #polisci-root .table-scroll {
  254. overflow-x: auto;
  255. max-height: 600px;
  256. overflow-y: auto;
  257. }
  258. #polisci-root #vote-table {
  259. width: 100%;
  260. border-collapse: collapse;
  261. font-size: 0.88rem;
  262. }
  263. #polisci-root #vote-table thead th {
  264. position: sticky;
  265. top: 0;
  266. background: var(--ps-accent);
  267. color: #fff;
  268. text-align: left;
  269. padding: 8px 10px;
  270. font-weight: 600;
  271. font-size: 0.82rem;
  272. white-space: nowrap;
  273. z-index: 1;
  274. }
  275. #polisci-root #vote-table tbody td {
  276. padding: 6px 10px;
  277. border-bottom: 1px solid var(--ps-border);
  278. vertical-align: top;
  279. }
  280. #polisci-root #vote-table tbody tr:nth-child(even) { background: var(--ps-row-alt); }
  281. #polisci-root #vote-table tbody tr:hover { background: var(--ps-hover); }
  282. #polisci-root #vote-table td:nth-child(1),
  283. #polisci-root #vote-table td:nth-child(2),
  284. #polisci-root #vote-table td:nth-child(3),
  285. #polisci-root #vote-table td:nth-child(9),
  286. #polisci-root #vote-table td:nth-child(10) {
  287. font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  288. font-variant-numeric: tabular-nums;
  289. white-space: nowrap;
  290. }
  291. /* Footer */
  292. #polisci-root .ps-footer {
  293. margin-top: 16px;
  294. padding-top: 12px;
  295. border-top: 1px solid var(--ps-border);
  296. font-size: 0.82rem;
  297. color: var(--ps-text-muted);
  298. }
  299. /* Comparison view (compare.html) */
  300. #polisci-root .compare-pills-section {
  301. margin: 12px 0 8px;
  302. padding: 10px 12px;
  303. border: 1px solid var(--ps-border);
  304. border-radius: 6px;
  305. background: var(--ps-surface, #fff);
  306. }
  307. #polisci-root .compare-pills-title {
  308. font-size: 0.95rem;
  309. margin: 0 0 6px;
  310. color: var(--ps-text-muted);
  311. font-weight: 600;
  312. text-transform: uppercase;
  313. letter-spacing: 0.04em;
  314. }
  315. #polisci-root .selected-pills {
  316. list-style: none;
  317. padding: 0;
  318. margin: 0 0 4px;
  319. display: flex;
  320. flex-wrap: wrap;
  321. gap: 6px;
  322. }
  323. #polisci-root .compare-pill {
  324. display: inline-flex;
  325. align-items: center;
  326. gap: 6px;
  327. padding: 4px 8px;
  328. border: 1px solid #ccc;
  329. border-radius: 999px;
  330. font-size: 0.9rem;
  331. line-height: 1.1;
  332. }
  333. #polisci-root .compare-pill-swatch {
  334. display: inline-block;
  335. width: 10px;
  336. height: 10px;
  337. border-radius: 50%;
  338. }
  339. #polisci-root .compare-pill-name {
  340. background: none;
  341. border: 0;
  342. padding: 0;
  343. font: inherit;
  344. color: inherit;
  345. cursor: pointer;
  346. text-decoration: underline;
  347. text-underline-offset: 2px;
  348. }
  349. #polisci-root .compare-pill-name:hover { color: var(--ps-accent); }
  350. #polisci-root .compare-pill-remove {
  351. background: none;
  352. border: 0;
  353. padding: 0 2px;
  354. margin-left: 2px;
  355. font-size: 1.1rem;
  356. line-height: 1;
  357. color: var(--ps-text-muted);
  358. cursor: pointer;
  359. }
  360. #polisci-root .compare-pill-remove:hover { color: #c0392b; }
  361. #polisci-root .align-switcher-wrap {
  362. margin: 10px 0;
  363. display: flex;
  364. align-items: center;
  365. gap: 8px;
  366. font-size: 0.9rem;
  367. color: var(--ps-text-muted);
  368. }
  369. #polisci-root .align-switcher-wrap select {
  370. padding: 4px 6px;
  371. border: 1px solid var(--ps-border);
  372. border-radius: 4px;
  373. font: inherit;
  374. }
  375. /* Responsive */
  376. @media (max-width: 768px) {
  377. #polisci-root { padding: 10px; }
  378. #polisci-root .ps-layout {
  379. grid-template-columns: 1fr;
  380. }
  381. #polisci-root .sidebar {
  382. position: static;
  383. padding: 10px;
  384. }
  385. #polisci-root .sidebar-toggle { display: block; margin-bottom: 10px; }
  386. #polisci-root .sidebar-body { display: none; }
  387. #polisci-root .sidebar.is-open .sidebar-body { display: block; }
  388. #polisci-root .ps-header h1 { font-size: 1.3rem; }
  389. #polisci-root .kpi-value { font-size: 1.3rem; }
  390. #polisci-root .chart-frame { height: 280px; }
  391. }
  392. /* Top-level nav between Member / Compare / Rankings pages */
  393. #polisci-root .ps-nav {
  394. margin: 4px 0 8px;
  395. font-size: 0.95rem;
  396. }
  397. #polisci-root .ps-nav a {
  398. color: var(--ps-accent);
  399. text-decoration: none;
  400. padding: 2px 6px;
  401. border-radius: 4px;
  402. }
  403. #polisci-root .ps-nav a:hover { background: var(--ps-hover); }
  404. #polisci-root .ps-nav a[aria-current="page"] {
  405. background: var(--ps-accent);
  406. color: #fff;
  407. font-weight: 600;
  408. }
  409. /* Ranking page */
  410. #polisci-root .rank-summary {
  411. margin-bottom: 12px;
  412. color: var(--ps-text-muted, #555);
  413. font-size: 0.95rem;
  414. }
  415. #polisci-root .rank-summary-line { margin: 0; }
  416. #polisci-root #rank-table {
  417. width: 100%;
  418. border-collapse: collapse;
  419. font-size: 0.92rem;
  420. }
  421. #polisci-root #rank-table thead th {
  422. background: var(--ps-row-alt);
  423. text-align: left;
  424. padding: 8px 10px;
  425. border-bottom: 2px solid var(--ps-border);
  426. position: sticky;
  427. top: 0;
  428. z-index: 1;
  429. }
  430. #polisci-root #rank-table tbody td {
  431. padding: 6px 10px;
  432. border-bottom: 1px solid var(--ps-border);
  433. }
  434. #polisci-root #rank-table tbody tr.rank-row { cursor: pointer; }
  435. #polisci-root #rank-table tbody tr:nth-child(even) { background: var(--ps-row-alt); }
  436. #polisci-root #rank-table tbody tr:hover { background: var(--ps-hover); }
  437. #polisci-root #rank-table td:first-child {
  438. width: 60px;
  439. font-variant-numeric: tabular-nums;
  440. color: var(--ps-text-muted, #555);
  441. }
  442. #polisci-root #rank-table .rank-value {
  443. text-align: right;
  444. font-variant-numeric: tabular-nums;
  445. font-weight: 600;
  446. }
  447. #polisci-root #rank-table .party-cell {
  448. font-weight: 600;
  449. width: 40px;
  450. text-align: center;
  451. }
  452. #polisci-root #rank-table .party-R { color: #d9534f; }
  453. #polisci-root #rank-table .party-D { color: #337ab7; }
  454. #polisci-root #rank-table .party-I { color: #5cb85c; }