swings = con.sql(f"""
WITH daily AS (
SELECT YEAR(DATE) AS yr, TMAX::DOUBLE AS tmax, TMIN::DOUBLE AS tmin,
LAG(TMIN::DOUBLE, 1) OVER (PARTITION BY YEAR(DATE) ORDER BY DATE) AS p1min,
LAG(TMAX::DOUBLE, 1) OVER (PARTITION BY YEAR(DATE) ORDER BY DATE) AS p1max
FROM read_csv_auto('{CSV}')
WHERE STATION = '{STATION}' AND TMAX IS NOT NULL AND TMIN IS NOT NULL AND {JAN_APR}
)
SELECT yr,
MAX(tmax - p1min) AS max_warm_2d,
MAX(p1max - tmin) AS max_cool_2d
FROM daily WHERE p1min IS NOT NULL
GROUP BY yr HAVING COUNT(*) >= 80
""").df()
fig, ax = plt.subplots(figsize=(7, 6))
is2026 = swings['yr'] == 2026
ax.scatter(swings.loc[~is2026, 'max_warm_2d'], swings.loc[~is2026, 'max_cool_2d'],
c='#2c3e50', alpha=0.5, s=40, label='Other years')
ax.scatter(swings.loc[is2026, 'max_warm_2d'], swings.loc[is2026, 'max_cool_2d'],
c='#c0392b', s=120, zorder=5, edgecolors='black', label='2026')
ax.annotate('2026', (float(swings.loc[is2026, 'max_warm_2d'].iloc[0]),
float(swings.loc[is2026, 'max_cool_2d'].iloc[0])),
textcoords="offset points", xytext=(10, 5), fontsize=11, fontweight='bold', color='#c0392b')
# Reference lines at means
ax.axvline(swings['max_warm_2d'].mean(), color='gray', ls=':', alpha=0.5)
ax.axhline(swings['max_cool_2d'].mean(), color='gray', ls=':', alpha=0.5)
ax.text(swings['max_warm_2d'].mean() + 0.5, ax.get_ylim()[0] + 1, 'avg warming', fontsize=8, color='gray')
ax.text(ax.get_xlim()[0] + 0.5, swings['max_cool_2d'].mean() + 0.5, 'avg cooling', fontsize=8, color='gray')
ax.set_xlabel('Max 2-Day Warming Swing (°F)')
ax.set_ylabel('Max 2-Day Cooling Swing (°F)')
ax.set_title('Warming vs. Cooling: 2026 is Extreme Only on the Cool Side')
ax.legend(fontsize=9)
plt.tight_layout()
plt.show()