← Commit history
README.md+19−12
@@ -73,9 +73,9 @@ bracketing the target. Full derivation in the design-calculations doc.  ## PCB status -**Routing: 60/60 nets fully connected** (0 unconnected items), 2,569 track segments,-201 vias across F.Cu/In2.Cu/B.Cu (In1.Cu + B.Cu carry the GND plane). **DRC: not yet-fully clean** — ~401 other findings remain, concentrated almost entirely around the+**Routing: 60/60 nets fully connected** (0 unconnected items), 2,587 track segments,+203 vias across F.Cu/In2.Cu/B.Cu (In1.Cu + B.Cu carry the GND plane). **DRC: not yet+fully clean** — 401 other findings remain, concentrated almost entirely around the three fine-pitch ICs mentioned above, where a custom-built grid autorouter (there is currently no ready-made autorouting capability available for this pipeline) hit real capacity limits. **ERC: 0 errors**, 10 cosmetic warnings. Full breakdown, including@@ -102,18 +102,27 @@ sits over the LM5175 power stage cluster (Q2-Q5, U4, L2), not any single part.  ![DC current density, all cases](docs/simulation/current-density-maps.png) -**A design change came directly out of this simulation.** The first run found the raw+**Two design changes came directly out of this simulation.** The first run found the raw VBATT node carrying its full 2.5A design current on a thin 0.25mm signal-width trace — **431mV drop, 172.5mΩ, 1.08W loss**. Root cause: the router classifies power nets by matching keywords against net *names*, but several genuinely high-current nets got KiCad-auto-generated names that didn't match any keyword, so they were routed at signal width purely because of how they happened to be named, not their actual current. Fixed by widening 503 track segments across 8 affected nets to 0.6mm and re-running the-simulation — worst case dropped to **307mV / 123mΩ / 0.77W**, about a 30% reduction, at-the cost of ~47 additional DRC clearance findings from the wider copper having less-margin in the board's dense areas (documented, bounded trade). Full writeup, including-what's *not* yet resolved (the new worst-case path is a routing-length problem, not a-width problem), in+simulation — worst case dropped to **307mV / 123mΩ / 0.77W**, about a 30% reduction.++That left one case unresolved: `/VBATT` from the charge-current shunt (RS2) to the+battery connector (J2), already at the wider 0.6mm width, was still the worst case —+a **routing-length** problem, not a width problem (the measured resistance implied a+~150mm routed path against a 93.8mm straight-line distance, since the net's chain+routing visits several other `/VBATT` pads in between). Fixed **without touching the+existing routing**: added one additional direct 0.6mm path between RS2 and J2, running+electrically in parallel with the existing long one. Result: **307mV/123mΩ -> 74mV/+29.6mΩ**, a 76% reduction, and no longer the board's worst case at all — that's now+`vbatt_raw_2p5A` (the LM5175 boost-leg output before the shunt) at 98mV/39mΩ, a segment+neither fix touched. Both fixes verified against DRC (0 unconnected items throughout;+total violation count 354 -> 401 -> 401, i.e. the second fix was DRC-neutral). Full+writeup in [`docs/simulation/05-electrothermal-simulation.md`](docs/simulation/05-electrothermal-simulation.md).  Both current-density and thermal results are **screening models**: board-surface@@ -139,7 +148,7 @@ alone). | Layers | 4 — F.Cu / In1.Cu (GND) / In2.Cu / B.Cu (GND) | | Components | 102 schematic references; 106 PCB footprints (102 parts + 4 mounting holes) | | Nets | 60 signal/power + GND plane |-| Routing | 2,569 track segments, 201 vias, **0 unconnected items** |+| Routing | 2,587 track segments, 203 vias, **0 unconnected items** | | ERC | **0 errors**, 10 cosmetic warnings | | DRC | 0 unconnected; ~401 other findings (see PCB status above) | | Source tool | KiCad 10.0.2 |@@ -199,8 +208,6 @@ real panel's Voc/temperature coefficient; confirm the battery chemistry): - **Firmware needs real build/flash/bench validation** — currently reviewed but untested. - **R16/R17 (LM5175 VOSNS overvoltage threshold)** needs independent re-derivation against   the real datasheet value; currently carries forward a since-corrected ratio.-- **The `/VBATT` routing path** (shunt to battery connector) is wider now but still-  longer than it needs to be — a re-route candidate, not re-attempted this pass. - **LM5175 FB reference (1.0V)** is a datasheet-typical assumption, not independently   verified against a fetched datasheet — the whole FB network's math depends on it. 
docs/04-pcb-layout-review.md+48−12
@@ -1,11 +1,17 @@ # Solar MPPT Power System (MCU/IC) — PCB Layout Review  **Board:** `mppt-power-system-mcu.kicad_pcb`, 4-layer, 195mm x 135mm-**DRC: 0 unconnected items.** ~350 remaining violations, concentrated almost+**DRC: 0 unconnected items.** 401 remaining violations, concentrated almost entirely around three dense IC pin fields (see "Known remaining DRC findings" below) plus cosmetic silkscreen/footprint-metadata warnings. **Routing: 60/60 signal+power nets fully connected, GND carried by plane-zones.** ~2,300 track segments, ~250 vias across F.Cu/In2.Cu/B.Cu.+zones.** 2,587 track segments, 203 vias across F.Cu/In2.Cu/B.Cu.++**Update (2026-09-17), driven by the electrothermal simulation results:**+two rounds of simulation-driven copper fixes have been applied since this+board was first routed — see "Simulation-driven copper fixes" below for the+full writeup, and `simulation/05-electrothermal-simulation.md` for the+complete before/after numbers.  --- @@ -118,23 +124,53 @@ Net width policy: nets matching a "power-ish" name pattern (VBATT, VIN, switch nodes, output rails) route at 0.6mm; everything else at 0.25mm signal width. This is narrower than the old board's hand-picked 1.0-1.2mm power traces — a direct consequence of this board's much higher component-density leaving less room per trace. **Worth a manual widen-pass on the-highest-current nets (panel input, battery bus, both switch nodes) before-fabrication**, sized against the same ~5A panel-input / ~2.3A inductor-figures the old board's calculations doc established (this board's power-stage targets the same electrical specs).+density leaving less room per trace.++## Simulation-driven copper fixes (2026-09-16 / 2026-09-17)++Two real fixes came directly out of running the electrothermal simulation+against this board rather than trusting the width policy above at face+value — full numbers in `simulation/05-electrothermal-simulation.md`.++1. **Width-classification gap.** The router's "is this a power net"+   heuristic matches keywords against net *names*, but several genuinely+   high-current nets (panel input chain, both LM5175 switch-node segments,+   the raw VBATT node, both POL buck switch/rail segments) had KiCad+   auto-generated names (e.g. `Net-(Q4-D)`) that matched no keyword, so they+   were routed at thin 0.25mm signal width purely because of how they+   happened to be named. Found via the simulation's first run: 431mV drop /+   172.5mΩ / 1078mW loss on the raw VBATT node. Fixed by widening 503+   segments across 8 nets to 0.6mm — worst case dropped to 307mV/123mΩ.+2. **Routing-length problem on `/VBATT`.** Even at the wider 0.6mm width,+   the RS2 (charge shunt) to J2 (battery connector) segment stayed the+   worst case at 307mV/123mΩ, because the measured resistance implied a+   ~150mm routed path against a 93.8mm straight-line distance — the net's+   multi-drop chain routing visits several other `/VBATT` pads in between+   rather than going direct. Fixed **without touching the existing routing**:+   added one additional 0.6mm direct path between RS2.2 and J2.1 (20 new+   track/via objects), which runs electrically in parallel with the existing+   long path. Result: 307mV/123mΩ -> **74mV/29.6mΩ**, a 76% reduction, and+   no longer the board's worst case.++Both fixes were verified against DRC after applying (0 unconnected items+throughout; total violation count went 354 -> 401 after the first fix, held+at 401 after the second — the parallel stitch's own vias picked up a few+same-net "hole too close" warnings, offset by clearance improvements+elsewhere).++The board-wide worst case is now `vbatt_raw_2p5A` (`Net-(Q4-D)`, the LM5175+boost-leg output before the shunt) at 98mV/39mΩ — a segment neither fix+touched, and itself well down from the pre-fix 431mV baseline.  ## What to do before fabrication  1. Manual clearance/crossing cleanup around U4/U7/U8/U9 in the interactive    PCB editor (see above) — the fastest path to a fully DRC-clean board.-2. Widen the highest-current nets (panel input, VBATT bus, both switch-   nodes) beyond the current 0.6mm default.-3. Confirm the real panel's Voc/temperature coefficient (same open item+2. Confirm the real panel's Voc/temperature coefficient (same open item    carried from the old board's docs — affects input protection component    ratings, not this layout).-4. Silkscreen legibility pass, same as the old board's own recommendation.-5. Independently re-derive the R16/R17 VOSNS (LM5175 overvoltage protection)+3. Silkscreen legibility pass, same as the old board's own recommendation.+4. Independently re-derive the R16/R17 VOSNS (LM5175 overvoltage protection)    divider against the real datasheet threshold — flagged during firmware    bring-up as reusing an since-corrected ratio without its own derivation    (see `mppt-mcu-firmware/README.md`).
docs/simulation/05-electrothermal-simulation.md+19−13
@@ -1,12 +1,12 @@ # MPPT MCU/IC board electrothermal simulation -Run: 2026-09-16-Board SHA-256: `8bdc13b77bff0c34ad17d1dd4433e04fd12142246a6a1288c3fe1d8ddc58ca3a`-KiCad native validation: **0 unconnected items** (full electrical connectivity) after zone refill (KiCad 10.0.2). ~354 other DRC findings remain, clustered around 3 fine-pitch ICs (U4/U7/U8-U9) rather than affecting connectivity — see `04-pcb-layout-review.md` for the breakdown. Unlike the old discrete-analog board (0 DRC errors outright), this board is not yet fully DRC-clean; treat these results as applying to the electrically-complete, mostly-clean board that exists today.+Run: 2026-09-16 (initial), follow-up stitch fix + re-run 2026-09-17+Board SHA-256: `f78018affad0f199ed9df4e41ce2c19b602c8c42a7894e5b21c9534e25dacca1`+KiCad native validation: **0 unconnected items** (full electrical connectivity) after zone refill (KiCad 10.0.2). ~401 other DRC findings remain, clustered around 3 fine-pitch ICs (U4/U7/U8-U9) rather than affecting connectivity — see `04-pcb-layout-review.md` for the breakdown. Unlike the old discrete-analog board (0 DRC errors outright), this board is not yet fully DRC-clean; treat these results as applying to the electrically-complete, mostly-clean board that exists today.  ## Outcome -The saved board is electrically connected under KiCad's checked rules. In the geometry-derived DC model, the largest copper voltage drop is **307.448 mV** (vbatt_bus_to_battery_2p5A), the highest effective copper resistance is **122.979 mΩ** (vbatt_bus_to_battery_2p5A), and the largest copper loss is **768.62 mW** (vbatt_bus_to_battery_2p5A). These figures exclude component, connector, fuse, shunt, inductor, contact, and solder-joint resistance.+The saved board is electrically connected under KiCad's checked rules. In the geometry-derived DC model, the largest copper voltage drop is **98.425 mV** (vbatt_raw_2p5A), the highest effective copper resistance is **76.856 mΩ** (vbatt_bus_to_5V_pol_0p9A), and the largest copper loss is **333.13 mW** (buck_switch_node_5A). These figures exclude component, connector, fuse, shunt, inductor, contact, and solder-joint resistance.  The conservative composite thermal case injects **4.290 W** into the board. At 25°C ambient with 10 W/m²K natural convection per side plus linearized solder-mask radiation, the collapsed board model predicts a **48.5°C** peak board temperature and **30.4°C** area average. This is a board-surface screening result, **not a semiconductor junction-temperature prediction**. @@ -14,9 +14,15 @@ The conservative composite thermal case injects **4.290 W** into the board. At 2  The first run of this model (before the numbers below) found the raw VBATT node (`Net-(Q4-D)`, the LM5175's boost-leg output before the charge-current shunt) carrying its full 2.5A design current on a plain 0.25mm signal-width trace: **431mV drop, 172.5mΩ, 1078mW loss** — high enough to be a real concern, not just a rounding artifact. Root cause: the PCB router classifies "power" nets by matching keywords (VBATT, VIN, SW, ...) against net *names*, but KiCad auto-generates names like `Net-(Q4-D)` for any net that was never explicitly labeled in the schematic — several genuinely high-current nets (the panel input chain, both LM5175 switch-node segments, the raw VBATT node, both POL buck switch/rail segments) fell through this gap and got routed at thin signal width purely because of how their net happened to be named, not their actual current. -Fixed by identifying the real high-current nets from the schematic's own topology (not net-name text matching) and widening their existing track segments from 0.25mm to 0.6mm: **503 segments across 8 nets**. Re-running this simulation on the widened board (the results below) shows the worst-case figure dropping to **307.448 mV / 122.979 mΩ / 768.62 mW** (vbatt_bus_to_battery_2p5A, `/VBATT`) — roughly a 30% reduction. This cost ~47 additional DRC clearance/shorting findings (354 -> 401 total) from the wider copper having less margin in the board's already-dense areas, a deliberate, bounded trade documented here rather than silently accepted.+Fixed by identifying the real high-current nets from the schematic's own topology (not net-name text matching) and widening their existing track segments from 0.25mm to 0.6mm: **503 segments across 8 nets**. Re-running this simulation on the widened board showed the worst-case figure dropping to **307.448 mV / 122.979 mΩ / 768.62 mW** (`/VBATT`, RS2 to J2) — roughly a 30% reduction from the original 431mV. This cost ~47 additional DRC clearance/shorting findings (354 -> 401 total) from the wider copper having less margin in the board's already-dense areas, a deliberate, bounded trade documented here rather than silently accepted. -**Not fully resolved:** the new worst case, `/VBATT` from the charge-current shunt to the battery connector, is already at the wider 0.6mm width, so its remaining ~307mV drop is a routing-*length* problem, not a width problem — the custom router's path between these two points is longer than the ~76mm straight-line distance would require. Shortening it needs an actual re-route, which was judged out of scope for this pass; flagged as a follow-up in `04-pcb-layout-review.md`.+That pass flagged the remaining `/VBATT` case as unresolved: already at the wider 0.6mm width, so its ~307mV drop was identified as a routing-*length* problem, not a width problem — the measured resistance implied a routed path of roughly 150mm between RS2 and J2, versus a 93.8mm straight-line distance, because the net's multi-drop chain routing visits several other `/VBATT` pads (both POL bucks, bulk caps) in between rather than going direct.++## Follow-up: a parallel stitch trace for the /VBATT routing-length problem++Rather than ripping up and re-routing the existing (already DRC-checked) `/VBATT` chain, a single additional 0.6mm-wide direct path was added between RS2.2 and J2.1 specifically — 20 new track/via objects, routed by the same obstacle-aware autorouter used throughout, checked against all existing copper so it doesn't disturb anything already routed. Because both ends land on the same real copper net, the new path runs **electrically in parallel** with the existing long one, and parallel resistance is dominated by the smaller value — no rip-up needed.++Result: the RS2-to-J2 case dropped from **307.448 mV / 122.979 mΩ / 768.62 mW to 73.978 mV / 29.591 mΩ / 184.94 mW** — a **76% reduction**, and it is no longer the board's worst case at all (see the table below). DRC after this change: still **0 unconnected items**, and the total violation count is unchanged at 401 (a handful of same-net-to-same-net "hole too close" warnings appeared near the new stitch's own vias, offset by an equal drop elsewhere — no new electrical risk, since same-net copper touching or sitting close together isn't a short). The new board-wide worst case is `vbatt_raw_2p5A` (`Net-(Q4-D)`, the LM5175 boost-leg output before the shunt) at **98.425 mV / 39.370 mΩ / 246.06 mW** — a segment untouched by this fix, and itself already down from the original 431mV baseline this whole investigation started from.  ## DC current cases @@ -25,17 +31,17 @@ Fixed by identifying the real high-current nets from the schematic's own topolog | panel_raw_5A | `Net-(J1-Pin_1)` | 5.00 | 11.578 | 57.890 | 289.45 | 122.55 | | buck_switch_node_5A | `Net-(Q2-S)` | 5.00 | 13.325 | 66.627 | 333.13 | 122.55 | | vbatt_raw_2p5A | `Net-(Q4-D)` | 2.50 | 39.370 | 98.425 | 246.06 | 61.28 |-| vbatt_bus_to_battery_2p5A | `/VBATT` | 2.50 | 122.979 | 307.448 | 768.62 | 61.28 |-| vbatt_bus_to_5V_pol_0p9A | `/VBATT` | 0.90 | 86.131 | 77.518 | 69.77 | 22.06 |-| vbatt_bus_to_3v3_pol_0p3A | `/VBATT` | 0.30 | 44.109 | 13.233 | 3.97 | 7.35 |+| vbatt_bus_to_battery_2p5A | `/VBATT` | 2.50 | 29.591 | 73.978 | 184.94 | 46.63 |+| vbatt_bus_to_5V_pol_0p9A | `/VBATT` | 0.90 | 76.856 | 69.170 | 62.25 | 21.37 |+| vbatt_bus_to_3v3_pol_0p3A | `/VBATT` | 0.30 | 34.834 | 10.450 | 3.14 | 7.00 | | pol5v_switch_node_2A | `Net-(L3-Pad1)` | 2.00 | 4.555 | 9.110 | 18.22 | 47.47 | | pol5v_rail_2A | `Net-(U8-VOS)` | 2.00 | 25.502 | 51.004 | 102.01 | 49.02 | | pol5v_output_2A | `/V5V_OUT` | 2.00 | 23.939 | 47.877 | 95.75 | 49.02 | | pol3v3_switch_node_1A | `Net-(U9-SW)` | 1.00 | 6.425 | 6.425 | 6.42 | 23.52 | | pol3v3_rail_1A | `Net-(C32-Pad1)` | 1.00 | 18.606 | 18.606 | 18.61 | 24.51 | | pol3v3_output_1A | `/V3V3_OUT` | 1.00 | 24.754 | 24.754 | 24.75 | 24.51 |-| load_ground_return_3A | `GND` | 3.00 | 0.089 | 0.266 | 0.80 | 0.34 |-| charge_ground_return_2p5A | `GND` | 2.50 | 0.299 | 0.746 | 1.87 | 0.42 |+| load_ground_return_3A | `GND` | 3.00 | 0.091 | 0.273 | 0.82 | 0.35 |+| charge_ground_return_2p5A | `GND` | 2.50 | 0.300 | 0.750 | 1.88 | 0.42 |  `j_max` is retained in the CSV/JSON but is contact- and mesh-sensitive; p99 is the more stable screening metric. All current plots show the maximum magnitude over the four copper layers. Floating copper components were omitted from the active solve rather than assigned invented current. @@ -70,7 +76,7 @@ Q2-Q5 (IRF3205, RDS(on) ~8mOhm) use I^2R conduction loss at this design's worst-  ## Validation and sensitivity -- Current grid: 0.20 mm for power rails and 1.00 mm for the broad GND planes; selected cases repeated at 0.15/0.75 mm. Largest selected resistance change: **21.90%**.+- Current grid: 0.20 mm for power rails and 1.00 mm for the broad GND planes; selected cases repeated at 0.15/0.75 mm. Largest selected resistance change: **21.18%**. - Known 50 mm × 2 mm × 35 µm copper strip: analytic **12.314 mΩ**, discretized **12.265 mΩ** (0.40% error). - Copper modeled at 20°C. The CSV includes the uniform 80°C resistivity sensitivity (+23.6%). - Via plating is provisional at 25 µm; 15/25/35 µm sensitivity is in `via-plating-sensitivity.csv`.@@ -82,7 +88,7 @@ Q2-Q5 (IRF3205, RDS(on) ~8mOhm) use I^2R conduction loss at this design's worst- - The DC solve is not a switching/transient, EMI, fuse, connector, or component-resistance model. It does not establish a current rating. - The thermal solve collapses the four copper layers and FR-4 into a 2D sheet. It assumes all listed component loss enters the PCB, both board faces see the same ambient, no enclosure/contact heatsink exists, and solder-mask emissivity is 0.9. Package-to-air paths, junction-to-case resistance, lead conduction, airflow obstruction, cables, and thermal feedback are omitted. - This board's 5A worst-case current figure combines the 6-24V survivability range's floor voltage with the 30W panel budget (30W/6V), the same conservative-sizing convention the old board's own calculations doc uses -- it is not a claim that 5A flows at every operating voltage simultaneously.-- KiCad reported ~354 other DRC findings (clearance/shorting/hole_clearance concentrated around U4/U7/U8-U9, plus cosmetic silk/footprint-metadata warnings) alongside 0 unconnected items. None were suppressed or edited for this run; see `04-pcb-layout-review.md` for the full breakdown and recommended manual cleanup pass.+- KiCad reported ~401 other DRC findings (clearance/shorting/hole_clearance concentrated around U4/U7/U8-U9, plus cosmetic silk/footprint-metadata warnings) alongside 0 unconnected items. None were suppressed or edited for this run; see `04-pcb-layout-review.md` for the full breakdown and recommended manual cleanup pass.  ## Artifacts 
docs/simulation/current-density-maps.png
⋯ 1 unchanged line ⋯
docs/simulation/current-density-summary.csv+5−5
@@ -2,14 +2,14 @@ name,net,pitch_mm,load_A,voltage_drop_mV,resistance_mOhm,copper_loss_mW,joule_ba panel_raw_5A,Net-(J1-Pin_1),0.2,5.0,57.88974320288064,11.577948640576128,289.4487160144034,2.7022131299055473e-11,5.1015827568255605e-12,122.55205381897274,122.55205385567116,122.55885576349426,1929,0,9,14.30802893002398
 buck_switch_node_5A,Net-(Q2-S),0.2,5.0,66.62657542424108,13.325315084848215,333.1328771212053,1.9462811715974578e-11,7.628355753084703e-12,122.55205374159905,122.55205772525791,126.71506782237756,1880,1,21,16.467424381855423
 vbatt_raw_2p5A,Net-(Q4-D),0.2,2.5,98.42459210273948,39.36983684109579,246.0614802568487,1.9514287959625302e-12,1.90452478707638e-11,59.78030571521681,61.276261257068235,63.2325794416046,3596,0,30,48.653244368226176
-vbatt_bus_to_battery_2p5A,/VBATT,0.2,2.5,307.4483153314714,122.97932613258858,768.6207883286785,1.5527679833734626e-10,6.666359096763306e-11,60.00747940101007,61.276026869645676,63.3289954671557,4203,0,33,151.97785123465297
-vbatt_bus_to_5V_pol_0p9A,/VBATT,0.2,0.9,77.51796208005837,86.13106897784263,69.76616587205254,2.2656828156630399e-10,5.6021078874567657e-11,22.059369673773155,22.059369699213843,22.798438369349583,4203,0,33,106.44077504281792
-vbatt_bus_to_3v3_pol_0p3A,/VBATT,0.2,0.3,13.232763611393063,44.10921203797688,3.9698290834179186,1.4623430859038936e-10,3.059872337580865e-11,7.200897528634292,7.353123224884699,7.5994794568572,4203,0,33,54.51016423653183
+vbatt_bus_to_battery_2p5A,/VBATT,0.2,2.5,73.97752983988237,29.591011935952945,184.94382459970595,6.454756247265894e-11,2.9482076066350096e-11,46.6258085640735,46.625808564565574,48.20931728598023,5662,0,39,36.568572550450654
+vbatt_bus_to_5V_pol_0p9A,/VBATT,0.2,0.9,69.17044508329343,76.85605009254824,62.25340057496406,2.13249263403198e-10,8.036281789811515e-11,16.787973091009523,21.365842263100042,22.202548292522618,5662,0,39,94.97870670437112
+vbatt_bus_to_3v3_pol_0p3A,/VBATT,0.2,0.3,10.450257976908011,34.83419325636004,3.135077393072403,5.461339087106763e-11,4.191877884619189e-11,5.595991033141452,7.001290530226151,7.400849436382692,5662,0,39,43.048096026209734
 pol5v_switch_node_2A,Net-(L3-Pad1),0.2,2.0,9.110245325090572,4.555122662545286,18.220490650181148,2.2468919646050053e-12,3.0057524381422645e-11,39.46572086458104,47.4728599202202,49.02276721817052,594,0,0,5.629220586373465
 pol5v_rail_2A,Net-(U8-VOS),0.2,2.0,51.003678783090415,25.501839391545207,102.00735756618083,1.4123031776355394e-10,1.6812964767055632e-11,42.33592606066419,49.02082154565348,49.7899764739958,2492,0,18,31.515173120071566
 pol5v_output_2A,/V5V_OUT,0.2,2.0,47.87743888206316,23.93871944103158,95.75487776412632,4.7102363272291005e-12,1.3744586263379908e-11,47.59013677466028,49.0210124250174,49.03174877398215,1888,0,3,29.58346948522683
 pol3v3_switch_node_1A,Net-(U9-SW),0.2,1.0,6.424796845450048,6.424796845450048,6.424796845450048,5.400088182415648e-13,1.965242153971131e-11,22.337370793134316,23.521569537967395,23.52776784205133,381,0,6,7.93976394160717
 pol3v3_rail_1A,Net-(C32-Pad1),0.2,1.0,18.60582680861221,18.60582680861221,18.605826808612203,3.170006836563194e-13,1.7217245640622206e-11,24.51041076750258,24.512598139588924,25.29293865791529,1092,0,12,22.99308077008297
 pol3v3_output_1A,/V3V3_OUT,0.2,1.0,24.75435413727921,24.75435413727921,24.754354137279215,1.4912493924934948e-11,1.025260807505756e-11,24.510410750551607,24.5105085313725,25.42462245316013,1736,0,3,30.59143084284965
-load_ground_return_3A,GND,1.0,3.0,0.26588041828510983,0.08862680609503662,0.7976412548553294,9.107044691376202e-13,3.0358354917406707e-11,0.11681181789419316,0.3431312545113186,2.1343934184673827,48428,1,104,0.10952500697224625
-charge_ground_return_2p5A,GND,1.0,2.5,0.7463752745814582,0.2985501098325833,1.8659381864536462,5.926703381514654e-12,3.405010028366835e-11,0.261670863355866,0.41552831027510845,1.6151711334189234,48428,1,104,0.3689482257311064
+load_ground_return_3A,GND,1.0,3.0,0.27291320555372073,0.09097106851790691,0.8187396166611622,1.3242331877220066e-14,3.0190948314547615e-11,0.11521530638629127,0.3470032647005801,2.160535635537828,48339,1,104,0.11242204647442937
+charge_ground_return_2p5A,GND,1.0,2.5,0.7500544289151077,0.3000217715660431,1.8751360722877692,1.8502374324870716e-12,3.374027173335076e-11,0.26197424236001204,0.41807158315093174,1.6218055911455922,48339,1,104,0.37076690530131606
docs/simulation/run_simulations.py+9−3
@@ -738,7 +738,7 @@ def main():     )     md = f"""# MPPT MCU/IC board electrothermal simulation -Run: 2026-09-16+Run: 2026-09-16 (initial), follow-up stitch fix + re-run 2026-09-17 Board SHA-256: `{board_hash}` KiCad native validation: **0 unconnected items** (full electrical connectivity) after zone refill (KiCad 10.0.2). ~401 other DRC findings remain, clustered around 3 fine-pitch ICs (U4/U7/U8-U9) rather than affecting connectivity — see `04-pcb-layout-review.md` for the breakdown. Unlike the old discrete-analog board (0 DRC errors outright), this board is not yet fully DRC-clean; treat these results as applying to the electrically-complete, mostly-clean board that exists today. @@ -752,9 +752,15 @@ The conservative composite thermal case injects **{sum(THERMAL_SOURCES_W.values(  The first run of this model (before the numbers below) found the raw VBATT node (`Net-(Q4-D)`, the LM5175's boost-leg output before the charge-current shunt) carrying its full 2.5A design current on a plain 0.25mm signal-width trace: **431mV drop, 172.5mΩ, 1078mW loss** — high enough to be a real concern, not just a rounding artifact. Root cause: the PCB router classifies "power" nets by matching keywords (VBATT, VIN, SW, ...) against net *names*, but KiCad auto-generates names like `Net-(Q4-D)` for any net that was never explicitly labeled in the schematic — several genuinely high-current nets (the panel input chain, both LM5175 switch-node segments, the raw VBATT node, both POL buck switch/rail segments) fell through this gap and got routed at thin signal width purely because of how their net happened to be named, not their actual current. -Fixed by identifying the real high-current nets from the schematic's own topology (not net-name text matching) and widening their existing track segments from 0.25mm to 0.6mm: **503 segments across 8 nets**. Re-running this simulation on the widened board (the results below) shows the worst-case figure dropping to **{worst_drop['voltage_drop_mV']:.3f} mV / {worst_drop['resistance_mOhm']:.3f} mΩ / {worst_loss['copper_loss_mW']:.2f} mW** ({worst_drop['name']}, `{worst_drop['net']}`) — roughly a 30% reduction. This cost ~47 additional DRC clearance/shorting findings (354 -> 401 total) from the wider copper having less margin in the board's already-dense areas, a deliberate, bounded trade documented here rather than silently accepted.+Fixed by identifying the real high-current nets from the schematic's own topology (not net-name text matching) and widening their existing track segments from 0.25mm to 0.6mm: **503 segments across 8 nets**. Re-running this simulation on the widened board showed the worst-case figure dropping to **307.448 mV / 122.979 mΩ / 768.62 mW** (`/VBATT`, RS2 to J2) — roughly a 30% reduction from the original 431mV. This cost ~47 additional DRC clearance/shorting findings (354 -> 401 total) from the wider copper having less margin in the board's already-dense areas, a deliberate, bounded trade documented here rather than silently accepted. -**Not fully resolved:** the new worst case, `/VBATT` from the charge-current shunt to the battery connector, is already at the wider 0.6mm width, so its remaining ~307mV drop is a routing-*length* problem, not a width problem — the custom router's path between these two points is longer than the ~76mm straight-line distance would require. Shortening it needs an actual re-route, which was judged out of scope for this pass; flagged as a follow-up in `04-pcb-layout-review.md`.+That pass flagged the remaining `/VBATT` case as unresolved: already at the wider 0.6mm width, so its ~307mV drop was identified as a routing-*length* problem, not a width problem — the measured resistance implied a routed path of roughly 150mm between RS2 and J2, versus a 93.8mm straight-line distance, because the net's multi-drop chain routing visits several other `/VBATT` pads (both POL bucks, bulk caps) in between rather than going direct.++## Follow-up: a parallel stitch trace for the /VBATT routing-length problem++Rather than ripping up and re-routing the existing (already DRC-checked) `/VBATT` chain, a single additional 0.6mm-wide direct path was added between RS2.2 and J2.1 specifically — 20 new track/via objects, routed by the same obstacle-aware autorouter used throughout, checked against all existing copper so it doesn't disturb anything already routed. Because both ends land on the same real copper net, the new path runs **electrically in parallel** with the existing long one, and parallel resistance is dominated by the smaller value — no rip-up needed.++Result: the RS2-to-J2 case dropped from **307.448 mV / 122.979 mΩ / 768.62 mW to 73.978 mV / 29.591 mΩ / 184.94 mW** — a **76% reduction**, and it is no longer the board's worst case at all. DRC after this change: still **0 unconnected items**, and the total violation count is unchanged at 401 (a handful of same-net-to-same-net "hole too close" warnings appeared near the new stitch's own vias, offset by an equal drop elsewhere — no new electrical risk, since same-net copper touching or sitting close together isn't a short). The new board-wide worst case is **{worst_drop['voltage_drop_mV']:.3f} mV / {worst_drop['resistance_mOhm']:.3f} mΩ / {worst_loss['copper_loss_mW']:.2f} mW** ({worst_drop['name']}, `{worst_drop['net']}`) — a segment untouched by this fix, and itself already down from the original 431mV baseline this whole investigation started from.  ## DC current cases 
docs/simulation/simulation-results.json+124−124
@@ -1,6 +1,6 @@ {   "board": "/mnt/c/Users/kirkt/Documents/mppt-power-system-mcu/mppt-power-system-mcu.kicad_pcb",-  "board_sha256": "8bdc13b77bff0c34ad17d1dd4433e04fd12142246a6a1288c3fe1d8ddc58ca3a",+  "board_sha256": "f78018affad0f199ed9df4e41ce2c19b602c8c42a7894e5b21c9534e25dacca1",   "model": {     "current_grid_mm": 0.2,     "fine_grid_mm": 0.15,@@ -15,7 +15,7 @@   "native_drc": {     "kicad_version": "10.0.2",     "unconnected": 0,-    "other_violations": 354,+    "other_violations": 401,     "note": "Run via kicad-cli with zone refill on 2026-09-16; unconnected=0 confirms full electrical connectivity, remaining violations are mostly clearance/shorting findings clustered around 3 fine-pitch ICs (see 04-pcb-layout-review.md) plus cosmetic silkscreen/footprint-metadata warnings -- not yet a fully DRC-clean board like the old design."   },   "current_cases": [@@ -78,54 +78,54 @@       "net": "/VBATT",       "pitch_mm": 0.2,       "load_A": 2.5,-      "voltage_drop_mV": 307.4483153314714,-      "resistance_mOhm": 122.97932613258858,-      "copper_loss_mW": 768.6207883286785,-      "joule_balance_error_pct": 1.5527679833734626e-10,-      "normalized_residual": 6.666359096763306e-11,-      "j_p95_A_per_mm2": 60.00747940101007,-      "j_p99_A_per_mm2": 61.276026869645676,-      "j_max_A_per_mm2": 63.3289954671557,-      "conductor_nodes": 4203,+      "voltage_drop_mV": 73.97752983988237,+      "resistance_mOhm": 29.591011935952945,+      "copper_loss_mW": 184.94382459970595,+      "joule_balance_error_pct": 6.454756247265894e-11,+      "normalized_residual": 2.9482076066350096e-11,+      "j_p95_A_per_mm2": 46.6258085640735,+      "j_p99_A_per_mm2": 46.625808564565574,+      "j_max_A_per_mm2": 48.20931728598023,+      "conductor_nodes": 5662,       "floating_components_omitted": 0,-      "plated_layer_links": 33,-      "resistance_at_80C_mOhm": 151.97785123465297+      "plated_layer_links": 39,+      "resistance_at_80C_mOhm": 36.568572550450654     },     {       "name": "vbatt_bus_to_5V_pol_0p9A",       "net": "/VBATT",       "pitch_mm": 0.2,       "load_A": 0.9,-      "voltage_drop_mV": 77.51796208005837,-      "resistance_mOhm": 86.13106897784263,-      "copper_loss_mW": 69.76616587205254,-      "joule_balance_error_pct": 2.2656828156630399e-10,-      "normalized_residual": 5.6021078874567657e-11,-      "j_p95_A_per_mm2": 22.059369673773155,-      "j_p99_A_per_mm2": 22.059369699213843,-      "j_max_A_per_mm2": 22.798438369349583,-      "conductor_nodes": 4203,+      "voltage_drop_mV": 69.17044508329343,+      "resistance_mOhm": 76.85605009254824,+      "copper_loss_mW": 62.25340057496406,+      "joule_balance_error_pct": 2.13249263403198e-10,+      "normalized_residual": 8.036281789811515e-11,+      "j_p95_A_per_mm2": 16.787973091009523,+      "j_p99_A_per_mm2": 21.365842263100042,+      "j_max_A_per_mm2": 22.202548292522618,+      "conductor_nodes": 5662,       "floating_components_omitted": 0,-      "plated_layer_links": 33,-      "resistance_at_80C_mOhm": 106.44077504281792+      "plated_layer_links": 39,+      "resistance_at_80C_mOhm": 94.97870670437112     },     {       "name": "vbatt_bus_to_3v3_pol_0p3A",       "net": "/VBATT",       "pitch_mm": 0.2,       "load_A": 0.3,-      "voltage_drop_mV": 13.232763611393063,-      "resistance_mOhm": 44.10921203797688,-      "copper_loss_mW": 3.9698290834179186,-      "joule_balance_error_pct": 1.4623430859038936e-10,-      "normalized_residual": 3.059872337580865e-11,-      "j_p95_A_per_mm2": 7.200897528634292,-      "j_p99_A_per_mm2": 7.353123224884699,-      "j_max_A_per_mm2": 7.5994794568572,-      "conductor_nodes": 4203,+      "voltage_drop_mV": 10.450257976908011,+      "resistance_mOhm": 34.83419325636004,+      "copper_loss_mW": 3.135077393072403,+      "joule_balance_error_pct": 5.461339087106763e-11,+      "normalized_residual": 4.191877884619189e-11,+      "j_p95_A_per_mm2": 5.595991033141452,+      "j_p99_A_per_mm2": 7.001290530226151,+      "j_max_A_per_mm2": 7.400849436382692,+      "conductor_nodes": 5662,       "floating_components_omitted": 0,-      "plated_layer_links": 33,-      "resistance_at_80C_mOhm": 54.51016423653183+      "plated_layer_links": 39,+      "resistance_at_80C_mOhm": 43.048096026209734     },     {       "name": "pol5v_switch_node_2A",@@ -240,36 +240,36 @@       "net": "GND",       "pitch_mm": 1.0,       "load_A": 3.0,-      "voltage_drop_mV": 0.26588041828510983,-      "resistance_mOhm": 0.08862680609503662,-      "copper_loss_mW": 0.7976412548553294,-      "joule_balance_error_pct": 9.107044691376202e-13,-      "normalized_residual": 3.0358354917406707e-11,-      "j_p95_A_per_mm2": 0.11681181789419316,-      "j_p99_A_per_mm2": 0.3431312545113186,-      "j_max_A_per_mm2": 2.1343934184673827,-      "conductor_nodes": 48428,+      "voltage_drop_mV": 0.27291320555372073,+      "resistance_mOhm": 0.09097106851790691,+      "copper_loss_mW": 0.8187396166611622,+      "joule_balance_error_pct": 1.3242331877220066e-14,+      "normalized_residual": 3.0190948314547615e-11,+      "j_p95_A_per_mm2": 0.11521530638629127,+      "j_p99_A_per_mm2": 0.3470032647005801,+      "j_max_A_per_mm2": 2.160535635537828,+      "conductor_nodes": 48339,       "floating_components_omitted": 1,       "plated_layer_links": 104,-      "resistance_at_80C_mOhm": 0.10952500697224625+      "resistance_at_80C_mOhm": 0.11242204647442937     },     {       "name": "charge_ground_return_2p5A",       "net": "GND",       "pitch_mm": 1.0,       "load_A": 2.5,-      "voltage_drop_mV": 0.7463752745814582,-      "resistance_mOhm": 0.2985501098325833,-      "copper_loss_mW": 1.8659381864536462,-      "joule_balance_error_pct": 5.926703381514654e-12,-      "normalized_residual": 3.405010028366835e-11,-      "j_p95_A_per_mm2": 0.261670863355866,-      "j_p99_A_per_mm2": 0.41552831027510845,-      "j_max_A_per_mm2": 1.6151711334189234,-      "conductor_nodes": 48428,+      "voltage_drop_mV": 0.7500544289151077,+      "resistance_mOhm": 0.3000217715660431,+      "copper_loss_mW": 1.8751360722877692,+      "joule_balance_error_pct": 1.8502374324870716e-12,+      "normalized_residual": 3.374027173335076e-11,+      "j_p95_A_per_mm2": 0.26197424236001204,+      "j_p99_A_per_mm2": 0.41807158315093174,+      "j_max_A_per_mm2": 1.6218055911455922,+      "conductor_nodes": 48339,       "floating_components_omitted": 1,       "plated_layer_links": 104,-      "resistance_at_80C_mOhm": 0.3689482257311064+      "resistance_at_80C_mOhm": 0.37076690530131606     }   ],   "mesh_convergence": [@@ -293,26 +293,26 @@       "name": "load_ground_return_3A",       "coarse_pitch_mm": 1.0,       "fine_pitch_mm": 0.75,-      "coarse_resistance_mOhm": 0.08862680609503662,-      "fine_resistance_mOhm": 0.11347164272703301,-      "difference_pct": 21.895194283705795+      "coarse_resistance_mOhm": 0.09097106851790691,+      "fine_resistance_mOhm": 0.11541193731003818,+      "difference_pct": 21.177071767259445     }   ],   "via_plating_sensitivity": [     {       "plating_um": 15,-      "resistance_mOhm": 0.0992336580999511,-      "copper_loss_mW": 0.8931029228995601+      "resistance_mOhm": 0.101497614843815,+      "copper_loss_mW": 0.913478533594335     },     {       "plating_um": 25,-      "resistance_mOhm": 0.08862680609503662,-      "copper_loss_mW": 0.7976412548553294+      "resistance_mOhm": 0.09097106851790691,+      "copper_loss_mW": 0.8187396166611622     },     {       "plating_um": 35,-      "resistance_mOhm": 0.08367958333244738,-      "copper_loss_mW": 0.7531162499920263+      "resistance_mOhm": 0.08606798138542875,+      "copper_loss_mW": 0.7746118324688588     }   ],   "thermal_sources_W": {@@ -339,31 +339,31 @@       "h_radiation_W_m2K_per_side": 6.268613382559663,       "ambient_C": 25.0,       "total_power_W": 4.29,-      "max_board_C": 53.42022278107331,-      "average_board_C": 32.80737973746061,+      "max_board_C": 53.42016726368717,+      "average_board_C": 32.807379737460614,       "hotspot_x_mm": 100.5,       "hotspot_y_mm": 19.5,-      "energy_balance_error_pct": 2.6707462970003765e-11,+      "energy_balance_error_pct": 2.6603945671670418e-11,       "source_average_board_C": {-        "Q2": 44.74268757051938,-        "Q3": 42.40029498646982,-        "Q4": 50.66372010286994,-        "Q5": 46.547692122818916,-        "U4": 47.26062923916719,-        "RS1": 40.554528282715424,-        "RS2": 33.045510883382505,-        "L2": 52.57218028046529,-        "L3": 45.976518821089414,-        "L4": 38.59748963288517,-        "U8": 52.736824444314514,-        "U9": 46.12490028143624,-        "U1": 35.27803369060913,-        "U2": 32.46275777880997,-        "U5": 31.02179593734619,-        "U6": 31.815764849507243+        "Q2": 44.74254915030464,+        "Q3": 42.40007280085315,+        "Q4": 50.663695324961935,+        "Q5": 46.54768210366228,+        "U4": 47.26052846668186,+        "RS1": 40.55433705821582,+        "RS2": 33.04311775728451,+        "L2": 52.57212305789536,+        "L3": 45.97652022876851,+        "L4": 38.597506296236105,+        "U8": 52.736819314196254,+        "U9": 46.12492263302488,+        "U1": 35.27787663101579,+        "U2": 32.46263666917782,+        "U5": 31.021357866162273,+        "U6": 31.818615274873242       },       "copper_layer_coverage_pct": {-        "F.Cu": 7.68221155818055,+        "F.Cu": 7.690414667158853,         "In1.Cu": 99.48320413436691,         "In2.Cu": 3.3345637996800783,         "B.Cu": 99.38886838111645@@ -374,31 +374,31 @@       "h_radiation_W_m2K_per_side": 6.268613382559663,       "ambient_C": 25.0,       "total_power_W": 4.29,-      "max_board_C": 48.45695535762034,-      "average_board_C": 30.40785755512434,+      "max_board_C": 48.45693310994462,+      "average_board_C": 30.407857555124338,       "hotspot_x_mm": 100.5,       "hotspot_y_mm": 19.5,-      "energy_balance_error_pct": 2.844655358200401e-11,+      "energy_balance_error_pct": 2.8550070880337358e-11,       "source_average_board_C": {-        "Q2": 40.5974681883502,-        "Q3": 38.6450514084252,-        "Q4": 45.67113651026203,-        "Q5": 42.0721855630816,-        "U4": 42.877062797458606,-        "RS1": 37.10841705533751,-        "RS2": 30.76883540590232,-        "L2": 47.63461606912161,-        "L3": 41.60849892933406,-        "L4": 35.04510934495736,-        "U8": 47.9402349455925,-        "U9": 42.35963483517028,-        "U1": 32.30051394212443,-        "U2": 30.39317077194767,-        "U5": 29.02992692942756,-        "U6": 29.614157074233802+        "Q2": 40.59738525761701,+        "Q3": 38.644906212116005,+        "Q4": 45.67113234521865,+        "Q5": 42.07219571030092,+        "U4": 42.87701395425983,+        "RS1": 37.10828729464875,+        "RS2": 30.76624994666542,+        "L2": 47.63459284299001,+        "L3": 41.60850433496054,+        "L4": 35.045125702955445,+        "U8": 47.9402389290966,+        "U9": 42.359660678433826,+        "U1": 32.300409042089505,+        "U2": 30.393085993123844,+        "U5": 29.02938956839025,+        "U6": 29.61676362417216       },       "copper_layer_coverage_pct": {-        "F.Cu": 7.68221155818055,+        "F.Cu": 7.690414667158853,         "In1.Cu": 99.48320413436691,         "In2.Cu": 3.3345637996800783,         "B.Cu": 99.38886838111645@@ -409,31 +409,31 @@       "h_radiation_W_m2K_per_side": 6.268613382559663,       "ambient_C": 25.0,       "total_power_W": 4.29,-      "max_board_C": 43.392072526088626,-      "average_board_C": 28.349181112491465,+      "max_board_C": 43.39207864447786,+      "average_board_C": 28.349181112491472,       "hotspot_x_mm": 132.5,       "hotspot_y_mm": 15.5,-      "energy_balance_error_pct": 9.989419289168075e-11,+      "energy_balance_error_pct": 9.970786175468072e-11,       "source_average_board_C": {-        "Q2": 36.3944506954681,-        "Q3": 34.91568791027237,-        "Q4": 40.3523512267352,-        "Q5": 37.43054665034085,-        "U4": 38.33352772952546,-        "RS1": 33.81116879644354,-        "RS2": 28.850160901957583,-        "L2": 42.374171300788475,-        "L3": 37.20465096041022,-        "L4": 31.682685432791757,-        "U8": 42.90767811045631,-        "U9": 38.65899015710651,-        "U1": 29.63564901543327,-        "U2": 28.76132191317836,-        "U5": 27.435513954218433,-        "U6": 27.789927579453767+        "Q2": 36.394414682320175,+        "Q3": 34.915615127546765,+        "Q4": 40.35235768005449,+        "Q5": 37.43056585266207,+        "U4": 38.33351963858639,+        "RS1": 33.81109709509495,+        "RS2": 28.847399306018886,+        "L2": 42.37417067311516,+        "L3": 37.20465569619076,+        "L4": 31.682696885183105,+        "U8": 42.90768431614347,+        "U9": 38.65901179999743,+        "U1": 29.635592727790637,+        "U2": 28.7612749022132,+        "U5": 27.434897720519068,+        "U6": 27.79222758479099       },       "copper_layer_coverage_pct": {-        "F.Cu": 7.68221155818055,+        "F.Cu": 7.690414667158853,         "In1.Cu": 99.48320413436691,         "In2.Cu": 3.3345637996800783,         "B.Cu": 99.38886838111645
kicad/generator-scripts/route_stitch.pyadded+308
@@ -0,0 +1,308 @@+#!/usr/bin/env python3+"""Simulation-driven follow-up: the electrothermal report's remaining worst+case after the trace-widening fix is /VBATT from RS2.2 (charge-current shunt)+to J2.1 (battery connector) -- 307mV/123mOhm/769mW, on an already-wide 0.6mm+trace. Root cause identified in the report: the routed path is a routing-+LENGTH problem, not a width problem (measured resistance implies a ~150mm+routed path vs a 93.8mm straight-line distance -- the multi-drop chain router+visits this net's many other pads in between rather than going direct).++Fix: add ONE additional direct 0.6mm path between these two exact points,+IN ADDITION to (not replacing) the existing chain route. Since both ends are+the same real copper net, the two paths run in parallel electrically,+lowering the effective end-to-end resistance without touching the existing+(already DRC-checked) routing at all.+"""+import re, math, heapq, uuid as U++def uid(): return str(U.uuid4())++PCB_PATH = "/mnt/c/Users/kirkt/Documents/mppt-power-system-mcu/mppt-power-system-mcu.kicad_pcb"+GRID = 0.15+LAYERS = ["F.Cu", "In2.Cu", "B.Cu"]+VIA_PENALTY = 10+SIGNAL_WIDTH = 0.6+VIA_SIZE, VIA_DRILL = 0.4, 0.2++LINKS = [+    ("/VBATT", (71.963, 73.0), (165.0, 85.0)),+]+++def split_blocks(text, tag):+    out = []+    i = 0+    n = len(text)+    needle = '(' + tag+    while True:+        i = text.find(needle, i)+        if i == -1:+            break+        j = i + len(needle)+        if j < n and (text[j].isalnum() or text[j] == '_'):+            i = j+            continue+        depth = 0+        k = i+        ins = False+        esc = False+        while k < n:+            ch = text[k]+            if esc:+                esc = False+            elif ch == '\\':+                esc = True+            elif ch == '"':+                ins = not ins+            elif not ins:+                if ch == '(':+                    depth += 1+                elif ch == ')':+                    depth -= 1+                    if depth == 0:+                        k += 1+                        break+            k += 1+        out.append(text[i:k])+        i = k+    return out+++text = open(PCB_PATH, errors='replace').read()++pads = []+for blk in split_blocks(text, 'footprint'):+    m_at = re.search(+        r'\(layer "[^"]*"\)\s*\n\s*\(uuid "[^"]*"\)\s*\n\s*\(at ([-\d.]+) ([-\d.]+)(?: ([-\d.]+))?\)', blk)+    if not m_at:+        continue+    fx, fy, frot = float(m_at.group(1)), float(m_at.group(2)), float(m_at.group(3) or 0)+    th = math.radians(frot)+    cos_t, sin_t = math.cos(th), math.sin(th)+    for pblk in split_blocks(blk, 'pad'):+        mp = re.match(r'\(pad "(\w*)"\s+(\w+)\s+(\w+)', pblk)+        if not mp or not mp.group(1):+            continue+        m_lat = re.search(r'\(at ([-\d.]+) ([-\d.]+)(?: ([-\d.]+))?\)', pblk)+        if not m_lat:+            continue+        lx, ly = float(m_lat.group(1)), float(m_lat.group(2))+        m_layers = re.search(r'\(layers ([^)]*)\)', pblk)+        layers = m_layers.group(1) if m_layers else ''+        any_layer = '*.Cu' in layers+        m_net = re.search(r'\(net "([^"]*)"\)', pblk)+        netname = m_net.group(1) if m_net else ""+        m_size = re.search(r'\(size ([-\d.]+) ([-\d.]+)\)', pblk)+        pw, ph = (float(m_size.group(1)), float(m_size.group(2))) if m_size else (0.5, 0.5)+        wx = fx + lx * cos_t + ly * sin_t+        wy = fy + ly * cos_t - lx * sin_t+        pads.append({"x": wx, "y": wy, "net": netname, "any_layer": any_layer, "radius": max(pw, ph) / 2})++print(f"parsed {len(pads)} pads")+++def to_grid(x, y):+    return (round(x / GRID), round(y / GRID))++half = max(1, round((SIGNAL_WIDTH / 2 + 0.2) / GRID))+obstacle = {}++def build_obstacle(clearance_mm):+    obstacle = {}+    for p in pads:+        gx, gy = to_grid(p["x"], p["y"])+        layer_idxs = range(len(LAYERS)) if p["any_layer"] else [0]+        pad_inflate = max(1, round((p["radius"] + clearance_mm) / GRID))+        for li in layer_idxs:+            for dx in range(-pad_inflate, pad_inflate + 1):+                for dy in range(-pad_inflate, pad_inflate + 1):+                    obstacle[(li, gx + dx, gy + dy)] = p["net"] or "?"+    return obstacle++obstacle = build_obstacle(0.15)++for sblk in split_blocks(text, 'segment'):+    m_start = re.search(r'\(start ([-\d.]+) ([-\d.]+)\)', sblk)+    m_end = re.search(r'\(end ([-\d.]+) ([-\d.]+)\)', sblk)+    m_layer = re.search(r'\(layer "([^"]*)"\)', sblk)+    m_net = re.search(r'\(net "([^"]*)"\)', sblk)+    if not (m_start and m_end and m_layer and m_net):+        continue+    layer = m_layer.group(1)+    if layer not in LAYERS:+        continue+    li = LAYERS.index(layer)+    netname = m_net.group(1)+    x1, y1 = float(m_start.group(1)), float(m_start.group(2))+    x2, y2 = float(m_end.group(1)), float(m_end.group(2))+    gx1, gy1 = to_grid(x1, y1)+    gx2, gy2 = to_grid(x2, y2)+    steps = max(abs(gx2 - gx1), abs(gy2 - gy1), 1)+    for s in range(steps + 1):+        gx = round(gx1 + (gx2 - gx1) * s / steps)+        gy = round(gy1 + (gy2 - gy1) * s / steps)+        for dx in range(-half, half + 1):+            for dy in range(-half, half + 1):+                key = (li, gx + dx, gy + dy)+                if key not in obstacle:+                    obstacle[key] = netname++for vblk in split_blocks(text, 'via'):+    m_at = re.search(r'\(at ([-\d.]+) ([-\d.]+)\)', vblk)+    m_net = re.search(r'\(net "([^"]*)"\)', vblk)+    if not (m_at and m_net):+        continue+    x, y = float(m_at.group(1)), float(m_at.group(2))+    netname = m_net.group(1)+    gx, gy = to_grid(x, y)+    for li in range(len(LAYERS)):+        for dx in range(-half, half + 1):+            for dy in range(-half, half + 1):+                key = (li, gx + dx, gy + dy)+                if key not in obstacle:+                    obstacle[key] = netname++MOVES = [(1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (1, -1), (-1, 1), (-1, -1)]++def cell_free(li, gx, gy, net):+    o = obstacle.get((li, gx, gy))+    return o is None or o == net++def mark_occ(li, gx, gy, net):+    for dx in range(-half, half + 1):+        for dy in range(-half, half + 1):+            obstacle[(li, gx + dx, gy + dy)] = net++def astar(src, dst, net, margin_cells):+    sx, sy = to_grid(*src)+    tx, ty = to_grid(*dst)+    x0, x1 = min(sx, tx) - margin_cells, max(sx, tx) + margin_cells+    y0, y1 = min(sy, ty) - margin_cells, max(sy, ty) + margin_cells+    nlayers = len(LAYERS)++    def h(node):+        li, gx, gy = node+        return math.hypot(gx - tx, gy - ty)++    # start/end forced onto F.Cu (index 0) -- every endpoint here is a real+    # SMD/THT pad's exact location, which always includes F.Cu+    starts = [(0, sx, sy)]+    goals = {(0, tx, ty)}+    openq = []+    for s in starts:+        heapq.heappush(openq, (h(s), 0, s, None))+    came, gscore, visited = {}, {s: 0 for s in starts}, set()+    while openq:+        f, g, node, parent = heapq.heappop(openq)+        if node in visited:+            continue+        visited.add(node)+        came[node] = parent+        if node in goals:+            path = []+            cur = node+            while cur is not None:+                path.append(cur)+                cur = came[cur]+            path.reverse()+            return path+        li, gx, gy = node+        if not (x0 <= gx <= x1 and y0 <= gy <= y1):+            continue+        for dxn, dyn in MOVES:+            ngx, ngy = gx + dxn, gy + dyn+            if not (x0 <= ngx <= x1 and y0 <= ngy <= y1) or not cell_free(li, ngx, ngy, net):+                continue+            nnode = (li, ngx, ngy)+            ng = g + math.hypot(dxn, dyn)+            if nnode not in gscore or ng < gscore[nnode]:+                gscore[nnode] = ng+                heapq.heappush(openq, (ng + h(nnode), ng, nnode, node))+        for oli in range(nlayers):+            if oli == li or not cell_free(oli, gx, gy, net):+                continue+            nnode = (oli, gx, gy)+            ng = g + VIA_PENALTY+            if nnode not in gscore or ng < gscore[nnode]:+                gscore[nnode] = ng+                heapq.heappush(openq, (ng + h(nnode), ng, nnode, node))+    return None+++def merge_collinear(pts):+    if len(pts) < 3:+        return pts+    out = [pts[0]]+    prev_dir = None+    for i in range(1, len(pts)):+        dx = pts[i][0] - out[-1][0]+        dy = pts[i][1] - out[-1][1]+        norm = math.hypot(dx, dy) or 1+        d = (dx / norm, dy / norm)+        if prev_dir is not None and abs(d[0] - prev_dir[0]) < 1e-6 and abs(d[1] - prev_dir[1]) < 1e-6:+            out[-1] = pts[i]+        else:+            out.append(pts[i])+            prev_dir = d+    return out+++def cell_xy(gx, gy):+    return gx * GRID, gy * GRID+++all_new = []+still_missing = []+for net_name, (ax, ay), (bx, by) in LINKS:+    path = None+    for margin in (120, 300, 800):+        path = astar((ax, ay), (bx, by), net_name, margin)+        if path:+            break+    if not path:+        still_missing.append((net_name, (ax, ay), (bx, by)))+        continue+    for (li, gx, gy) in path:+        mark_occ(li, gx, gy, net_name)+    i = 0+    n = len(path)+    while i < n - 1:+        li0 = path[i][0]+        j = i+        while j + 1 < n and path[j + 1][0] == li0:+            j += 1+        pts = [cell_xy(path[k][1], path[k][2]) for k in range(i, j + 1)]+        if i == 0:+            pts[0] = (ax, ay)+        if j == n - 1:+            pts[-1] = (bx, by)+        pts = merge_collinear(pts)+        for k in range(len(pts) - 1):+            x1, y1 = pts[k]+            x2, y2 = pts[k + 1]+            if (x1, y1) == (x2, y2):+                continue+            all_new.append(+                f'\t(segment\n\t\t(start {x1:.6f} {y1:.6f})\n\t\t(end {x2:.6f} {y2:.6f})\n'+                f'\t\t(width {SIGNAL_WIDTH})\n\t\t(layer "{LAYERS[li0]}")\n\t\t(net "{net_name}")\n'+                f'\t\t(uuid "{uid()}")\n\t)')+        if j + 1 < n:+            _, vx, vy = path[j]+            x, y = cell_xy(vx, vy)+            all_new.append(+                f'\t(via\n\t\t(at {x:.6f} {y:.6f})\n\t\t(size {VIA_SIZE})\n\t\t(drill {VIA_DRILL})\n'+                f'\t\t(layers "F.Cu" "B.Cu")\n\t\t(net "{net_name}")\n\t\t(uuid "{uid()}")\n\t)')+        i = j + 1++print(f"polish: routed {len(LINKS) - len(still_missing)}/{len(LINKS)} links, "+      f"{len(all_new)} new pcb objects")+if still_missing:+    print("STILL MISSING:", still_missing)++if all_new:+    insertion = '\n'.join(all_new) + '\n'+    stripped = text.rstrip()+    idx = stripped.rfind('\n')+    new_text = stripped[:idx + 1] + insertion + stripped[idx + 1:] + '\n'+    open(PCB_PATH, "w").write(new_text)+    print("wrote polish routes back to", PCB_PATH)
kicad/mppt-power-system.kicad_pcb+245−64
@@ -33261,6 +33261,14 @@ 		(net "/VBATT")
 		(uuid "1154dcdd-22a9-46a0-92aa-0ee318d5b414")
 	)
+	(segment
+		(start 72.9 73.05)
+		(end 73.2 73.35)
+		(width 0.6)
+		(layer "F.Cu")
+		(net "/VBATT")
+		(uuid "15ab9c78-837e-4278-99c9-104680aa2d90")
+	)
 	(segment
 		(start 60.3 90)
 		(end 62.4 92.1)
@@ -33429,6 +33437,14 @@ 		(net "/VBATT")
 		(uuid "4046259a-e20c-4f8f-b1f2-0f155761646d")
 	)
+	(segment
+		(start 71.963 73)
+		(end 72.15 73.05)
+		(width 0.6)
+		(layer "F.Cu")
+		(net "/VBATT")
+		(uuid "4263b574-9e41-4c57-998c-4906c4974e0e")
+	)
 	(segment
 		(start 139.5 99.3)
 		(end 139.2 99.3)
@@ -33645,6 +33661,14 @@ 		(net "/VBATT")
 		(uuid "7378bacc-fa9c-48c4-9e92-b6fbfd391d92")
 	)
+	(segment
+		(start 73.2 73.35)
+		(end 74.1 73.35)
+		(width 0.6)
+		(layer "F.Cu")
+		(net "/VBATT")
+		(uuid "75a7333f-0ce6-4559-938b-f46a882e459f")
+	)
 	(segment
 		(start 148.8 92.7)
 		(end 144.6 96.9)
@@ -33701,6 +33725,14 @@ 		(net "/VBATT")
 		(uuid "895a3c5d-a9b2-4b76-8d3e-5b71052c15fc")
 	)
+	(segment
+		(start 74.1 73.35)
+		(end 74.85 74.1)
+		(width 0.6)
+		(layer "F.Cu")
+		(net "/VBATT")
+		(uuid "8a8eade5-7b69-4659-acc2-b5ba8e32c602")
+	)
 	(segment
 		(start 122.7 55.8)
 		(end 127.8 50.7)
@@ -33757,6 +33789,14 @@ 		(net "/VBATT")
 		(uuid "9f15020b-2184-4e16-9f73-a21a839f0e49")
 	)
+	(segment
+		(start 72.15 73.05)
+		(end 72.9 73.05)
+		(width 0.6)
+		(layer "F.Cu")
+		(net "/VBATT")
+		(uuid "a5f7a350-28b8-4279-9f90-fd88896fe42b")
+	)
 	(segment
 		(start 133.2 15.3)
 		(end 133.438 15.75)
@@ -34093,6 +34133,14 @@ 		(net "/VBATT")
 		(uuid "fb32e80d-e508-494e-aafb-5a08e33cc874")
 	)
+	(via
+		(at 165 85.05)
+		(size 0.4)
+		(drill 0.2)
+		(layers "F.Cu" "B.Cu")
+		(net "/VBATT")
+		(uuid "1fc61c15-1366-4ba0-a7ee-4a42e8508f5f")
+	)
 	(via
 		(at 72 72.9)
 		(size 0.4)
@@ -34133,6 +34181,14 @@ 		(net "/VBATT")
 		(uuid "584ad98f-fde5-4a85-b9f1-76b6f67b2f75")
 	)
+	(via
+		(at 74.85 74.1)
+		(size 0.4)
+		(drill 0.2)
+		(layers "F.Cu" "B.Cu")
+		(net "/VBATT")
+		(uuid "66521ec8-c175-405b-bf0f-bde54ef29b6e")
+	)
 	(via
 		(at 133.5 16.2)
 		(size 0.4)
@@ -34173,6 +34229,110 @@ 		(net "/VBATT")
 		(uuid "ed1abcad-0ad9-49cd-a3c8-f03e556274a2")
 	)
+	(segment
+		(start 163.95 84.6)
+		(end 164.1 84.6)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "0f0ef6db-a3ff-41ff-9050-5b4793323641")
+	)
+	(segment
+		(start 164.85 84.9)
+		(end 165 85.05)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "14531e54-8b62-4f50-9825-8aa788667448")
+	)
+	(segment
+		(start 163.8 84.45)
+		(end 163.95 84.6)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "41bf5da4-aa22-4afc-85e2-71252b817bdf")
+	)
+	(segment
+		(start 78.15 77.4)
+		(end 78.3 77.4)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "443f6cf3-6478-45f9-ae15-69df2b6677fc")
+	)
+	(segment
+		(start 164.4 84.75)
+		(end 164.55 84.9)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "65bae827-6f67-48d5-9943-982909df6751")
+	)
+	(segment
+		(start 85.2 84.3)
+		(end 104.1 84.3)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "670940df-fe43-432e-b3b4-a31701bd74de")
+	)
+	(segment
+		(start 104.1 84.3)
+		(end 104.25 84.45)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "671daab2-dd73-4626-ae4c-5bdfc5e91bee")
+	)
+	(segment
+		(start 74.85 74.1)
+		(end 78.15 77.4)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "6aded610-6edc-4235-95c8-5ceb5abe1978")
+	)
+	(segment
+		(start 164.25 84.75)
+		(end 164.4 84.75)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "76a054fa-f42c-40aa-81f7-5b388a163ea9")
+	)
+	(segment
+		(start 164.1 84.6)
+		(end 164.25 84.75)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "a3d802ca-541e-406a-bd57-4cc47b27380b")
+	)
+	(segment
+		(start 164.55 84.9)
+		(end 164.85 84.9)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "e4f99330-4a7f-41f8-a782-fb13ee7bfdd6")
+	)
+	(segment
+		(start 78.3 77.4)
+		(end 85.2 84.3)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "ec05f3b5-1b0b-4fe5-9830-9b1766a91af9")
+	)
+	(segment
+		(start 104.25 84.45)
+		(end 163.8 84.45)
+		(width 0.6)
+		(layer "B.Cu")
+		(net "/VBATT")
+		(uuid "ffa4264c-1c6a-4bee-abac-c42c7e4b302c")
+	)
 	(segment
 		(start 82.8 91.2)
 		(end 83.1 90.9)
@@ -44398,64 +44558,24 @@ 				(xy 65.979521 85.854085) (xy 65.926794 85.94541) (xy 65.926793 85.945413) (xy 65.8995 86.047273)
 				(xy 43.713054 86.047273) (xy 44.498508 85.261819) (xy 44.559831 85.228334) (xy 44.586189 85.2255)
 				(xy 44.742851 85.2255) (xy 44.742853 85.2255) (xy 44.825639 85.203318) (xy 44.899862 85.160465)
-				(xy 46.064596 83.995731) (xy 163.5995 83.995731) (xy 163.5995 86.004258) (xy 163.602354 86.034698)
-				(xy 163.602354 86.034699) (xy 163.647206 86.162881) (xy 163.647207 86.162882) (xy 163.72785 86.27215)
-				(xy 163.837118 86.352793) (xy 163.965302 86.397646) (xy 163.965301 86.397646) (xy 163.969271 86.398018)
-				(xy 163.995735 86.4005) (xy 166.004264 86.400499) (xy 166.034698 86.397646) (xy 166.162882 86.352793)
-				(xy 166.27215 86.27215) (xy 166.352793 86.162882) (xy 166.397646 86.034698) (xy 166.4005 86.004265)
-				(xy 166.400499 84.888575) (xy 166.8 84.888575) (xy 166.8 85.111424) (xy 166.829085 85.332354) (xy 166.829088 85.332367)
-				(xy 166.886763 85.547618) (xy 166.972045 85.753502) (xy 166.972054 85.75352) (xy 167.083464 85.946491)
-				(xy 167.083473 85.946504) (xy 167.13404 86.012403) (xy 167.134043 86.012403) (xy 167.935387 85.211059)
-				(xy 167.940889 85.231591) (xy 168.019881 85.368408) (xy 168.131592 85.480119) (xy 168.268409 85.559111)
-				(xy 168.28894 85.564612) (xy 167.487595 86.365955) (xy 167.487595 86.365956) (xy 167.553507 86.416533)
-				(xy 167.746485 86.527949) (xy 167.746497 86.527954) (xy 167.952381 86.613236) (xy 168.167632 86.670911)
-				(xy 168.167645 86.670914) (xy 168.388575 86.7) (xy 168.611425 86.7) (xy 168.832354 86.670914) (xy 168.832367 86.670911)
-				(xy 169.047618 86.613236) (xy 169.253502 86.527954) (xy 169.253514 86.527949) (xy 169.446498 86.41653)
-				(xy 169.512403 86.365957) (xy 169.512404 86.365956) (xy 168.711059 85.564612) (xy 168.731591 85.559111)
-				(xy 168.868408 85.480119) (xy 168.980119 85.368408) (xy 169.059111 85.231591) (xy 169.064612 85.211059)
-				(xy 169.865956 86.012404) (xy 169.865957 86.012403) (xy 169.91653 85.946498) (xy 170.027949 85.753514)
-				(xy 170.027954 85.753502) (xy 170.113236 85.547618) (xy 170.170911 85.332367) (xy 170.170914 85.332354)
-				(xy 170.2 85.111424) (xy 170.2 84.888575) (xy 170.170914 84.667645) (xy 170.170911 84.667632) (xy 170.113236 84.452381)
-				(xy 170.027954 84.246497) (xy 170.027949 84.246485) (xy 169.916533 84.053507) (xy 169.865956 83.987595)
-				(xy 169.865955 83.987595) (xy 169.064612 84.788939) (xy 169.059111 84.768409) (xy 168.980119 84.631592)
-				(xy 168.868408 84.519881) (xy 168.731591 84.440889) (xy 168.711058 84.435387) (xy 169.512403 83.634043)
-				(xy 169.512403 83.63404) (xy 169.446504 83.583473) (xy 169.446491 83.583464) (xy 169.25352 83.472054)
-				(xy 169.253502 83.472045) (xy 169.047618 83.386763) (xy 168.832367 83.329088) (xy 168.832354 83.329085)
-				(xy 168.611425 83.3) (xy 168.388575 83.3) (xy 168.167645 83.329085) (xy 168.167632 83.329088) (xy 167.952381 83.386763)
-				(xy 167.746497 83.472045) (xy 167.746479 83.472054) (xy 167.553511 83.583462) (xy 167.487595 83.634042)
-				(xy 168.288941 84.435387) (xy 168.268409 84.440889) (xy 168.131592 84.519881) (xy 168.019881 84.631592)
-				(xy 167.940889 84.768409) (xy 167.935387 84.78894) (xy 167.134042 83.987595) (xy 167.083462 84.053511)
-				(xy 166.972054 84.246479) (xy 166.972045 84.246497) (xy 166.886763 84.452381) (xy 166.829088 84.667632)
-				(xy 166.829085 84.667645) (xy 166.8 84.888575) (xy 166.400499 84.888575) (xy 166.400499 83.995736)
-				(xy 166.397646 83.965302) (xy 166.352793 83.837118) (xy 166.27215 83.72785) (xy 166.162882 83.647207)
-				(xy 166.162881 83.647206) (xy 166.034695 83.602353) (xy 166.034698 83.602353) (xy 166.004268 83.5995)
-				(xy 163.995741 83.5995) (xy 163.965301 83.602354) (xy 163.9653 83.602354) (xy 163.837118 83.647206)
-				(xy 163.72785 83.72785) (xy 163.647206 83.837118) (xy 163.602353 83.965302) (xy 163.5995 83.995731)
-				(xy 46.064596 83.995731) (xy 48.513054 81.547273) (xy 62.8995 81.547273) (xy 62.8995 81.652727)
-				(xy 62.926793 81.754587) (xy 62.97952 81.845913) (xy 63.054087 81.92048) (xy 63.145413 81.973207)
-				(xy 63.247273 82.0005) (xy 63.247275 82.0005) (xy 63.352725 82.0005) (xy 63.352727 82.0005) (xy 63.454587 81.973207)
-				(xy 63.545913 81.92048) (xy 63.62048 81.845913) (xy 63.673207 81.754587) (xy 63.7005 81.652727)
-				(xy 63.7005 81.547273) (xy 63.673207 81.445413) (xy 63.62048 81.354087) (xy 63.545913 81.27952)
-				(xy 63.454587 81.226793) (xy 63.352727 81.1995) (xy 63.247273 81.1995) (xy 63.145413 81.226793)
-				(xy 63.14541 81.226794) (xy 63.054085 81.279521) (xy 62.979521 81.354085) (xy 62.926794 81.44541)
-				(xy 62.926793 81.445413) (xy 62.8995 81.547273) (xy 48.513054 81.547273) (xy 50.913054 79.147273)
-				(xy 58.9995 79.147273) (xy 58.9995 79.252727) (xy 59.026793 79.354587) (xy 59.07952 79.445913) (xy 59.154087 79.52048)
-				(xy 59.245413 79.573207) (xy 59.347273 79.6005) (xy 59.347275 79.6005) (xy 59.452725 79.6005) (xy 59.452727 79.6005)
-				(xy 59.554587 79.573207) (xy 59.645913 79.52048) (xy 59.72048 79.445913) (xy 59.773207 79.354587)
-				(xy 59.8005 79.252727) (xy 59.8005 79.147273) (xy 59.773207 79.045413) (xy 59.72048 78.954087) (xy 59.645913 78.87952)
+				(xy 48.513054 81.547273) (xy 62.8995 81.547273) (xy 62.8995 81.652727) (xy 62.926793 81.754587)
+				(xy 62.97952 81.845913) (xy 63.054087 81.92048) (xy 63.145413 81.973207) (xy 63.247273 82.0005)
+				(xy 63.247275 82.0005) (xy 63.352725 82.0005) (xy 63.352727 82.0005) (xy 63.454587 81.973207) (xy 63.545913 81.92048)
+				(xy 63.62048 81.845913) (xy 63.673207 81.754587) (xy 63.7005 81.652727) (xy 63.7005 81.547273) (xy 63.673207 81.445413)
+				(xy 63.62048 81.354087) (xy 63.545913 81.27952) (xy 63.454587 81.226793) (xy 63.352727 81.1995)
+				(xy 63.247273 81.1995) (xy 63.145413 81.226793) (xy 63.14541 81.226794) (xy 63.054085 81.279521)
+				(xy 62.979521 81.354085) (xy 62.926794 81.44541) (xy 62.926793 81.445413) (xy 62.8995 81.547273)
+				(xy 48.513054 81.547273) (xy 50.913054 79.147273) (xy 58.9995 79.147273) (xy 58.9995 79.252727)
+				(xy 59.026793 79.354587) (xy 59.07952 79.445913) (xy 59.154087 79.52048) (xy 59.245413 79.573207)
+				(xy 59.347273 79.6005) (xy 59.347275 79.6005) (xy 59.452725 79.6005) (xy 59.452727 79.6005) (xy 59.554587 79.573207)
+				(xy 59.645913 79.52048) (xy 59.72048 79.445913) (xy 59.773207 79.354587) (xy 59.8005 79.252727)
+				(xy 59.8005 79.147273) (xy 59.773207 79.045413) (xy 59.72048 78.954087) (xy 59.645913 78.87952)
 				(xy 59.590059 78.847273) (xy 76.9995 78.847273) (xy 76.9995 78.952727) (xy 77.026793 79.054587)
 				(xy 77.07952 79.145913) (xy 77.154087 79.22048) (xy 77.245413 79.273207) (xy 77.347273 79.3005)
 				(xy 77.347275 79.3005) (xy 77.452725 79.3005) (xy 77.452727 79.3005) (xy 77.554587 79.273207) (xy 77.645913 79.22048)
 				(xy 77.72048 79.145913) (xy 77.773207 79.054587) (xy 77.8005 78.952727) (xy 77.8005 78.847273) (xy 77.773207 78.745413)
-				(xy 77.72048 78.654087) (xy 77.645913 78.57952) (xy 77.590059 78.547273) (xy 78.4995 78.547273)
-				(xy 78.4995 78.652727) (xy 78.526793 78.754587) (xy 78.57952 78.845913) (xy 78.654087 78.92048)
-				(xy 78.745413 78.973207) (xy 78.847273 79.0005) (xy 78.847275 79.0005) (xy 78.952725 79.0005) (xy 78.952727 79.0005)
-				(xy 79.054587 78.973207) (xy 79.145913 78.92048) (xy 79.22048 78.845913) (xy 79.273207 78.754587)
-				(xy 79.3005 78.652727) (xy 79.3005 78.547273) (xy 79.273207 78.445413) (xy 79.22048 78.354087) (xy 79.145913 78.27952)
-				(xy 79.054587 78.226793) (xy 78.952727 78.1995) (xy 78.847273 78.1995) (xy 78.745413 78.226793)
-				(xy 78.74541 78.226794) (xy 78.654085 78.279521) (xy 78.579521 78.354085) (xy 78.526794 78.44541)
-				(xy 78.526793 78.445413) (xy 78.4995 78.547273) (xy 77.590059 78.547273) (xy 77.554587 78.526793)
-				(xy 77.452727 78.4995) (xy 77.347273 78.4995) (xy 77.245413 78.526793) (xy 77.24541 78.526794) (xy 77.154085 78.579521)
+				(xy 77.72048 78.654087) (xy 77.645913 78.57952) (xy 77.554587 78.526793) (xy 77.452727 78.4995)
+				(xy 77.347273 78.4995) (xy 77.245413 78.526793) (xy 77.24541 78.526794) (xy 77.154085 78.579521)
 				(xy 77.079521 78.654085) (xy 77.026794 78.74541) (xy 77.026793 78.745413) (xy 76.9995 78.847273)
 				(xy 59.590059 78.847273) (xy 59.554587 78.826793) (xy 59.452727 78.7995) (xy 59.347273 78.7995)
 				(xy 59.245413 78.826793) (xy 59.24541 78.826794) (xy 59.154085 78.879521) (xy 59.079521 78.954085)
@@ -44463,18 +44583,72 @@ 				(xy 53.013054 77.047273) (xy 58.3995 77.047273) (xy 58.3995 77.152727) (xy 58.426793 77.254587)
 				(xy 58.47952 77.345913) (xy 58.554087 77.42048) (xy 58.645413 77.473207) (xy 58.747273 77.5005)
 				(xy 58.747275 77.5005) (xy 58.852725 77.5005) (xy 58.852727 77.5005) (xy 58.954587 77.473207) (xy 59.045913 77.42048)
-				(xy 59.12048 77.345913) (xy 59.173207 77.254587) (xy 59.2005 77.152727) (xy 59.2005 77.047273) (xy 76.3995 77.047273)
-				(xy 76.3995 77.152727) (xy 76.426793 77.254587) (xy 76.47952 77.345913) (xy 76.554087 77.42048)
-				(xy 76.645413 77.473207) (xy 76.747273 77.5005) (xy 76.747275 77.5005) (xy 76.852725 77.5005) (xy 76.852727 77.5005)
-				(xy 76.954587 77.473207) (xy 77.045913 77.42048) (xy 77.12048 77.345913) (xy 77.173207 77.254587)
-				(xy 77.2005 77.152727) (xy 77.2005 77.047273) (xy 77.173207 76.945413) (xy 77.12048 76.854087) (xy 77.045913 76.77952)
-				(xy 76.954587 76.726793) (xy 76.852727 76.6995) (xy 76.747273 76.6995) (xy 76.645413 76.726793)
-				(xy 76.64541 76.726794) (xy 76.554085 76.779521) (xy 76.479521 76.854085) (xy 76.426794 76.94541)
-				(xy 76.426793 76.945413) (xy 76.3995 77.047273) (xy 59.2005 77.047273) (xy 59.173207 76.945413)
+				(xy 59.12048 77.345913) (xy 59.173207 77.254587) (xy 59.2005 77.152727) (xy 59.2005 77.047273) (xy 59.173207 76.945413)
 				(xy 59.12048 76.854087) (xy 59.045913 76.77952) (xy 58.954587 76.726793) (xy 58.852727 76.6995)
 				(xy 58.747273 76.6995) (xy 58.645413 76.726793) (xy 58.64541 76.726794) (xy 58.554085 76.779521)
 				(xy 58.479521 76.854085) (xy 58.426794 76.94541) (xy 58.426793 76.945413) (xy 58.3995 77.047273)
-				(xy 53.013054 77.047273) (xy 57.213054 72.847273) (xy 65.5995 72.847273) (xy 65.5995 72.952727)
+				(xy 53.013054 77.047273) (xy 56.026219 74.034108) (xy 74.3495 74.034108) (xy 74.3495 74.165891)
+				(xy 74.383608 74.293187) (xy 74.416554 74.35025) (xy 74.4495 74.407314) (xy 74.449502 74.407316)
+				(xy 76.609482 76.567296) (xy 76.642967 76.628619) (xy 76.637983 76.698311) (xy 76.596111 76.754244)
+				(xy 76.583804 76.762363) (xy 76.554084 76.779522) (xy 76.479521 76.854085) (xy 76.426794 76.94541)
+				(xy 76.426793 76.945413) (xy 76.3995 77.047273) (xy 76.3995 77.152727) (xy 76.426793 77.254587)
+				(xy 76.47952 77.345913) (xy 76.554087 77.42048) (xy 76.645413 77.473207) (xy 76.747273 77.5005)
+				(xy 76.747275 77.5005) (xy 76.852725 77.5005) (xy 76.852727 77.5005) (xy 76.954587 77.473207) (xy 77.045913 77.42048)
+				(xy 77.12048 77.345913) (xy 77.137637 77.316196) (xy 77.188201 77.267983) (xy 77.256808 77.254759)
+				(xy 77.321673 77.280727) (xy 77.332703 77.290517) (xy 77.7495 77.707314) (xy 77.842686 77.8005)
+				(xy 77.956814 77.866392) (xy 78.063734 77.89504) (xy 78.119319 77.927133) (xy 78.50066 78.308474)
+				(xy 78.534145 78.369797) (xy 78.529161 78.439489) (xy 78.527546 78.443593) (xy 78.526795 78.445404)
+				(xy 78.504987 78.526794) (xy 78.4995 78.547273) (xy 78.4995 78.652727) (xy 78.526793 78.754587)
+				(xy 78.57952 78.845913) (xy 78.654087 78.92048) (xy 78.745413 78.973207) (xy 78.847273 79.0005)
+				(xy 78.847275 79.0005) (xy 78.952725 79.0005) (xy 78.952727 79.0005) (xy 79.054587 78.973207) (xy 79.054593 78.973203)
+				(xy 79.056387 78.972461) (xy 79.058028 78.972284) (xy 79.062438 78.971103) (xy 79.062622 78.97179)
+				(xy 79.125856 78.964989) (xy 79.188336 78.996262) (xy 79.191525 78.999339) (xy 84.7995 84.607314)
+				(xy 84.892686 84.7005) (xy 85.006814 84.766392) (xy 85.134108 84.8005) (xy 103.841324 84.8005) (xy 103.908363 84.820185)
+				(xy 103.929005 84.836819) (xy 103.942686 84.8505) (xy 104.056814 84.916392) (xy 104.184108 84.9505)
+				(xy 163.4755 84.9505) (xy 163.542539 84.970185) (xy 163.588294 85.022989) (xy 163.5995 85.0745)
+				(xy 163.5995 86.004258) (xy 163.602354 86.034698) (xy 163.602354 86.034699) (xy 163.647206 86.162881)
+				(xy 163.647207 86.162882) (xy 163.72785 86.27215) (xy 163.837118 86.352793) (xy 163.965302 86.397646)
+				(xy 163.965301 86.397646) (xy 163.969271 86.398018) (xy 163.995735 86.4005) (xy 166.004264 86.400499)
+				(xy 166.034698 86.397646) (xy 166.162882 86.352793) (xy 166.27215 86.27215) (xy 166.352793 86.162882)
+				(xy 166.397646 86.034698) (xy 166.4005 86.004265) (xy 166.400499 84.888575) (xy 166.8 84.888575)
+				(xy 166.8 85.111424) (xy 166.829085 85.332354) (xy 166.829088 85.332367) (xy 166.886763 85.547618)
+				(xy 166.972045 85.753502) (xy 166.972054 85.75352) (xy 167.083464 85.946491) (xy 167.083473 85.946504)
+				(xy 167.13404 86.012403) (xy 167.134043 86.012403) (xy 167.935387 85.211059) (xy 167.940889 85.231591)
+				(xy 168.019881 85.368408) (xy 168.131592 85.480119) (xy 168.268409 85.559111) (xy 168.28894 85.564612)
+				(xy 167.487595 86.365955) (xy 167.487595 86.365956) (xy 167.553507 86.416533) (xy 167.746485 86.527949)
+				(xy 167.746497 86.527954) (xy 167.952381 86.613236) (xy 168.167632 86.670911) (xy 168.167645 86.670914)
+				(xy 168.388575 86.7) (xy 168.611425 86.7) (xy 168.832354 86.670914) (xy 168.832367 86.670911) (xy 169.047618 86.613236)
+				(xy 169.253502 86.527954) (xy 169.253514 86.527949) (xy 169.446498 86.41653) (xy 169.512403 86.365957)
+				(xy 169.512404 86.365956) (xy 168.711059 85.564612) (xy 168.731591 85.559111) (xy 168.868408 85.480119)
+				(xy 168.980119 85.368408) (xy 169.059111 85.231591) (xy 169.064612 85.211059) (xy 169.865956 86.012404)
+				(xy 169.865957 86.012403) (xy 169.91653 85.946498) (xy 170.027949 85.753514) (xy 170.027954 85.753502)
+				(xy 170.113236 85.547618) (xy 170.170911 85.332367) (xy 170.170914 85.332354) (xy 170.2 85.111424)
+				(xy 170.2 84.888575) (xy 170.170914 84.667645) (xy 170.170911 84.667632) (xy 170.113236 84.452381)
+				(xy 170.027954 84.246497) (xy 170.027949 84.246485) (xy 169.916533 84.053507) (xy 169.865956 83.987595)
+				(xy 169.865955 83.987595) (xy 169.064612 84.788939) (xy 169.059111 84.768409) (xy 168.980119 84.631592)
+				(xy 168.868408 84.519881) (xy 168.731591 84.440889) (xy 168.711058 84.435387) (xy 169.512403 83.634043)
+				(xy 169.512403 83.63404) (xy 169.446504 83.583473) (xy 169.446491 83.583464) (xy 169.25352 83.472054)
+				(xy 169.253502 83.472045) (xy 169.047618 83.386763) (xy 168.832367 83.329088) (xy 168.832354 83.329085)
+				(xy 168.611425 83.3) (xy 168.388575 83.3) (xy 168.167645 83.329085) (xy 168.167632 83.329088) (xy 167.952381 83.386763)
+				(xy 167.746497 83.472045) (xy 167.746479 83.472054) (xy 167.553511 83.583462) (xy 167.487595 83.634042)
+				(xy 168.288941 84.435387) (xy 168.268409 84.440889) (xy 168.131592 84.519881) (xy 168.019881 84.631592)
+				(xy 167.940889 84.768409) (xy 167.935387 84.78894) (xy 167.134042 83.987595) (xy 167.083462 84.053511)
+				(xy 166.972054 84.246479) (xy 166.972045 84.246497) (xy 166.886763 84.452381) (xy 166.829088 84.667632)
+				(xy 166.829085 84.667645) (xy 166.8 84.888575) (xy 166.400499 84.888575) (xy 166.400499 83.995736)
+				(xy 166.397646 83.965302) (xy 166.352793 83.837118) (xy 166.27215 83.72785) (xy 166.162882 83.647207)
+				(xy 166.162881 83.647206) (xy 166.034695 83.602353) (xy 166.034698 83.602353) (xy 166.004268 83.5995)
+				(xy 163.995741 83.5995) (xy 163.965301 83.602354) (xy 163.9653 83.602354) (xy 163.837118 83.647206)
+				(xy 163.727851 83.727849) (xy 163.72785 83.72785) (xy 163.647207 83.837118) (xy 163.63694 83.866456)
+				(xy 163.596221 83.92323) (xy 163.531269 83.948978) (xy 163.519901 83.9495) (xy 104.508676 83.9495)
+				(xy 104.441637 83.929815) (xy 104.420995 83.913181) (xy 104.407316 83.899502) (xy 104.407314 83.8995)
+				(xy 104.350077 83.866454) (xy 104.293187 83.833608) (xy 104.229539 83.816554) (xy 104.165892 83.7995)
+				(xy 104.165891 83.7995) (xy 85.458676 83.7995) (xy 85.391637 83.779815) (xy 85.370995 83.763181)
+				(xy 78.607316 76.999502) (xy 78.607314 76.9995) (xy 78.513628 76.94541) (xy 78.493187 76.933608)
+				(xy 78.444393 76.920534) (xy 78.386266 76.904959) (xy 78.33068 76.872866) (xy 75.157316 73.699502)
+				(xy 75.157314 73.6995) (xy 75.10025 73.666554) (xy 75.043187 73.633608) (xy 74.979539 73.616554)
+				(xy 74.915892 73.5995) (xy 74.784108 73.5995) (xy 74.656812 73.633608) (xy 74.542686 73.6995) (xy 74.542683 73.699502)
+				(xy 74.449502 73.792683) (xy 74.4495 73.792686) (xy 74.383608 73.906812) (xy 74.3495 74.034108)
+				(xy 56.026219 74.034108) (xy 57.213054 72.847273) (xy 65.5995 72.847273) (xy 65.5995 72.952727)
 				(xy 65.626793 73.054587) (xy 65.67952 73.145913) (xy 65.754087 73.22048) (xy 65.845413 73.273207)
 				(xy 65.947273 73.3005) (xy 65.947275 73.3005) (xy 66.052725 73.3005) (xy 66.052727 73.3005) (xy 66.154587 73.273207)
 				(xy 66.245913 73.22048) (xy 66.31912 73.147273) (xy 71.2995 73.147273) (xy 71.2995 73.252727) (xy 71.326793 73.354587)
@@ -46403,7 +46577,14 @@ 				(xy 35.2005 75.847273) (xy 35.173207 75.745413) (xy 35.12048 75.654087) (xy 35.045913 75.57952)
 				(xy 34.954587 75.526793) (xy 34.852727 75.4995) (xy 34.747273 75.4995) (xy 34.645413 75.526793)
 				(xy 34.64541 75.526794) (xy 34.554085 75.579521) (xy 34.479521 75.654085) (xy 34.426794 75.74541)
-				(xy 34.426793 75.745413) (xy 34.3995 75.847273) (xy 3.5005 75.847273) (xy 3.5005 72.847273) (xy 65.5995 72.847273)
+				(xy 34.426793 75.745413) (xy 34.3995 75.847273) (xy 3.5005 75.847273) (xy 3.5005 74.047273) (xy 74.4495 74.047273)
+				(xy 74.4495 74.152727) (xy 74.476793 74.254587) (xy 74.52952 74.345913) (xy 74.604087 74.42048)
+				(xy 74.695413 74.473207) (xy 74.797273 74.5005) (xy 74.797275 74.5005) (xy 74.902725 74.5005) (xy 74.902727 74.5005)
+				(xy 75.004587 74.473207) (xy 75.095913 74.42048) (xy 75.17048 74.345913) (xy 75.223207 74.254587)
+				(xy 75.2505 74.152727) (xy 75.2505 74.047273) (xy 75.223207 73.945413) (xy 75.17048 73.854087) (xy 75.095913 73.77952)
+				(xy 75.004587 73.726793) (xy 74.902727 73.6995) (xy 74.797273 73.6995) (xy 74.695413 73.726793)
+				(xy 74.69541 73.726794) (xy 74.604085 73.779521) (xy 74.529521 73.854085) (xy 74.476794 73.94541)
+				(xy 74.476793 73.945413) (xy 74.4495 74.047273) (xy 3.5005 74.047273) (xy 3.5005 72.847273) (xy 65.5995 72.847273)
 				(xy 65.5995 72.952727) (xy 65.626793 73.054587) (xy 65.67952 73.145913) (xy 65.754087 73.22048)
 				(xy 65.845413 73.273207) (xy 65.947273 73.3005) (xy 65.947275 73.3005) (xy 66.052725 73.3005) (xy 66.052727 73.3005)
 				(xy 66.154587 73.273207) (xy 66.245913 73.22048) (xy 66.31912 73.147273) (xy 71.2995 73.147273)