From ad771ff2b5c5f52d21f6942a42607db7778b8f3a Mon Sep 17 00:00:00 2001 From: slaguru666 <111923774+slaguru666@users.noreply.github.com> Date: Wed, 12 Aug 2026 19:25:12 +0100 Subject: [PATCH] A uniselector for the pause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Foundry's pause is a spinning d20 and a caption. This replaces both from CSS alone, without touching the markup: figure#pause becomes a small navy panel with a yellow rule along the top, and the becomes the arm of a uniselector. A uniselector is the stepping switch inside a telephone exchange — an arm that clicks round one contact at a time, hunting for a free line. It is the right object for this game. The department's whole business is a machine that says where things belong, and OPEN DAY is set inside one. Eleven contacts, because eleven minutes is the interval this setting keeps returning to. It STEPS rather than sweeps: steps(11) over 7.7s, so a contact every 700ms. A continuous spin reads as a loading throbber; a discrete click reads as a machine working through a list, which is what the department is doing while the table is out of the room. The arm carries a faint trailing sector, because without it a 700ms step is easy to miss and the stepping is the whole idea. No new text. Foundry's caption is localised and this only restyles it — a string hardcoded in a stylesheet would be one the lang file could never reach. Two things the browser had to be asked rather than assumed: - Core pins #pause with BOTH top and bottom, so an auto height stretched it to 180px for a 16px caption. It is pinned here instead and sized to content. - The arm is rotated, so getBoundingClientRect returns the diagonal of its own square (75px for a 52px element). The layout takes its size from the flex basis and never from the measured box. prefers-reduced-motion stops the movement and keeps the object — a stepping dial in the corner of the eye is exactly what that preference is asking about. Version 1.0.4. Co-Authored-By: Claude Opus 5 --- packs/armour/LOG | 2 +- packs/expedition/LOG | 2 +- packs/gear/LOG | 2 +- packs/lastadmission/LOG | 2 +- packs/npcs/LOG | 2 +- packs/powers/LOG | 2 +- packs/pregens/LOG | 2 +- packs/primer/LOG | 2 +- packs/prologue/LOG | 2 +- packs/rules/LOG | 2 +- packs/skills/LOG | 2 +- packs/slice/LOG | 2 +- packs/starter/LOG | 2 +- packs/tables/LOG | 2 +- packs/talents/LOG | 2 +- packs/vehicles/LOG | 2 +- packs/weapons/LOG | 2 +- styles/ringbrp.css | 101 ++++++++++++++++++++++++++++++++++++++++ system.json | 2 +- 19 files changed, 119 insertions(+), 18 deletions(-) diff --git a/packs/armour/LOG b/packs/armour/LOG index 5bb77fc..49cdcec 100644 --- a/packs/armour/LOG +++ b/packs/armour/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.951787 172dab000 Delete type=3 #1 +2026/08/12-19:24:52.815175 17303f000 Delete type=3 #1 diff --git a/packs/expedition/LOG b/packs/expedition/LOG index 6063951..25f92e0 100644 --- a/packs/expedition/LOG +++ b/packs/expedition/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.036764 172dab000 Delete type=3 #1 +2026/08/12-19:24:52.889991 17384b000 Delete type=3 #1 diff --git a/packs/gear/LOG b/packs/gear/LOG index ba3adaa..e397aed 100644 --- a/packs/gear/LOG +++ b/packs/gear/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.954786 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.817229 17303f000 Delete type=3 #1 diff --git a/packs/lastadmission/LOG b/packs/lastadmission/LOG index 4494859..15d4892 100644 --- a/packs/lastadmission/LOG +++ b/packs/lastadmission/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.015776 172dab000 Delete type=3 #1 +2026/08/12-19:24:52.871528 174057000 Delete type=3 #1 diff --git a/packs/npcs/LOG b/packs/npcs/LOG index bece731..f965d77 100644 --- a/packs/npcs/LOG +++ b/packs/npcs/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.996296 1735b7000 Delete type=3 #1 +2026/08/12-19:24:52.853027 17303f000 Delete type=3 #1 diff --git a/packs/powers/LOG b/packs/powers/LOG index db9ba5a..c333a23 100644 --- a/packs/powers/LOG +++ b/packs/powers/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.030689 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.884011 174057000 Delete type=3 #1 diff --git a/packs/pregens/LOG b/packs/pregens/LOG index b0551db..469709f 100644 --- a/packs/pregens/LOG +++ b/packs/pregens/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.979932 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.837710 17303f000 Delete type=3 #1 diff --git a/packs/primer/LOG b/packs/primer/LOG index 5c2b0f5..e6e7721 100644 --- a/packs/primer/LOG +++ b/packs/primer/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.025079 172dab000 Delete type=3 #1 +2026/08/12-19:24:52.880282 174057000 Delete type=3 #1 diff --git a/packs/prologue/LOG b/packs/prologue/LOG index ab9ac92..ba708a6 100644 --- a/packs/prologue/LOG +++ b/packs/prologue/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.020396 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.876362 172833000 Delete type=3 #1 diff --git a/packs/rules/LOG b/packs/rules/LOG index 47f4d72..d956fbf 100644 --- a/packs/rules/LOG +++ b/packs/rules/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.035224 1735b7000 Delete type=3 #1 +2026/08/12-19:24:52.888015 174057000 Delete type=3 #1 diff --git a/packs/skills/LOG b/packs/skills/LOG index 18c4d76..6ce03b1 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.942094 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.808706 17303f000 Delete type=3 #1 diff --git a/packs/slice/LOG b/packs/slice/LOG index 706211f..bb2c129 100644 --- a/packs/slice/LOG +++ b/packs/slice/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.028001 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.882429 174057000 Delete type=3 #1 diff --git a/packs/starter/LOG b/packs/starter/LOG index 6df5c01..319db93 100644 --- a/packs/starter/LOG +++ b/packs/starter/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.007789 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.863812 17384b000 Delete type=3 #1 diff --git a/packs/tables/LOG b/packs/tables/LOG index d8ebc97..869173d 100644 --- a/packs/tables/LOG +++ b/packs/tables/LOG @@ -1 +1 @@ -2026/08/12-19:12:21.001198 172dab000 Delete type=3 #1 +2026/08/12-19:24:52.857469 17384b000 Delete type=3 #1 diff --git a/packs/talents/LOG b/packs/talents/LOG index 2b1a82a..665b9da 100644 --- a/packs/talents/LOG +++ b/packs/talents/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.946329 173dc3000 Delete type=3 #1 +2026/08/12-19:24:52.811553 17303f000 Delete type=3 #1 diff --git a/packs/vehicles/LOG b/packs/vehicles/LOG index 178e118..57c5462 100644 --- a/packs/vehicles/LOG +++ b/packs/vehicles/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.956885 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.819322 17303f000 Delete type=3 #1 diff --git a/packs/weapons/LOG b/packs/weapons/LOG index 9eaa83d..dea0860 100644 --- a/packs/weapons/LOG +++ b/packs/weapons/LOG @@ -1 +1 @@ -2026/08/12-19:12:20.948434 17259f000 Delete type=3 #1 +2026/08/12-19:24:52.813317 17384b000 Delete type=3 #1 diff --git a/styles/ringbrp.css b/styles/ringbrp.css index 3a0b5f7..1210f8f 100644 --- a/styles/ringbrp.css +++ b/styles/ringbrp.css @@ -1684,3 +1684,104 @@ .rb-dying { border-left: 3px solid var(--rb-danger); padding-left: 8px; } .rb-stable { border-left: 3px solid var(--rb-yellow); padding-left: 8px; } .rb-dead { border-left: 3px solid var(--rb-white); padding-left: 8px; } + +/* ============================================================ + THE PAUSE — a uniselector, stepping + ============================================================ + Foundry's pause is a
holding an and a +
. Both are replaced here without touching the markup. + + A uniselector is the stepping switch inside a telephone exchange: an arm that clicks + round one contact at a time, hunting for a free line. It is the right object for this + game — the department's whole business is a machine that says where things belong, + and OPEN DAY is set inside one. Eleven contacts, because eleven minutes is the + interval this setting keeps coming back to. + + It STEPS rather than sweeps. A continuous spin reads as a loading throbber; a + discrete click every 700ms reads as a machine working through a list, which is what + the department is doing while the table is out of the room. + + No new text: Foundry's own caption is localised and this only restyles it. A string + hardcoded here would be one the lang file could never reach. + ============================================================ */ + +#pause { + /* Core pins this with BOTH top and bottom, so an auto height stretches it down the + whole screen — 180px tall for a 16px caption. Pin it once, here, and size to + content. The arm is rotated, so its bounding box is the diagonal of its own square: + the panel is laid out from the flex basis, never from getBoundingClientRect. */ + position: fixed; + left: 50%; bottom: 14vh; top: auto; right: auto; + transform: translateX(-50%); + height: auto; width: max-content; + display: flex; align-items: center; gap: 16px; + min-width: 320px; padding: 14px 22px 14px 16px; + background: color-mix(in srgb, var(--rb-void) 88%, transparent); + border: 1px solid var(--rb-line); + border-top: 2px solid var(--rb-yellow); + border-radius: 0; + box-shadow: 0 10px 40px rgba(0,0,0,.55); +} + +/* the dial: eleven contacts, standing still */ +#pause::before { + content: ""; + position: absolute; left: 16px; top: 50%; + width: 52px; height: 52px; margin-top: -26px; + border-radius: 50%; + border: 1px solid var(--rb-hairline); + background: + repeating-conic-gradient(from -90deg, + var(--rb-line) 0deg 2.4deg, transparent 2.4deg 32.727deg); + -webkit-mask: radial-gradient(circle, transparent 0 15px, #000 16px); + mask: radial-gradient(circle, transparent 0 15px, #000 16px); + opacity: .95; +} + +/* the arm. The keeps its box and loses its pixels: object-position walks the + raster out of the frame, which leaves a paintable element without a second wrapper. */ +#pause img { + position: relative; z-index: 1; + flex: 0 0 52px; width: 52px; height: 52px; margin: 0; + object-fit: none; object-position: -999px -999px; + border: none; filter: none; + /* the arm, and behind it the contact it has just left — without the trailing sector + a 700ms step is easy to miss entirely, and the whole point is that it is stepping */ + background: conic-gradient(from -92deg, + var(--rb-yellow) 0deg 5deg, + var(--rb-yellow-dim) 5deg 30deg, + transparent 30deg 360deg); + -webkit-mask: radial-gradient(circle, #000 0 22px, transparent 23px); + mask: radial-gradient(circle, #000 0 22px, transparent 23px); + animation: rb-uniselector 7.7s steps(11, end) infinite; +} +/* Foundry adds fa-spin to that img; ours is the only rotation that should run. */ +#pause img.fa-spin { animation: rb-uniselector 7.7s steps(11, end) infinite; } + +/* the hub, and the amber that says the record is being written */ +#pause::after { + content: ""; + position: absolute; left: 38px; top: 50%; + width: 8px; height: 8px; margin-top: -4px; + border-radius: 50%; + background: var(--rb-yellow); + animation: rb-pause-pip 2.6s ease-in-out infinite; +} + +#pause figcaption { + font-family: var(--rb-display); + font-size: 13px; letter-spacing: .22em; text-transform: uppercase; + color: var(--rb-yellow); + text-shadow: none; padding: 0; margin: 0; + border-left: 1px solid var(--rb-hairline); padding-left: 16px; +} + +@keyframes rb-uniselector { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } +@keyframes rb-pause-pip { 0%, 100% { opacity: .25; } 50% { opacity: 1; } } + +/* A stepping dial in the corner of the eye is exactly the sort of thing a reduced-motion + preference is asking us not to do. Keep the object, stop the movement. */ +@media (prefers-reduced-motion: reduce) { + #pause img, #pause img.fa-spin, #pause::after { animation: none; } + #pause img { transform: rotate(-32deg); } +} diff --git a/system.json b/system.json index 7648ab0..44e2169 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "ringbrp", "title": "The Custodians", "description": "A Basic Roleplaying game of agents who cross the crossing to contain what should not be there — and who come back a little less from here each time.", - "version": "1.0.3", + "version": "1.0.4", "compatibility": { "minimum": 13, "verified": "14.364"