ax1.annotate(label, (np.log10(R), np.log10(M)),
textcoords="offset points", xytext=(8, 6), fontsize=10)
# Cascade annotations
x_ann = 5.0
y_proton = x_ann + intercept(h, 6256.33)
y_earth = x_ann + intercept(h_S, 0.5522974)
y_gal_sat = x_ann + intercept(h_G, 0.115457)
y_gal_ast = x_ann + intercept(h_G, 0.4149)
y_gal_mid = 0.5 * (y_gal_sat + y_gal_ast)
# Arrow: proton level -> Earth level
ax1.annotate("", xy=(x_ann, y_earth), xytext=(x_ann, y_proton),
arrowprops=dict(arrowstyle="<->", color="black", lw=1.4))
ax1.text(x_ann + 0.7, 0.5 * (y_proton + y_earth),
r"$\mathcal{S}_{0\to1}^{\,2}\approx 2.8\times 10^{67}$",
fontsize=11, va="center")
# Arrow: Earth level -> galaxy level
ax1.annotate("", xy=(x_ann, y_gal_mid), xytext=(x_ann, y_earth),
arrowprops=dict(arrowstyle="<->", color="black", lw=1.4))
ax1.text(x_ann + 0.7, y_earth + 1.5,
r"$\mathcal{S}_{1\to2}^{\,2}\approx 1.65\times 10^{7}$",
fontsize=11, va="bottom")
ax1.set_xlabel(r"$\log_{10}(R\ /\ \mathrm{m})$", fontsize=12)
ax1.set_ylabel(r"$\log_{10}(M\ /\ \mathrm{kg})$", fontsize=12)
ax1.set_title("Full cascade: particle $\\to$ Earth $\\to$ galaxy", fontsize=13)
ax1.grid(True, alpha=0.3)
ax1.legend(loc="lower right", fontsize=8)
# ---------- Panel 2: zoom on astrophysical levels ----------
R_grid2 = np.logspace(-2, 22, 300)
for h_s, kappa, label, color in lines:
M_grid = (R_grid2 / t1) * np.sqrt(np.pi * h_s / (G * c)) * kappa
ax2.plot(np.log10(R_grid2), np.log10(M_grid),
color=color, lw=1.8, label=label)
for label, R, M, color, marker in bodies:
if label in ("Earth", "Sun", "Galaxy"):
ax2.scatter(np.log10(R), np.log10(M), s=110,
color=color, marker=marker, edgecolor="black", zorder=5)
ax2.annotate(label, (np.log10(R), np.log10(M)),