blue-chestnut-solar-expert 0.0.17 → 0.0.19

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.
Files changed (104) hide show
  1. package/dist/components/polygon-buttons.d.ts +11 -0
  2. package/dist/components/polygon-information.d.ts +11 -0
  3. package/dist/components/undo-icon.d.ts +11 -0
  4. package/dist/stencil-library/{config-hh5GAFbi.js → config-BV_PiZGS.js} +5 -3
  5. package/dist/stencil-library/config-BV_PiZGS.js.map +1 -0
  6. package/dist/stencil-library/eraser-icon.entry.esm.js.map +1 -1
  7. package/dist/stencil-library/eraser-icon.entry.js +1 -1
  8. package/dist/stencil-library/eraser-icon.entry.js.map +1 -1
  9. package/dist/stencil-library/house-icon.entry.esm.js.map +1 -1
  10. package/dist/stencil-library/house-icon.entry.js +1 -1
  11. package/dist/stencil-library/house-icon.entry.js.map +1 -1
  12. package/dist/stencil-library/icon-selector.entry.esm.js.map +1 -1
  13. package/dist/stencil-library/icon-selector.entry.js +4 -1
  14. package/dist/stencil-library/icon-selector.entry.js.map +1 -1
  15. package/dist/stencil-library/loading-widget.entry.esm.js.map +1 -1
  16. package/dist/stencil-library/loading-widget.entry.js +2 -2
  17. package/dist/stencil-library/loading-widget.entry.js.map +1 -1
  18. package/dist/stencil-library/map-draw.entry.esm.js.map +1 -1
  19. package/dist/stencil-library/map-draw.entry.js +118 -170
  20. package/dist/stencil-library/map-draw.entry.js.map +1 -1
  21. package/dist/stencil-library/map-selector.entry.esm.js.map +1 -1
  22. package/dist/stencil-library/map-selector.entry.js +4 -4
  23. package/dist/stencil-library/map-selector.entry.js.map +1 -1
  24. package/dist/stencil-library/move-icon.entry.esm.js.map +1 -1
  25. package/dist/stencil-library/move-icon.entry.js +1 -1
  26. package/dist/stencil-library/move-icon.entry.js.map +1 -1
  27. package/dist/stencil-library/octagon-minus-icon.entry.esm.js.map +1 -1
  28. package/dist/stencil-library/octagon-minus-icon.entry.js +1 -1
  29. package/dist/stencil-library/octagon-minus-icon.entry.js.map +1 -1
  30. package/dist/stencil-library/polygon-buttons.entry.esm.js.map +1 -0
  31. package/dist/stencil-library/polygon-buttons.entry.js +28 -0
  32. package/dist/stencil-library/polygon-buttons.entry.js.map +1 -0
  33. package/dist/stencil-library/polygon-information.entry.esm.js.map +1 -0
  34. package/dist/stencil-library/polygon-information.entry.js +74 -0
  35. package/dist/stencil-library/polygon-information.entry.js.map +1 -0
  36. package/dist/stencil-library/search-icon.entry.esm.js.map +1 -1
  37. package/dist/stencil-library/search-icon.entry.js +1 -1
  38. package/dist/stencil-library/search-icon.entry.js.map +1 -1
  39. package/dist/stencil-library/settings-icon.entry.esm.js.map +1 -1
  40. package/dist/stencil-library/settings-icon.entry.js +1 -1
  41. package/dist/stencil-library/settings-icon.entry.js.map +1 -1
  42. package/dist/stencil-library/settings-modal.entry.esm.js.map +1 -1
  43. package/dist/stencil-library/settings-modal.entry.js +10 -10
  44. package/dist/stencil-library/settings-modal.entry.js.map +1 -1
  45. package/dist/stencil-library/solar-calculator.entry.esm.js.map +1 -1
  46. package/dist/stencil-library/solar-calculator.entry.js +2 -2
  47. package/dist/stencil-library/solar-calculator.entry.js.map +1 -1
  48. package/dist/stencil-library/solar-expert.entry.esm.js.map +1 -1
  49. package/dist/stencil-library/solar-expert.entry.js +3 -3
  50. package/dist/stencil-library/solar-expert.entry.js.map +1 -1
  51. package/dist/stencil-library/solar-system-form.entry.esm.js.map +1 -1
  52. package/dist/stencil-library/solar-system-form.entry.js +223 -184
  53. package/dist/stencil-library/solar-system-form.entry.js.map +1 -1
  54. package/dist/stencil-library/stencil-library.esm.js +1 -1
  55. package/dist/stencil-library/{store-CbFNgpiN.js → store-By_Yq2NT.js} +22 -4
  56. package/dist/stencil-library/store-By_Yq2NT.js.map +1 -0
  57. package/dist/stencil-library/{store-DsXeXraH.js → store-Dr69Zmu_.js} +27 -5
  58. package/dist/stencil-library/store-Dr69Zmu_.js.map +1 -0
  59. package/dist/stencil-library/tool-box.entry.esm.js.map +1 -1
  60. package/dist/stencil-library/tool-box.entry.js +11 -5
  61. package/dist/stencil-library/tool-box.entry.js.map +1 -1
  62. package/dist/stencil-library/{tools-DO8CG56H.js → tools-DU7Muwzb.js} +17 -3
  63. package/dist/stencil-library/tools-DU7Muwzb.js.map +1 -0
  64. package/dist/stencil-library/undo-icon.entry.esm.js.map +1 -0
  65. package/dist/stencil-library/undo-icon.entry.js +20 -0
  66. package/dist/stencil-library/undo-icon.entry.js.map +1 -0
  67. package/dist/stencil-library/utils-CTW6J-87.js +99 -0
  68. package/dist/stencil-library/utils-CTW6J-87.js.map +1 -0
  69. package/dist/types/components/icons/undo.d.ts +5 -0
  70. package/dist/types/components/map-draw/map-draw.d.ts +5 -0
  71. package/dist/types/components/map-draw/polygon-buttons.d.ts +6 -0
  72. package/dist/types/components/map-draw/polygon-information.d.ts +9 -0
  73. package/dist/types/components/map-draw/tool-box.d.ts +1 -0
  74. package/dist/types/components/solar-system-form/solar-system-form.d.ts +3 -2
  75. package/dist/types/components.d.ts +73 -10
  76. package/dist/types/config.d.ts +1 -0
  77. package/dist/types/constants.d.ts +2 -1
  78. package/dist/types/types/lang.d.ts +6 -0
  79. package/dist/types/utils/render/polygon.d.ts +6 -1
  80. package/dist/types/utils/render/tools.d.ts +3 -1
  81. package/dist/types/utils/simulation/simulation.d.ts +8 -0
  82. package/dist/types/utils/simulation/solarCurves.d.ts +3 -0
  83. package/dist/types/utils/simulation/types.d.ts +49 -0
  84. package/package.json +2 -2
  85. package/dist/stencil-library/config-hh5GAFbi.js.map +0 -1
  86. package/dist/stencil-library/store-B-oT8BM6.js +0 -579
  87. package/dist/stencil-library/store-B-oT8BM6.js.map +0 -1
  88. package/dist/stencil-library/store-B74GO7_R.js +0 -579
  89. package/dist/stencil-library/store-B74GO7_R.js.map +0 -1
  90. package/dist/stencil-library/store-CJCtVxJR.js +0 -546
  91. package/dist/stencil-library/store-CJCtVxJR.js.map +0 -1
  92. package/dist/stencil-library/store-CbFNgpiN.js.map +0 -1
  93. package/dist/stencil-library/store-CzUjX3ZS.js +0 -579
  94. package/dist/stencil-library/store-CzUjX3ZS.js.map +0 -1
  95. package/dist/stencil-library/store-D2T-tfKH.js +0 -573
  96. package/dist/stencil-library/store-D2T-tfKH.js.map +0 -1
  97. package/dist/stencil-library/store-DsXeXraH.js.map +0 -1
  98. package/dist/stencil-library/store-TjbCCrIW.js +0 -573
  99. package/dist/stencil-library/store-TjbCCrIW.js.map +0 -1
  100. package/dist/stencil-library/store-Y8q2XvVS.js +0 -579
  101. package/dist/stencil-library/store-Y8q2XvVS.js.map +0 -1
  102. package/dist/stencil-library/store-tzn2ldy2.js +0 -579
  103. package/dist/stencil-library/store-tzn2ldy2.js.map +0 -1
  104. package/dist/stencil-library/tools-DO8CG56H.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import { r as registerInstance, g as getElement, h } from './index-DZjEuBrX.js';
2
2
  import { f as fetchSolarData, g as getBuildingImages } from './api-E7GpMOpJ.js';
3
- import { D as DOTTED_LINE_COLOR, R as ROW_SPACING, C as COLUMN_SPACING, a as DEFAULT_SOLAR_EXPERT_CONFIG, b as DEFAULT_SOLAR_PANEL_TYPE, c as DEFAULT_SUNNINESS, B as BORDER_INSET } from './config-hh5GAFbi.js';
4
- import { r as roofTool, t as tools, m as moveTool, o as obstructionTool, d as deleteTool } from './tools-DO8CG56H.js';
5
- import { o as onChange, s as state, g as getLanguageStrings } from './store-CbFNgpiN.js';
3
+ import { D as DOTTED_LINE_COLOR, R as ROW_SPACING, C as COLUMN_SPACING, a as DEFAULT_SOLAR_EXPERT_CONFIG, b as DEFAULT_SOLAR_PANEL_TYPE, c as DEFAULT_SUNNINESS, B as BORDER_INSET } from './config-BV_PiZGS.js';
4
+ import { r as roofTool, t as tools, o as obstructionTool, m as moveTool, d as deleteTool, a as markRoofEdgeTool } from './tools-DU7Muwzb.js';
5
+ import { l as latLngToPixel, g as getPixelInMeters, c as calculatePolygonArea } from './utils-CTW6J-87.js';
6
+ import { o as onChange, s as state, g as getLanguageStrings } from './store-Dr69Zmu_.js';
6
7
 
7
8
  /*
8
9
  Copyright 2023 Google LLC
@@ -391,7 +392,7 @@ function projectPointPerpendicularToLine({ x, y, lastPoint, secondLastPoint, })
391
392
  return { x, y };
392
393
  }
393
394
 
394
- function drawPolygon({ polygonCtx, polygonCanvas, polygon, shiftKeyPressed, mousePoint, strokeColor, fillColor }) {
395
+ function drawPolygon({ polygonCtx, polygonCanvas, polygon, shiftKeyPressed, mousePoint, strokeColor, fillColor, highlightedEdge, highlightColor }) {
395
396
  if (!polygonCtx || !polygonCanvas)
396
397
  return;
397
398
  // Draw the polygon
@@ -416,6 +417,16 @@ function drawPolygon({ polygonCtx, polygonCanvas, polygon, shiftKeyPressed, mous
416
417
  if (polygon.points.length > 0) {
417
418
  polygonCtx.stroke();
418
419
  }
420
+ if (highlightedEdge && polygon.closed) {
421
+ polygonCtx.beginPath();
422
+ polygonCtx.strokeStyle = highlightColor;
423
+ polygonCtx.lineWidth = 2;
424
+ polygonCtx.moveTo(highlightedEdge.pointA.x, highlightedEdge.pointA.y);
425
+ polygonCtx.lineTo(highlightedEdge.pointB.x, highlightedEdge.pointB.y);
426
+ polygonCtx.stroke();
427
+ polygonCtx.strokeStyle = strokeColor;
428
+ polygonCtx.lineWidth = 1;
429
+ }
419
430
  if (polygon.points.length > 1 && !polygon.closed && shiftKeyPressed) {
420
431
  const projectedPoint = projectPointPerpendicularToLine({
421
432
  x: mousePoint.x,
@@ -1342,101 +1353,6 @@ function version(uuid) {
1342
1353
  return parseInt(uuid.slice(14, 15), 16);
1343
1354
  }
1344
1355
 
1345
- function calculatePolygonArea(points) {
1346
- let area = 0;
1347
- for (let i = 0; i < points.length; i++) {
1348
- const j = (i + 1) % points.length;
1349
- area += points[i].x * points[j].y;
1350
- area -= points[j].x * points[i].y;
1351
- }
1352
- return Math.abs(area / 2);
1353
- }
1354
- ;
1355
- function azimuthToCardinal(azimuth) {
1356
- // Convert angle to cardinal direction
1357
- if (azimuth >= 337.5 || azimuth < 22.5)
1358
- return "North";
1359
- if (azimuth >= 22.5 && azimuth < 67.5)
1360
- return "Northeast";
1361
- if (azimuth >= 67.5 && azimuth < 112.5)
1362
- return "East";
1363
- if (azimuth >= 112.5 && azimuth < 157.5)
1364
- return "Southeast";
1365
- if (azimuth >= 157.5 && azimuth < 202.5)
1366
- return "South";
1367
- if (azimuth >= 202.5 && azimuth < 247.5)
1368
- return "Southwest";
1369
- if (azimuth >= 247.5 && azimuth < 292.5)
1370
- return "West";
1371
- return "Northwest";
1372
- }
1373
- function calculatePolygonOrientation(points) {
1374
- if (points.length < 3)
1375
- return 0;
1376
- // Calculate the average direction of the polygon
1377
- let totalAngle = 0;
1378
- for (let i = 0; i < points.length; i++) {
1379
- const j = (i + 1) % points.length;
1380
- const angle = Math.atan2(points[j].y - points[i].y, points[j].x - points[i].x);
1381
- totalAngle += angle;
1382
- }
1383
- const avgAngle = (totalAngle / points.length) * (180 / Math.PI);
1384
- const normalizedAngle = (avgAngle + 360) % 360;
1385
- return normalizedAngle;
1386
- }
1387
- ;
1388
- function calculatePolygonAngle(points) {
1389
- if (points.length < 3)
1390
- return 0;
1391
- // Calculate the average angle of the polygon
1392
- let totalAngle = 0;
1393
- for (let i = 0; i < points.length; i++) {
1394
- const j = (i + 1) % points.length;
1395
- const k = (i + 2) % points.length;
1396
- const v1 = {
1397
- x: points[j].x - points[i].x,
1398
- y: points[j].y - points[i].y,
1399
- };
1400
- const v2 = {
1401
- x: points[k].x - points[j].x,
1402
- y: points[k].y - points[j].y,
1403
- };
1404
- const dot = v1.x * v2.x + v1.y * v2.y;
1405
- const mag1 = Math.sqrt(v1.x * v1.x + v1.y * v1.y);
1406
- const mag2 = Math.sqrt(v2.x * v2.x + v2.y * v2.y);
1407
- const angle = Math.acos(dot / (mag1 * mag2));
1408
- totalAngle += angle;
1409
- }
1410
- return (totalAngle / points.length) * (180 / Math.PI);
1411
- }
1412
- ;
1413
- function latLngToPixel(bounds, canvas, latLng) {
1414
- const ctx = canvas.getContext('2d');
1415
- if (!ctx) {
1416
- throw new Error('Canvas context not found');
1417
- }
1418
- const latToPixel = (lat) => {
1419
- return canvas.height * (1 - (lat - bounds.south) / (bounds.north - bounds.south));
1420
- };
1421
- const lngToPixel = (lng) => {
1422
- return canvas.width * (lng - bounds.west) / (bounds.east - bounds.west);
1423
- };
1424
- return {
1425
- x: lngToPixel(latLng.longitude),
1426
- y: latToPixel(latLng.latitude),
1427
- };
1428
- }
1429
- function getPixelInMeters(rgbTiff) {
1430
- const latDiff = rgbTiff.bounds.north - rgbTiff.bounds.south;
1431
- // const lngDiff = rgbTiff.bounds.east - rgbTiff.bounds.west;
1432
- // const pixelWidth = rgbTiff.width;
1433
- const pixelHeight = rgbTiff.height;
1434
- const pixelInMeters = latDiff * 111320 / pixelHeight;
1435
- // const latAvg = (rgbTiff.bounds.north + rgbTiff.bounds.south) / 2;
1436
- // const pixelInMetersLng = lngDiff * 111320 * Math.cos(latAvg * Math.PI / 180) / pixelWidth;
1437
- return pixelInMeters;
1438
- }
1439
-
1440
1356
  /**
1441
1357
  * Get the intersections of a line parallel to the x-axis of the projected coordinate system with a polygon.
1442
1358
  * @param projectedPoint the point to draw the line from
@@ -2197,7 +2113,7 @@ function getOptimalSolarPositionFully(roof, obstacles, solarPanel, azimuth, inse
2197
2113
  return unprojectedPanels;
2198
2114
  }
2199
2115
 
2200
- const outputCss = "/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-green-600: oklch(62.7% 0.194 149.214);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-gray-100: oklch(96.7% 0.003 264.542);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --container-2xl: 42rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --radius-lg: 0.5rem;\n --radius-4xl: 2rem;\n --animate-spin: spin 1s linear infinite;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1 {\n top: calc(var(--spacing) * 1);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .right-4 {\n right: calc(var(--spacing) * 4);\n }\n .bottom-4 {\n bottom: calc(var(--spacing) * 4);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1 {\n left: calc(var(--spacing) * 1);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-3 {\n left: calc(var(--spacing) * 3);\n }\n .z-10 {\n z-index: 10;\n }\n .z-20 {\n z-index: 20;\n }\n .z-50 {\n z-index: 50;\n }\n .m-auto {\n margin: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .mt-6 {\n margin-top: calc(var(--spacing) * 6);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .table {\n display: table;\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-16 {\n height: calc(var(--spacing) * 16);\n }\n .h-48 {\n height: calc(var(--spacing) * 48);\n }\n .h-\\[400px\\] {\n height: 400px;\n }\n .h-full {\n height: 100%;\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-16 {\n width: calc(var(--spacing) * 16);\n }\n .w-64 {\n width: calc(var(--spacing) * 64);\n }\n .w-full {\n width: 100%;\n }\n .max-w-2xl {\n max-width: var(--container-2xl);\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-3 {\n flex: 3;\n }\n .border-collapse {\n border-collapse: collapse;\n }\n .-translate-x-1 {\n --tw-translate-x: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1 {\n --tw-translate-y: calc(var(--spacing) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-help {\n cursor: help;\n }\n .resize {\n resize: both;\n }\n .appearance-none {\n appearance: none;\n }\n .grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .grid-rows-2 {\n grid-template-rows: repeat(2, minmax(0, 1fr));\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-row {\n flex-direction: row;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .items-stretch {\n align-items: stretch;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .justify-start {\n justify-content: flex-start;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .space-y-4 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-6 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-4xl {\n border-radius: var(--radius-4xl);\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-t-2 {\n border-top-style: var(--tw-border-style);\n border-top-width: 2px;\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-\\[\\#271200\\] {\n border-color: #271200;\n }\n .border-gray-200 {\n border-color: var(--color-gray-200);\n }\n .border-gray-300 {\n border-color: var(--color-gray-300);\n }\n .border-red-500 {\n border-color: var(--color-red-500);\n }\n .bg-\\[\\#271200\\] {\n background-color: #271200;\n }\n .bg-\\[\\#f3ebda\\] {\n background-color: #f3ebda;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-gray-200 {\n background-color: var(--color-gray-200);\n }\n .bg-gray-800 {\n background-color: var(--color-gray-800);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-3 {\n padding: calc(var(--spacing) * 3);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .pt-4 {\n padding-top: calc(var(--spacing) * 4);\n }\n .pt-7 {\n padding-top: calc(var(--spacing) * 7);\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pl-2 {\n padding-left: calc(var(--spacing) * 2);\n }\n .pl-4 {\n padding-left: calc(var(--spacing) * 4);\n }\n .pl-10 {\n padding-left: calc(var(--spacing) * 10);\n }\n .text-center {\n text-align: center;\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-\\[\\#271200\\] {\n color: #271200;\n }\n .text-\\[\\#964500\\] {\n color: #964500;\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-600 {\n color: var(--color-gray-600);\n }\n .text-gray-700 {\n color: var(--color-gray-700);\n }\n .text-green-600 {\n color: var(--color-green-600);\n }\n .text-red-500 {\n color: var(--color-red-500);\n }\n .text-white {\n color: var(--color-white);\n }\n .underline {\n text-decoration-line: underline;\n }\n .accent-\\[\\#964500\\] {\n accent-color: #964500;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .group-hover\\:opacity-100 {\n &:is(:where(.group):hover *) {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n }\n .hover\\:bg-\\[\\#3a1b00\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #3a1b00;\n }\n }\n }\n .hover\\:bg-\\[\\#271200\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #271200;\n }\n }\n }\n .hover\\:bg-\\[\\#964500\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #964500;\n }\n }\n }\n .hover\\:bg-\\[\\#ffffff\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #ffffff;\n }\n }\n }\n .hover\\:bg-gray-200 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-200);\n }\n }\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-gray-500 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-500);\n }\n }\n }\n .hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--color-white);\n }\n }\n }\n .focus\\:border-transparent {\n &:focus {\n border-color: transparent;\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-\\[\\#271200\\] {\n &:focus {\n --tw-ring-color: #271200;\n }\n }\n .focus\\:ring-\\[\\#964500\\] {\n &:focus {\n --tw-ring-color: #964500;\n }\n }\n .focus\\:ring-blue-500 {\n &:focus {\n --tw-ring-color: var(--color-blue-500);\n }\n }\n .focus\\:ring-offset-0 {\n &:focus {\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .lg\\:gap-4 {\n @media (width >= 64rem) {\n gap: calc(var(--spacing) * 4);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:rounded-full {\n &::-webkit-slider-runnable-track {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:bg-black\\/25 {\n &::-webkit-slider-runnable-track {\n background-color: color-mix(in srgb, #000 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 25%, transparent);\n }\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:h-\\[10px\\] {\n &::-webkit-slider-thumb {\n height: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:w-\\[10px\\] {\n &::-webkit-slider-thumb {\n width: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:appearance-none {\n &::-webkit-slider-thumb {\n appearance: none;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:rounded-full {\n &::-webkit-slider-thumb {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:bg-white {\n &::-webkit-slider-thumb {\n background-color: var(--color-white);\n }\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-outline-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-outline-style: solid;\n --tw-duration: initial;\n }\n }\n}\n";
2116
+ const outputCss = "/*! tailwindcss v4.1.7 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --font-sans: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\",\n \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\",\n \"Courier New\", monospace;\n --color-red-500: oklch(63.7% 0.237 25.331);\n --color-green-600: oklch(62.7% 0.194 149.214);\n --color-blue-500: oklch(62.3% 0.214 259.815);\n --color-gray-200: oklch(92.8% 0.006 264.531);\n --color-gray-300: oklch(87.2% 0.01 258.338);\n --color-gray-400: oklch(70.7% 0.022 261.325);\n --color-gray-500: oklch(55.1% 0.027 264.364);\n --color-gray-600: oklch(44.6% 0.03 256.802);\n --color-gray-700: oklch(37.3% 0.034 259.733);\n --color-gray-800: oklch(27.8% 0.033 256.848);\n --color-black: #000;\n --color-white: #fff;\n --spacing: 0.25rem;\n --container-md: 28rem;\n --text-xs: 0.75rem;\n --text-xs--line-height: calc(1 / 0.75);\n --text-sm: 0.875rem;\n --text-sm--line-height: calc(1.25 / 0.875);\n --text-lg: 1.125rem;\n --text-lg--line-height: calc(1.75 / 1.125);\n --text-xl: 1.25rem;\n --text-xl--line-height: calc(1.75 / 1.25);\n --text-2xl: 1.5rem;\n --text-2xl--line-height: calc(2 / 1.5);\n --font-weight-medium: 500;\n --font-weight-semibold: 600;\n --font-weight-bold: 700;\n --radius-lg: 0.5rem;\n --radius-4xl: 2rem;\n --animate-spin: spin 1s linear infinite;\n --default-transition-duration: 150ms;\n --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --default-font-family: var(--font-sans);\n --default-mono-font-family: var(--font-mono);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");\n font-feature-settings: var(--default-font-feature-settings, normal);\n font-variation-settings: var(--default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);\n font-feature-settings: var(--default-mono-font-feature-settings, normal);\n font-variation-settings: var(--default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type=\"button\"], [type=\"reset\"], [type=\"submit\"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden=\"until-found\"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .pointer-events-none {\n pointer-events: none;\n }\n .absolute {\n position: absolute;\n }\n .fixed {\n position: fixed;\n }\n .relative {\n position: relative;\n }\n .inset-0 {\n inset: calc(var(--spacing) * 0);\n }\n .top-0 {\n top: calc(var(--spacing) * 0);\n }\n .top-1\\/2 {\n top: calc(1/2 * 100%);\n }\n .bottom-full {\n bottom: 100%;\n }\n .left-0 {\n left: calc(var(--spacing) * 0);\n }\n .left-1\\/2 {\n left: calc(1/2 * 100%);\n }\n .left-3 {\n left: calc(var(--spacing) * 3);\n }\n .z-20 {\n z-index: 20;\n }\n .z-50 {\n z-index: 50;\n }\n .m-auto {\n margin: auto;\n }\n .mt-1 {\n margin-top: calc(var(--spacing) * 1);\n }\n .mt-4 {\n margin-top: calc(var(--spacing) * 4);\n }\n .mt-6 {\n margin-top: calc(var(--spacing) * 6);\n }\n .mb-1 {\n margin-bottom: calc(var(--spacing) * 1);\n }\n .mb-2 {\n margin-bottom: calc(var(--spacing) * 2);\n }\n .mb-4 {\n margin-bottom: calc(var(--spacing) * 4);\n }\n .mb-6 {\n margin-bottom: calc(var(--spacing) * 6);\n }\n .block {\n display: block;\n }\n .flex {\n display: flex;\n }\n .grid {\n display: grid;\n }\n .inline {\n display: inline;\n }\n .inline-block {\n display: inline-block;\n }\n .inline-flex {\n display: inline-flex;\n }\n .h-4 {\n height: calc(var(--spacing) * 4);\n }\n .h-5 {\n height: calc(var(--spacing) * 5);\n }\n .h-16 {\n height: calc(var(--spacing) * 16);\n }\n .h-48 {\n height: calc(var(--spacing) * 48);\n }\n .h-\\[400px\\] {\n height: 400px;\n }\n .h-full {\n height: 100%;\n }\n .w-4 {\n width: calc(var(--spacing) * 4);\n }\n .w-5 {\n width: calc(var(--spacing) * 5);\n }\n .w-16 {\n width: calc(var(--spacing) * 16);\n }\n .w-64 {\n width: calc(var(--spacing) * 64);\n }\n .w-full {\n width: 100%;\n }\n .max-w-md {\n max-width: var(--container-md);\n }\n .flex-1 {\n flex: 1;\n }\n .flex-3 {\n flex: 3;\n }\n .-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1/2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .transform {\n transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);\n }\n .animate-spin {\n animation: var(--animate-spin);\n }\n .cursor-help {\n cursor: help;\n }\n .appearance-none {\n appearance: none;\n }\n .grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .grid-rows-2 {\n grid-template-rows: repeat(2, minmax(0, 1fr));\n }\n .grid-rows-3 {\n grid-template-rows: repeat(3, minmax(0, 1fr));\n }\n .flex-col {\n flex-direction: column;\n }\n .flex-row {\n flex-direction: row;\n }\n .flex-wrap {\n flex-wrap: wrap;\n }\n .items-center {\n align-items: center;\n }\n .items-start {\n align-items: flex-start;\n }\n .items-stretch {\n align-items: stretch;\n }\n .justify-between {\n justify-content: space-between;\n }\n .justify-center {\n justify-content: center;\n }\n .justify-end {\n justify-content: flex-end;\n }\n .justify-start {\n justify-content: flex-start;\n }\n .gap-0 {\n gap: calc(var(--spacing) * 0);\n }\n .gap-1 {\n gap: calc(var(--spacing) * 1);\n }\n .gap-2 {\n gap: calc(var(--spacing) * 2);\n }\n .gap-4 {\n gap: calc(var(--spacing) * 4);\n }\n .space-y-4 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .space-y-6 {\n :where(& > :not(:last-child)) {\n --tw-space-y-reverse: 0;\n margin-block-start: calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));\n margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));\n }\n }\n .rounded {\n border-radius: 0.25rem;\n }\n .rounded-4xl {\n border-radius: var(--radius-4xl);\n }\n .rounded-full {\n border-radius: calc(infinity * 1px);\n }\n .rounded-lg {\n border-radius: var(--radius-lg);\n }\n .border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .border-t-2 {\n border-top-style: var(--tw-border-style);\n border-top-width: 2px;\n }\n .border-b-2 {\n border-bottom-style: var(--tw-border-style);\n border-bottom-width: 2px;\n }\n .border-\\[\\#271200\\] {\n border-color: #271200;\n }\n .border-gray-200 {\n border-color: var(--color-gray-200);\n }\n .border-gray-300 {\n border-color: var(--color-gray-300);\n }\n .border-red-500 {\n border-color: var(--color-red-500);\n }\n .bg-\\[\\#00000056\\] {\n background-color: #00000056;\n }\n .bg-\\[\\#271200\\] {\n background-color: #271200;\n }\n .bg-\\[\\#f3ebda\\] {\n background-color: #f3ebda;\n }\n .bg-\\[\\#ffffff\\] {\n background-color: #ffffff;\n }\n .bg-black {\n background-color: var(--color-black);\n }\n .bg-gray-200 {\n background-color: var(--color-gray-200);\n }\n .bg-gray-800 {\n background-color: var(--color-gray-800);\n }\n .bg-transparent {\n background-color: transparent;\n }\n .bg-white {\n background-color: var(--color-white);\n }\n .p-1 {\n padding: calc(var(--spacing) * 1);\n }\n .p-2 {\n padding: calc(var(--spacing) * 2);\n }\n .p-3 {\n padding: calc(var(--spacing) * 3);\n }\n .p-4 {\n padding: calc(var(--spacing) * 4);\n }\n .p-6 {\n padding: calc(var(--spacing) * 6);\n }\n .px-4 {\n padding-inline: calc(var(--spacing) * 4);\n }\n .py-2 {\n padding-block: calc(var(--spacing) * 2);\n }\n .pt-2 {\n padding-top: calc(var(--spacing) * 2);\n }\n .pt-4 {\n padding-top: calc(var(--spacing) * 4);\n }\n .pt-7 {\n padding-top: calc(var(--spacing) * 7);\n }\n .pr-4 {\n padding-right: calc(var(--spacing) * 4);\n }\n .pb-3 {\n padding-bottom: calc(var(--spacing) * 3);\n }\n .pb-4 {\n padding-bottom: calc(var(--spacing) * 4);\n }\n .pl-2 {\n padding-left: calc(var(--spacing) * 2);\n }\n .pl-4 {\n padding-left: calc(var(--spacing) * 4);\n }\n .pl-10 {\n padding-left: calc(var(--spacing) * 10);\n }\n .text-center {\n text-align: center;\n }\n .text-2xl {\n font-size: var(--text-2xl);\n line-height: var(--tw-leading, var(--text-2xl--line-height));\n }\n .text-lg {\n font-size: var(--text-lg);\n line-height: var(--tw-leading, var(--text-lg--line-height));\n }\n .text-sm {\n font-size: var(--text-sm);\n line-height: var(--tw-leading, var(--text-sm--line-height));\n }\n .text-xl {\n font-size: var(--text-xl);\n line-height: var(--tw-leading, var(--text-xl--line-height));\n }\n .text-xs {\n font-size: var(--text-xs);\n line-height: var(--tw-leading, var(--text-xs--line-height));\n }\n .font-bold {\n --tw-font-weight: var(--font-weight-bold);\n font-weight: var(--font-weight-bold);\n }\n .font-medium {\n --tw-font-weight: var(--font-weight-medium);\n font-weight: var(--font-weight-medium);\n }\n .font-semibold {\n --tw-font-weight: var(--font-weight-semibold);\n font-weight: var(--font-weight-semibold);\n }\n .text-\\[\\#271200\\] {\n color: #271200;\n }\n .text-gray-400 {\n color: var(--color-gray-400);\n }\n .text-gray-500 {\n color: var(--color-gray-500);\n }\n .text-gray-600 {\n color: var(--color-gray-600);\n }\n .text-gray-700 {\n color: var(--color-gray-700);\n }\n .text-green-600 {\n color: var(--color-green-600);\n }\n .text-red-500 {\n color: var(--color-red-500);\n }\n .text-white {\n color: var(--color-white);\n }\n .accent-\\[\\#964500\\] {\n accent-color: #964500;\n }\n .opacity-0 {\n opacity: 0%;\n }\n .shadow {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .transition-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--default-transition-duration));\n }\n .duration-200 {\n --tw-duration: 200ms;\n transition-duration: 200ms;\n }\n .group-hover\\:opacity-100 {\n &:is(:where(.group):hover *) {\n @media (hover: hover) {\n opacity: 100%;\n }\n }\n }\n .hover\\:bg-\\[\\#0000003c\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #0000003c;\n }\n }\n }\n .hover\\:bg-\\[\\#3a1b00\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #3a1b00;\n }\n }\n }\n .hover\\:bg-\\[\\#271200\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #271200;\n }\n }\n }\n .hover\\:bg-\\[\\#964500\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #964500;\n }\n }\n }\n .hover\\:bg-\\[\\#ffffff\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #ffffff;\n }\n }\n }\n .hover\\:bg-gray-200 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-200);\n }\n }\n }\n .hover\\:bg-gray-300 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-300);\n }\n }\n }\n .hover\\:bg-gray-500 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--color-gray-500);\n }\n }\n }\n .hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--color-white);\n }\n }\n }\n .focus\\:border-2 {\n &:focus {\n border-style: var(--tw-border-style);\n border-width: 2px;\n }\n }\n .focus\\:border-black {\n &:focus {\n border-color: var(--color-black);\n }\n }\n .focus\\:border-transparent {\n &:focus {\n border-color: transparent;\n }\n }\n .focus\\:ring-2 {\n &:focus {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .focus\\:ring-\\[\\#271200\\] {\n &:focus {\n --tw-ring-color: #271200;\n }\n }\n .focus\\:ring-\\[\\#964500\\] {\n &:focus {\n --tw-ring-color: #964500;\n }\n }\n .focus\\:ring-blue-500 {\n &:focus {\n --tw-ring-color: var(--color-blue-500);\n }\n }\n .focus\\:ring-offset-0 {\n &:focus {\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n }\n }\n .focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .lg\\:gap-4 {\n @media (width >= 64rem) {\n gap: calc(var(--spacing) * 4);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:rounded-full {\n &::-webkit-slider-runnable-track {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-runnable-track\\]\\:bg-black\\/25 {\n &::-webkit-slider-runnable-track {\n background-color: color-mix(in srgb, #000 25%, transparent);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--color-black) 25%, transparent);\n }\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:h-\\[10px\\] {\n &::-webkit-slider-thumb {\n height: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:w-\\[10px\\] {\n &::-webkit-slider-thumb {\n width: 10px;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:appearance-none {\n &::-webkit-slider-thumb {\n appearance: none;\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:rounded-full {\n &::-webkit-slider-thumb {\n border-radius: calc(infinity * 1px);\n }\n }\n .\\[\\&\\:\\:-webkit-slider-thumb\\]\\:bg-white {\n &::-webkit-slider-thumb {\n background-color: var(--color-white);\n }\n }\n}\n@property --tw-translate-x {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-rotate-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-rotate-z {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-x {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-skew-y {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-space-y-reverse {\n syntax: \"*\";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: \"*\";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-font-weight {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: \"<percentage>\";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: \"*\";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: \"<length>\";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: \"*\";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: \"*\";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-duration {\n syntax: \"*\";\n inherits: false;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-rotate-x: initial;\n --tw-rotate-y: initial;\n --tw-rotate-z: initial;\n --tw-skew-x: initial;\n --tw-skew-y: initial;\n --tw-space-y-reverse: 0;\n --tw-border-style: solid;\n --tw-font-weight: initial;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-duration: initial;\n }\n }\n}\n";
2201
2117
 
2202
2118
  const MapDraw = class {
2203
2119
  constructor(hostRef) {
@@ -2225,6 +2141,7 @@ const MapDraw = class {
2225
2141
  buildingInsights = null;
2226
2142
  pixelInMeters = 0.2;
2227
2143
  isMobile = false;
2144
+ highlightedEdge = null;
2228
2145
  get el() { return getElement(this); }
2229
2146
  canvasElement;
2230
2147
  polygonCanvas;
@@ -2300,9 +2217,9 @@ const MapDraw = class {
2300
2217
  // If on mobile, automatically calculate panels using Google API data
2301
2218
  if (state.isMobile && this.buildingInsights) {
2302
2219
  const maxPanels = this.buildingInsights.solarPotential.maxArrayPanelsCount;
2303
- const approximatedPanels = Math.floor(maxPanels / 3); // Use one third of max panels
2220
+ const approximatedPanels = Math.floor(maxPanels * 3 / 4); // Use two thirds of max panels
2304
2221
  const positionedPanels = Array(approximatedPanels).fill(null)
2305
- .map((_, i) => ({
2222
+ .map((_, __) => ({
2306
2223
  panel: this.solarPanel,
2307
2224
  pixelPosition: {
2308
2225
  x: -1,
@@ -2364,6 +2281,32 @@ const MapDraw = class {
2364
2281
  const { x, y } = this.convertToCanvasCoordinates(event);
2365
2282
  this.mousePoint = { x, y };
2366
2283
  const currentPolygon = this.getCurrentPolygon();
2284
+ let redraw = false;
2285
+ if (this.currentTool.name === "markRoofEdge") {
2286
+ let distances = [];
2287
+ for (let i = 0; i < currentPolygon?.points.length; i++) {
2288
+ const pointA = currentPolygon?.points[i];
2289
+ const pointB = currentPolygon
2290
+ ?.points[(i + 1) % currentPolygon?.points.length];
2291
+ const distanceA = Math.sqrt(Math.pow(x - pointA.x, 2) + Math.pow(y - pointA.y, 2));
2292
+ const distanceB = Math.sqrt(Math.pow(x - pointB.x, 2) + Math.pow(y - pointB.y, 2));
2293
+ const edgeLength = Math.sqrt(Math.pow(pointA.x - pointB.x, 2) +
2294
+ Math.pow(pointA.y - pointB.y, 2));
2295
+ distances.push({
2296
+ dist: distanceA + distanceB - edgeLength,
2297
+ edge: { pointA, pointB },
2298
+ });
2299
+ }
2300
+ const closestEdge = distances.sort((a, b) => a.dist - b.dist)[0];
2301
+ if (closestEdge && (closestEdge.dist < 10)) {
2302
+ this.highlightedEdge = closestEdge.edge;
2303
+ redraw = true;
2304
+ }
2305
+ else if (this.highlightedEdge) {
2306
+ this.highlightedEdge = null;
2307
+ redraw = true;
2308
+ }
2309
+ }
2367
2310
  // Check for point hover
2368
2311
  const newHoveredPointIndex = currentPolygon?.points.findIndex((point) => {
2369
2312
  const distance = Math.sqrt(Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2));
@@ -2393,7 +2336,7 @@ const MapDraw = class {
2393
2336
  JSON.stringify(this.hoveredPolygon)) {
2394
2337
  this.hoveredPointIndex = newHoveredPointIndex;
2395
2338
  this.hoveredPolygon = newHoveredPolygon;
2396
- this.drawPolygons();
2339
+ redraw = true;
2397
2340
  }
2398
2341
  // Handle dragging
2399
2342
  if (this.draggedPointIndex !== null && currentPolygon &&
@@ -2406,9 +2349,12 @@ const MapDraw = class {
2406
2349
  (metersInPixels * metersInPixels);
2407
2350
  currentPolygon.details.area = area;
2408
2351
  }
2409
- this.drawPolygons();
2352
+ redraw = true;
2410
2353
  }
2411
2354
  if (this.shiftKeyPressed) {
2355
+ redraw = true;
2356
+ }
2357
+ if (redraw) {
2412
2358
  this.drawPolygons();
2413
2359
  }
2414
2360
  }
@@ -2431,6 +2377,8 @@ const MapDraw = class {
2431
2377
  pixelInMeters: this.pixelInMeters,
2432
2378
  shiftKeyPressed: this.shiftKeyPressed,
2433
2379
  mousePoint: this.mousePoint,
2380
+ highlightColor: this.config.highlightColor,
2381
+ highlightedEdge: this.highlightedEdge,
2434
2382
  });
2435
2383
  const solarPanels = this.roofPolygonsSolarPanels[polygon._id];
2436
2384
  const convertedSolarPanel = {
@@ -2458,6 +2406,7 @@ const MapDraw = class {
2458
2406
  ? this.config.closedObstructionColor
2459
2407
  : this.config.openObstructionColor,
2460
2408
  fillColor,
2409
+ highlightColor: this.config.highlightColor,
2461
2410
  });
2462
2411
  }
2463
2412
  }
@@ -2515,7 +2464,31 @@ const MapDraw = class {
2515
2464
  this.altKeyPressed = false;
2516
2465
  }
2517
2466
  }
2467
+ undo() {
2468
+ const currentPolygon = this.getCurrentPolygon();
2469
+ if (!currentPolygon) {
2470
+ return;
2471
+ }
2472
+ if (currentPolygon.closed) {
2473
+ currentPolygon.closed = false;
2474
+ if (currentPolygon.type === "roof") {
2475
+ delete this.roofPolygonsSolarPanels[currentPolygon._id];
2476
+ this.currentTool = roofTool;
2477
+ this.highlightedEdge = null;
2478
+ }
2479
+ else if (currentPolygon.type === "obstruction") {
2480
+ this.currentTool = obstructionTool;
2481
+ }
2482
+ }
2483
+ else {
2484
+ currentPolygon.points.pop();
2485
+ }
2486
+ this.drawPolygons();
2487
+ }
2518
2488
  handleMouseDown(event) {
2489
+ if (this.currentTool.name === "undo") {
2490
+ return;
2491
+ }
2519
2492
  if (state.isMobile)
2520
2493
  return; // Prevent interactions on mobile
2521
2494
  if (!this.polygonCanvas || !this.polygonCtx)
@@ -2523,6 +2496,23 @@ const MapDraw = class {
2523
2496
  if (!this.polygonCanvas.contains(event.target))
2524
2497
  return;
2525
2498
  let { x, y } = this.convertToCanvasCoordinates(event);
2499
+ if (this.currentTool.name === "markRoofEdge") {
2500
+ if (!this.highlightedEdge) {
2501
+ return;
2502
+ }
2503
+ const x = this.highlightedEdge.pointA.x -
2504
+ this.highlightedEdge.pointB.x;
2505
+ const y = this.highlightedEdge.pointA.y -
2506
+ this.highlightedEdge.pointB.y;
2507
+ const azimuth = Math.atan2(-x, y) * (180 / Math.PI);
2508
+ this.calculateSolarPanels();
2509
+ this.handleAzimuthChange({
2510
+ target: {
2511
+ value: azimuth,
2512
+ },
2513
+ });
2514
+ return;
2515
+ }
2526
2516
  if (this.currentTool.name === "delete") {
2527
2517
  if (!this.hoveredPolygon) {
2528
2518
  return;
@@ -2542,10 +2532,10 @@ const MapDraw = class {
2542
2532
  this.drawPolygons();
2543
2533
  return;
2544
2534
  }
2535
+ const currentPolygon = this.getCurrentPolygon();
2545
2536
  if (this.currentTool.name === "move") {
2546
2537
  // Check if we're clicking on a point of the selected polygon
2547
2538
  if (this.selectedPolygon) {
2548
- const currentPolygon = this.getCurrentPolygon();
2549
2539
  const pointIndex = currentPolygon?.points.findIndex((point) => {
2550
2540
  const distance = Math.sqrt(Math.pow(x - point.x, 2) + Math.pow(y - point.y, 2));
2551
2541
  return distance < 10;
@@ -2563,7 +2553,8 @@ const MapDraw = class {
2563
2553
  this.drawPolygons();
2564
2554
  return;
2565
2555
  }
2566
- if (!this.selectedPolygon || this.getCurrentPolygon()?.closed) {
2556
+ if (!this.selectedPolygon || currentPolygon?.closed ||
2557
+ this.currentTool.name !== this.selectedPolygon?.type) {
2567
2558
  // no polygon is active, create a new one
2568
2559
  const newPolygon = {
2569
2560
  _id: v4(),
@@ -2590,10 +2581,6 @@ const MapDraw = class {
2590
2581
  this.drawPolygons();
2591
2582
  return;
2592
2583
  }
2593
- const { _id, type } = this.selectedPolygon;
2594
- const currentPolygon = type === "roof"
2595
- ? this.roofPolygons[_id]
2596
- : this.obstructionPolygons[_id];
2597
2584
  if (currentPolygon.closed) {
2598
2585
  return;
2599
2586
  }
@@ -2655,7 +2642,7 @@ const MapDraw = class {
2655
2642
  this.drawPolygons();
2656
2643
  this.currentTool = moveTool;
2657
2644
  }
2658
- calculateSolarPanels() {
2645
+ calculateSolarPanels({ redraw = true } = {}) {
2659
2646
  const currentPolygon = this.getCurrentPolygon();
2660
2647
  if (!currentPolygon.details) {
2661
2648
  return;
@@ -2681,7 +2668,9 @@ const MapDraw = class {
2681
2668
  DEFAULT_SUNNINESS,
2682
2669
  },
2683
2670
  };
2684
- this.drawPolygons();
2671
+ if (redraw) {
2672
+ this.drawPolygons();
2673
+ }
2685
2674
  }
2686
2675
  handlePitchChange(event) {
2687
2676
  const target = event.target;
@@ -2710,6 +2699,13 @@ const MapDraw = class {
2710
2699
  }
2711
2700
  }
2712
2701
  handleToolSelect(tool) {
2702
+ const currentPolygon = this.getCurrentPolygon();
2703
+ if (currentPolygon && !currentPolygon.closed &&
2704
+ currentPolygon.points.length > 0) {
2705
+ alert("Please close the polygon before selecting a tool");
2706
+ // TODO translate
2707
+ return;
2708
+ }
2713
2709
  this.currentTool = tool;
2714
2710
  }
2715
2711
  scrollToCanvas() {
@@ -2731,72 +2727,24 @@ const MapDraw = class {
2731
2727
  render() {
2732
2728
  const t = getLanguageStrings(state.settings.language);
2733
2729
  const currentPolygon = this.getCurrentPolygon();
2734
- return (h("div", { key: 'bc5cb8df93f77ad4fe45c79b1deef0609a77253a', class: "flex flex-col justify-center items-center w-full h-full gap-4", id: "map-draw" }, this.showInstructions && !state.isMobile && (h("div", { key: '54410436177fb4a4f306e7526dcd3a04f20335ea', class: "w-full rounded-4xl p-4 bg-white" }, t.mapDraw.instructions.parts.roof, " ", h("button", { key: '642ed241afe9a207fde659f084149e3e35f6ccd1', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(roofTool) }, h("icon-selector", { key: '4071eff3dcc4a6d3d1d5d49177c3b21c761a3861', name: "house", inline: true })), " ", t.mapDraw.instructions.parts.obstruction, " ", h("button", { key: '7b9188696846fbea5f06415649f71bbd7f3b13c7', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(obstructionTool) }, h("icon-selector", { key: 'a2494edd178f787d96aff921aec005d93df4031e', name: "octagon-minus", inline: true })), " ", t.mapDraw.instructions.parts.delete, " ", h("button", { key: 'ff5aa2388ea6e657dc1435cbebfb9b911a687934', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(deleteTool) }, h("icon-selector", { key: 'f3cbd140baf8cb028f66bff5a1a8968cbef89363', name: "eraser", inline: true })), " ", t.mapDraw.instructions.parts.move, " ", h("button", { key: '3e81bf328648f3d2a8b4f60075b33fe2cf9b5ad6', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(moveTool) }, h("icon-selector", { key: 'be1d5191ed1b2a3c8cf66776b1ea159d4ff43afd', name: "move", inline: true })), " ", t.mapDraw.instructions.parts.end)), h("div", { key: 'e94aca98a9480808b71049af0e1fb7d7343f22a0', class: "w-full flex flex-row justify-between items-center" }, !state.isMobile && (this.showInstructions
2730
+ return (h("div", { key: 'cbd284f644e2de18b7bdcf8e32bc4660dfd73c17', class: "flex flex-col justify-center items-center w-full h-full gap-4", id: "map-draw" }, this.showInstructions && !state.isMobile && (h("div", { key: 'fdac6c98216f25c59f818abd04d6b31749411f36', class: "w-full rounded-4xl p-4 bg-white" }, t.mapDraw.instructions.parts.roof, " ", h("button", { key: '33c4ec412af722afa4f49ac3b13a3dc5b2671dff', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(roofTool) }, h("icon-selector", { key: '32a52f0c5e6d17d2ae91ff67735f61816c6300e5', name: "house", inline: true })), " ", t.mapDraw.instructions.parts.obstruction, " ", h("button", { key: 'cfc542a10d4c523c74628501e71b1a149a456bba', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(obstructionTool) }, h("icon-selector", { key: '730c7ba279c261a07072065089e6e5a796dd65ce', name: "octagon-minus", inline: true })), " ", t.mapDraw.instructions.parts.delete, " ", h("button", { key: '4a0c1f35dd229d5d1f73706c946d875fdb19398c', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(deleteTool) }, h("icon-selector", { key: '6cb8a652dcf655638d0b9383bce5e3bae04157ce', name: "eraser", inline: true })), " ", t.mapDraw.instructions.parts.move, " ", h("button", { key: 'ecbfa21a128a9469aceb11fa45bc3b2d29bf19d0', class: "inline-flex items-center justify-center p-1 rounded-full hover:bg-gray-300 transition-colors", onClick: () => this.handleToolSelect(moveTool) }, h("icon-selector", { key: 'fa25bf829d6baf05d6e850264722b22121b95e57', name: "move", inline: true })), " ", t.mapDraw.instructions.parts.end)), h("div", { key: 'c031d5061259dfd7b9440a090c7b765e17996069', class: "w-full flex flex-row justify-between items-center" }, !state.isMobile && (this.showInstructions
2735
2731
  ? (h("button", { class: "px-4 py-2 rounded-4xl hover:bg-gray-300 transition-colors duration-200 bg-white p-4", onClick: () => this.showInstructions = false }, t.mapDraw.instructions.hide))
2736
- : (h("button", { class: "px-4 py-2 rounded-4xl hover:bg-gray-300 transition-colors duration-200 bg-white p-4", onClick: () => this.showInstructions = true }, t.mapDraw.instructions.show))), h("button", { key: '0c6706ca25dee7f3a7c0c7f375a7c43216f4e5dc', class: "flex items-center gap-2 bg-white p-2 rounded-4xl hover:bg-gray-300", onClick: this.handleSettingsClick }, h("settings-icon", { key: 'a0c2d9d7c75444a497fd79e627efa80878b77b76' }))), h("div", { key: 'b4299108e6cf2b3c44781108204061ff1f868b17', class: "w-full" }, !state.isMobile && (h("tool-box", { key: '25958772c5bcad715eed7e61e9fcf8ba834085e4', currentTool: this.currentTool, onToolSelect: (tool) => this.handleToolSelect(tool) }))), this.loadingState === "empty" && (h("div", { key: '73298d935a0d154587f44aefa01e535b4724965f', class: "w-full" }, h("p", { key: '355a0d78e9429be46867be7918ebee5bb988d86b', class: "text-white text-center flex items-center justify-center rounded-4xl p-4 w-full", style: {
2732
+ : (h("button", { class: "px-4 py-2 rounded-4xl hover:bg-gray-300 transition-colors duration-200 bg-white p-4", onClick: () => this.showInstructions = true }, t.mapDraw.instructions.show))), h("button", { key: 'aedbf225990bf5642d649b6ef408c06bb1095810', class: "flex items-center gap-2 bg-white p-2 rounded-4xl hover:bg-gray-300", onClick: this.handleSettingsClick }, h("settings-icon", { key: '48dff61fa919464eaaa85bae2bbfc14e77ad60d7' }))), h("div", { key: 'c988c8626c5264388b5b3c6f594814d7d8094e12', class: "w-full" }, !state.isMobile && (h("tool-box", { key: '73025cef91d5e6ce71d248fa8e9bedff4708ca78', currentTool: this.currentTool, onToolSelect: (tool) => this.handleToolSelect(tool), undoCallback: () => this.undo() }))), this.loadingState === "empty" && (h("div", { key: '1e6fced276e02c6cf0485615a03d9e2a69337cb3', class: "w-full" }, h("p", { key: 'af2f61ae5ed321ff78e9bb0071d350e892d5347e', class: "text-white text-center flex items-center justify-center rounded-4xl p-4 w-full", style: {
2737
2733
  backgroundColor: "rgba(0, 0, 0, 0.5)",
2738
2734
  } }, t.mapDraw.noAddressSelected))), (state.latitude && state.longitude &&
2739
- this.loadingState === "loading") && (h("div", { key: '63ef7715a479e33e10f32e4ef73512e742feae52', class: "flex items-center justify-center w-full bg-opacity-75 z-20 pt-7 rounded-4xl" }, h("div", { key: '09e523207603a59802393725446693ab9dfb0eec', class: "animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-[#271200]" }))), h("div", { key: '1ba6f36469c629c4a735eb778a525e519b868dcc', class: "flex items-start justify-center h-full w-full bg-[#f3ebda] rounded-4xl" }, h("div", { key: '78a383993d84bd7a5a804a9b8aed982bca3593db', class: "relative h-full flex items-center justify-center w-full rounded-4xl bg-[#271200]", style: {
2735
+ this.loadingState === "loading") && (h("div", { key: '49a12e888f221aed7121703431c7cd52e92032bf', class: "flex items-center justify-center w-full bg-opacity-75 z-20 pt-7 rounded-4xl" }, h("div", { key: 'b56761fb67070775f30cfc297eb1de0eb85d5ca3', class: "animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-[#271200]" }))), h("div", { key: 'a74ff52cd50960865311fa2e0d9424c269cfc773', class: "flex items-start justify-center h-full w-full bg-[#f3ebda] rounded-4xl" }, h("div", { key: '809984994b4e195419ceff03938cfd7985a59725', class: "relative h-full flex items-center justify-center w-full rounded-4xl bg-[#271200]", style: {
2740
2736
  aspectRatio: this.rgbTiff
2741
2737
  ? `${this.rgbTiff.width}/${this.rgbTiff.height}`
2742
2738
  : "1/1",
2743
- } }, h("canvas", { key: '9f73b8eacc53d97584d1a1f2ad75cce42f94d883', ref: (el) => this.canvasElement = el, class: "absolute top-0 left-0 w-full h-full rounded-4xl", id: "map-draw-canvas", style: {
2739
+ } }, h("canvas", { key: 'b866ab03c36c2bf9baf1f21a65149bae7effc2b4', ref: (el) => this.canvasElement = el, class: "absolute top-0 left-0 w-full h-full rounded-4xl", id: "map-draw-canvas", style: {
2744
2740
  cursor: this.currentTool.cursor,
2745
- } }), h("canvas", { key: 'd817b13ad847248e5cccbe4a572db0d38115f40d', ref: (el) => this.polygonCanvas = el, class: "absolute top-0 left-0 w-full h-full rounded-4xl", style: {
2741
+ } }), h("canvas", { key: '5d549d4f336085f1b5f3f71a0c9a6193356f624e', ref: (el) => this.polygonCanvas = el, class: "absolute top-0 left-0 w-full h-full rounded-4xl", style: {
2746
2742
  cursor: this.currentTool.cursor,
2747
- } }), currentPolygon?.details && (h("button", { key: 'e1ac09242d33d5ff1df6442682c812734aec3ed6', class: "absolute bottom-4 right-4 px-4 py-2 bg-[#f3ebda] rounded-4xl hover:bg-[#ffffff] text-[#271200] transition-colors duration-200 z-10 text-xs", onClick: () => this.calculateSolarPanels() }, t.mapDraw.calculateSolarPanels)))), !state.isMobile && (h("div", { key: '08f69bf2844c1bced2dc1cc17c38a6aeccd4b8b7', class: "flex gap-4 flex-row justify-center items-center w-full" }, h("div", { key: 'e587229364e9644a764ebf57a22c73a8fd139054', class: "w-full bg-[#f3ebda] rounded-4xl p-4" }, h("h3", { key: '0606f98d16973c8dbf75ad59030de9716c757dbc', class: "text-lg font-semibold mb-4 text-center" }, t.mapDraw.information), currentPolygon?.details
2748
- ? (h("div", { class: "space-y-4" }, h("div", null, h("div", { class: "grid grid-cols-2 gap-2" }, h("div", null, h("h4", { class: "text-sm font-medium text-gray-600" }, t.mapDraw.area), h("p", { class: "text-lg" }, currentPolygon.details
2749
- ?.area
2750
- .toFixed(2), " m\u00B2")), h("div", null, h("div", null, h("h4", { class: "text-sm font-medium text-gray-600" }, t.mapDraw.panels), h("p", { class: "text-lg" }, this
2751
- .roofPolygonsSolarPanels[currentPolygon
2752
- ._id]?.positionedPanels
2753
- ?.length ?? 0))))), h("div", null, h("h4", { class: "text-sm font-medium text-gray-600" }, t.mapDraw.azimuth), h("div", { class: "flex gap-2 flex-row justify-start bg-white rounded-4xl p-2" }, h("input", { class: "text-lg w-full", onKeyDown: (e) => {
2754
- if (e.key === "Enter") {
2755
- this.handleAzimuthChange(e);
2756
- e.target
2757
- .blur();
2758
- }
2759
- }, value: currentPolygon
2760
- .details
2761
- ?.azimuth }), "(", azimuthToCardinal(currentPolygon.details
2762
- ?.azimuth), ")"), h("input", { type: "range", min: "0", max: "360", class: "w-full custom-range appearance-none rounded-full bg-transparent [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-black/25 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-[10px] [&::-webkit-slider-thumb]:w-[10px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", value: currentPolygon
2763
- .details?.azimuth, onInput: (e) => {
2764
- const target = e
2765
- .target;
2766
- const azimuth = parseFloat(target.value);
2767
- currentPolygon.details
2768
- .azimuth = azimuth;
2769
- if (currentPolygon
2770
- .type ===
2771
- "roof" &&
2772
- this.roofPolygonsSolarPanels[currentPolygon
2773
- ._id]) {
2774
- this.calculateSolarPanels();
2775
- }
2776
- } })), h("div", null, h("h4", { class: "text-sm font-medium text-gray-600 pl-2" }, t.mapDraw.pitch), h("div", { class: "flex gap-2 flex-row justify-start bg-white rounded-4xl p-2" }, h("input", { class: "text-lg w-full", onKeyDown: (e) => {
2777
- if (e.key === "Enter") {
2778
- this.handlePitchChange(e);
2779
- e.target
2780
- .blur();
2781
- }
2782
- }, value: currentPolygon
2783
- .details
2784
- ?.pitch }), "\u00B0"), h("input", { type: "range", min: "0", max: "90", class: "w-full custom-range appearance-none rounded-full bg-transparent [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-black/25 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-[10px] [&::-webkit-slider-thumb]:w-[10px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", value: currentPolygon
2785
- .details?.pitch, onInput: (e) => {
2786
- const target = e
2787
- .target;
2788
- const pitch = parseFloat(target.value);
2789
- currentPolygon.details
2790
- .pitch = pitch;
2791
- if (currentPolygon
2792
- .type ===
2793
- "roof" &&
2794
- this.roofPolygonsSolarPanels[currentPolygon
2795
- ._id]) {
2796
- this.calculateSolarPanels();
2797
- }
2798
- } }))))
2799
- : (h("p", { class: "text-gray-500 text-center" }, t.mapDraw.noPolygonSelected))))), h("div", { key: '1155d23559182bc9571bdeeba276896dae44d8e6', class: "w-full" }, h("solar-system-form", { key: 'dd918fdc47abf838cbb1d12932ec837bf357515f', systemConfigs: this.roofPolygonsSolarPanels, roofPolygons: this.roofPolygons, obstructionPolygons: this.obstructionPolygons })), this.showSettings && (h("settings-modal", { key: 'cedf9b3c329cf19870631da50950254de778977d', settings: state.settings, onClose: this.handleSettingsClose, onSave: this.handleSettingsSave }))));
2743
+ } }))), currentPolygon?.closed && (h("div", { key: '34f6ccc30d1cb84cd131bb5fd5e5822952fbdc4b', class: "w-full" }, h("polygon-buttons", { key: 'a55d395407a9696c52fbbc9b1961019b84750666', currentTool: this.currentTool.name, calculateSolarPanels: () => this.calculateSolarPanels(), selectEdgeTool: () => this.handleToolSelect(markRoofEdgeTool) }))), !state.isMobile && (h("div", { key: 'b140b9a19d220424ed66723026b8d1253869ffaa', class: "w-full" }, h("polygon-information", { key: '9d241320683fd9f68454ebdab4fe099b4f7db115', currentPolygon: currentPolygon, positionedPanels: currentPolygon
2744
+ ? this
2745
+ .roofPolygonsSolarPanels[currentPolygon._id]
2746
+ ?.positionedPanels
2747
+ : undefined, handleAzimuthChange: (event) => this.handleAzimuthChange(event), handlePitchChange: (event) => this.handlePitchChange(event), calculateSolarPanels: () => this.calculateSolarPanels() }))), h("div", { key: 'd76fd150e00745e069bab4f03c3f06b25260d9f5', class: "w-full" }, h("solar-system-form", { key: 'b8b92e44de52ab612da319bab6e1dc77df9d8f56', systemConfigs: this.roofPolygonsSolarPanels, roofPolygons: this.roofPolygons, obstructionPolygons: this.obstructionPolygons })), this.showSettings && (h("settings-modal", { key: 'bc6c1c9ed2da06e741e386a0eb2c51e19365bbec', settings: state.settings, onClose: this.handleSettingsClose, onSave: this.handleSettingsSave }))));
2800
2748
  }
2801
2749
  static get watchers() { return {
2802
2750
  "rgbTiff": ["drawMap"],