// Brazil map with the 5 northern states where Limine operates highlighted. // Coordinates use real (lat, lon) pairs in equirectangular projection, // based on simplified IBGE/Natural Earth state boundaries. const BRAZIL_BBOX = { latN: 6.0, latS: -34.5, lonW: -74.5, lonE: -33.5 }; const VIEW = { w: 620, h: 720 }; function project(lat, lon) { const { latN, latS, lonW, lonE } = BRAZIL_BBOX; const x = ((lon - lonW) / (lonE - lonW)) * VIEW.w; const y = ((latN - lat) / (latN - latS)) * VIEW.h; return [x, y]; } function poly(points) { return points.map(p => project(p[0], p[1]).join(",")).join(" "); } // Accurate Brazil national outline (clockwise from far north). // Points are [lat, lon] from real geographic landmarks. const BRAZIL_OUTLINE = [ // North — Roraima/Venezuela border [5.27, -60.74], [5.10, -60.05], [4.52, -59.98], [4.05, -59.65], [3.65, -59.78], // Guyana / Suriname / French Guiana — Amapá north coast [2.55, -59.85], [1.85, -56.45], [2.13, -55.90], [2.55, -54.55], [3.55, -54.20], [4.10, -53.10], [4.18, -52.20], [3.85, -51.55], [2.10, -50.85], [1.20, -50.10], // Mouth of Amazon — Marajó simplified [0.10, -49.55], [-0.50, -48.40], [-1.45, -48.50], // North-east coast [-2.50, -44.30], [-2.85, -41.80], [-3.72, -38.55], [-5.10, -35.45], [-5.80, -35.20], [-7.12, -34.80], [-8.05, -34.90], [-9.65, -35.74], [-10.94, -37.05], [-12.97, -38.50], [-13.90, -38.95], [-15.85, -38.90], [-16.45, -39.07], [-18.35, -39.70], [-20.32, -40.34], // South-east coast [-21.30, -40.95], [-22.40, -41.70], [-22.91, -43.17], [-23.05, -44.30], [-23.96, -46.33], [-25.02, -47.95], [-25.95, -48.55], [-27.60, -48.55], [-28.50, -48.85], [-29.35, -49.72], [-30.03, -50.18], [-31.35, -51.05], [-32.04, -52.10], [-33.22, -52.70], [-33.74, -53.37], // Uruguay border [-33.10, -53.50], [-32.18, -53.45], [-31.55, -54.05], [-30.91, -55.55], [-30.20, -56.95], [-29.75, -57.65], // Argentina border (Rio Uruguai) [-28.55, -56.05], [-27.50, -55.50], [-26.25, -54.65], [-25.59, -54.59], // Paraguay border [-24.05, -54.62], [-23.95, -55.65], [-22.55, -55.70], [-22.10, -56.30], [-22.10, -57.95], [-21.05, -57.90], [-20.50, -58.15], [-19.65, -57.95], // Bolivia border [-19.00, -57.78], [-17.85, -57.50], [-16.30, -58.45], [-15.50, -60.20], [-14.60, -60.40], [-13.60, -60.55], [-12.50, -64.30], [-11.00, -65.30], [-10.78, -65.34], // Bolivia/Peru border (Acre) [-11.04, -68.75], [-11.14, -69.40], [-10.93, -69.95], [-10.00, -71.10], [-9.42, -72.20], [-9.00, -72.80], [-7.63, -72.66], // Peru border (south-west Amazonas) [-6.40, -73.05], [-4.45, -70.80], [-4.25, -69.94], // Colombia border [-2.25, -69.95], [-1.45, -69.85], [-0.18, -69.45], [0.65, -69.30], [0.65, -67.05], // Venezuela border [1.20, -66.85], [1.75, -66.20], [2.20, -65.55], [3.30, -65.30], [3.85, -64.65], [4.10, -63.85], [4.55, -62.80], [4.10, -62.30], [4.55, -61.10], [5.20, -60.95], [5.27, -60.74], ]; // Each state polygon uses many real boundary points. // Coordinates are [lat, lon] following IBGE simplified borders. const COVERED_STATES = [ { uf: "RR", name: "Roraima", label: { lat: 2.7, lon: -62.0 }, poly: [ [5.27, -60.74], [5.10, -60.05], [4.52, -59.98], [4.05, -59.65], [3.65, -59.78], [2.55, -59.85], [1.85, -58.90], [1.40, -58.50], [1.20, -59.30], [1.00, -60.20], [0.65, -61.40], [0.90, -62.85], [0.65, -64.05], [0.95, -64.70], [1.85, -65.60], [2.55, -66.20], [3.10, -65.95], [3.85, -64.65], [4.10, -63.85], [4.55, -62.80], [4.10, -62.30], [4.55, -61.10], [5.20, -60.95], [5.27, -60.74], ], }, { uf: "AP", name: "Amapá", label: { lat: 1.4, lon: -52.0 }, poly: [ [4.18, -52.20], [3.85, -51.55], [2.10, -50.85], [1.20, -50.10], [0.10, -49.55], [-0.30, -50.30], [0.20, -51.20], [0.55, -51.95], [1.10, -52.55], [1.85, -52.95], [2.40, -53.55], [3.05, -54.10], [3.55, -54.20], [4.10, -53.10], [4.18, -52.20], ], }, { uf: "AM", name: "Amazonas", label: { lat: -4.5, lon: -64.5 }, poly: [ // N: from Colombia/Venezuela border south through Pico da Neblina [0.65, -69.30], [0.65, -67.05], [1.20, -66.85], [1.75, -66.20], [2.20, -65.55], [3.30, -65.30], // E border with RR [3.10, -65.95], [2.55, -66.20], [1.85, -65.60], [0.95, -64.70], [0.65, -64.05], [0.90, -62.85], [0.65, -61.40], [1.00, -60.20], [0.10, -60.20], // E border with PA [-1.00, -58.40], [-2.50, -57.95], [-4.10, -57.55], [-6.05, -57.95], [-7.85, -58.00], // S border with MT [-9.20, -58.20], [-9.40, -60.20], // SW border with RO [-8.00, -60.10], [-7.85, -62.00], [-7.55, -63.30], [-7.40, -65.20], [-7.40, -67.40], // S border with AC (small) [-7.40, -70.40], [-6.75, -71.10], [-5.50, -72.40], // W border with Peru/Colombia [-4.45, -70.80], [-4.25, -69.94], [-2.25, -69.95], [-1.45, -69.85], [-0.18, -69.45], [0.65, -69.30], ], }, { uf: "AC", name: "Acre", label: { lat: -9.2, lon: -70.5 }, poly: [ [-7.40, -72.10], [-7.40, -70.40], [-7.55, -68.50], [-9.00, -67.30], [-10.10, -67.20], [-10.78, -68.10], [-11.04, -68.75], [-11.14, -69.40], [-10.93, -69.95], [-10.00, -71.10], [-9.42, -72.20], [-9.00, -72.80], [-7.63, -72.66], [-7.40, -72.10], ], }, { uf: "RO", name: "Rondônia", label: { lat: -11.0, lon: -62.5 }, poly: [ [-7.85, -62.00], [-8.00, -60.10], [-9.40, -60.20], [-11.50, -60.20], [-12.80, -60.50], [-13.60, -60.55], [-13.40, -61.50], [-12.85, -62.85], [-12.50, -64.30], [-11.00, -65.30], [-10.78, -65.34], [-10.10, -67.20], [-9.00, -67.30], [-7.55, -68.50], [-7.55, -65.50], [-7.55, -63.30], [-7.85, -62.00], ], }, ]; // Remaining Brazilian states drawn as light context (no interactivity). // Simplified outlines based on real boundaries. const CONTEXT_STATES = [ // Pará — between AM/AP and MA, north-south huge state { uf: "PA", poly: [ [1.20, -50.10], [0.10, -49.55], [-0.50, -48.40], [-1.45, -48.50], [-2.50, -46.50], [-2.30, -45.55], [-3.00, -46.10], [-5.50, -46.20], [-6.50, -47.30], [-8.20, -47.20], [-9.50, -48.40], [-9.20, -50.20], [-9.50, -52.10], [-8.50, -54.50], [-7.85, -56.00], [-7.85, -58.00], [-6.05, -57.95], [-4.10, -57.55], [-2.50, -57.95], [-1.00, -58.40], [0.10, -60.20], [1.00, -60.20], [1.20, -59.30], [1.40, -58.50], [1.85, -58.90], [2.55, -59.85], [1.85, -56.45], [2.13, -55.90], [2.55, -54.55], [3.55, -54.20], [3.05, -54.10], [2.40, -53.55], [1.85, -52.95], [1.10, -52.55], [1.20, -50.10], ], }, // Maranhão { uf: "MA", poly: [ [-1.45, -48.50], [-2.50, -46.50], [-2.30, -45.55], [-2.50, -44.30], [-2.85, -44.10], [-3.85, -42.10], [-5.10, -41.85], [-6.50, -42.10], [-7.60, -42.75], [-8.80, -45.95], [-9.50, -46.30], [-9.30, -47.50], [-8.20, -47.20], [-6.50, -47.30], [-5.50, -46.20], [-3.00, -46.10], [-2.30, -45.55], [-2.50, -46.50], [-1.45, -48.50], ], }, // Tocantins { uf: "TO", poly: [ [-5.50, -46.20], [-6.50, -47.30], [-8.20, -47.20], [-9.30, -47.50], [-9.50, -46.30], [-10.80, -46.20], [-12.00, -45.95], [-12.95, -46.50], [-13.40, -47.30], [-12.85, -48.55], [-12.50, -49.85], [-11.40, -50.50], [-10.45, -50.35], [-9.50, -50.10], [-9.20, -50.20], [-9.50, -48.40], [-8.20, -47.20], [-6.50, -47.30], [-5.50, -46.20], ], }, // Mato Grosso { uf: "MT", poly: [ [-9.40, -60.20], [-11.50, -60.20], [-12.80, -60.50], [-13.60, -60.55], [-14.60, -60.40], [-15.50, -60.20], [-16.30, -58.45], [-17.85, -57.50], [-16.50, -55.10], [-15.30, -54.50], [-15.85, -52.50], [-14.50, -50.95], [-12.50, -49.85], [-12.85, -48.55], [-11.40, -50.50], [-10.45, -50.35], [-9.50, -50.10], [-9.20, -50.20], [-9.50, -52.10], [-8.50, -54.50], [-7.85, -56.00], [-7.85, -58.00], [-9.20, -58.20], [-9.40, -60.20], ], }, // Mato Grosso do Sul { uf: "MS", poly: [ [-17.85, -57.50], [-19.00, -57.78], [-19.65, -57.95], [-20.50, -58.15], [-21.05, -57.90], [-22.10, -57.95], [-22.10, -56.30], [-22.55, -55.70], [-23.95, -55.65], [-24.05, -54.62], [-23.95, -54.30], [-23.05, -53.20], [-22.50, -52.10], [-21.50, -52.05], [-20.40, -51.50], [-19.30, -51.40], [-18.40, -51.40], [-17.85, -52.30], [-17.30, -53.50], [-16.50, -55.10], [-17.85, -57.50], ], }, // Goiás { uf: "GO", poly: [ [-12.50, -49.85], [-14.50, -50.95], [-15.85, -52.50], [-15.30, -54.50], [-16.50, -55.10], [-17.30, -53.50], [-17.85, -52.30], [-18.40, -51.40], [-19.30, -51.40], [-19.50, -50.20], [-18.50, -49.10], [-18.10, -47.95], [-17.30, -47.50], [-16.10, -46.05], [-14.50, -46.10], [-13.40, -46.40], [-12.95, -46.50], [-12.85, -48.55], [-12.50, -49.85], ], }, // Distrito Federal — tiny { uf: "DF", poly: [ [-15.50, -48.20], [-15.55, -47.40], [-16.05, -47.40], [-16.05, -48.20], [-15.50, -48.20], ], }, // Bahia { uf: "BA", poly: [ [-8.80, -45.95], [-7.60, -42.75], [-8.50, -40.50], [-9.40, -38.30], [-10.50, -37.50], [-10.94, -37.05], [-12.97, -38.50], [-13.90, -38.95], [-15.85, -38.90], [-16.45, -39.07], [-18.35, -39.70], [-18.30, -40.40], [-17.50, -40.50], [-16.50, -40.50], [-15.50, -41.80], [-15.00, -43.10], [-14.50, -43.90], [-14.10, -44.40], [-13.40, -46.40], [-14.50, -46.10], [-12.95, -46.50], [-12.00, -45.95], [-10.80, -46.20], [-9.50, -46.30], [-8.80, -45.95], ], }, // Piauí { uf: "PI", poly: [ [-2.85, -41.80], [-3.85, -42.10], [-5.10, -41.85], [-6.50, -42.10], [-7.60, -42.75], [-8.80, -45.95], [-9.50, -46.30], [-10.80, -46.20], [-10.30, -45.30], [-10.50, -44.40], [-9.40, -43.10], [-8.50, -42.50], [-7.50, -41.20], [-6.80, -40.40], [-5.50, -40.80], [-4.40, -41.40], [-3.50, -41.40], [-2.85, -41.80], ], }, // Ceará { uf: "CE", poly: [ [-2.85, -41.80], [-3.50, -41.40], [-4.40, -41.40], [-5.50, -40.80], [-6.80, -40.40], [-7.10, -39.30], [-7.30, -38.30], [-6.40, -37.80], [-5.10, -37.50], [-4.30, -37.50], [-3.72, -38.55], [-2.85, -41.80], ], }, // Rio Grande do Norte { uf: "RN", poly: [ [-3.72, -38.55], [-4.30, -37.50], [-5.10, -37.50], [-6.40, -37.80], [-6.50, -36.20], [-6.40, -35.20], [-5.80, -35.20], [-5.10, -35.45], [-3.72, -38.55], ], }, // Paraíba { uf: "PB", poly: [ [-6.40, -35.20], [-6.50, -36.20], [-6.40, -37.80], [-7.10, -39.30], [-7.50, -38.50], [-8.30, -38.00], [-7.50, -36.50], [-7.12, -34.80], [-6.40, -35.20], ], }, // Pernambuco { uf: "PE", poly: [ [-7.12, -34.80], [-7.50, -36.50], [-8.30, -38.00], [-7.50, -38.50], [-7.10, -39.30], [-7.50, -40.50], [-8.50, -40.50], [-9.40, -39.50], [-9.10, -38.30], [-8.80, -37.30], [-9.00, -36.40], [-8.50, -35.50], [-8.05, -34.90], [-7.12, -34.80], ], }, // Alagoas { uf: "AL", poly: [ [-8.05, -34.90], [-8.50, -35.50], [-9.00, -36.40], [-9.65, -36.50], [-10.20, -36.60], [-9.65, -35.74], [-8.05, -34.90], ], }, // Sergipe { uf: "SE", poly: [ [-9.65, -35.74], [-10.20, -36.60], [-10.94, -37.05], [-11.10, -37.40], [-10.50, -37.50], [-9.40, -38.30], [-9.65, -36.50], [-9.65, -35.74], ], }, // Minas Gerais { uf: "MG", poly: [ [-14.10, -44.40], [-14.50, -43.90], [-15.00, -43.10], [-15.50, -41.80], [-16.50, -40.50], [-17.50, -40.50], [-18.30, -40.40], [-18.35, -39.70], [-19.80, -40.95], [-20.32, -40.34], [-21.30, -41.05], [-22.40, -41.70], [-22.85, -42.50], [-22.40, -43.50], [-22.85, -44.40], [-22.85, -46.50], [-22.30, -46.95], [-22.00, -48.30], [-20.50, -49.40], [-19.50, -50.20], [-18.50, -49.10], [-18.10, -47.95], [-17.30, -47.50], [-16.10, -46.05], [-14.50, -46.10], [-14.10, -44.40], ], }, // Espírito Santo { uf: "ES", poly: [ [-18.35, -39.70], [-19.80, -40.95], [-20.32, -40.34], [-21.30, -41.05], [-20.85, -41.50], [-19.85, -41.50], [-18.85, -40.95], [-18.35, -39.70], ], }, // Rio de Janeiro { uf: "RJ", poly: [ [-20.85, -41.50], [-21.30, -41.05], [-22.40, -41.70], [-22.91, -43.17], [-23.05, -44.30], [-23.10, -44.50], [-22.85, -44.40], [-22.40, -43.50], [-22.30, -42.50], [-21.50, -42.10], [-20.85, -41.50], ], }, // São Paulo { uf: "SP", poly: [ [-22.85, -44.40], [-23.10, -44.50], [-23.05, -44.30], [-23.96, -46.33], [-24.50, -47.50], [-25.02, -47.95], [-25.30, -48.30], [-24.85, -49.30], [-24.10, -50.50], [-23.40, -51.90], [-22.50, -52.10], [-22.30, -51.10], [-21.50, -51.50], [-20.50, -50.50], [-20.50, -49.40], [-22.00, -48.30], [-22.30, -46.95], [-22.85, -46.50], [-22.85, -44.40], ], }, // Paraná { uf: "PR", poly: [ [-22.50, -52.10], [-23.05, -53.20], [-23.95, -54.30], [-24.05, -54.62], [-25.59, -54.59], [-26.25, -54.65], [-26.50, -53.50], [-26.40, -50.50], [-25.95, -48.55], [-25.30, -48.30], [-24.85, -49.30], [-24.10, -50.50], [-23.40, -51.90], [-22.50, -52.10], ], }, // Santa Catarina { uf: "SC", poly: [ [-26.40, -50.50], [-26.50, -53.50], [-26.25, -54.65], [-27.50, -55.50], [-28.30, -54.20], [-28.85, -51.30], [-29.35, -49.72], [-28.50, -48.85], [-27.60, -48.55], [-26.40, -50.50], ], }, // Rio Grande do Sul { uf: "RS", poly: [ [-28.30, -54.20], [-27.50, -55.50], [-28.55, -56.05], [-29.75, -57.65], [-30.20, -56.95], [-30.91, -55.55], [-31.55, -54.05], [-32.18, -53.45], [-33.10, -53.50], [-33.74, -53.37], [-33.22, -52.70], [-32.04, -52.10], [-31.35, -51.05], [-30.03, -50.18], [-29.35, -49.72], [-28.85, -51.30], [-28.30, -54.20], ], }, ]; function BrazilMap({ activeUf, onHover }) { return ( {/* National outline as background wash */} {/* Context states (other Brazilian states) — light, no interaction */} {CONTEXT_STATES.map(s => ( ))} {/* Covered states — interactive, highlighted */} {COVERED_STATES.map(s => ( onHover && onHover(s.uf)} onMouseLeave={() => onHover && onHover(null)} style={{ cursor: "pointer", fill: activeUf === s.uf ? "#F2F6FB" : "var(--c-sky)", stroke: "#0A1B36", strokeWidth: 1.2, strokeLinejoin: "round", transition: "fill .15s ease", }} /> ))} {/* UF labels on covered states */} {COVERED_STATES.map(s => { const [x, y] = project(s.label.lat, s.label.lon); return ( {s.uf} ); })} {/* Manaus marker (HQ) */} {(() => { const [x, y] = project(-3.12, -60.02); return ( Manaus ); })()} ); } Object.assign(window, { BrazilMap, COVERED_STATES });