"""Figures for the n18/n19 interacting-arena folio (Le Sage II).
All numbers are measured outputs of n18-rust (see conversation of record:
G1 three-size scan, NEWTON range & mass law, BUDGET, MINIMAL).
House palette: accent #b03a2e, ok #2e6b46, ink #1a1a1a, muted #6b6b6b.
"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np

ACC, OK, INK, MUT = "#b03a2e", "#2e6b46", "#1a1a1a", "#6b6b6b"
plt.rcParams.update({
    "font.size": 11, "axes.edgecolor": MUT, "axes.labelcolor": INK,
    "xtick.color": MUT, "ytick.color": MUT, "axes.spines.top": False,
    "axes.spines.right": False, "svg.fonttype": "none",
    "figure.facecolor": "white", "axes.facecolor": "white",
})

def grid(ax):
    ax.grid(True, alpha=0.25, linewidth=0.6)
    ax.set_axisbelow(True)

# ---------------------------------------------------------------- fig A ---
g = np.array([0.0, 0.01, 0.03, 0.1, 0.3, 1.0])
F256 = np.array([-1.3152e-5, -1.1160e-5, -1.7698e-5, -3.4622e-5, 2.3960e-5, 6.0173e-4])
F512 = np.array([-1.3092e-5, -1.0913e-5, -1.3703e-5, -2.2711e-5, 3.2944e-5, 5.9996e-4])
F1024 = {0.0: -1.3073e-5, 1.0: 5.9988e-4}

fig, (a1, a2) = plt.subplots(1, 2, figsize=(9.6, 3.9), constrained_layout=True)
a1.axhline(0, color=MUT, linewidth=0.8)
a1.plot(g, F256, "o-", color=MUT, markersize=5, linewidth=1.6, label="N = 256")
a1.plot(g, F512, "s-", color=ACC, markersize=5, linewidth=1.6, label="N = 512")
a1.plot(list(F1024), list(F1024.values()), "D", color=INK, markersize=6,
        label="N = 1024", zorder=5)
a1.set_xscale("symlog", linthresh=0.008)
a1.set_yscale("symlog", linthresh=2e-5)
a1.set_xlabel("interaction  g")
a1.set_ylabel("F between record-keeping grains")
a1.set_title("The sign flip: records attract when the medium interacts", fontsize=11)
a1.legend(frameon=False, loc="upper left", fontsize=9)
a1.annotate("repulsion (n13, linear medium)", xy=(0.02, -3.2e-5), fontsize=8.5,
            color=MUT, ha="center")
a1.annotate("attraction", xy=(0.25, 1.3e-4), fontsize=8.5, color=ACC)
grid(a1)

sizes = [256, 512, 1024]
Fg1 = np.array([6.0173e-4, 5.9996e-4, 5.9988e-4]) * 1e4
a2.plot(sizes, Fg1, "o-", color=ACC, markersize=7, linewidth=1.6)
a2.set_xscale("log", base=2)
a2.set_xticks(sizes); a2.set_xticklabels(["256", "512", "1024"])
a2.set_xlim(200, 1400)
a2.set_ylim(5.90, 6.10)
a2.set_xlabel("lattice size N")
a2.set_ylabel("F at g = 1  (×10⁻⁴)")
a2.set_title("Three box doublings: stable to 0.03%", fontsize=11)
for s, f in zip(sizes, Fg1):
    a2.annotate(f"{f:.3f}", xy=(s, f), xytext=(0, 9),
                textcoords="offset points", ha="center", fontsize=8.5, color=INK)
grid(a2)
fig.savefig("figs/interacting-flip.svg")
fig.savefig("/private/tmp/claude-501/-Users-antoine-agi-website/4fd9d383-f580-4a59-b059-29f286ea0be2/scratchpad/figA.png", dpi=110)
plt.close(fig)

# ---------------------------------------------------------------- fig B ---
d = np.array([16, 24, 32, 48, 64, 96])
dF = np.array([3.7201e-4, 6.1306e-4, 6.3891e-4, 6.4058e-4, 6.0319e-4, 5.1952e-4])

fig, (b1, b2) = plt.subplots(1, 2, figsize=(9.6, 3.9), constrained_layout=True)
b1.plot(d, dF * 1e4, "o-", color=ACC, markersize=6, linewidth=1.6)
b1.axhspan(6.03e-4 * 1e4, 6.41e-4 * 1e4, color=OK, alpha=0.12)
b1.annotate("plateau ±5% over d = 24–64\n(the 1D gravity law: constant force)",
            xy=(40, 6.55), fontsize=8.5, color=OK, ha="center")
b1.annotate("screening at the\ntransparency length", xy=(88, 5.45), fontsize=8.5,
            color=MUT, ha="center")
b1.set_ylim(0, 7.2)
b1.set_xlabel("separation d (sites)")
b1.set_ylabel("induced force dF (×10⁻⁴)")
b1.set_title("The force law (g = 1, N = 512)", fontsize=11)
grid(b1)

dressA = np.array([2.785e-2, 5.098e-2, 9.182e-2, 9.182e-2, 1.646e-1])
dressB = np.array([5.098e-2, 5.098e-2, 5.098e-2, 9.182e-2, 5.098e-2])
dFm = np.array([2.8225e-4, 6.1306e-4, 1.2199e-3, 2.4788e-3, 2.2663e-3])
prod = dressA * dressB
xs = np.linspace(prod.min() * 0.7, prod.max() * 1.3, 10)
b2.plot(xs, 0.25 * xs, "--", color=MUT, linewidth=1.2, label="F = G·m_A·m_B  (G = 0.25)")
b2.plot(prod, dFm, "o", color=ACC, markersize=7)
b2.set_xscale("log"); b2.set_yscale("log")
b2.set_xlabel("dressing product  m_A · m_B")
b2.set_ylabel("induced force dF")
b2.set_title("The mass law: bilinear to ±20% over ×5.9", fontsize=11)
b2.legend(frameon=False, fontsize=9, loc="upper left")
grid(b2)
fig.savefig("figs/newton-laws.svg")
fig.savefig("/private/tmp/claude-501/-Users-antoine-agi-website/4fd9d383-f580-4a59-b059-29f286ea0be2/scratchpad/figB.png", dpi=110)
plt.close(fig)

# ---------------------------------------------------------------- fig C ---
fig, (c1, c2) = plt.subplots(1, 2, figsize=(9.6, 3.9), constrained_layout=True)

labels = ["exact force", "static\n(frozen dressings)", "contact\n(cloud overlap)",
          "dynamic\n(flux × response)"]
v24 = np.array([6.1306e-4, -1.5120e-4, -4.0081e-5, 8.0434e-4]) * 1e4
v48 = np.array([6.4058e-4, -1.1235e-4, -6.2735e-5, 8.1567e-4]) * 1e4
ypos = np.arange(4)[::-1]
c1.barh(ypos + 0.19, v24, height=0.34, color=[INK, MUT, MUT, ACC], alpha=0.95)
c1.barh(ypos - 0.19, v48, height=0.34, color=[INK, MUT, MUT, ACC], alpha=0.55)
c1.axvline(0, color=MUT, linewidth=0.8)
c1.set_yticks(ypos); c1.set_yticklabels(labels, fontsize=9)
c1.set_xlabel("force (×10⁻⁴)   dark = d 24, light = d 48")
c1.set_title("Budget: the dynamic term carries it all", fontsize=11)
grid(c1)

dm = np.array([24, 48, 96])
M0 = np.array([-6.4406e-6, -4.7974e-6, -3.6717e-6]) * 1e4
M1 = np.array([-3.0236e-5, -2.6939e-5, -2.0878e-5]) * 1e4
M2 = np.array([8.7572e-4, 5.7608e-4, 2.1738e-4]) * 1e4
c2.axhline(0, color=MUT, linewidth=0.8)
c2.plot(dm, M2, "o-", color=ACC, linewidth=1.6, markersize=6,
        label="M2: noise in interacting medium")
c2.plot(dm, M1, "s-", color=MUT, linewidth=1.4, markersize=5,
        label="M1: noise, linear medium (pushes)")
c2.plot(dm, M0, "^-", color=OK, linewidth=1.4, markersize=5,
        label="M0: static landscape only")
c2.set_xlabel("separation d (sites)")
c2.set_ylabel("force on passive bump (×10⁻⁴)")
c2.set_title("Dissection: only flux × medium-response attracts", fontsize=11)
c2.legend(frameon=False, fontsize=8.5)
grid(c2)
fig.savefig("figs/mechanism-dissection.svg")
fig.savefig("/private/tmp/claude-501/-Users-antoine-agi-website/4fd9d383-f580-4a59-b059-29f286ea0be2/scratchpad/figC.png", dpi=110)
plt.close(fig)

print("wrote figs/interacting-flip.svg, figs/newton-laws.svg, figs/mechanism-dissection.svg")
