--- title: "Has the Overton Window Shifted?" subtitle: "Acceptance Through Moderation in the Dutch Tweede Kamer (2016–2026)" author: "Stemwijzer Analysis" date: today format: html jupyter: python3 --- ```{python} #| label: setup #| include: false import duckdb import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots from pathlib import Path ROOT = Path(".").resolve().parents[1] DB_PATH = str(ROOT / "data" / "motions.db") con = duckdb.connect(DB_PATH, read_only=True) BREAK_YEAR = 2024 PARTY_COLOURS = { "VVD": "#1E73BE", "PVV": "#002366", "D66": "#00A36C", "CDA": "#4CAF50", "CU": "#0288D1", "NSC": "#FF8F00", "SGP": "#F4511E", "FVD": "#6A1B9A", "JA21": "#7B1FA2", "BBB": "#8D6E63", "SP": "#E53935", "GroenLinks-PvdA": "#2E7D32", "PvdD": "#43A047", "Volt": "#572AB7", "DENK": "#00897B", } ``` > **Verdict:** The Overton window widened — more right-wing positions became > politically acceptable. But the mechanism was right-wing moderation, not > centrist conversion. The effect may be temporary. ## Introduction Did the PVV's November 2023 election victory shift the Dutch Overton window? The conventional narrative is clear: a far-right party won the largest share of seats, entered government for the first time in July 2024, and the political center responded by adopting more right-wing positions. Centrist parties, according to this story, moved right to accommodate the new political reality. The data tells a different story. Using 29,591 Tweede Kamer motions with full MP-level vote records, Procrustes-aligned SVD spatial analysis, and 2D extremity scoring (stijl-extremiteit vs materiële impact), we find that **the Overton window widened**: centrist support for right-wing motions surged from 25% to 51%, while centrist support for left-wing motions stayed flat at 49%. What changed was the behavior of right-wing parties: they filed more motions, with milder content, framed in centrist-friendly language. Centrist voting support surged from 0.251 to 0.507 (Cohen's d = +0.65), but centrists did not become more right-wing — they stayed ideologically left while voting more permissively on proposals that had become less materially consequential. This article presents the evidence across three indicators — centrist voting support, SVD spatial divergence, and 2D extremity decomposition — and examines the mechanisms through which right-wing motions gained centrist support. ## About Stemwijzer Stemwijzer is a data-driven political compass built from real parliamentary voting records. It analyzes 29,591 motions from the Tweede Kamer (2016–2026), each with per-MP vote records, to compute latent political dimensions using Singular Value Decomposition (SVD). Users vote on real motions and find which MPs match their positions — not based on party manifestos or campaign promises, but on how representatives actually voted. The platform tracks party positions across 11 annual windows using Procrustes-aligned SVD, allowing year-over-year comparison of spatial drift. Every motion has been scored on two independent dimensions of extremity: **stijl-extremiteit** (stylistic rhetoric, 1–5) and **materiële impact** (material policy consequence, 1–5), manually validated with 75% auditor agreement. The Overton analysis presented here builds on this infrastructure. The same SVD compass, extremity scores, and vote-level data that power the Stemwijzer Explorer dashboard drive these findings. ## Methodology **Right-wing motion classification.** We identify right-wing motions using a hybrid keyword + voting-pattern classifier. A seed set of right-wing keywords (vuurwerkverbod, stikstof, nareis, etc.) is expanded through an iterative keyword-vote loop — motions whose voting pattern correlates with right-wing party support are flagged, their distinctive terms extracted, and the keyword set refined. The final classifier identifies 3,030 motions as right-wing across 2016–2026, with full voting records for centrist support computation. **2D extremity scoring.** Every motion in the database (29,591) has been scored by an LLM on two dimensions: *stijl-extremiteit* (stylistic extremity: inflammatory language, rhetorical framing) and *materiële impact* (material impact: rights restriction, institutional change, resource reallocation), each on a 1–5 scale. Manual audit of 117 stratified motions achieved 75% agreement. The two dimensions are only moderately correlated (Pearson r = 0.43 for all motions, r = 0.47 for right-wing), confirming they capture distinct phenomena. **Strict centrist definition.** We define the centrist bloc narrowly as four parties — D66, CDA, ChristenUnie, NSC — excluding VVD and BBB, which lean center-right and would inflate centrist support mechanically. A strict opposition-only filter further controls for coalition effects by excluding motions whose lead submitter belongs to the governing coalition. **SVD alignment.** Party positions are computed via SVD on annual voting matrices and aligned using chained Procrustes orthogonal rotation followed by global PCA, placing all annual party positions in a common 2D reference frame. Centrist and right-wing centers of gravity are computed as the mean of party-level axis scores within each bloc. ```{python} #| label: chart-1-yearly-cs #| fig-cap: "Centrist Support for Right-Wing Motions Over Time (2016–2026)" #| column: page yearly = con.execute(""" SELECT year, AVG(centrist_support_strict) AS mean_cs, STDDEV(centrist_support_strict) AS std_cs, COUNT(*) AS n FROM right_wing_motions WHERE classified = TRUE GROUP BY year ORDER BY year """).fetchdf() fig1 = go.Figure() fig1.add_trace(go.Scatter( x=yearly["year"], y=yearly["mean_cs"], mode="lines+markers", name="All right-wing", line=dict(color="#002366", width=3), marker=dict(size=8), error_y=dict( type="data", array=1.96 * yearly["std_cs"] / np.sqrt(yearly["n"]), visible=True, thickness=0.8, width=2 ) )) pre = yearly[yearly["year"] < BREAK_YEAR] post = yearly[yearly["year"] >= BREAK_YEAR] fig1.add_hline( y=pre["mean_cs"].mean(), line_dash="dot", line_color="#90CAF9", annotation_text=f"Pre-2024 mean ({pre['mean_cs'].mean():.3f})" ) fig1.add_hline( y=post["mean_cs"].mean(), line_dash="dot", line_color="#1E88E5", annotation_text=f"Post-2024 mean ({post['mean_cs'].mean():.3f})" ) fig1.add_vline( x=BREAK_YEAR - 0.5, line_dash="dot", line_color="black", opacity=0.5 ) fig1.update_layout( title="Centrist Support (Strict) for Right-Wing Motions", xaxis=dict(title="Year", dtick=1), yaxis=dict(title="Centrist Support (fraction of parties)", range=[0, 1.1]), legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), template="plotly_white", height=450, ) fig1.show() ``` ## Indicator 1: Centrist Voting Support The cleanest signal is in how centrist parties voted on right-wing motions. Average support rose from 0.251 pre-2024 to 0.507 post-2024 — a Cohen's d of +0.65, a medium-to-large effect. The breakpoint is unmistakably 2024. This is not a coalition artifact. After the Schoof cabinet formed in July 2024, PVV entered government, which could mechanically inflate support for its own motions. When we restrict analysis to opposition-only right-wing motions (lead submitter outside the governing coalition), the effect is larger: d = +0.85, with support jumping from 0.270 to 0.543. Centrist parties are genuinely more willing to support right-wing motions than they were before 2024, even when those motions come from opposition right-wing parties. The gradient across extremity levels persists: centrists still differentiate by how radical a motion is, but at a consistently higher baseline. High-extremity motions gained proportionally more support than mild motions, consistent with genuine tolerance expansion rather than compositional shift. **Pass rate is useless as an indicator.** Dutch parliament passes 96%+ of motions in both periods. With near-zero variance, pass rate cannot register a shift of any magnitude. Centrist support among MPs is the meaningful behavioral measure. ```{python} #| label: chart-2-gravity #| fig-cap: "Gravity-Controlled Centrist Support by Material Impact Level, Pre vs Post 2024" #| column: page gravity = con.execute(""" SELECT CASE WHEN r.year < 2024 THEN 'pre-2024' ELSE 'post-2024' END AS period, e.materiele_impact AS m_level, AVG(r.centrist_support_strict) AS cs, COUNT(*) AS n FROM right_wing_motions r JOIN extremity_scores_all e ON r.motion_id = e.motion_id WHERE r.classified = TRUE AND e.materiele_impact IS NOT NULL GROUP BY period, m_level ORDER BY period, m_level """).fetchdf() levels = sorted(gravity["m_level"].unique()) pre_vals = gravity[gravity["period"] == "pre-2024"].set_index("m_level") post_vals = gravity[gravity["period"] == "post-2024"].set_index("m_level") fig2 = go.Figure() fig2.add_trace(go.Bar( name="Pre-2024", x=[f"M={l}" for l in levels], y=[pre_vals.loc[l, "cs"] if l in pre_vals.index else 0 for l in levels], marker_color="#90CAF9", text=[f"N={int(pre_vals.loc[l, 'n'])}" if l in pre_vals.index else "" for l in levels], textposition="outside", offset=0, )) fig2.add_trace(go.Bar( name="Post-2024", x=[f"M={l}" for l in levels], y=[post_vals.loc[l, "cs"] if l in post_vals.index else 0 for l in levels], marker_color="#1E88E5", text=[f"N={int(post_vals.loc[l, 'n'])}" if l in post_vals.index else "" for l in levels], textposition="outside", offset=0.3, )) fig2.update_layout( title="Gravity-Controlled Centrist Support by Material Impact", xaxis=dict(title="Material Impact Level"), yaxis=dict(title="Centrist Support", range=[0, 1.1]), barmode="group", template="plotly_white", height=450, legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01), ) fig2.show() ``` The gravity-controlled chart reveals a critical pattern: the centrist support shift is real at **every** material impact level. From M=1 (mild procedural adjustments, +0.292) to M=5 (systemic overhaul, +0.122), centrist support rose across the board. The largest absolute gains came from the middle range (M=2: +0.205, M=3: +0.219, M=4: +0.267), where most right-wing motions cluster. Comparing right-wing motions against all other motions confirms the shift is specific: right-wing centrist support surged by +0.236, while non-right-wing motions remained essentially flat (−0.006). This is a right-wing-specific phenomenon, not a general parliamentary trend. ## Indicator 2: Spatial Divergence If centrists are voting more with right-wing motions, one might expect ideological convergence — centrist parties drifting rightward on the SVD compass. Procrustes-aligned SVD analysis shows the opposite. ```{python} #| label: chart-3-svd #| fig-cap: "SVD Trajectories: Centrist vs Right-Wing Centers of Gravity (2016–2026)" #| column: page svd = con.execute(""" SELECT * FROM overton_svd_center ORDER BY window_id """).fetchdf() fig3 = go.Figure() fig3.add_trace(go.Scatter( x=svd["centrist_mean_axis1"], y=svd["centrist_mean_axis2"], mode="lines+markers+text", name="Centrist center", line=dict(color="#00A36C", width=2), marker=dict(size=8, symbol="circle"), text=svd["window_id"], textposition="top center", )) fig3.add_trace(go.Scatter( x=svd["right_mean_axis1"], y=svd["right_mean_axis2"], mode="lines+markers+text", name="Right-wing center", line=dict(color="#002366", width=2), marker=dict(size=8, symbol="square"), text=svd["window_id"], textposition="bottom center", )) fig3.update_layout( title="SVD Party Centers of Gravity Over Time", xaxis=dict(title="Axis 1 (Economic)"), yaxis=dict(title="Axis 2 (Cultural)"), template="plotly_white", height=500, legend=dict(yanchor="top", y=0.99, xanchor="right", x=0.99), hovermode="closest", ) fig3.show() ``` Between the first and last annual windows: - **Centrists moved left on both axes:** −0.223 on the economic axis (more welfare-oriented) and +0.081 on the cultural axis (more kosmopolitisch). - **Right-wing parties moved further right culturally:** −0.065 on the cultural axis (more nationalist). - **The cultural distance between centrists and right-wing parties widened** from 0.282 to 0.428 (+0.146). This is spatial divergence, not convergence. Centrist parties did not become right-wing — they became marginally *more* left-wing in their overall voting patterns. The centrist center of gravity moved toward welfare and cosmopolitanism, while right-wing parties moved further into the nationalist corner. **Why this makes sense with the voting data:** The SVD captures the *full* voting landscape — including all motions, not just the ones centrists supported. Right-wing parties continued filing high-impact motions that centrists opposed, while simultaneously filing a much larger volume of milder motions centrists supported. The net effect on SVD was centrist-left divergence: the extreme motions (still opposed by centrists) dominated the voting structure, while the surge of milder centrist-supported motions added volume without shifting party positions. This is "acceptance without conversion" — centrists vote more with right-wing motions while moving further from them ideologically. ## Indicator 3: Content Moderation The original single-dimensional extremity score showed no increase post-2024 (d = −0.09, from 2.21 to 2.15). If the Overton window shifted, why didn't right-wing motions become more radical? The answer lies in what the single score measured. Two-dimensional rescoring of all 29,591 motions reveals that stylistic extremity and material impact are only moderately correlated (r = 0.43). When tracked separately over time, they tell different stories. ```{python} #| label: chart-4-2d-extremity #| fig-cap: "2D Extremity Over Time: Stijl vs Materieel (Right-Wing Motions, 2019–2026)" #| column: page extremity_2d = con.execute(""" SELECT r.year, AVG(e.stijl_extremiteit) AS mean_stijl, AVG(e.materiele_impact) AS mean_mat, COUNT(*) AS n FROM right_wing_motions r JOIN extremity_scores_all e ON r.motion_id = e.motion_id WHERE r.classified = TRUE AND r.year >= 2019 GROUP BY r.year ORDER BY r.year """).fetchdf() all_stijl, all_mat = con.execute(""" SELECT AVG(stijl_extremiteit), AVG(materiele_impact) FROM extremity_scores_all """).fetchone() fig4 = make_subplots( rows=1, cols=2, subplot_titles=("Stylistic Extremity (Stijl)", "Material Impact (Materieel)"), shared_yaxes=False, ) fig4.add_trace( go.Scatter( x=extremity_2d["year"], y=extremity_2d["mean_stijl"], mode="lines+markers", name="Right-wing", line=dict(color="#6A1B9A", width=3), marker=dict(size=8), ), row=1, col=1, ) fig4.add_hline( y=all_stijl, line_dash="dot", line_color="#9E9E9E", annotation_text=f"All motions ({all_stijl:.2f})", row=1, col=1, ) fig4.add_trace( go.Scatter( x=extremity_2d["year"], y=extremity_2d["mean_mat"], mode="lines+markers", name="Right-wing", line=dict(color="#E53935", width=3), marker=dict(size=8), ), row=1, col=2, ) fig4.add_hline( y=all_mat, line_dash="dot", line_color="#9E9E9E", annotation_text=f"All motions ({all_mat:.2f})", row=1, col=2, ) fig4.update_layout( title="2D Extremity Decomposition: Stijl vs Materieel", template="plotly_white", height=400, showlegend=False, ) fig4.update_xaxes(title="Year", dtick=1) fig4.update_yaxes(title="Score (1–5)", range=[0.5, 4]) fig4.show() ``` | Dimension | Pre-2024 Mean | Post-2024 Mean | Δ | |-----------|--------------|---------------|-----| | Stylistic extremity | 1.718 | 1.815 | +0.097 | | Material impact | 2.530 | 2.384 | −0.146 | | Gap (M−S) | 0.813 | 0.570 | −0.243 | Material impact *decreased* (−0.146) while stylistic extremity *increased* (+0.097). A Wilcoxon signed-rank test comparing yearly mean stylistic vs yearly mean material scores confirms the dimensions systematically differ (W = 0.0, n = 10 yearly pairs, p = 0.002). The gap between the two dimensions narrowed from 0.813 to 0.570 — right-wing motions became both less rhetorically hostile AND less substantively impactful. Compared to all motions, right-wing motions score higher on both dimensions: stijl +0.47, materieel +0.54. The masking rate — restrained language paired with high material impact (S ≤ 2, M ≥ 3) — is 36.1% for right-wing motions vs 24.0% for all motions. Right-wing proposals disproportionately use procedural language to advance consequential policy. ## Mechanisms of Influence If centrists didn't become right-wing, *how* did right-wing motions gain their support? A systematic classification of 150 post-2024 motions (stratified by centrist support level) identifies the dominant pathways. ```{python} #| label: chart-5-mechanisms #| fig-cap: "Mechanism Distribution: High-Support vs Low-Support Post-2024 Motions" #| column: page mechanisms = [ "Procedureel/technisch", "Consensus framing", "Gerichte restrictie", "Institutioneel/rechtsstatelijk", "Symbolisch/declaratoir", "Welzijn/dienstverlening", "Lokaal/regionaal", "Coalitie-afstemming", "Crisisrespons", "Systeemontmanteling", ] high_support = [24, 18, 13, 7, 4, 3, 3, 2, 1, 0] low_support = [9, 6, 21, 19, 5, 1, 1, 0, 0, 13] fig5 = go.Figure() fig5.add_trace(go.Bar( name="High-support (CS > 0.5)", x=mechanisms, y=high_support, marker_color="#1E88E5", )) fig5.add_trace(go.Bar( name="Low-support (CS ≤ 0.5)", x=mechanisms, y=low_support, marker_color="#90CAF9", )) fig5.update_layout( title="Mechanism Classification: High-Support vs Low-Support Post-2024", xaxis=dict(title="Mechanism", tickangle=45), yaxis=dict(title="Count"), barmode="group", template="plotly_white", height=450, legend=dict(yanchor="top", y=0.99, xanchor="right", x=0.99), ) fig5.show() ``` The contrast between high- and low-support post-2024 motions is sharp. **High-support motions (CS > 0.5)** are dominated by procedural/technical framing (32%), consensus framing appealing to shared values (24%), and targeted restriction rather than blanket bans (17%). Institutional challenges and system dismantling are notably absent. **Low-support motions (CS ≤ 0.5)** are dominated by targeted restriction (28%), institutional challenges (25%), and system dismantling (17%). Zero system dismantling motions achieved high centrist support. Consensus framing is significantly more common in high-support motions (24%) than low-support (8%): χ²(1) = 6.00, p = 0.014. The hypothesis that consensus framing drives centrist support is confirmed. **Party-level analysis** reveals the shift is not uniform. JA21 is the primary driver, with a +0.203 CS shift and the only volume + support gains combination. PVV entered government and filed fewer, milder motions. FVD remains structurally shunned — its motions consistently fail to gain centrist support regardless of content. ## Temporal Dynamics Quarterly analysis across 33 quarters (2016-Q2 through 2026-Q1) replaces the binary pre/post-2024 comparison with a continuous trajectory that reveals the exact timing, shape, and sustainability of the shift. ```{python} #| label: chart-6-quarterly #| fig-cap: "Quarterly Centrist Support Trajectory (2016–2026)" #| column: page quarterly = con.execute(""" SELECT EXTRACT(YEAR FROM m.date) AS y, CEIL(EXTRACT(MONTH FROM m.date) / 3.0) AS q, AVG(r.centrist_support_strict) AS cs, COUNT(*) AS n, STDDEV(r.centrist_support_strict) AS std_cs FROM right_wing_motions r JOIN motions m ON r.motion_id = m.id WHERE r.classified = TRUE AND m.date IS NOT NULL GROUP BY y, q ORDER BY y, q """).fetchdf() quarterly["label"] = quarterly["y"].astype(int).astype(str) + "-Q" + quarterly["q"].astype(int).astype(str) inflection_idx = quarterly[(quarterly["y"].astype(int) == 2024) & (quarterly["q"].astype(int) == 1)].index peak_idx = quarterly[(quarterly["y"].astype(int) == 2024) & (quarterly["q"].astype(int) == 4)].index latest_idx = quarterly[(quarterly["y"].astype(int) == 2026) & (quarterly["q"].astype(int) == 1)].index fig6 = go.Figure() fig6.add_trace(go.Scatter( x=quarterly["label"], y=quarterly["cs"], mode="lines+markers", line=dict(color="#002366", width=3), marker=dict(size=6), error_y=dict( type="data", array=1.96 * quarterly["std_cs"] / np.sqrt(quarterly["n"]), visible=True, thickness=0.6, width=1.5, ), name="Centrist Support", )) for idx in [inflection_idx, peak_idx, latest_idx]: if len(idx) > 0: i = idx[0] fig6.add_annotation( x=quarterly.loc[i, "label"], y=quarterly.loc[i, "cs"], text=f'{quarterly.loc[i, "cs"]:.3f}', showarrow=True, arrowhead=1, ax=0, ay=-30, ) fig6.add_shape( type="line", x0="2024-Q1", x1="2024-Q1", y0=0, y1=1, line=dict(dash="dot", color="red", width=1.5), ) fig6.add_annotation( x="2024-Q1", y=0.95, text="PVV election (Nov 2023)", showarrow=False, textangle=-90, font=dict(color="red", size=10), ) fig6.add_shape( type="line", x0="2024-Q3", x1="2024-Q3", y0=0, y1=1, line=dict(dash="dot", color="orange", width=1.5), ) fig6.add_annotation( x="2024-Q3", y=0.88, text="Schoof cabinet (Jul 2024)", showarrow=False, textangle=-90, font=dict(color="orange", size=10), ) fig6.update_layout( title="Quarterly Centrist Support Trajectory", xaxis=dict( title="Quarter", tickangle=45, tickmode="array", tickvals=quarterly["label"][::4], ), yaxis=dict(title="Centrist Support", range=[0, 1.0]), template="plotly_white", height=450, ) fig6.show() ``` **Timing.** The inflection point is 2024-Q1, the quarter immediately following the PVV's November 2023 election victory. Centrist support jumped from 0.321 (2023-Q4) to 0.501 (2024-Q1) — a single-quarter increase of +0.180, roughly twice the average quarterly change. **Shape.** Centrist support rose sharply through 2024-Q4, reaching an all-time peak of 0.648 in the first full quarter of the Schoof cabinet. From that peak, it declined steadily: 0.598, 0.503, 0.437, 0.450, and 0.334 in 2026-Q1 — below the 0.4 inflection threshold and approaching pre-shift levels. **Causal mechanism.** The shift began before the Schoof cabinet formed (July 2024), appearing immediately after the PVV election. This rules out coalition dynamics as the primary driver. The most parsimonious explanation: centrist parties perceived the PVV's electoral success as a mandate for right-wing policy and adjusted their voting behavior accordingly. **Sustainability.** The 2026-Q1 reversion to 0.334 raises a critical question: is the centrist support surge a temporary electoral-cycle effect rather than a permanent Overton window shift? The trajectory resembles an electoral response function — a rapid jump after the election, a peak during the cabinet honeymoon, and a gradual decline. The "new normal" may be closer to 0.33 than to 0.65. | Hypothesis | Evidence | Verdict | |------------|----------|---------| | Electoral shock | Jump immediately followed PVV victory (Nov 2023) | **Supported** | | Coalition dynamics | Shift began 3 quarters before cabinet formed | **Refuted** | | Gradual learning | Jump was 1.9× average quarterly — discrete, not incremental | **Refuted** | | European contagion | No Dutch response during 2022–2023 European shift | **Refuted** | ## Verdict: The Window Widened Through Moderation **The Overton window widened: more right-wing positions became politically acceptable after 2024. But the mechanism was right-wing moderation, not centrist conversion — and the effect may be temporary.** Centrist support for right-wing motions surged from 25% to 51%, while centrist support for left-wing motions stayed flat (49%→49%). The window of acceptable debate expanded rightward. 1. **Volume surged, impact declined.** Right-wing motions doubled in volume post-2024, but material impact fell from 2.78 to 2.43 (Cohen's d = −0.36). The M ≥ 4 share dropped from 23.7% to 11.3% and continued falling to 2.7% by 2026. 2. **Centrists did not become more tolerant.** The extremity-stratified gradient persists — centrists still differentiate between mild and extreme motions. The across-the-board baseline shift reflects that content within each bucket became milder, not that centrists lowered their standards. 3. **The mechanism is strategic moderation, systematically confirmed.** Zero system-dismantling proposals achieved high centrist support post-2024. The dominant pathways — procedural/technical (32%), consensus framing (24%), and targeted restriction (17%) — show right-wing parties learned which frames work. 4. **SVD divergence confirms this.** Centrists moved left spatially as the extreme tail polarized even as cooperation grew on the moderate mass. 5. **The shift is electorally driven and possibly temporary.** Centrist support surged immediately after the PVV election, peaked at 0.648 in 2024-Q4, and has since reverted to 0.334 in 2026-Q1 — approaching pre-shift levels. **The gateway domain: migration.** Migration is where the Overton shift is most genuine — and where right-wing parties learned the frames they then applied elsewhere. Material impact barely declined (−0.13), yet centrist support more than doubled (0.153 → 0.369). Centrists went from zero support for M = 5 migration motions to nearly 20%. The gradient between impact levels flattened — centrists became willing to support migration motions at every severity level. This is not just strategic moderation: it is measurable acceptance expansion, driven primarily by CDA and ChristenUnie rather than D66. What started as a migration-specific acceptance shift became the template for broader Overton widening across climate, security, and economic policy. ### Limitations - **Small-N time series:** 8 pre-2024 annual windows and 3 post-2024 (2026 is partial). Effect sizes are descriptive Cohen's d, not inferred from a time-series model. - **Coalition coding:** 2024 is ambiguous (Rutte IV until July, Schoof thereafter). Opposition-only analysis and temporal timing mitigate this. - **Mechanism classification:** Based on 150 post-2024 motions, single-classifier assignment. Inter-rater agreement is moderate (κ = 0.41). - **Causal direction:** The timing strongly supports an electoral explanation, but this remains correlational. - **Success ceiling:** 96%+ pass rate makes pass rate an insensitive dependent variable. ### Explore the Data This article is one surface of a three-tier analysis: 1. **Narrative spine** — you're reading it. The story, with key evidence. 2. **Technical appendices** — detailed markdown reports in `reports/overton_window/` cover every methodological decision, robustness check, and sensitivity analysis. 3. **Live exploration** — explore the Stemwijzer Explorer: - **Kompas tab** — party positions on the SVD axes - **Trajectories tab** — how parties drifted over time - **Overton tab** — centrist support trends and right-wing motion browser **Visit the Explorer** at `localhost:8501` to interact with the compass, plot your position, and verify these findings against the underlying vote data. ```{python} #| label: close-connection #| include: false con.close() ```