File size: 3,856 Bytes
dfe8a5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bavi Mac Model Forecast</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
  <style>
    html, body, #map { height: 100%; margin: 0; }
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
    .panel { position: absolute; z-index: 1000; top: 16px; left: 16px; width: min(360px, calc(100vw - 32px)); padding: 14px 16px; background: rgba(255,255,255,.96); border: 1px solid #d5d9df; box-shadow: 0 3px 14px rgba(0,0,0,.18); }
    h1 { margin: 0 0 7px; font-size: 20px; }
    p { margin: 5px 0; font-size: 13px; line-height: 1.4; color: #374151; }
    .legend { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 9px; font-size: 12px; color: #374151; }
    .key { display: inline-flex; align-items: center; gap: 5px; }
    .swatch { width: 20px; height: 3px; display: inline-block; }
    .mean { background: #d7263d; }
    .actual { background: #111827; }
    .corridor { width: 20px; height: 10px; background: rgba(245,158,11,.32); border: 1px solid #d97706; }
  </style>
</head>
<body>
  <div id="map"></div>
  <section class="panel">
    <h1>Bavi: Mac checkpoint prediction</h1>
    <p><b>Initial fix:</b> 10 Jul 2026 06:00 UTC, 21.9°N 126.9°E</p>
    <p><b>Run:</b> local Mac Apple MPS, 50 ensemble members, 120-hour horizon</p>
    <p><b>Important:</b> this is a research proxy using a mean-normalized atmospheric field because the matching 2026 ERA5 field is not available locally. It is not an operational warning forecast.</p>
    <div class="legend">
      <span class="key"><i class="swatch actual"></i>official initial fix</span>
      <span class="key"><i class="swatch mean"></i>model mean</span>
      <span class="key"><i class="swatch corridor"></i>10–90% corridor</span>
    </div>
  </section>
  <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
  <script>
    const initial = [21.9, 126.9];
    const forecast = [
      {h: 6, lat: 22.4336, lon: 126.5818, la: 22.3279, lb: 22.5795, oa: 126.4390, ob: 126.7272},
      {h: 12, lat: 22.7873, lon: 126.3022, la: 22.5105, lb: 23.0514, oa: 126.0263, ob: 126.6464},
      {h: 24, lat: 23.8919, lon: 125.4258, la: 23.5613, lb: 24.3624, oa: 124.9874, ob: 125.9527},
      {h: 48, lat: 25.6544, lon: 124.6313, la: 24.6905, lb: 26.3908, oa: 123.1265, ob: 126.0750},
      {h: 72, lat: 26.4361, lon: 123.5473, la: 24.9631, lb: 28.2892, oa: 120.7869, ob: 125.8778},
      {h: 96, lat: 26.6257, lon: 121.9343, la: 24.2808, lb: 28.4809, oa: 118.0243, ob: 126.7538},
      {h: 120, lat: 28.6126, lon: 121.8454, la: 26.2118, lb: 30.8639, oa: 117.2112, ob: 126.6462}
    ];
    const map = L.map('map', {worldCopyJump: true}).setView([25, 126], 4);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom: 18, attribution: '&copy; OpenStreetMap contributors'}).addTo(map);
    L.marker(initial).addTo(map).bindPopup('<b>Official initial fix</b><br>21.9°N, 126.9°E<br>10 Jul 2026 06:00 UTC').openPopup();
    const meanLine = [initial];
    forecast.forEach(p => {
      meanLine.push([p.lat, p.lon]);
      L.rectangle([[p.la, p.oa], [p.lb, p.ob]], {color:'#d97706', weight:1, fillColor:'#f59e0b', fillOpacity:.18}).addTo(map).bindTooltip('+' + p.h + 'h model 10–90% box');
      L.circleMarker([p.lat, p.lon], {radius: 5, color:'#d7263d', fillColor:'#d7263d', fillOpacity:1}).addTo(map).bindTooltip('+' + p.h + 'h: ' + p.lat.toFixed(2) + '°N, ' + p.lon.toFixed(2) + '°E');
    });
    L.polyline(meanLine, {color:'#d7263d', weight:4, opacity:.9}).addTo(map);
    L.polyline([initial, [21.9,126.9]], {color:'#111827', weight:5}).addTo(map);
    map.fitBounds(L.latLngBounds(meanLine), {padding: [45, 45]});
  </script>
</body>
</html>