47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
16:45DeepSeek V4.1 Flash Is Shockingly Good for the Price
Sep 10, 2026 · YouTube
17:14How much better is GPT-6 Astra over Claude Opus 5? Real Website and Coding Tests
Sep 5, 2026 · YouTube
29:13Implementing a multiplayer game with GPT-6 Astra (+ Gemini 3.8, Opus 5, Sol Pro)
Sep 5, 2026 · YouTube
19:42Meta Muse Spark 1.3 Review: A Huge Leap Forward
Sep 2, 2026 · YouTube
17:31Testing Gemini 3.8 Flash on Real Coding Challenges (vs. other models)
Sep 2, 2026 · YouTube
Build one self-contained HTML page for a museum armoury exhibit: a standing figure and a slider that re-equips that same figure across three periods of human history.
Choose any three periods from recorded human history, anywhere in the world. Put them in chronological order and keep adjacent choices at least 100 years apart. For each, name a specific year and place; if an exact year is impossible, give the tightest defensible date range and explain it in the label.
Choose periods you can depict accurately. You are judged on the drawing as well as the interface.
Math.random, clocks, or accumulated state.localStorage, sessionStorage, cookies, or indexedDB.One line per period: date, place, equipment, weapon, and one specific detail a non-specialist might miss.
One paragraph explaining the attachment points, layer order, and interpolation between periods.
One fenced html block containing the complete page.
Name the least certain historical choice and any accuracy compromise you made for legibility.
I will move the slider slowly in both directions, watch the feet and shoulders for drift, compare labels to drawings, inspect the SVG structure, and go straight to the final period before judging the rest.
One permanent SVG body establishes the head, shoulders, pelvis, knees, ankles and soles. Named, fixed-coordinate mounts carry the leg coverings, torso equipment, arm defences, headgear, sword, shield and gripping hands. The drawing order is body → leg equipment → torso and skirts → arm defences → helmet → weapons and shields → hands. The slider changes only equipment opacity, using complementary, piecewise-linear weights between adjacent stops; it never transforms the body or its mounts. Intermediate positions are explicitly labelled as visual blends, with both equipment inventories shown. All output is calculated directly from the slider value, so reversing direction or returning to a stop reproduces the same drawing.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>One Body, Three Armours — Museum Study</title>
<style>
:root {
color-scheme: dark;
--bg: #111818;
--panel: #172020;
--ink: #f0eadc;
--muted: #b1b9ae;
--gold: #d8b77b;
--line: #35413e;
}
* { box-sizing: border-box; }
body {
margin: 0;
background: var(--bg);
color: var(--ink);
font-family: Georgia, "Times New Roman", serif;
}
button, input { font: inherit; }
button:focus-visible, input:focus-visible {
outline: 2px solid var(--gold);
outline-offset: 6px;
}
.page { max-width: 1180px; margin: auto; padding: 36px 32px 24px; }
header {
display: flex; justify-content: space-between; gap: 28px;
align-items: flex-end; padding-bottom: 25px;
border-bottom: 1px solid var(--line);
}
.eyebrow, .accession, .small-label, .period, .control-heading {
font-family: Arial, Helvetica, sans-serif;
text-transform: uppercase; letter-spacing: .16em; font-size: 11px;
}
.eyebrow { color: var(--gold); margin: 0 0 12px; }
h1 { font-weight: normal; font-size: clamp(32px, 4vw, 49px); margin: 0; }
.intro {
max-width: 315px; margin: 0 0 3px; color: var(--muted);
font: 14px/1.65 Arial, Helvetica, sans-serif;
}
.exhibit { display: grid; grid-template-columns: 1.25fr 1fr; gap: 36px; }
.display { min-width: 0; }
.stage {
position: relative; margin-top: 22px; overflow: hidden;
background: radial-gradient(ellipse at 50% 38%, #34423e 0, #1a2725 45%, #14201e 76%);
border: 1px solid #2a3834;
}
.accession {
position: absolute; top: 17px; left: 18px;
color: #adb8aa; font-size: 9px; pointer-events: none;
}
.stage-note {
position: absolute; bottom: 13px; right: 15px; color: #93a195;
font: 9px Arial, Helvetica, sans-serif; letter-spacing: .15em;
text-transform: uppercase;
}
#figure { display: block; width: 100%; height: 590px; }
#figure [data-era="1"], #figure [data-era="2"] { opacity: 0; }
/* Equipment opacity is assigned directly by JS. No transitions or animations. */
.caption {
padding: 19px 0 22px; min-height: 176px;
border-bottom: 1px solid var(--line);
}
.small-label { color: var(--gold); margin: 0 0 9px; font-size: 10px; }
#readout-title { margin: 0 0 12px; font-size: 23px; font-weight: normal; line-height: 1.25; }
.inventory { margin: 0; font: 12px/1.6 Arial, Helvetica, sans-serif; }
.inventory + .inventory { border-top: 1px solid var(--line); padding-top: 11px; margin-top: 11px; }
.inventory dt { color: #b7c4b8; float: left; clear: left; width: 76px; }
.inventory dd { margin-left: 76px; color: #e3e3d7; margin-bottom: 4px; }
.blend-heading { color: var(--gold); font: 12px/1.5 Arial, sans-serif; margin: 0 0 7px; }
.curation { padding-top: 44px; }
.section-number { color: var(--gold); font: italic 23px Georgia, serif; }
h2 { font-size: 31px; line-height: 1.16; font-weight: normal; margin: 11px 0 18px; }
.explanation { color: var(--muted); font: 14px/1.75 Arial, sans-serif; margin: 0; }
.controls {
margin-top: 32px; padding: 22px 0;
border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.control-heading { display: flex; justify-content: space-between; color: var(--gold); margin-bottom: 20px; }
#position { color: var(--muted); letter-spacing: .05em; }
.range-wrap { padding: 0 10px; }
input[type="range"] {
display: block; width: 100%; height: 26px; margin: 0;
appearance: none; -webkit-appearance: none;
background: transparent; cursor: ew-resize; accent-color: var(--gold);
}
input[type="range"]::-webkit-slider-runnable-track {
height: 3px; background: #697567; border-radius: 2px;
}
input[type="range"]::-moz-range-track {
height: 3px; background: #697567; border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none; -webkit-appearance: none;
width: 19px; height: 19px; margin-top: -8px;
border: 3px solid var(--panel); border-radius: 50%;
background: var(--gold); box-shadow: 0 0 0 1px var(--gold);
}
input[type="range"]::-moz-range-thumb {
width: 13px; height: 13px; border: 3px solid var(--panel);
border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 1px var(--gold);
}
.stops { display: grid; grid-template-columns: repeat(3, 1fr); margin-top: 10px; gap: 8px; }
.stop {
border: 1px solid transparent; padding: 10px 3px;
background: transparent; color: var(--muted); cursor: pointer; text-align: center;
}
.stop strong { display: block; font: normal 22px Georgia, serif; }
.stop span { display: block; font: 10px Arial, sans-serif; margin-top: 6px; letter-spacing: .05em; }
.stop[aria-pressed="true"] { border-color: #665c44; background: #252b24; color: var(--gold); }
.stop:hover { color: var(--ink); border-color: #4b554a; }
.help { color: #9ba99e; margin: 15px 0 0; font: 11px/1.7 Arial, sans-serif; }
.observation { padding: 23px 0 0; }
#detail { color: #d8dbce; font-size: 18px; line-height: 1.55; margin: 0; min-height: 110px; }
.key { display: flex; gap: 10px; align-items: flex-start; margin-top: 25px; color: var(--muted); font: 11px/1.65 Arial, sans-serif; }
.key i { width: 22px; height: 1px; margin-top: 8px; background: var(--gold); flex-shrink: 0; }
footer {
display: flex; justify-content: space-between; gap: 24px;
color: #97a498; padding-top: 22px; margin-top: 20px;
border-top: 1px solid var(--line); font: 10px/1.6 Arial, sans-serif;
}
footer p { max-width: 720px; margin: 0; }
footer span { white-space: nowrap; color: var(--gold); letter-spacing: .12em; }
@media (max-width: 760px) {
.page { padding: 24px 19px; }
header { display: block; }
.intro { max-width: none; margin-top: 16px; }
.exhibit { grid-template-columns: 1fr; gap: 0; }
.curation { padding-top: 27px; }
#figure { height: 540px; }
.caption { min-height: 0; }
.controls { margin-top: 22px; }
#detail { min-height: 0; }
footer { display: block; }
footer span { display: block; margin-top: 13px; }
}
@media (max-width: 390px) { #figure { height: 470px; } }
</style>
</head>
<body>
<main class="page">
<header>
<div>
<p class="eyebrow">The armoury / comparative study 01</p>
<h1>One body. Three armours.</h1>
</div>
<p class="intro">From a flexible shirt of iron rings to an articulated steel shell. Re-equip the same standing figure across four centuries.</p>
</header>
<div class="exhibit">
<section class="display" aria-label="Armoured figure and equipment inventory">
<div class="stage">
<div class="accession">Front elevation<br><br>Fixed anatomical scale</div>
<svg id="figure" xmlns="http://www.w3.org/2000/svg" viewBox="100 48 400 630"
role="img" aria-labelledby="svg-title svg-description">
<title id="svg-title">Norman armour, Hastings, 1066</title>
<desc id="svg-description">A single standing body carries interchangeable historical equipment. Its head, shoulders, legs and feet remain fixed.</desc>
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2=".15">
<stop stop-color="#53666a"/>
<stop offset=".25" stop-color="#a4b5b4"/>
<stop offset=".48" stop-color="#e1e5d9"/>
<stop offset=".63" stop-color="#a6b6b4"/>
<stop offset="1" stop-color="#4d6268"/>
</linearGradient>
<linearGradient id="steel-dark" x1="0" y1="0" x2="1" y2="0">
<stop stop-color="#35494e"/>
<stop offset=".42" stop-color="#a5b6b3"/>
<stop offset="1" stop-color="#40575e"/>
</linearGradient>
<linearGradient id="blade" x1="0" y1="0" x2="1" y2="0">
<stop stop-color="#6d8589"/>
<stop offset=".48" stop-color="#e9eee2"/>
<stop offset=".51" stop-color="#8fa8aa"/>
<stop offset="1" stop-color="#c3cfca"/>
</linearGradient>
<linearGradient id="cloth" x1="0" y1="0" x2="1" y2="0">
<stop stop-color="#541e20"/>
<stop offset=".36" stop-color="#a34a42"/>
<stop offset=".65" stop-color="#903a35"/>
<stop offset="1" stop-color="#4e2224"/>
</linearGradient>
<linearGradient id="ochre" x1="0" y1="0" x2="1" y2=".8">
<stop stop-color="#d6b16c"/>
<stop offset="1" stop-color="#8a6239"/>
</linearGradient>
<linearGradient id="linen" x1="0" y1="0" x2="1" y2="1">
<stop stop-color="#ede1bb"/>
<stop offset="1" stop-color="#a79975"/>
</linearGradient>
<pattern id="mail" patternUnits="userSpaceOnUse" width="7" height="8">
<path d="M0 0H7V8H0Z" fill="#4d5d5b"/>
<g fill="none" stroke-width=".75">
<ellipse cx="1.75" cy="2" rx="2.05" ry="2.65" stroke="#a1ada1"/>
<ellipse cx="5.25" cy="6" rx="2.05" ry="2.65" stroke="#b0b8ab"/>
<path d="M0 4L3.5 0M3.5 8L7 4" stroke="#263b3c"/>
</g>
</pattern>
<pattern id="grip-wrap" width="8" height="6" patternUnits="userSpaceOnUse">
<path d="M0 0H8V6H0Z" fill="#533c2d"/>
<path d="M0 5L8 1" stroke="#ab8253" stroke-width="1"/>
</pattern>
<!-- These shapes are limbs/equipment, never complete alternative bodies. -->
<path id="leg-outline" d="M-21-108 Q-27-64-18-10
L-16 111 Q-16 127-30 134 L-39 140 L-40 149
L13 149 Q18 140 13 125 L18 5 Q27-62 21-108Z"/>
<path id="arm-outline" d="M-3-13 Q-18-13-23 17
L-29 67 L-42 135 Q-48 153-38 161
Q-28 169-20 157 L-11 112 L2 70 L15 18 Q17-7-3-13Z"/>
<g id="mail-leg" stroke="#263a3a" stroke-width="1.6" stroke-linejoin="round">
<use href="#leg-outline" fill="url(#mail)"/>
<path d="M-19-36Q0-27 19-36M-15 115Q0 122 14 115" fill="none" stroke="#283c39"/>
<path d="M-38 146H13" stroke="#d1bb8a" stroke-width="2"/>
<path d="M-16 123Q-1 129 13 123" fill="none" stroke="#9c8964" stroke-width="2"/>
</g>
<g id="plate-leg" stroke="#2c4147" stroke-width="1.6" stroke-linejoin="round">
<!-- Cuisse: top concealed beneath the tasset. -->
<path d="M-21-89Q0-103 21-89 L17-20Q0-7-17-20Z" fill="url(#steel)"/>
<path d="M-17-85Q0-94 17-85M-17-24Q0-14 17-24" fill="none" stroke="#d7ded3"/>
<path d="M0-89L0-23" fill="none" stroke="#eef0df" opacity=".65"/>
<!-- Poleyn, side wing, and overlapping knee lames. -->
<path d="M-16-18Q-31-28-36-9Q-40 6-21 15L-15 6Z" fill="url(#steel-dark)"/>
<path d="M-16-16Q0-24 17-15L20 3Q1 21-20 4Z" fill="url(#steel)"/>
<path d="M-17 7Q0 21 17 7L16 20Q0 28-16 19Z" fill="url(#steel-dark)"/>
<path d="M-17-12Q0-19 17-12M-17 3Q0 14 18 2" fill="none" stroke="#d7dfd4"/>
<circle cx="-18" cy="-3" r="2.2" fill="#d4c493"/>
<circle cx="17" cy="-3" r="2.2" fill="#d4c493"/>
<!-- Greave, with its front ridge and ankle flare. -->
<path d="M-16 23Q0 29 16 23L12 105L15 121Q0 131-16 119L-13 101Z" fill="url(#steel)"/>
<path d="M0 30L0 118M-12 29L-10 108" fill="none" stroke="#e0e5d9"/>
<path d="M12 35L10 110" fill="none" stroke="#556d70"/>
<circle cx="12" cy="44" r="1.5" fill="#d8d6b6"/>
<circle cx="10" cy="104" r="1.5" fill="#d8d6b6"/>
<!-- Articulated sabaton: same ankle and sole as the body. -->
<path d="M-15 119Q0 124 13 119L14 139L11 149H-40L-39 141L-26 133Z" fill="url(#steel-dark)"/>
<path d="M-18 125Q-2 132 13 127
M-24 132Q-7 137 14 133
M-31 138Q-8 142 14 140
M-38 144L12 145" fill="none" stroke="#c9d4cc"/>
<path d="M-38 149H12" stroke="#141f20" stroke-width="2.5"/>
</g>
<g id="mail-arm" stroke="#2b3d3c" stroke-width="1.5">
<use href="#arm-outline" fill="url(#mail)"/>
<path d="M-29 65Q-15 74 1 68M-40 140L-18 147" fill="none" stroke="#788b7c"/>
</g>
<g id="short-mail-arm" stroke="#2b3d3c" stroke-width="1.5">
<path d="M-3-13Q-18-13-23 17L-30 73Q-14 85 1 75L15 18Q17-7-3-13Z" fill="url(#mail)"/>
<path d="M-29 70Q-14 81 2 72" fill="none" stroke="#c0ba93"/>
</g>
<g id="plate-arm" stroke="#2a4046" stroke-width="1.6" stroke-linejoin="round">
<!-- Mail survives only in the articulation gaps. -->
<path d="M-10-9L10 5L0 79L-14 94L-31 81L-20 45Z" fill="url(#mail)"/>
<path d="M-15 17Q-2 13 10 23L1 66Q-13 75-27 65Z" fill="url(#steel)"/>
<path d="M-14 22L-23 60M5 25L-3 62" fill="none" stroke="#d6e0d5"/>
<path d="M-27 66Q-9 57 2 72L-2 89Q-15 99-31 84Z" fill="url(#steel-dark)"/>
<path d="M-26 65Q-43 66-42 83L-30 100L-20 86Z" fill="url(#steel)"/>
<path d="M-29 72Q-15 65-1 75M-29 83Q-15 91-3 84" fill="none" stroke="#d6dfd3"/>
<circle cx="-29" cy="80" r="2" fill="#d3bd86"/>
<path d="M-29 91Q-17 99-5 93L-18 139Q-31 149-40 138Z" fill="url(#steel)"/>
<path d="M-25 99L-34 133" fill="none" stroke="#edf0df"/>
<path d="M-40 135Q-30 145-17 137L-15 151Q-29 160-44 148Z" fill="url(#steel-dark)"/>
<path d="M-40 139Q-29 149-17 142" fill="none" stroke="#dae2d7"/>
</g>
<g id="bare-fist" stroke="#513d31" stroke-width="1.3" stroke-linecap="round">
<path d="M-7-10Q-13-9-12-1L-11 8Q-8 15 2 12L9 8L9-7Q6-13 1-9L-1-4Z" fill="#ba916a"/>
<path d="M-1-4L6-3M-4 1L8 2M-4 6L8 7M-8-7Q-2-9-1-4L-3 4" fill="none"/>
</g>
<g id="mail-fist" stroke="#2e4141" stroke-width="1.4">
<path d="M-9-12Q-16-9-13 2L-10 11Q-3 17 8 10L11 3L8-10Q2-15-1-8Z" fill="url(#mail)"/>
<path d="M-8-8Q-2-10 0-5L-3 4M-11 10Q-1 14 8 8" fill="none" stroke="#b8bda9"/>
<path d="M-9-12L8-10" stroke="#b2a47d" stroke-width="2"/>
</g>
<g id="steel-fist" stroke="#30464a" stroke-width="1.2" stroke-linejoin="round">
<path d="M-10-12L8-11L12 4L6 13L-7 13L-14 2Z" fill="url(#steel)"/>
<path d="M-10-4L9-3L10 2L-11 1ZM-10 3L9 4L7 9L-8 8Z" fill="url(#steel-dark)"/>
<path d="M-7-4L-7 8M-2-4L-2 9M3-3L3 9" fill="none" stroke="#d7ded3"/>
<path d="M-10-10Q-2-13 1-6L-3 3L-8 1Z" fill="url(#steel)"/>
<circle cx="-8" cy="-7" r="1.4" fill="#d9c796"/>
</g>
</defs>
<!-- Quiet architectural datum, not part of the figure. -->
<g fill="none" stroke="#94a188" stroke-width=".65" opacity=".2">
<path d="M300 68V650M172 650H453"/>
<ellipse cx="300" cy="335" rx="153" ry="252"/>
<path d="M160 210H440M174 500H426" stroke-dasharray="2 7"/>
<path d="M173 78H184M173 78V649M173 649H184"/>
</g>
<ellipse cx="302" cy="654" rx="119" ry="12" fill="#0b1312" opacity=".7"/>
<path d="M193 667H421" stroke="#8a967b" stroke-width=".65" opacity=".35"/>
<!-- ONE PERMANENT BODY.
World anchors:
head(300,130), neck(300,172), shoulders(245,210)/(355,210),
elbows(225,286)/(375,286), hands(212,358)/(388,358),
pelvis(300,386), knees(270,500)/(330,500),
ankles(270,620)/(330,620), soles y=649.
No JavaScript changes any geometry or transform. -->
<g id="body" stroke="#202d2b" stroke-width="1.8" stroke-linejoin="round">
<g id="body-leg-right" transform="translate(270 500)">
<use href="#leg-outline" fill="#746e53"/>
<path d="M-16 121Q0 125 13 121L13 140L11 149H-40L-39 140L-29 134Z" fill="#4b3d2e"/>
<path d="M-15 127L10 131M-23 134L10 137" stroke="#a28b63" fill="none"/>
</g>
<g id="body-leg-left" transform="translate(330 500) scale(-1 1)">
<use href="#leg-outline" fill="#746e53"/>
<path d="M-16 121Q0 125 13 121L13 140L11 149H-40L-39 140L-29 134Z" fill="#4b3d2e"/>
<path d="M-15 127L10 131M-23 134L10 137" stroke="#a28b63" fill="none"/>
</g>
<path id="body-torso" d="M250 191Q270 181 282 180H318Q335 181 350 191
L358 247L339 329L347 386Q300 414 253 386L261 329L242 247Z" fill="#655f49"/>
<path d="M265 330Q300 344 337 330M265 354L259 389M335 354L341 389" fill="none" stroke="#8b8262"/>
<g id="body-arm-right" transform="translate(245 210)">
<use href="#arm-outline" fill="#777158"/>
<path d="M-32 86L-13 93M-37 113L-20 121" stroke="#989174" fill="none"/>
</g>
<g id="body-arm-left" transform="translate(355 210) scale(-1 1)">
<use href="#arm-outline" fill="#777158"/>
<path d="M-32 86L-13 93M-37 113L-20 121" stroke="#989174" fill="none"/>
</g>
<path id="body-neck" d="M286 148L283 185Q300 198 317 185L314 148Z" fill="#ad805c"/>
<g id="body-head" transform="translate(300 130)">
<path d="M-23-19Q-21-38 0-38Q21-38 23-19L22 10Q18 31 0 36Q-18 31-22 10Z" fill="#bd956e"/>
<path d="M-17-4L-7-5M7-5L17-4" stroke="#4a3c30" stroke-width="2"/>
<path d="M0-3L-3 10L3 11M-7 21Q0 24 7 21" fill="none" stroke="#805e45" stroke-width="1.2"/>
</g>
</g>
<!-- LEG ATTACHMENTS: fixed knees, ankles and soles. -->
<g id="mount-leg-right" transform="translate(270 500)">
<g data-era="1"><use href="#mail-leg"/></g>
<g data-era="2"><use href="#plate-leg"/></g>
</g>
<g id="mount-leg-left" transform="translate(330 500) scale(-1 1)">
<g data-era="1"><use href="#mail-leg"/></g>
<g data-era="2"><use href="#plate-leg"/></g>
</g>
<!-- TORSO ATTACHMENT: all three kits share this single mount. -->
<g id="mount-torso" transform="translate(300 210)" stroke-linejoin="round">
<g data-era="0" stroke="#2c3d39" stroke-width="1.7">
<path d="M-51-18Q0-39 51-18L44 91L64 251L10 259L0 190L-10 259L-64 251L-44 91Z" fill="url(#mail)"/>
<path d="M-44 87Q0 108 44 87M0 150V190M-58 249L-14 256M14 256L58 249" fill="none" stroke="#a5ab93"/>
<path d="M-45 127Q0 140 45 127L46 137Q0 150-46 137Z" fill="#56412c"/>
<path d="M-8 135H9V146H-8Z" fill="#b8a16b" stroke="#5f5034"/>
<path d="M-4 137H6V143H-4Z" fill="#4e422d"/>
<path d="M7 142L16 185L22 183L16 141" fill="#665036" stroke="#403b29"/>
<circle cx="18" cy="176" r="1.4" fill="#c7af75" stroke="none"/>
<path d="M-39 158L-47 229M38 158L46 229" fill="none" stroke="#263c3b" opacity=".65"/>
</g>
<g data-era="1" stroke="#293d3c" stroke-width="1.7">
<path d="M-51-18Q0-39 51-18L44 91L64 249L11 258L0 191L-11 258L-64 249L-44 91Z" fill="url(#mail)"/>
<path d="M-42-23L-20-31Q0-10 20-31L42-23L34 97L59 254L14 265L0 195L-14 265L-59 254L-34 97Z" fill="url(#cloth)" stroke="#412b29"/>
<path d="M-40-20L-33 97L-55 250M40-20L33 97L55 250
M-19-28Q0-9 19-28M-54 251L-16 260M16 260L54 251" fill="none" stroke="#c7775e" stroke-width="1.4"/>
<path d="M-22 1L-12 102M22 1L12 103M-23 148L-36 242M23 148L36 242M0 149V192" fill="none" stroke="#571f24" stroke-width="2"/>
<path d="M-38 124Q0 135 38 124L40 135Q0 147-40 135Z" fill="#7b5a37" stroke="#493b2c"/>
<path d="M-9 132H9V144H-9Z" fill="#cbb47b" stroke="#77613b"/>
<path d="M-5 135H5V141H-5Z" fill="#5f482e" stroke="none"/>
<path d="M8 140L6 190L14 195L16 141Z" fill="#8e6a42" stroke="#4a3c2a"/>
<path d="M9 152H14M9 164H14M8 176H13" stroke="#cfb782"/>
</g>
<g data-era="2" stroke="#2c4147" stroke-width="1.7">
<!-- Small mail skirt and underarm voiders, not a full mail coat. -->
<path d="M-47-12L47-12L52 61L38 99H-38L-52 61Z" fill="url(#mail)"/>
<path d="M-43 172L43 172L50 235L9 239L0 207L-9 239L-50 235Z" fill="url(#mail)"/>
<!-- Rounded breastplate, with separate overlapping plackart. -->
<path d="M-39-23Q0-34 39-23Q38 5 50 30L42 102Q0 125-42 102L-50 30Q-38 5-39-23Z" fill="url(#steel)"/>
<path d="M-35-19Q0-29 35-19M-45 30Q-36 41-37 73M45 30Q36 41 37 73" fill="none" stroke="#e0e5d7" stroke-width="2"/>
<path d="M-41 88Q-17 83 0 55Q17 83 41 88L35 132Q0 144-35 132Z" fill="url(#steel-dark)"/>
<path d="M-39 89Q-17 86 0 59Q17 86 39 89" fill="none" stroke="#e3e7da" stroke-width="2"/>
<path d="M0-17Q-6 17 0 53M0 63V125" fill="none" stroke="#e2e7d8" opacity=".65"/>
<circle cx="0" cy="75" r="2.4" fill="#d2c492"/>
<path d="M27 19L39 22L38 36L29 33Z" fill="#586b6d"/>
<circle cx="32" cy="23" r="1.7" fill="#ded4b1"/>
<circle cx="32" cy="31" r="1.7" fill="#ded4b1"/>
<!-- Overlapping fauld lames. -->
<path d="M-36 128Q0 143 36 128L40 143Q0 158-40 143Z" fill="url(#steel)"/>
<path d="M-40 142Q0 157 40 142L44 158Q0 174-44 158Z" fill="url(#steel-dark)"/>
<path d="M-44 157Q0 173 44 157L48 176Q0 192-48 176Z" fill="url(#steel)"/>
<path d="M-34 132Q0 146 34 132M-38 147Q0 161 38 147M-43 163Q0 179 43 163" fill="none" stroke="#d8dfd3"/>
<g fill="#d0bc8e">
<circle cx="-31" cy="139" r="1.7"/><circle cx="31" cy="139" r="1.7"/>
<circle cx="-35" cy="154" r="1.7"/><circle cx="35" cy="154" r="1.7"/>
<circle cx="-39" cy="171" r="1.7"/><circle cx="39" cy="171" r="1.7"/>
</g>
<!-- Suspended tassets and their visible leather tabs. -->
<path d="M-39 180L-35 195M-16 185L-15 198M16 185L15 198M39 180L35 195" stroke="#735438" stroke-width="5"/>
<path d="M-44 188L-9 196L-13 241Q-33 248-51 232Z" fill="url(#steel)"/>
<path d="M44 188L9 196L13 241Q33 248 51 232Z" fill="url(#steel)"/>
<path d="M-43 193L-13 200M-48 230Q-31 241-16 237
M43 193L13 200M48 230Q31 241 16 237" fill="none" stroke="#e1e4d5"/>
<g fill="#d9c996">
<circle cx="-37" cy="199" r="2"/><circle cx="-18" cy="203" r="2"/>
<circle cx="37" cy="199" r="2"/><circle cx="18" cy="203" r="2"/>
</g>
</g>
</g>
<!-- ARM MOUNTS; the underlying shoulder and elbow centres never move. -->
<g id="mount-arm-right" transform="translate(245 210)">
<g data-era="0"><use href="#short-mail-arm"/></g>
<g data-era="1"><use href="#mail-arm"/></g>
<g data-era="2">
<use href="#plate-arm"/>
<g stroke="#2b4146" stroke-width="1.6" stroke-linejoin="round">
<path d="M-19-14Q-5-29 15-16L23 5L16 27Q-8 29-24 13Z" fill="url(#steel)"/>
<path d="M-23 7Q-4 23 20 14L17 27Q-5 35-26 18Z" fill="url(#steel-dark)"/>
<path d="M-25 19Q-5 34 17 27L12 38Q-9 41-27 29Z" fill="url(#steel)"/>
<path d="M-16-13Q-2-22 13-13M-22 12Q-5 28 17 20M-24 25Q-7 37 13 32" fill="none" stroke="#dce3d7"/>
<circle cx="-16" cy="-7" r="2" fill="#ccb887"/>
<circle cx="-19" cy="14" r="1.8" fill="#ccb887"/>
<circle cx="-21" cy="26" r="1.8" fill="#ccb887"/>
</g>
</g>
</g>
<g id="mount-arm-left" transform="translate(355 210) scale(-1 1)">
<g data-era="0"><use href="#short-mail-arm"/></g>
<g data-era="1"><use href="#mail-arm"/></g>
<g data-era="2">
<use href="#plate-arm"/>
<!-- Wearer's LEFT pauldron is deliberately larger. -->
<g stroke="#2b4146" stroke-width="1.6" stroke-linejoin="round">
<path d="M-23-17Q-3-34 20-16L29 11L22 35Q-9 40-30 17Z" fill="url(#steel)"/>
<path d="M-29 10Q-8 33 26 23L22 37Q-7 47-32 24Z" fill="url(#steel-dark)"/>
<path d="M-31 25Q-9 45 22 37L16 49Q-12 53-33 36Z" fill="url(#steel)"/>
<path d="M-21-15Q0-26 18-13M-27 16Q-8 36 23 28M-29 31Q-9 48 18 42" fill="none" stroke="#dde3d7"/>
<circle cx="-19" cy="-8" r="2" fill="#cfba88"/>
<circle cx="-24" cy="17" r="1.8" fill="#cfba88"/>
<circle cx="-26" cy="32" r="1.8" fill="#cfba88"/>
</g>
</g>
</g>
<!-- HEAD MOUNT. Helmets enclose, rather than replace, the same head. -->
<g id="mount-head" transform="translate(300 130)" stroke-linejoin="round">
<g data-era="0" stroke="#293e3e" stroke-width="1.6">
<!-- Coif's face opening leaves the permanent face visible. -->
<path d="M-30-24Q0-44 30-24L30 13Q29 37 44 58
Q0 78-44 58Q-29 37-30 13Z
M-20-16L-19 12Q-15 29 0 34Q15 29 19 12L20-16Z"
fill="url(#mail)" fill-rule="evenodd"/>
<path d="M-18 15Q0 40 18 15M-38 57Q0 71 38 57" fill="none" stroke="#aeb39e"/>
<!-- Riveted conical helmet, brow band, and nasal. -->
<path d="M-34-17Q-28-43 0-54Q28-43 34-17L33-9Q0-17-33-9Z" fill="url(#steel)"/>
<path d="M0-52Q-10-31-10-16M0-52Q12-30 12-16" fill="none" stroke="#617576"/>
<path d="M-33-18Q0-25 33-18L33-9Q0-16-33-9Z" fill="url(#steel-dark)"/>
<path d="M-4-17H4L5 19L0 24L-5 19Z" fill="url(#steel)"/>
<g fill="#d8d0ad" stroke="none">
<circle cx="-26" cy="-15" r="1.5"/><circle cx="-16" cy="-17" r="1.5"/>
<circle cx="16" cy="-17" r="1.5"/><circle cx="26" cy="-15" r="1.5"/>
<circle cx="0" cy="-13" r="1.5"/>
</g>
</g>
<g data-era="1" stroke="#293f43" stroke-width="1.6">
<path d="M-27 8L27 8Q27 37 43 59Q0 78-43 59Q-27 37-27 8Z" fill="url(#mail)"/>
<path d="M-38 57Q0 71 38 57" fill="none" stroke="#aeb59f"/>
<path d="M-35-39L33-39L37-25L31 37L0 45L-32 37L-38-24Z" fill="url(#steel-dark)"/>
<path d="M-35-39L-23-45H23L33-39Z" fill="url(#steel)"/>
<path d="M0-38V42L31 35L35-24L31-36Z" fill="#b7c1b8" opacity=".37"/>
<path d="M-36-25L0-28L36-25M-33 33L0 41L31 33" fill="none" stroke="#d2d7c9"/>
<path d="M-29-13L-6-15L-6-9L-29-7ZM6-15L29-13L29-7L6-9Z" fill="#13272a" stroke="#6c8281" stroke-width=".8"/>
<path d="M-3-36H3V39H-3Z" fill="#899c9b"/>
<path d="M0-35V38" stroke="#d5dccc" stroke-width="1"/>
<g fill="#253b3e" stroke="none">
<circle cx="12" cy="5" r="1.8"/><circle cx="21" cy="6" r="1.8"/>
<circle cx="11" cy="14" r="1.8"/><circle cx="20" cy="15" r="1.8"/>
<circle cx="10" cy="23" r="1.8"/><circle cx="19" cy="24" r="1.8"/>
<circle cx="-12" cy="5" r="1.8"/><circle cx="-21" cy="6" r="1.8"/>
<circle cx="-11" cy="14" r="1.8"/><circle cx="-20" cy="15" r="1.8"/>
<circle cx="-10" cy="23" r="1.8"/><circle cx="-19" cy="24" r="1.8"/>
</g>
<g fill="#d0cbae" stroke="#5b6b67" stroke-width=".6">
<circle cx="-29" cy="-32" r="1.6"/><circle cx="-16" cy="-33" r="1.6"/>
<circle cx="16" cy="-33" r="1.6"/><circle cx="28" cy="-32" r="1.6"/>
<circle cx="-28" cy="29" r="1.6"/><circle cx="27" cy="29" r="1.6"/>
<circle cx="0" cy="31" r="1.6"/><circle cx="0" cy="-21" r="1.6"/>
</g>
</g>
<g data-era="2" stroke="#2a4147" stroke-width="1.6">
<path d="M-23 24L23 24L29 60Q0 71-29 60Z" fill="url(#mail)"/>
<!-- Rounded skull and independently hinged cheek plates. -->
<path d="M-31-12Q-34-45 0-48Q34-45 31-12L28 23Q16 39 0 41Q-16 39-28 23Z" fill="url(#steel)"/>
<path d="M-26-20Q-23-41 0-43Q23-41 26-20" fill="none" stroke="#e7e9db"/>
<path d="M-28-2L-5 12L0 42Q-24 40-30 20Z" fill="url(#steel-dark)"/>
<path d="M28-2L5 12L0 42Q24 40 30 20Z" fill="url(#steel)"/>
<path d="M0 17V40" stroke="#364f54"/>
<!-- Front of the projecting visor: eye slit above, breaths below. -->
<path d="M-30-17Q0-25 30-17L31-5L23 17L0 26L-23 17L-31-5Z" fill="url(#steel)"/>
<path d="M-27-11L-3-13V-8L-26-6ZM3-13L27-11L26-6L3-8Z" fill="#152a2e" stroke="none"/>
<path d="M0-6L0 23M-27-1L0 5L27-1M-21 16L0 24L21 16" fill="none" stroke="#dae2d6"/>
<g fill="#2e474d" stroke="none">
<ellipse cx="-15" cy="6" rx="1.3" ry="2"/>
<ellipse cx="-9" cy="9" rx="1.3" ry="2"/>
<ellipse cx="-15" cy="12" rx="1.3" ry="2"/>
<ellipse cx="15" cy="6" rx="1.3" ry="2"/>
<ellipse cx="9" cy="9" rx="1.3" ry="2"/>
<ellipse cx="15" cy="12" rx="1.3" ry="2"/>
</g>
<circle cx="-30" cy="-9" r="3.8" fill="url(#steel-dark)"/>
<circle cx="30" cy="-9" r="3.8" fill="url(#steel-dark)"/>
<circle cx="-30" cy="-9" r="1.5" fill="#d9c99a"/>
<circle cx="30" cy="-9" r="1.5" fill="#d9c99a"/>
<path d="M-28 9L-23 12M-27 16L-22 19M23 12L28 9M22 19L27 16" stroke="#d2d9cc" stroke-width="2"/>
<path d="M-24 30Q0 47 24 30L21 40Q0 52-21 40Z" fill="url(#steel-dark)"/>
<path d="M-20 38Q0 48 20 38" fill="none" stroke="#d6ddcf"/>
<circle cx="5" cy="35" r="1.6" fill="#d2be88"/>
</g>
</g>
<!-- SWORD MOUNT: all handles meet the same right-hand anchor. -->
<g id="mount-weapon-right" transform="translate(212 358)" stroke-linejoin="round">
<g data-era="0" stroke="#30464a" stroke-width="1.5">
<path d="M-10 23H10L9 229L0 278L-9 229Z" fill="url(#blade)"/>
<!-- Broad fuller stops short of the point. -->
<path d="M-3 29H3L2 224L0 238L-2 224Z" fill="#617b7f" stroke="none"/>
<path d="M-8 30L-7 224M8 30L7 224" stroke="#e0e7da" stroke-width=".8"/>
<path d="M-6-15H6L5 21H-5Z" fill="url(#grip-wrap)" stroke="#322e26"/>
<path d="M-31 20L31 20L31 26L7 25H-7L-31 26Z" fill="url(#steel-dark)"/>
<!-- Brazil-nut pommel, rather than a later wheel. -->
<path d="M-13-19Q-15-28 0-31Q15-28 13-19Q0-11-13-19Z" fill="url(#steel)"/>
<path d="M-9-21Q0-17 9-21" fill="none" stroke="#d7decf"/>
</g>
<g data-era="1" stroke="#30464a" stroke-width="1.5">
<path d="M-10 23H10L7 172L4 239L0 278L-4 239L-7 172Z" fill="url(#blade)"/>
<path d="M-3 29H3L2 176L0 193L-2 176Z" fill="#668184" stroke="none"/>
<path d="M-6-17H6L5 22H-5Z" fill="url(#grip-wrap)" stroke="#332e27"/>
<path d="M-34 19L-12 21H12L34 19L34 25L10 27H-10L-34 25Z" fill="url(#steel)"/>
<circle cx="0" cy="-28" r="11" fill="url(#steel)"/>
<circle cx="0" cy="-28" r="7" fill="none" stroke="#dbe0d0"/>
<circle cx="0" cy="-28" r="2" fill="#687d7c" stroke="none"/>
</g>
<g data-era="2" stroke="#30464a" stroke-width="1.5">
<path d="M-9 20H9L5 153L0 286L-5 153Z" fill="url(#blade)"/>
<!-- A ridge, not a fuller: diamond-section thrusting blade. -->
<path d="M0 25V280" stroke="#eff0df" stroke-width="1"/>
<path d="M-5-51H5L6 16H-6Z" fill="url(#grip-wrap)" stroke="#342f28"/>
<path d="M-5-48H5M-5-14H5M-5 11H5" stroke="#c5b37d" stroke-width="2"/>
<path d="M-37 22L-34 16L-12 14H12L34 16L37 22L32 24L12 21H-12L-32 24Z" fill="url(#steel)"/>
<path d="M-6-52Q-13-60-8-69Q0-75 8-69Q13-60 6-52Z" fill="url(#steel)"/>
<path d="M0-69V-55" stroke="#edf0df"/>
</g>
</g>
<!-- LEFT FOREARM SHIELD MOUNT; straps are behind the opaque shield. -->
<g id="mount-shield-left" transform="translate(388 358)" stroke-linejoin="round">
<g data-era="0" stroke="#493b29" stroke-width="1.8">
<path d="M-48-66Q-43-92 0-95Q43-92 49-66
L44 34Q30 105 10 173Q-23 131-39 62Z" fill="url(#ochre)"/>
<path d="M-41-65Q-35-85 0-87Q35-85 42-65
L37 34Q25 98 9 157Q-18 119-32 61Z"
fill="none" stroke="#883f30" stroke-width="5"/>
<path d="M-45-65Q-39-89 0-91Q40-89 46-65L41 34Q28 102 10 166" fill="none" stroke="#edd09a" stroke-width="1.1"/>
<path d="M-18-77Q-10-16-5 37L8 139" fill="none" stroke="#e5bf7d" stroke-width="1.1" opacity=".6"/>
<ellipse cx="0" cy="-25" rx="19" ry="20" fill="#7d8880" stroke="#364a49"/>
<ellipse cx="0" cy="-25" rx="12" ry="14" fill="url(#steel-dark)" stroke="#405752"/>
<path d="M-7-32Q0-42 7-31" fill="none" stroke="#d3d9c8"/>
<g fill="#d0c5a0" stroke="#515949" stroke-width=".7">
<circle cx="0" cy="-42" r="1.8"/><circle cx="0" cy="-8" r="1.8"/>
<circle cx="-16" cy="-25" r="1.8"/><circle cx="16" cy="-25" r="1.8"/>
</g>
<g fill="#e3c58b" stroke="none">
<circle cx="-37" cy="-65" r="1.3"/><circle cx="37" cy="-65" r="1.3"/>
<circle cx="-35" cy="-31" r="1.3"/><circle cx="35" cy="-31" r="1.3"/>
<circle cx="-31" cy="7" r="1.3"/><circle cx="32" cy="7" r="1.3"/>
<circle cx="-23" cy="52" r="1.3"/><circle cx="26" cy="52" r="1.3"/>
<circle cx="-10" cy="96" r="1.3"/><circle cx="18" cy="96" r="1.3"/>
</g>
</g>
<g data-era="1" stroke="#584832" stroke-width="1.8">
<path d="M-48-62Q0-70 48-62L44 3Q34 62 0 102Q-34 62-44 3Z" fill="url(#linen)"/>
<path d="M-41-56Q0-63 41-56L37 2Q28 53 0 89Q-28 53-37 2Z" fill="none" stroke="#8f4236" stroke-width="5"/>
<path d="M-45-60Q0-67 45-60L41 2Q32 60 0 97" fill="none" stroke="#eed8a8" stroke-width="1"/>
<path d="M-35-52Q-24 15-6 69" fill="none" stroke="#f2e7c8" stroke-width="2" opacity=".6"/>
<!-- Leather edge stitching, no anachronistic central metal boss. -->
<path d="M-36-60L-36-54M-21-62L-21-56M-6-63L-6-57
M9-63L9-57M24-62L24-56M36-60L36-54
M-43-38L-37-38M43-38L37-38
M-41-17L-35-17M41-17L35-17
M-37 8L-31 7M37 8L31 7
M-29 32L-24 30M29 32L24 30
M-19 55L-14 52M19 55L14 52"
fill="none" stroke="#d7bd88" stroke-width="1.2"/>
</g>
<!-- 1470 deliberately has no shield; its steel left hand is visible. -->
</g>
<!-- Grip overlays: these do not alter the hand anchors. -->
<g id="mount-hand-right" transform="translate(212 358)">
<g data-era="0"><use href="#bare-fist"/></g>
<g data-era="1"><use href="#mail-fist"/></g>
<g data-era="2"><use href="#steel-fist"/></g>
</g>
<g id="mount-hand-left" transform="translate(388 358) scale(-1 1)">
<!-- First two hands are behind their shields. -->
<g data-era="2"><use href="#steel-fist"/></g>
</g>
</svg>
<div class="stage-note">Equipment reconstruction / not a portrait</div>
</div>
<!-- This inventory is deliberately UNDER the figure. -->
<div class="caption" id="readout" aria-live="polite" aria-atomic="true">
<p class="small-label" id="readout-state">Exact stop / I</p>
<h2 id="readout-title">1066 · Hastings, England</h2>
<div id="inventory">
<dl class="inventory">
<dt>Equipment</dt><dd>Norman mail hauberk, coif, nasal helmet and kite shield.</dd>
<dt>Materials</dt><dd>Iron mail and helmet; wool clothing; leather-faced wooden shield.</dd>
<dt>Weapon</dt><dd>Steel single-handed sword; broad fuller, straight guard, Brazil-nut pommel.</dd>
</dl>
</div>
</div>
</section>
<aside class="curation" aria-label="Timeline controls and curatorial notes">
<div class="section-number">I—III</div>
<h2>A changing shell.<br>An unchanging stance.</h2>
<p class="explanation">Each stop is a complete equipment study. Between stops, only the equipment dissolves: the person beneath it keeps the same proportions, posture and ground line.</p>
<div class="controls">
<label class="control-heading" for="timeline">
<span>Re-equip the figure</span>
<output id="position" for="timeline">Study I</output>
</label>
<div class="range-wrap">
<input id="timeline" type="range" min="0" max="2" step="0.001" value="0"
aria-describedby="slider-help"
aria-valuetext="1066, Hastings, England. Exact stop.">
</div>
<div class="stops" aria-label="Jump to an exact period">
<button class="stop" type="button" data-stop="0" aria-pressed="true"><strong>1066</strong><span>HASTINGS</span></button>
<button class="stop" type="button" data-stop="1" aria-pressed="false"><strong>1250</strong><span>PARIS</span></button>
<button class="stop" type="button" data-stop="2" aria-pressed="false"><strong>1470</strong><span>MILAN</span></button>
</div>
<p class="help" id="slider-help">Drag slowly to compare, or select a year for an exact stop. Arrow keys make fine adjustments; Home and End select the first and last studies. The three studies are equally spaced, not a continuous calendar.</p>
</div>
<div class="observation">
<p class="small-label">Look closely</p>
<p id="detail">The divided mail skirt accommodates riding. The Norman’s lower legs remain in wool hose—not the full mail chausses seen at the next stop.</p>
</div>
<div class="key">
<i aria-hidden="true"></i>
<span>Intermediate drawings are comparison overlays, not proposed historical armour. Their inventories identify both contributing studies.</span>
</div>
<noscript><p class="help">JavaScript is disabled. The complete 1066 study is displayed; enable JavaScript to operate the timeline.</p></noscript>
</aside>
</div>
<footer>
<p>Year-specific reconstructions of documented equipment types, not replicas of three individually dated objects. Visual reference traditions: the Bayeux Tapestry; mid-thirteenth-century French manuscript armour, including the Morgan Bible; and surviving fifteenth-century Milanese harnesses. Mail rings and small fittings are enlarged for legibility.</p>
<span>IRON / TEXTILE / STEEL</span>
</footer>
</main>
<script>
"use strict";
/* No time, randomness, persistence, animation loop, or accumulated pose.
Every displayed property is a pure function of the current range value. */
const periods = [
{
year: "1066",
place: "Hastings, England",
short: "Hastings",
name: "Norman mail",
equipment: "Norman mail hauberk, coif, nasal helmet and kite shield.",
materials: "Iron mail and helmet; wool clothing; leather-faced wooden shield.",
weapon: "Steel single-handed sword; broad fuller, straight guard, Brazil-nut pommel.",
detail: "The divided mail skirt accommodates riding. The Norman’s lower legs remain in wool hose—not the full mail chausses seen at the next stop."
},
{
year: "1250",
place: "Paris, Kingdom of France",
short: "Paris",
name: "Knight’s mail harness",
equipment: "Mail hauberk, coif, mittens and chausses; great helm, sleeveless linen surcoat and heater shield.",
materials: "Iron mail; iron/steel helmet; linen and wool clothing; leather-faced wooden shield.",
weapon: "Steel arming sword; tapering fullered blade, straight guard and wheel pommel.",
detail: "Protection now reaches the hands and feet. Mail mittens cover the sword hand, while mail chausses enclose the legs beneath the split surcoat."
},
{
year: "1470",
place: "Milan, Duchy of Milan",
short: "Milan",
name: "Milanese plate harness",
equipment: "Milanese plate harness and armet; asymmetric pauldrons, articulated gauntlets, tassets, greaves and sabatons. No shield.",
materials: "Steel plates; iron mail at gaps; textile arming foundation, leather straps and sword grip.",
weapon: "Steel longsword; long two-hand-capable grip, tapered diamond-section blade and pear-shaped pommel, held here in one hand at rest.",
detail: "The larger pauldron is on the wearer’s left—your right. Smooth, rounded plates overlap at the waist, knees and feet; mail remains visible only at vulnerable gaps."
}
];
const roman = ["I", "II", "III"];
const slider = document.getElementById("timeline");
const layers = Array.from(document.querySelectorAll("#figure [data-era]"));
const buttons = Array.from(document.querySelectorAll("[data-stop]"));
const state = document.getElementById("readout-state");
const title = document.getElementById("readout-title");
const inventory = document.getElementById("inventory");
const detail = document.getElementById("detail");
const position = document.getElementById("position");
const svgTitle = document.getElementById("svg-title");
const svgDescription = document.getElementById("svg-description");
function inventoryBlock(period, heading) {
const block = document.createElement("div");
block.className = "inventory";
if (heading) {
const h = document.createElement("p");
h.className = "blend-heading";
h.textContent = heading;
block.appendChild(h);
}
const dl = document.createElement("dl");
dl.className = "inventory";
[
["Equipment", period.equipment],
["Materials", period.materials],
["Weapon", period.weapon]
].forEach(([label, value]) => {
const dt = document.createElement("dt");
const dd = document.createElement("dd");
dt.textContent = label;
dd.textContent = value;
dl.append(dt, dd);
});
block.appendChild(dl);
return block;
}
function render() {
const value = Math.max(0, Math.min(2, Number(slider.value)));
const weights = periods.map((_, i) => Math.max(0, 1 - Math.abs(value - i)));
layers.forEach(layer => {
layer.style.opacity = String(weights[Number(layer.dataset.era)]);
});
const exact = Number.isInteger(value);
const index = exact ? value : Math.floor(value);
buttons.forEach((button, i) => {
button.setAttribute("aria-pressed", String(exact && i === index));
});
inventory.replaceChildren();
if (exact) {
const p = periods[index];
const heading = p.year + " · " + p.place;
state.textContent = "Exact stop / " + roman[index];
title.textContent = heading;
inventory.appendChild(inventoryBlock(p, ""));
detail.textContent = p.detail;
position.textContent = "Study " + roman[index];
slider.setAttribute("aria-valuetext", heading + ". Exact stop. " + p.name + ".");
svgTitle.textContent = p.name + " — " + heading;
svgDescription.textContent =
"One fixed standing body. " + p.equipment + " " + p.weapon +
" The head, shoulders, legs and feet have the same anchors in every study.";
} else {
const a = periods[index];
const b = periods[index + 1];
const pa = (weights[index] * 100).toFixed(1);
const pb = (weights[index + 1] * 100).toFixed(1);
const heading = "Between " + a.year + " · " + a.short +
" and " + b.year + " · " + b.short;
state.textContent = "Comparison blend / not a historical ensemble";
title.textContent = heading;
inventory.append(
inventoryBlock(a, a.year + " · " + a.place + " — " + pa + "% opacity"),
inventoryBlock(b, b.year + " · " + b.place + " — " + pb + "% opacity")
);
detail.textContent = "You are comparing " + a.name.toLowerCase() +
" with " + b.name.toLowerCase() +
". Both equipment sets are partially visible; the body and every attachment remain stationary.";
position.textContent = roman[index] + " ↔ " + roman[index + 1];
slider.setAttribute("aria-valuetext", heading + ". Comparison overlay: " +
pa + " percent " + a.year + ", " + pb + " percent " + b.year + ".");
svgTitle.textContent = heading + " — equipment comparison overlay";
svgDescription.textContent =
"Two partially transparent equipment sets on one fixed body, not a historical composite. " +
a.year + ": " + a.equipment + " " + a.weapon + " " +
b.year + ": " + b.equipment + " " + b.weapon;
}
}
slider.addEventListener("input", render);
buttons.forEach(button => {
button.addEventListener("click", () => {
slider.value = button.dataset.stop;
render();
});
});
render();
</script>
</body>
</html>
1470, Milan. The harness combines documented Milanese forms rather than reproducing one securely dated, complete surviving suit. The armet’s cheek-piece hinges, pauldron articulation and gauntlet fingers are simplified in frontal view; mail rings and rivets are enlarged throughout. The closed visor also compresses its real forward projection in this elevation.