Compare commits

...
Author SHA1 Message Date
Ludovic MarieandClaude Opus 5.5 226df33b82 Performance: Horizon against vanilla and vanilla + mods, in the README and on the site
A Performance section in the README (Mac mini M4 Pro, render distance 16:
start-up, loading after a teleport, memory and FPS, mean and range of
three games each, with the conditions) and the six benchmark reports it
comes from in benchmarks/perf/2026-10-15-mac-mini-m4pro. The site renders
the same table as a section after Parity, hidden when the README has none.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 07:00:21 +02:00
11 changed files with 2449 additions and 5 deletions

No files matched your search

+15
View File
@@ -113,6 +113,21 @@ The [native client](docs/native-client.md) opens on a vanilla-style title screen
- shields, maps, books, fireworks, beacons, advancements and statistics;
- Anvil saves, joining vanilla servers, and opening a world to LAN.
## Performance
Horizon against vanilla 26.3 and vanilla with Sodium, Lithium, FerriteCore and ImmediatelyFast: same seed (1234), same scenes (a village and a mountain), the same 1280×720 view, three games each, all driven and measured by `tools/perf_bench.py` ([method](docs/benchmark.md)). Each cell is the mean of the three games, with the range in brackets.
| Mac mini M4 Pro, render distance 16 | Horizon | Vanilla | Vanilla + mods |
| --- | --- | --- | --- |
| Launch to title screen | 5.3 s (3.7–7.9) | 12.4 s (10.1–14.5) | 19.3 s (16.0–21.1) |
| Launch to playing in a new world | 19.4 s (11.1–31.6) | 37.1 s (30.9–42.0) | 50.4 s (41.1–56.0) |
| Teleport to the village, chunks loaded | 4.2 s (3.2–5.4) | 12.5 s (11.9–13.7) | 13.4 s (10.3–17.7) |
| Teleport to the mountain, chunks loaded | 22.1 s (12.8–32.7) | 24.6 s (22.4–27.8) | 25.5 s (21.5–32.6) |
| Memory while flying | 1.66 GB | 2.23 GB | 2.37 GB |
| Average FPS flying over the village | 393 (122–598) | 61 (47–68) | 53 (50–59) |
Measured on 2026-10-15 on main with #267, #269 and #280, macOS 27, in a locked screen session shared with CI runners (1-minute load average 36–47, reported in each run): treat the spread as part of the result. Horizon drew offscreen there and vanilla in a window, so its FPS has no presentation cost; loading, start-up and memory don't depend on it. At render distance 8 the order is the same. Every run's full report (frame-time histogram, 1% and 0.1% lows, conditions, hardware) is in [benchmarks/perf/2026-10-15-mac-mini-m4pro](benchmarks/perf/2026-10-15-mac-mini-m4pro); runs on an RTX 4080, an integrated GPU and a laptop on battery come next.
## Agent control
AI agents and scripts can play Horizon. `horizon-ctl`, shipped beside the game in every release folder, is a command line that reads the game as JSON and acts like a player; `horizon-ctl mcp` serves the same commands as an MCP server (one tool per command, screenshots returned as images).
@@ -0,0 +1,398 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:35:57Z",
"app": {
"name": "horizon-client",
"version": "0.1.0",
"commit": "3f42787b"
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "",
"driver": "",
"backend": "metal",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 16,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 46.22,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 5281.435,
"stdev": 2260.202,
"min": 3670.293,
"max": 7865.118,
"ci95": 5615.107
},
"startup.world_ms": {
"n": 3,
"mean": 19399.299,
"stdev": 10767.032,
"min": 11064.274,
"max": 31555.835,
"ci95": 26748.949
},
"chunks.village.load_ms": {
"n": 3,
"mean": 4216.286,
"stdev": 1125.65,
"min": 3171.995,
"max": 5408.641,
"ci95": 2796.496
},
"chunks.village.meshed_count": {
"n": 3,
"mean": 46008.667,
"stdev": 2182.164,
"min": 43575.0,
"max": 47791.0,
"ci95": 5421.234
},
"fps.village.avg_fps": {
"n": 3,
"mean": 392.708,
"stdev": 244.514,
"min": 122.101,
"max": 597.769,
"ci95": 607.456
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 34.096,
"stdev": 26.158,
"min": 6.503,
"max": 58.533,
"ci95": 64.986
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 15.369,
"stdev": 10.165,
"min": 5.019,
"max": 25.339,
"ci95": 25.254
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 22109.864,
"stdev": 9981.189,
"min": 12833.391,
"max": 32671.311,
"ci95": 24796.65
},
"chunks.mountain.meshed_count": {
"n": 3,
"mean": 60214.0,
"stdev": 20370.065,
"min": 40988.0,
"max": 81562.0,
"ci95": 50606.13
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 168.488,
"stdev": 132.476,
"min": 21.538,
"max": 278.763,
"ci95": 329.116
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 12.712,
"stdev": 8.34,
"min": 3.127,
"max": 18.315,
"ci95": 20.72
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 7.659,
"stdev": 4.129,
"min": 3.005,
"max": 10.881,
"ci95": 10.257
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 1828.172,
"stdev": 12.996,
"min": 1814.656,
"max": 1840.578,
"ci95": 32.288
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 1659.659,
"stdev": 7.872,
"min": 1650.766,
"max": 1665.734,
"ci95": 19.557
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 7174,
"seconds": 12.001,
"avg_fps": 597.769,
"low_1pct_fps": 58.533,
"low_01pct_fps": 25.339,
"p50_ms": 1.105,
"p95_ms": 4.246,
"p99_ms": 10.609,
"p999_ms": 25.118,
"max_ms": 75.71,
"histogram": [
1531,
4741,
366,
175,
35,
50,
65,
66,
60,
38,
14,
12,
6,
7,
3,
2,
2,
0,
1,
0,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 1462,
"seconds": 11.974,
"avg_fps": 122.101,
"low_1pct_fps": 6.503,
"low_01pct_fps": 5.019,
"p50_ms": 2.058,
"p95_ms": 31.007,
"p99_ms": 112.655,
"p999_ms": 194.129,
"max_ms": 204.335,
"histogram": [
21,
687,
195,
84,
43,
33,
45,
37,
47,
51,
31,
33,
25,
36,
23,
11,
15,
14,
12,
11,
8,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 5499,
"seconds": 12.0,
"avg_fps": 458.253,
"low_1pct_fps": 37.251,
"low_01pct_fps": 15.749,
"p50_ms": 1.253,
"p95_ms": 6.822,
"p99_ms": 13.254,
"p999_ms": 53.18,
"max_ms": 77.046,
"histogram": [
712,
3496,
527,
266,
83,
83,
74,
74,
72,
44,
18,
11,
9,
11,
8,
2,
2,
4,
3,
0,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 260,
"seconds": 12.072,
"avg_fps": 21.538,
"low_1pct_fps": 3.127,
"low_01pct_fps": 3.005,
"p50_ms": 20.354,
"p95_ms": 174.542,
"p99_ms": 294.454,
"p999_ms": 332.752,
"max_ms": 332.752,
"histogram": [
0,
36,
17,
17,
6,
6,
3,
5,
6,
10,
6,
8,
9,
10,
19,
16,
10,
13,
25,
16,
18,
4,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 3345,
"seconds": 11.999,
"avg_fps": 278.763,
"low_1pct_fps": 16.694,
"low_01pct_fps": 9.092,
"p50_ms": 1.593,
"p95_ms": 12.614,
"p99_ms": 37.671,
"p999_ms": 92.703,
"max_ms": 133.394,
"histogram": [
0,
2422,
285,
134,
57,
73,
51,
68,
41,
34,
36,
36,
16,
21,
22,
17,
12,
12,
5,
3,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 2462,
"seconds": 12.0,
"avg_fps": 205.163,
"low_1pct_fps": 18.315,
"low_01pct_fps": 10.881,
"p50_ms": 2.006,
"p95_ms": 17.997,
"p99_ms": 40.1,
"p999_ms": 77.189,
"max_ms": 109.276,
"histogram": [
0,
1228,
355,
226,
94,
77,
62,
65,
60,
64,
38,
54,
31,
32,
33,
18,
14,
7,
3,
1,
0,
0,
0,
0
]
}
],
"label": "pub-horizon"
}
@@ -0,0 +1,398 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:32:05Z",
"app": {
"name": "horizon-client",
"version": "0.1.0",
"commit": "3f42787b"
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "",
"driver": "",
"backend": "metal",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 8,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 46.288,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 7786.967,
"stdev": 4088.035,
"min": 5120.805,
"max": 12493.58,
"ci95": 10156.062
},
"startup.world_ms": {
"n": 3,
"mean": 23146.275,
"stdev": 12436.963,
"min": 14639.422,
"max": 37419.838,
"ci95": 30897.623
},
"chunks.village.load_ms": {
"n": 3,
"mean": 5013.855,
"stdev": 2028.402,
"min": 2907.197,
"max": 6953.7,
"ci95": 5039.237
},
"chunks.village.meshed_count": {
"n": 3,
"mean": 10117.0,
"stdev": 1588.092,
"min": 8930.0,
"max": 11921.0,
"ci95": 3945.358
},
"fps.village.avg_fps": {
"n": 3,
"mean": 380.117,
"stdev": 152.317,
"min": 207.974,
"max": 497.424,
"ci95": 378.408
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 17.297,
"stdev": 5.55,
"min": 11.279,
"max": 22.214,
"ci95": 13.788
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 10.398,
"stdev": 1.441,
"min": 8.842,
"max": 11.686,
"ci95": 3.579
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 8664.268,
"stdev": 4657.457,
"min": 3541.194,
"max": 12642.662,
"ci95": 11570.697
},
"chunks.mountain.meshed_count": {
"n": 3,
"mean": 17739.667,
"stdev": 4124.842,
"min": 13499.0,
"max": 21738.0,
"ci95": 10247.503
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 467.08,
"stdev": 76.765,
"min": 403.274,
"max": 552.27,
"ci95": 190.711
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 21.042,
"stdev": 7.793,
"min": 13.974,
"max": 29.4,
"ci95": 19.361
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 9.903,
"stdev": 2.189,
"min": 8.54,
"max": 12.428,
"ci95": 5.438
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 1577.167,
"stdev": 21.646,
"min": 1552.172,
"max": 1589.75,
"ci95": 53.777
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 1537.297,
"stdev": 18.879,
"min": 1524.484,
"max": 1558.977,
"ci95": 46.901
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 2491,
"seconds": 11.977,
"avg_fps": 207.974,
"low_1pct_fps": 11.279,
"low_01pct_fps": 8.842,
"p50_ms": 0.88,
"p95_ms": 24.632,
"p99_ms": 67.621,
"p999_ms": 110.416,
"max_ms": 116.484,
"histogram": [
1508,
356,
94,
51,
37,
46,
46,
39,
34,
47,
28,
28,
23,
33,
31,
23,
21,
21,
19,
6,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 5220,
"seconds": 12.001,
"avg_fps": 434.954,
"low_1pct_fps": 18.398,
"low_01pct_fps": 10.666,
"p50_ms": 0.774,
"p95_ms": 7.82,
"p99_ms": 33.91,
"p999_ms": 84.374,
"max_ms": 103.752,
"histogram": [
3897,
531,
180,
107,
73,
74,
57,
54,
36,
37,
22,
30,
24,
21,
19,
18,
16,
14,
9,
1,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 5973,
"seconds": 12.008,
"avg_fps": 497.424,
"low_1pct_fps": 22.214,
"low_01pct_fps": 11.686,
"p50_ms": 0.762,
"p95_ms": 6.934,
"p99_ms": 26.212,
"p999_ms": 74.127,
"max_ms": 105.126,
"histogram": [
4592,
569,
195,
97,
78,
76,
72,
61,
39,
28,
17,
33,
23,
28,
24,
11,
14,
9,
6,
1,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 4836,
"seconds": 11.992,
"avg_fps": 403.274,
"low_1pct_fps": 13.974,
"low_01pct_fps": 8.742,
"p50_ms": 0.707,
"p95_ms": 8.505,
"p99_ms": 38.346,
"p999_ms": 109.016,
"max_ms": 120.946,
"histogram": [
3661,
433,
165,
121,
66,
50,
53,
39,
47,
29,
15,
28,
25,
26,
25,
5,
12,
10,
17,
9,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 5353,
"seconds": 12.01,
"avg_fps": 445.695,
"low_1pct_fps": 19.753,
"low_01pct_fps": 8.54,
"p50_ms": 0.71,
"p95_ms": 8.506,
"p99_ms": 30.239,
"p999_ms": 82.313,
"max_ms": 218.733,
"histogram": [
4012,
535,
187,
104,
66,
72,
53,
46,
44,
45,
33,
23,
21,
32,
36,
16,
10,
11,
3,
3,
1,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 6628,
"seconds": 12.001,
"avg_fps": 552.27,
"low_1pct_fps": 29.4,
"low_01pct_fps": 12.428,
"p50_ms": 0.714,
"p95_ms": 6.707,
"p99_ms": 18.865,
"p999_ms": 54.65,
"max_ms": 133.947,
"histogram": [
4932,
707,
271,
149,
80,
99,
79,
56,
61,
53,
31,
28,
20,
19,
20,
9,
7,
4,
1,
2,
0,
0,
0,
0
]
}
],
"label": "pub-horizon"
}
@@ -0,0 +1,403 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:56:59Z",
"app": {
"name": "minecraft",
"version": "26.3",
"mods": [
{
"name": "fabric-loader",
"version": "0.19.5"
},
{
"name": "sodium",
"version": "mc26.3-0.9.2-fabric"
},
{
"name": "lithium",
"version": "mc26.3-0.26.2-fabric"
},
{
"name": "ferrite-core",
"version": "9.0.0-fabric"
},
{
"name": "immediatelyfast",
"version": "1.17.1+26.3-fabric"
}
]
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "Apple",
"driver": "4.1 Metal - 91.7",
"backend": "opengl",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 16,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 35.961,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 19300.326,
"stdev": 2828.141,
"min": 16043.14,
"max": 21132.475,
"ci95": 7026.058
},
"startup.world_ms": {
"n": 3,
"mean": 50423.659,
"stdev": 8119.357,
"min": 41103.14,
"max": 55961.362,
"ci95": 20171.23
},
"chunks.village.load_ms": {
"n": 3,
"mean": 13437.795,
"stdev": 3809.937,
"min": 10283.957,
"max": 17670.952,
"ci95": 9465.173
},
"fps.village.avg_fps": {
"n": 3,
"mean": 53.32,
"stdev": 5.103,
"min": 49.967,
"max": 59.193,
"ci95": 12.677
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 9.817,
"stdev": 0.633,
"min": 9.307,
"max": 10.525,
"ci95": 1.572
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 6.717,
"stdev": 1.007,
"min": 5.78,
"max": 7.781,
"ci95": 2.501
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 25536.212,
"stdev": 6161.551,
"min": 21454.85,
"max": 32623.83,
"ci95": 15307.376
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 36.87,
"stdev": 18.572,
"min": 19.41,
"max": 56.383,
"ci95": 46.139
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 6.045,
"stdev": 3.0,
"min": 3.708,
"max": 9.428,
"ci95": 7.454
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 4.864,
"stdev": 1.619,
"min": 3.288,
"max": 6.522,
"ci95": 4.021
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 2672.901,
"stdev": 108.822,
"min": 2547.469,
"max": 2742.125,
"ci95": 270.351
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 2372.76,
"stdev": 117.571,
"min": 2243.563,
"max": 2473.469,
"ci95": 292.086
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 610,
"seconds": 12.008,
"avg_fps": 50.801,
"low_1pct_fps": 9.618,
"low_01pct_fps": 5.78,
"p50_ms": 14.837,
"p95_ms": 47.768,
"p99_ms": 76.311,
"p999_ms": 173.006,
"max_ms": 173.006,
"histogram": [
0,
0,
0,
0,
1,
15,
39,
51,
48,
77,
59,
60,
48,
70,
58,
35,
20,
18,
8,
2,
1,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 600,
"seconds": 12.008,
"avg_fps": 49.967,
"low_1pct_fps": 9.307,
"low_01pct_fps": 7.781,
"p50_ms": 15.377,
"p95_ms": 45.626,
"p99_ms": 90.931,
"p999_ms": 128.516,
"max_ms": 128.516,
"histogram": [
0,
0,
0,
0,
0,
3,
15,
44,
53,
72,
73,
77,
51,
80,
65,
26,
14,
14,
9,
4,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 711,
"seconds": 12.012,
"avg_fps": 59.193,
"low_1pct_fps": 10.525,
"low_01pct_fps": 6.589,
"p50_ms": 13.784,
"p95_ms": 34.98,
"p99_ms": 68.485,
"p999_ms": 151.765,
"max_ms": 151.765,
"histogram": [
0,
0,
0,
9,
8,
14,
21,
55,
72,
80,
106,
92,
83,
72,
56,
14,
10,
11,
4,
3,
1,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 418,
"seconds": 12.006,
"avg_fps": 34.817,
"low_1pct_fps": 4.998,
"low_01pct_fps": 4.781,
"p50_ms": 18.052,
"p95_ms": 84.979,
"p99_ms": 184.893,
"p999_ms": 209.176,
"max_ms": 209.176,
"histogram": [
0,
0,
0,
0,
3,
4,
19,
21,
19,
38,
42,
43,
41,
45,
42,
24,
23,
21,
18,
6,
9,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 233,
"seconds": 12.004,
"avg_fps": 19.41,
"low_1pct_fps": 3.708,
"low_01pct_fps": 3.288,
"p50_ms": 29.988,
"p95_ms": 168.153,
"p99_ms": 241.102,
"p999_ms": 304.121,
"max_ms": 304.121,
"histogram": [
0,
0,
0,
0,
3,
2,
5,
2,
14,
10,
9,
12,
18,
24,
29,
15,
15,
16,
22,
22,
13,
2,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 677,
"seconds": 12.007,
"avg_fps": 56.383,
"low_1pct_fps": 9.428,
"low_01pct_fps": 6.522,
"p50_ms": 13.331,
"p95_ms": 45.556,
"p99_ms": 78.202,
"p999_ms": 153.321,
"max_ms": 153.321,
"histogram": [
0,
0,
0,
7,
15,
32,
36,
78,
61,
62,
72,
79,
52,
59,
49,
31,
17,
15,
9,
2,
1,
0,
0,
0
]
}
],
"label": "pub-vanilla-mods"
}
@@ -0,0 +1,403 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:50:33Z",
"app": {
"name": "minecraft",
"version": "26.3",
"mods": [
{
"name": "fabric-loader",
"version": "0.19.5"
},
{
"name": "sodium",
"version": "mc26.3-0.9.2-fabric"
},
{
"name": "lithium",
"version": "mc26.3-0.26.2-fabric"
},
{
"name": "ferrite-core",
"version": "9.0.0-fabric"
},
{
"name": "immediatelyfast",
"version": "1.17.1+26.3-fabric"
}
]
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "Apple",
"driver": "4.1 Metal - 91.7",
"backend": "opengl",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 8,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 28.616,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 11913.795,
"stdev": 1682.464,
"min": 10064.344,
"max": 13353.625,
"ci95": 4179.81
},
"startup.world_ms": {
"n": 3,
"mean": 23628.795,
"stdev": 3821.829,
"min": 19928.344,
"max": 27561.417,
"ci95": 9494.716
},
"chunks.village.load_ms": {
"n": 3,
"mean": 5859.756,
"stdev": 671.071,
"min": 5318.887,
"max": 6610.744,
"ci95": 1667.167
},
"fps.village.avg_fps": {
"n": 3,
"mean": 93.728,
"stdev": 30.987,
"min": 74.79,
"max": 129.488,
"ci95": 76.983
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 17.012,
"stdev": 10.129,
"min": 9.452,
"max": 28.521,
"ci95": 25.164
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 11.577,
"stdev": 6.366,
"min": 6.817,
"max": 18.808,
"ci95": 15.815
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 11856.681,
"stdev": 4220.225,
"min": 7673.523,
"max": 16113.02,
"ci95": 10484.465
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 144.139,
"stdev": 18.171,
"min": 123.234,
"max": 156.15,
"ci95": 45.144
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 16.863,
"stdev": 7.609,
"min": 8.317,
"max": 22.902,
"ci95": 18.903
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 9.871,
"stdev": 4.76,
"min": 6.407,
"max": 15.299,
"ci95": 11.826
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 2052.464,
"stdev": 24.452,
"min": 2033.672,
"max": 2080.109,
"ci95": 60.747
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 1998.708,
"stdev": 35.637,
"min": 1960.07,
"max": 2030.289,
"ci95": 88.535
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 923,
"seconds": 12.002,
"avg_fps": 76.906,
"low_1pct_fps": 13.064,
"low_01pct_fps": 9.107,
"p50_ms": 9.609,
"p95_ms": 33.104,
"p99_ms": 58.172,
"p999_ms": 109.81,
"max_ms": 109.81,
"histogram": [
0,
0,
8,
136,
75,
69,
66,
72,
51,
73,
71,
74,
69,
61,
53,
14,
12,
12,
6,
1,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 901,
"seconds": 12.047,
"avg_fps": 74.79,
"low_1pct_fps": 9.452,
"low_01pct_fps": 6.817,
"p50_ms": 7.86,
"p95_ms": 43.522,
"p99_ms": 77.616,
"p999_ms": 146.699,
"max_ms": 146.699,
"histogram": [
0,
0,
1,
81,
71,
97,
118,
119,
84,
53,
48,
46,
47,
36,
30,
19,
16,
18,
12,
5,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 1555,
"seconds": 12.009,
"avg_fps": 129.488,
"low_1pct_fps": 28.521,
"low_01pct_fps": 18.808,
"p50_ms": 6.567,
"p95_ms": 16.327,
"p99_ms": 28.019,
"p999_ms": 47.44,
"max_ms": 58.896,
"histogram": [
0,
0,
32,
221,
169,
221,
259,
225,
126,
109,
65,
57,
28,
19,
17,
4,
2,
1,
0,
0,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 1837,
"seconds": 12.004,
"avg_fps": 153.034,
"low_1pct_fps": 22.902,
"low_01pct_fps": 15.299,
"p50_ms": 4.665,
"p95_ms": 17.025,
"p99_ms": 32.332,
"p999_ms": 64.213,
"max_ms": 66.518,
"histogram": [
0,
0,
353,
421,
225,
203,
164,
127,
91,
63,
47,
48,
31,
22,
24,
10,
3,
5,
0,
0,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 1874,
"seconds": 12.001,
"avg_fps": 156.15,
"low_1pct_fps": 19.369,
"low_01pct_fps": 7.907,
"p50_ms": 4.561,
"p95_ms": 16.565,
"p99_ms": 34.031,
"p999_ms": 81.478,
"max_ms": 171.477,
"histogram": [
0,
18,
334,
456,
220,
243,
167,
145,
84,
46,
36,
32,
24,
24,
26,
8,
6,
3,
1,
0,
1,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 1483,
"seconds": 12.034,
"avg_fps": 123.234,
"low_1pct_fps": 8.317,
"low_01pct_fps": 6.407,
"p50_ms": 4.438,
"p95_ms": 26.448,
"p99_ms": 93.738,
"p999_ms": 154.876,
"max_ms": 157.287,
"histogram": [
0,
32,
287,
363,
158,
167,
134,
89,
61,
36,
31,
12,
19,
18,
12,
19,
12,
15,
4,
12,
2,
0,
0,
0
]
}
],
"label": "pub-vanilla-mods"
}
@@ -0,0 +1,387 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:45:34Z",
"app": {
"name": "minecraft",
"version": "26.3",
"mods": [
{
"name": "fabric-loader",
"version": "0.19.5"
}
]
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "Apple",
"driver": "4.1 Metal - 91.7",
"backend": "opengl",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 16,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 47.376,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 12397.912,
"stdev": 2214.074,
"min": 10094.327,
"max": 14510.041,
"ci95": 5500.509
},
"startup.world_ms": {
"n": 3,
"mean": 37146.912,
"stdev": 5671.908,
"min": 30897.327,
"max": 41968.041,
"ci95": 14090.938
},
"chunks.village.load_ms": {
"n": 3,
"mean": 12510.29,
"stdev": 1034.733,
"min": 11864.748,
"max": 13703.767,
"ci95": 2570.626
},
"fps.village.avg_fps": {
"n": 3,
"mean": 60.563,
"stdev": 11.943,
"min": 46.795,
"max": 68.132,
"ci95": 29.67
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 12.993,
"stdev": 1.675,
"min": 11.965,
"max": 14.926,
"ci95": 4.162
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 8.751,
"stdev": 0.598,
"min": 8.239,
"max": 9.409,
"ci95": 1.487
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 24624.587,
"stdev": 2787.515,
"min": 22405.306,
"max": 27753.221,
"ci95": 6925.13
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 46.852,
"stdev": 4.543,
"min": 41.755,
"max": 50.474,
"ci95": 11.286
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 9.08,
"stdev": 1.001,
"min": 7.975,
"max": 9.924,
"ci95": 2.486
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 7.003,
"stdev": 1.502,
"min": 5.352,
"max": 8.288,
"ci95": 3.731
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 2487.797,
"stdev": 85.991,
"min": 2392.141,
"max": 2558.688,
"ci95": 213.631
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 2228.044,
"stdev": 56.806,
"min": 2172.375,
"max": 2285.922,
"ci95": 141.124
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 803,
"seconds": 12.028,
"avg_fps": 66.761,
"low_1pct_fps": 11.965,
"low_01pct_fps": 8.606,
"p50_ms": 11.953,
"p95_ms": 32.478,
"p99_ms": 60.875,
"p999_ms": 116.201,
"max_ms": 116.201,
"histogram": [
0,
0,
0,
0,
0,
0,
17,
99,
122,
166,
129,
90,
50,
53,
39,
11,
11,
9,
5,
2,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 562,
"seconds": 12.01,
"avg_fps": 46.795,
"low_1pct_fps": 12.088,
"low_01pct_fps": 9.409,
"p50_ms": 17.366,
"p95_ms": 46.135,
"p99_ms": 74.565,
"p999_ms": 106.285,
"max_ms": 106.285,
"histogram": [
0,
0,
0,
0,
0,
0,
2,
14,
30,
53,
64,
94,
94,
68,
72,
28,
15,
15,
12,
1,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 818,
"seconds": 12.006,
"avg_fps": 68.132,
"low_1pct_fps": 14.926,
"low_01pct_fps": 8.239,
"p50_ms": 12.761,
"p95_ms": 29.499,
"p99_ms": 39.102,
"p999_ms": 121.374,
"max_ms": 121.374,
"histogram": [
0,
0,
0,
0,
1,
3,
17,
85,
109,
141,
147,
117,
79,
53,
39,
19,
3,
2,
0,
3,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 502,
"seconds": 12.022,
"avg_fps": 41.755,
"low_1pct_fps": 9.924,
"low_01pct_fps": 7.369,
"p50_ms": 18.716,
"p95_ms": 58.279,
"p99_ms": 82.805,
"p999_ms": 135.701,
"max_ms": 135.701,
"histogram": [
0,
0,
0,
0,
0,
5,
5,
27,
24,
49,
57,
53,
52,
58,
69,
37,
30,
18,
15,
3,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 580,
"seconds": 12.002,
"avg_fps": 48.327,
"low_1pct_fps": 9.342,
"low_01pct_fps": 8.288,
"p50_ms": 15.232,
"p95_ms": 55.367,
"p99_ms": 98.37,
"p999_ms": 120.663,
"max_ms": 120.663,
"histogram": [
0,
0,
0,
0,
1,
4,
25,
49,
51,
61,
70,
56,
60,
68,
52,
27,
19,
21,
13,
3,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 606,
"seconds": 12.006,
"avg_fps": 50.474,
"low_1pct_fps": 7.975,
"low_01pct_fps": 5.352,
"p50_ms": 14.435,
"p95_ms": 48.644,
"p99_ms": 94.658,
"p999_ms": 186.844,
"max_ms": 186.844,
"histogram": [
0,
0,
0,
0,
0,
1,
17,
50,
64,
72,
84,
67,
61,
66,
50,
29,
15,
15,
11,
2,
2,
0,
0,
0
]
}
],
"label": "pub-vanilla"
}
@@ -0,0 +1,387 @@
{
"format": "horizon-benchmark-report",
"version": 1,
"kind": "game",
"created": "2026-10-15T04:39:59Z",
"app": {
"name": "minecraft",
"version": "26.3",
"mods": [
{
"name": "fabric-loader",
"version": "0.19.5"
}
]
},
"hardware": {
"os": "macos",
"arch": "aarch64",
"cpu_threads": 14,
"os_version": "27.0.1",
"cpu": "Apple M4 Pro",
"ram_mb": 65536,
"gpu": {
"name": "Apple M4 Pro",
"vendor": "Apple",
"driver": "4.1 Metal - 91.7",
"backend": "opengl",
"kind": ""
}
},
"conditions": {
"scenario": "perf_bench:village,mountain",
"seed": "1234",
"render_distance": 8,
"simulation_distance": 12,
"vsync": false,
"offscreen": true,
"repeats": 3,
"warmup_s": 2.0,
"load_avg_1m": 40.387,
"window": [
1280,
720
]
},
"metrics": {
"startup.title_ms": {
"n": 3,
"mean": 12839.436,
"stdev": 2322.332,
"min": 10161.349,
"max": 14297.279,
"ci95": 5769.458
},
"startup.world_ms": {
"n": 3,
"mean": 25355.436,
"stdev": 5418.929,
"min": 19177.349,
"max": 29303.68,
"ci95": 13462.453
},
"chunks.village.load_ms": {
"n": 3,
"mean": 6388.631,
"stdev": 2036.184,
"min": 4264.091,
"max": 8323.134,
"ci95": 5058.568
},
"fps.village.avg_fps": {
"n": 3,
"mean": 115.902,
"stdev": 65.065,
"min": 47.911,
"max": 177.581,
"ci95": 161.643
},
"fps.village.low_1pct_fps": {
"n": 3,
"mean": 20.334,
"stdev": 14.036,
"min": 5.317,
"max": 33.122,
"ci95": 34.87
},
"fps.village.low_01pct_fps": {
"n": 3,
"mean": 11.963,
"stdev": 7.6,
"min": 4.15,
"max": 19.33,
"ci95": 18.881
},
"chunks.mountain.load_ms": {
"n": 3,
"mean": 12173.22,
"stdev": 2593.324,
"min": 9195.096,
"max": 13933.227,
"ci95": 6442.695
},
"fps.mountain.avg_fps": {
"n": 3,
"mean": 163.112,
"stdev": 58.942,
"min": 95.064,
"max": 198.232,
"ci95": 146.431
},
"fps.mountain.low_1pct_fps": {
"n": 3,
"mean": 30.409,
"stdev": 16.505,
"min": 13.19,
"max": 46.093,
"ci95": 41.004
},
"fps.mountain.low_01pct_fps": {
"n": 3,
"mean": 19.518,
"stdev": 10.651,
"min": 9.845,
"max": 30.932,
"ci95": 26.46
},
"memory.rss_peak_mb": {
"n": 3,
"mean": 2001.417,
"stdev": 56.845,
"min": 1967.063,
"max": 2067.031,
"ci95": 141.222
},
"memory.rss_steady_mb": {
"n": 3,
"mean": 1948.943,
"stdev": 97.998,
"min": 1885.516,
"max": 2061.813,
"ci95": 243.46
}
},
"frames": [
{
"phase": "village",
"repeat": 0,
"frames": 2131,
"seconds": 12.0,
"avg_fps": 177.581,
"low_1pct_fps": 33.122,
"low_01pct_fps": 19.33,
"p50_ms": 4.459,
"p95_ms": 11.146,
"p99_ms": 20.673,
"p999_ms": 45.508,
"max_ms": 55.237,
"histogram": [
0,
0,
17,
937,
318,
252,
215,
157,
103,
39,
31,
18,
19,
14,
5,
2,
2,
2,
0,
0,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 1,
"frames": 1467,
"seconds": 12.004,
"avg_fps": 122.213,
"low_1pct_fps": 22.563,
"low_01pct_fps": 12.41,
"p50_ms": 6.78,
"p95_ms": 16.592,
"p99_ms": 29.728,
"p999_ms": 69.574,
"max_ms": 91.584,
"histogram": [
0,
0,
0,
103,
211,
221,
252,
240,
143,
108,
67,
50,
27,
20,
13,
6,
2,
2,
2,
0,
0,
0,
0,
0
]
},
{
"phase": "village",
"repeat": 2,
"frames": 576,
"seconds": 12.022,
"avg_fps": 47.911,
"low_1pct_fps": 5.317,
"low_01pct_fps": 4.15,
"p50_ms": 8.575,
"p95_ms": 82.916,
"p99_ms": 163.996,
"p999_ms": 240.959,
"max_ms": 240.959,
"histogram": [
0,
0,
0,
23,
27,
61,
78,
89,
37,
30,
27,
35,
28,
26,
24,
13,
13,
18,
29,
12,
6,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 0,
"frames": 2355,
"seconds": 12.013,
"avg_fps": 196.041,
"low_1pct_fps": 31.945,
"low_01pct_fps": 17.776,
"p50_ms": 3.966,
"p95_ms": 11.292,
"p99_ms": 20.229,
"p999_ms": 47.014,
"max_ms": 71.034,
"histogram": [
0,
13,
561,
715,
325,
189,
178,
126,
90,
57,
35,
27,
15,
8,
9,
3,
2,
1,
1,
0,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 1,
"frames": 1141,
"seconds": 12.002,
"avg_fps": 95.064,
"low_1pct_fps": 13.19,
"low_01pct_fps": 9.845,
"p50_ms": 7.072,
"p95_ms": 27.933,
"p99_ms": 58.816,
"p999_ms": 101.246,
"max_ms": 101.894,
"histogram": [
0,
0,
7,
186,
126,
119,
128,
102,
98,
80,
62,
70,
53,
38,
32,
12,
10,
11,
5,
2,
0,
0,
0,
0
]
},
{
"phase": "mountain",
"repeat": 2,
"frames": 2379,
"seconds": 12.001,
"avg_fps": 198.232,
"low_1pct_fps": 46.093,
"low_01pct_fps": 30.932,
"p50_ms": 4.062,
"p95_ms": 10.38,
"p99_ms": 16.968,
"p999_ms": 26.767,
"max_ms": 39.249,
"histogram": [
0,
5,
442,
805,
307,
243,
186,
160,
91,
57,
32,
24,
16,
5,
5,
1,
0,
0,
0,
0,
0,
0,
0,
0
]
}
],
"label": "pub-vanilla"
}
+4 -2
View File
@@ -6,7 +6,8 @@ One static page in Horizon's design language (`docs/design-system.md`), with the
`crates/horizon-theme` (generated into `src/tokens.css` by `cargo run -p xtask -- tokens`):
Geist and Geist Mono, cool neutrals in a light and a dark appearance (the system's, or the
toggle's) and one violet accent, numbered index lists with one-pixel rules, and short, eased
motion. A headline and the download, then a scroll through what it is, the screenshots, the parity grid, the launcher, the patch
motion. A headline and the download, then a scroll through what it is, the screenshots, the parity grid, the
performance comparison, the launcher, the patch
notes, the community links and the contributors. Plain HTML, CSS and JavaScript; no framework and
no runtime dependencies.
@@ -35,7 +36,8 @@ shots/ (gitignored) full-page screenshots at 360–1920 px, a 1250×
## What comes from where
- **Built in** (`build.mjs`): the parity table, its score, harness count and audit date,
all from `README.md`; the Discord and Sponsor links from
all from `README.md`; the Performance section from the README's `## Performance` table and the
paragraphs around it (hidden when the README has none); the Discord and Sponsor links from
`launcher/links.json`; the latest releases and the contributors (`/repos/ludovic111/horizon/contributors`,
bots left out, the owner first), when GitHub answers; without an answer the build still succeeds and
the Contributors block and its menu entries stay hidden until the page loads them. Locally these come from
+27
View File
@@ -106,6 +106,29 @@ const parityCells = body
const matching = body.filter(([, score]) => Number(score) === 1).length;
const parityHeadline = matching === body.length ? "Every subsystem matches vanilla." : `${matching} of ${body.length} subsystems match vanilla.`;
// --- The performance table (optional: without one the section stays hidden) -------------
const perf = section(readme, "Performance") ?? "";
const perfCells = (l) => l.replace(/^\|/, "").replace(/\|\s*$/, "").split("|").map((c) => c.trim());
const [perfHead, ...perfRows] = perf
.split("\n")
.filter((l) => /^\|/.test(l) && !/^\|\s*-/.test(l))
.map(perfCells);
const [perfIntro = "", ...perfNotes] = perf
.split("\n")
.filter((l) => !/^\|/.test(l))
.join("\n")
.split(/\n\s*\n/)
.filter((p) => p.trim());
const perfTable = perfHead
? `<div class="perf-scroll reveal"><table class="perf-table">
<caption>${inline(perfHead[0])}</caption>
<thead><tr><td></td>${perfHead.slice(1).map((h) => `<th scope="col">${inline(h)}</th>`).join("")}</tr></thead>
<tbody>
${perfRows.map(([name, ...values]) => ` <tr><th scope="row">${inline(name)}</th>${values.map((v) => `<td>${inline(v)}</td>`).join("")}</tr>`).join("\n")}
</tbody>
</table></div>`
: "";
// --- The latest notes -------------------------------------------------
const isGame = (tag) => /^v\d{4}\.\d{1,2}\.\d{1,2}/.test(tag);
@@ -190,6 +213,10 @@ const values = {
PARITY_CELLS: parityCells,
PARITY_HEADLINE: parityHeadline,
SUBSYSTEMS: String(body.length),
PERF_INTRO: markdown(perfIntro),
PERF_TABLE: perfTable,
PERF_NOTES: markdown(perfNotes.join("\n\n")),
PERF_HIDDEN: perfTable ? "" : " hidden",
NOTES: notesHtml,
LAUNCHER_META: `${launcher ? `Launcher ${escape(launcher.tag_name.replace("launcher-v", ""))} for` : "For"} Linux x86-64, macOS on Apple Silicon and Windows x64.`,
DISCORD: escape(links.discord || DEFAULT_LINKS.discord),
+15 -3
View File
@@ -41,6 +41,7 @@
<a href="#about">About</a>
<a href="#screenshots">In game</a>
<a href="#parity">Parity</a>
<a href="#performance"{{PERF_HIDDEN}}>Performance</a>
<a href="#launcher">Launcher</a>
<a href="#patch-notes">Notes</a>
<a href="#community">Community</a>
@@ -60,6 +61,7 @@
<a href="#about">About</a>
<a href="#screenshots">In game</a>
<a href="#parity">Parity</a>
<a href="#performance"{{PERF_HIDDEN}}>Performance</a>
<a href="#launcher">Launcher</a>
<a href="#patch-notes">Patch notes</a>
<a href="#community">Community</a>
@@ -154,10 +156,20 @@
</div>
</section>
<section id="performance" class="section performance" aria-labelledby="performance-title"{{PERF_HIDDEN}}>
<div class="container">
<p class="kicker reveal"><span>04</span>Performance</p>
<h2 id="performance-title" class="title reveal">Measured against vanilla, on the same machine.</h2>
<div class="prose reveal">{{PERF_INTRO}}</div>
{{PERF_TABLE}}
<div class="prose perf-notes reveal">{{PERF_NOTES}}</div>
</div>
</section>
<section id="launcher" class="section launcher" aria-labelledby="launcher-title">
<div class="container launcher-grid">
<div class="launcher-copy">
<p class="kicker reveal"><span>04</span>The launcher</p>
<p class="kicker reveal"><span>05</span>The launcher</p>
<h2 id="launcher-title" class="title reveal">One small app, then play</h2>
<p class="lede reveal">The launcher installs Horizon, prepares it from your copy of the game and keeps both up to date.</p>
<ul class="features index">
@@ -196,7 +208,7 @@
<section id="patch-notes" class="section notes" aria-labelledby="notes-title">
<div class="container">
<div class="section-head">
<p class="kicker reveal"><span>05</span>Patch notes</p>
<p class="kicker reveal"><span>06</span>Patch notes</p>
<h2 id="notes-title" class="title reveal">What changed</h2>
</div>
<div class="releases reveal" id="releases" aria-live="polite">
@@ -207,7 +219,7 @@
<section id="community" class="section community" aria-labelledby="community-title">
<div class="container">
<p class="kicker reveal"><span>06</span>Community</p>
<p class="kicker reveal"><span>07</span>Community</p>
<h2 id="community-title" class="title reveal">Built in the open</h2>
<div class="cards index">
<a class="card row reveal" data-card data-link="discord" href="{{DISCORD}}"><span class="row-index" aria-hidden="true">01</span><span class="card-title">Discord</span><span class="card-text">Questions, bug reports and screenshots.</span><span class="card-arrow" aria-hidden="true">→</span></a>
+12
View File
@@ -250,6 +250,18 @@ code {
figcaption { display: flex; gap: 12px; margin-top: 10px; font-size: var(--text-caption); color: var(--muted); }
figcaption span { font-family: var(--mono); font-size: var(--text-micro); letter-spacing: var(--text-micro-tracking); padding-top: 1px; }
/* Performance: the README's comparison table, one row per measure. */
.performance .title { margin-bottom: 16px; }
.perf-scroll { overflow-x: auto; margin-top: 40px; border-top: 1px solid var(--rule); }
.perf-table { width: 100%; border-collapse: collapse; font-size: var(--text-caption); line-height: var(--text-caption-line); }
.perf-table caption { caption-side: top; text-align: left; padding: 14px 0; font: var(--text-micro) / var(--text-micro-line) var(--mono); letter-spacing: var(--text-micro-tracking); color: var(--muted); }
.perf-table th, .perf-table td { padding: 14px 24px 14px 0; border-bottom: 1px solid var(--rule); text-align: left; vertical-align: top; }
.perf-table thead th { font-weight: 500; color: var(--muted); white-space: nowrap; }
.perf-table tbody th { font-weight: 400; color: var(--ink-soft); min-width: 22ch; }
.perf-table td { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--muted); }
.perf-table td:first-of-type { color: var(--ink); }
.perf-notes { margin-top: 24px; font-size: var(--text-caption); color: var(--muted); }
/* Parity: the count, then every subsystem as an index row. */
.parity-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; align-items: end; margin-bottom: 64px; }
.count { font-size: clamp(96px, 16vw, 220px); line-height: 0.85; letter-spacing: -0.05em; font-weight: 500; }