source: Klonkt/src/assets/css/guardian.css@ d7e72b8

main
Last change on this file since d7e72b8 was ea211b9, checked in by roboburr <roboburr@…>, 5 weeks ago

Je hoort te weten dat je de doorslag geeft (shaer-8vt)

De telling is een race naar de drempel: zodra het aantal gehaald is, is het
besluit gevallen. Bij 2 van 3 is de tweede ja meteen de beslissing -- en sinds
Barts meerderheidsbesluit van vandaag is bij een volgverzoek met twee guardians
de EERSTE ja dat al. Wie antwoordde wist dat niet, en het scherm zei het nergens.

Dat kon niet, en waarom niet was de vondst bij shaer-nf9: gatedProgress werkt op
een LOKALE slug en er zijn geen lokale wards. De telling loopt op de server van
het kind, en die stuurde hem niet mee. Nu wel: shaer:decisive reist mee met de
doorgestuurde Offer, voor gate-voorstellen en voor volgverzoeken in beide
richtingen.

EEN JA/NEE, GEEN TELLING, en dat is een besluit. Een getal ("1 van 2") reist mee,
veroudert onderweg en leest daarna als een feit; de beschikbare set schuift met
3.6 bovendien mee. En hoeveel guardians een kind heeft, en wie er al gestemd
heeft, is niet vanzelf iets dat elke mede-guardian hoort te zien. Een
waarschuwing veroudert ook, maar hij CLAIMT niets -- en dat scheelt.

BIJ TWIJFEL WAARSCHUWEN. Ontbreekt het veld (een oudere server), dan zeggen we
dat je beslist. De twee fouten zijn niet gelijk: zeggen dat je beslist terwijl
dat niet zo is maakt iemand voorzichtiger dan nodig; niets zeggen terwijl hij wel
beslist laat hem het onwetend doen. Daar staat een toets op, en de mutatie die
ertoe doet -- onbekend als "je beslist niets" lezen -- maakt hem rood.

Eerlijk over de mutatietest: mijn eerste poging (de Number.isFinite-guards
weghalen) gaf nul fouten, want die geven voor undefined dezelfde uitkomst. De
regel bijt wel tegen de realistische verkeerde versie.

Zes toetsen, drie talen. Suite 747/747.

  • Property mode set to 100644
File size: 15.1 KB
RevLine 
[318d0c2]1/* Guardian PWA (FEP-633c): its own calm, dark surface; the buoy orange is
2 the accent. Standalone: this page never inherits the site theme. */
3:root {
4 --bg: #141a24;
5 --card: #1e2632;
6 --ink: #e8ecf2;
7 --sub: #93a0b4;
[c26cc18]8 --line: #2c3646;
[318d0c2]9 --accent: #ff6b35;
10 --ok: #4caf7d;
[742ba7e]11 --danger: #e05a5a; /* alleen voor onomkeerbare stappen, zoals een ward loslaten */
[318d0c2]12}
13* { box-sizing: border-box; }
14body {
15 margin: 0;
16 background: var(--bg);
17 color: var(--ink);
18 font: 16px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
[c26cc18]19 padding-bottom: 48px;
[318d0c2]20}
21.g-head {
22 display: flex;
23 align-items: center;
[c26cc18]24 gap: 12px;
25 padding: 16px;
[318d0c2]26 background: var(--card);
[c26cc18]27 border-bottom: 1px solid var(--line);
[318d0c2]28 position: sticky;
29 top: 0;
[c26cc18]30 z-index: 2;
[318d0c2]31}
[c26cc18]32.g-head-txt { flex: 1; }
33.g-head h1 { font-size: 1.15rem; margin: 0; }
34.g-head .g-sub { margin: 0; color: var(--sub); font-size: .78rem; }
35.g-buoy { font-size: 1.7rem; }
36.g-me { color: var(--sub); font-size: .85rem; }
[318d0c2]37#site-picker {
38 background: var(--bg); color: var(--ink);
[c26cc18]39 border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
[318d0c2]40}
[c26cc18]41main { max-width: 640px; margin: 0 auto; padding: 8px 16px; }
42
43section { padding: 18px 0; border-bottom: 1px solid var(--line); }
44section:last-child { border-bottom: 0; }
45.g-sec-head { display: flex; align-items: center; gap: 8px; }
46.g-sec-head h2 { font-size: 1.02rem; margin: 0; }
47.g-badge {
48 background: var(--accent); color: #fff; font-size: .72rem; font-weight: 700;
49 min-width: 20px; text-align: center; border-radius: 10px; padding: 1px 7px;
50}
51.g-sec-sub { color: var(--sub); font-size: .84rem; margin: 4px 0 12px; }
52.g-empty { color: var(--sub); font-size: .9rem; margin: 6px 0 0; }
53.g-msg { font-size: .85rem; color: var(--ok); margin: 8px 0 0; }
[318d0c2]54.g-msg.err { color: #ff7a7a; }
55.g-list { display: flex; flex-direction: column; gap: 8px; }
56
[c26cc18]57.g-card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
[318d0c2]58.g-card.help { border-left: 3px solid var(--accent); }
59.g-card .row { display: flex; align-items: center; gap: 10px; }
[c26cc18]60.g-card .row .grow { flex: 1; min-width: 0; }
61.g-card .who { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
62.g-card .when { color: var(--sub); font-size: .76rem; white-space: nowrap; }
63.g-card .body { margin-top: 8px; font-size: .92rem; overflow-wrap: anywhere; }
64.g-card .body img { max-width: 100%; border-radius: 8px; margin-top: 6px; }
65.g-link { display: inline-block; margin-top: 8px; color: var(--accent); font-size: .82rem; text-decoration: none; }
66
67.tag { font-size: .72rem; font-weight: 600; padding: 3px 9px; border-radius: 20px; white-space: nowrap; }
68.tag.wait { background: #3a2f1a; color: #e8b04b; }
69.tag.ok { background: #17301f; color: var(--ok); }
[780a7c6]70.tag.co { background: #2a1f3a; color: #c39bff; }
[318d0c2]71
[c26cc18]72#adopt-form { display: flex; gap: 8px; }
[318d0c2]73#adopt-form input {
[c26cc18]74 flex: 1; min-width: 0;
75 background: var(--bg); color: var(--ink);
76 border: 1px solid var(--line); border-radius: 10px; padding: 11px 12px;
[318d0c2]77}
78button {
79 background: var(--accent); color: #fff; border: 0;
[c26cc18]80 border-radius: 10px; padding: 11px 18px; font-weight: 600; cursor: pointer;
[318d0c2]81}
[c26cc18]82button:disabled { opacity: .5; cursor: default; }
83button.quiet { background: transparent; color: var(--sub); border: 1px solid var(--line); font-weight: 500; }
84button.quiet.is-on { color: var(--ok); border-color: var(--ok); }
85button.small { padding: 6px 12px; font-size: .82rem; }
[f1c50f9]86
87/* Wards' corner (v2 meekijken) */
88.g-card.feed .g-when { color: var(--muted, #888); font-size: .8em; margin-left: auto; }
89.g-card.feed .feed-body { margin-top: 6px; line-height: 1.4; }
90.g-card.feed .feed-body img { max-width: 100%; border-radius: 8px; }
[d9ad6c5]91
92/* ── The body of a post ────────────────────────────────────────────────────
93 The 🛟 card shows a real post, so it is rendered by the same partial de
94 Krant and Berichten use (partials/note-body). These are that partial's
95 classes, in the PWA's own colours: the dashboard is standalone and does not
96 load the site's stylesheet. */
97.g-note .tl-content { line-height: 1.5; overflow-wrap: anywhere; }
98.g-note .tl-content p { margin: .35rem 0; }
99.g-note .tl-content p:first-child { margin-top: 0; }
100.g-note .tl-content p:last-child { margin-bottom: 0; }
101.g-note .tl-content a { color: var(--accent); }
102.g-note img.emoji { height: 1.25em; width: auto; margin: 0 .05em; vertical-align: -.2em;
103 display: inline-block; border-radius: 0; background: none; }
104
105/* Quote card and link preview: one card, two origins. */
106.g-note .tl-quote { margin: 8px 0 0; padding: 8px 10px; border-radius: 10px;
107 border: 1px solid var(--line); background: var(--card-2, rgba(128,128,128,.07)); }
108.g-note .tl-quote-head { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; min-width: 0; }
109.g-note .tl-quote-avatar { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
110.g-note .tl-quote-name { font-weight: 600; font-size: .82rem; white-space: nowrap; }
111.g-note .tl-quote-handle { color: var(--sub); font-size: .76rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
112.g-note .tl-quote-body { color: var(--sub); font-size: .88rem; line-height: 1.45; max-height: 14em; overflow: hidden; }
113.g-note .tl-quote-media { display: block; margin: 6px 0 0; }
114
115/* The capture a 🛟 usually carries. */
116.g-note .tl-media { display: flex; flex-direction: column; gap: 6px; margin: 8px 0 0; }
117.g-note .tl-media-img { display: block; border-radius: 10px; overflow: hidden; }
118.g-note .tl-media-img img { width: 100%; height: auto; display: block; background: #fff; }
119.g-note .tl-media-video, .g-note .tl-media-audio { width: 100%; margin: 8px 0 0; border-radius: 10px; display: block; }
120.g-note .tl-media-video { max-height: 320px; background: #000; }
[70677e96]121
122/* ── Paneel per ward ───────────────────────────────────────────────────────
123 Een guardian denkt per kind, niet per functie: achter de regel van een kind
124 zit alles over dat kind. De regel zelf draagt de tellers, zodat een dicht
125 paneel nooit iets verbergt dat een antwoord nodig heeft. */
126.g-card.ward > .row { gap: 8px; }
127.g-panel { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }
128.g-panel[hidden] { display: none; }
129.g-panel-sec + .g-panel-sec { margin-top: 16px; }
130.g-panel-sec h3 { margin: 0 0 6px; font-size: .82rem; font-weight: 600; letter-spacing: .03em;
131 text-transform: uppercase; color: var(--sub); }
132.g-panel-sec .g-card { background: transparent; border-color: var(--line); }
133.g-panel-sec .g-card + .g-card { margin-top: 6px; }
134.g-panel-sec .row { flex-wrap: wrap; }
135.g-empty.small { margin: 0; font-size: .85rem; }
136.tag.help { color: var(--accent); border-color: var(--accent); }
[742ba7e]137
138/* Loslaten van een ward: geen browser-confirm maar een stap in het paneel, met
139 de gevolgen erbij. Rustig van kleur; het is een besluit, geen alarm. */
140.g-warn { margin-top: 10px; padding: 12px 14px; border-radius: 10px;
141 border: 1px solid var(--danger); background: color-mix(in srgb, var(--danger) 8%, transparent); }
142.g-warn strong { display: block; margin-bottom: 6px; }
143.g-warn p { margin: 0 0 8px; font-size: .88rem; line-height: 1.45; color: var(--sub); }
144.g-warn p.grave { color: var(--ink); font-weight: 500; }
145.g-warn .row { margin-top: 10px; gap: 8px; }
146button.danger { background: var(--danger); color: #fff; border-color: var(--danger); }
[0202104]147
148/* ── Beschikbaarheid (FEP-633c 3.6) ────────────────────────────────────────
149 De buddy-list-stip op de verantwoordelijkheids-as: groen beschikbaar, geel
150 afwezig-verklaard met een einde, grijs slapend-geconstateerd (een antwoord
151 herstelt alles). Labels zijn UI; de draad houdt de spec-termen. */
152.g-avdot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
153.g-avdot.is-active { background: var(--ok); }
154.g-avdot.is-away { background: #e0a83a; }
155.g-avdot.is-dormant { background: #8a93a3; }
156.g-avlabel { color: var(--sub); font-size: .8rem; white-space: nowrap; }
157.row.g-guard { gap: 8px; margin-top: 6px; }
[d56d471]158/* The status of a proposal this guardian sent (5.6): one quiet line per
159 feature. The colour says the state before the words do. */
160.g-prop { margin: 6px 0 0; color: var(--sub); }
161.g-prop-accepted { color: var(--ok); }
162.g-prop-rejected, .g-prop-expired { color: var(--danger); }
[0202104]163.g-away-row { display: flex; gap: 8px; }
164.g-card.lapse { border-left: 3px solid #8a93a3; }
165.g-card.lapse .row { margin-top: 8px; gap: 8px; }
[88d7c8f]166
167/* Een voorgestelde gated setting (FEP-633c 5.6) van een mede-guardian. */
168.g-card.gated { border-left: 3px solid var(--accent); }
169.g-card.gated .row { margin-top: 8px; gap: 8px; }
[792af53]170
171/* Het gate-paneel per ward (shaer-ahy.1). Een rij per gate, met het soort en de
172 drempel erbij. Bewust rustig: dit is een overzicht om te LEZEN, en pas daarna
173 een plek om iets voor te stellen. */
174.g-gate { padding: .5rem 0; border-top: 1px solid var(--g-line, rgba(0,0,0,.08)); }
175.g-gate:first-of-type { border-top: 0; }
176.g-gate-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
177.g-gate-name { font-weight: 600; }
178/* Het soort is een fluistering, geen kop: het hoort erbij te staan zonder de
179 naam van de gate te overstemmen. */
180.g-gate-kind { font-size: .78em; opacity: .65; }
181.g-gate-meta { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: .15rem; }
182.g-gate-meta .g-dim { opacity: .55; }
183/* Onomkeerbaar krijgt gewicht, want dat is het enige in dit paneel dat je niet
184 kunt terugdraaien. */
185.g-gate-warn { font-weight: 600; }
186.g-gate-wait { font-weight: 600; }
[a29c8c8]187
188/* De gedeelde staat van een hulpvraag (shaer-lgo). Rustig: dit is geen alarm,
189 het moet alleen onmogelijk te missen zijn wie er al op af is. */
190.g-help-state { margin-top: .5rem; }
191.g-help-pick { font-size: .9em; }
192.g-help-age { opacity: .6; } /* oud, maar niet weg */
193.g-help-done { font-weight: 600; }
194.g-confirm { margin-top: .5rem; }
[ee78e03]195
196/* Het archief van afgehandelde hulpvragen: aanwezig, niet in de weg. */
197.g-help-archive { margin-top: .5rem; opacity: .75; }
[7d7b36d]198
199/* De geschiedenis onderaan een wardpaneel: aanwezig, duidelijk afgesloten, en
200 visueel losgemaakt van wat nog wacht. */
201.g-panel-history { border-top: 2px solid var(--g-line, rgba(0,0,0,.12)); margin-top: 1rem; opacity: .8; }
[9588b51]202
[50e80ac]203/* ── Het poortenpaneel als cockpit (shaer-ahy.1, Barts richting 8-8) ──
204 Elke gate is een toets zoals op een aircopaneel: lampje links, naam erop,
205 en een klein verzonken statusveld met de stand als tekst. Het lampje en het
206 veld zeggen hetzelfde in twee vormen -- kleur alleen is geen antwoord. */
207.g-gates { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: .5rem; margin: .35rem 0; }
208.g-sw-wrap { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
209.g-sw {
210 display: flex; flex-direction: column; align-items: stretch; gap: .3rem;
211 text-align: left; padding: .5rem .6rem; border-radius: 10px;
212 border: 1px solid var(--g-line, rgba(0,0,0,.18));
213 background: var(--g-key, linear-gradient(180deg, rgba(255,255,255,.9), rgba(0,0,0,.04)));
214 box-shadow: inset 0 1px 0 rgba(255,255,255,.6), 0 1px 2px rgba(0,0,0,.12);
215 cursor: pointer; font: inherit;
216 /* Expliciet, niet geerfd (Barts aanwijzing, 8-8): de paginakleur zakte weg
217 in het toetsvlak. Het opschrift is het donkerste op de toets. */
218 color: var(--g-key-ink, #1b1e22);
219}
220.g-sw:active:not([disabled]) { box-shadow: inset 0 1px 3px rgba(0,0,0,.25); transform: translateY(1px); }
221/* Niet verstelbaar is niet kapot: de toets drukt niet in, de stand blijft leesbaar. */
222.g-sw[disabled] { cursor: default; opacity: .8; }
223.g-sw-head { display: flex; align-items: center; gap: .45em; min-width: 0; }
224.g-sw-name { font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
225
226/* Het lampje. Aan gloeit, uit is dof, onbeslist is een open kringetje (geen
227 besluit is de afwezigheid van een), wachten knippert -- de enige stand die
228 vanzelf verandert, dus de enige die om je blik mag vragen -- en gepland is
229 een lege fitting: een poort die nog niet bestaat is geen dichte deur. */
230.g-sw-lamp { flex: none; width: .6em; height: .6em; border-radius: 50%; box-shadow: inset 0 0 2px rgba(0,0,0,.35); }
231.g-lamp-on { background: var(--g-lamp-on, #2f9e5f); box-shadow: 0 0 6px 1px rgba(47,158,95,.55); }
232.g-lamp-off { background: var(--g-lamp-off, #7a8087); }
233.g-lamp-undecided { background: transparent; border: 1px dashed currentColor; opacity: .55; box-shadow: none; }
234.g-lamp-waiting { background: var(--g-warn, #b8860b); animation: g-lamp-pulse 1.4s ease-in-out infinite; }
235.g-lamp-planned { background: transparent; border: 1px dotted currentColor; opacity: .4; box-shadow: none; }
236@keyframes g-lamp-pulse { 50% { opacity: .3; } }
237@media (prefers-reduced-motion: reduce) { .g-lamp-waiting { animation: none; } }
238
239/* In het donker geen lichte toetsen: de site heeft een echt donker thema
240 (style.css), en een wit-op-lichtgrijs paneel is daar onleesbaar. Zelfde
241 vorm, andere verf; de vars blijven overschrijfbaar. */
242@media (prefers-color-scheme: dark) {
243 .g-sw {
244 background: var(--g-key, linear-gradient(180deg, rgba(255,255,255,.10), rgba(0,0,0,.25)));
245 box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 1px 2px rgba(0,0,0,.5);
246 color: var(--g-key-ink, rgba(255,255,255,.95));
247 }
248 .g-sw-state { background: var(--g-lcd, rgba(0,0,0,.4)); }
249}
250
251/* Het statusveld: verzonken venstertje, vaste letter, zoals de temperatuur op
252 het aircopaneel. */
253.g-sw-state {
254 align-self: flex-start; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
255 font-size: .74em; padding: .1em .5em; border-radius: 4px;
256 border: 1px solid var(--g-line, rgba(0,0,0,.18));
257 background: var(--g-lcd, rgba(0,0,0,.07));
258 box-shadow: inset 0 1px 2px rgba(0,0,0,.12);
259 /* Het oplichtende display van de toets: de stand in de accentkleur van het
260 huis (Barts aanwijzing, 8-8), zoals de cijfers op het aircopaneel. */
261 color: var(--accent, #6b8f71);
262 font-weight: 600;
263}
264.g-sw-meta { display: flex; flex-wrap: wrap; gap: .3em .7em; opacity: .7; font-size: .82em; }
265
266/* De poortenlijst blijft ingeklapt tot je hem opent. Met twaalf toetsen duwt
267 een open paneel alles eronder van het scherm. */
[23da947]268.g-gates-toggle { display: block; width: 100%; text-align: left; margin: .25rem 0; }
[b2646cc]269
270/* De waarschuwing bij een gate-voorstel (shaer-nf9). Geen rode paniekbalk: dit
271 moet gelezen worden, niet weggeklikt. Een rand links, zoals een citaat. */
272.g-warn { margin: .5rem 0; padding: .4rem 0 .4rem .7rem; border-left: 3px solid var(--g-warn, #b8860b); }
273.g-warn p { margin: 0 0 .25rem; }
274.g-warn p:last-child { margin-bottom: 0; }
275.g-confirm .g-warn { border-left: 0; padding-left: 0; }
[0b0cd54]276
277/* De vraag van het kind zelf (shaer-8ru). Het enige op een poortrij dat van het
278 kind komt, dus niet grijs weggeschreven tussen de drempels. */
279.g-gate-asked { margin: .2rem 0 0; color: var(--g-asked, #7a5ea8); font-weight: 600; }
[ea211b9]280
281/* "Jouw antwoord beslist dit" (shaer-8vt). Zwaarder dan de rest van de
282 waarschuwing: dit is het verschil tussen meedoen en beslissen. */
283.g-decisive { font-weight: 700; color: var(--g-decisive, #a33); }
Note: See TracBrowser for help on using the repository browser.