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

main
Last change on this file since d56d471 was d56d471, checked in by Robin <roboburr@…>, 6 weeks ago

Een voorstel krijgt een antwoord, een status en een zichtbare kring

Robin meldde drie dingen na de voorstelronde: er lijkt niets te gebeuren, de
status van een voorstel is nergens te volgen, en in /guardian zie je niet wie
de mede-guardians van een kind zijn. Onderzoek op beta wees de kern aan: de
ronde is aangekomen en geteld, maar elk voorstel was shaer:externalEmbeds, en
die stond al aan. Afspelen is nooit voorgesteld, en dat KON ook niet: de knop
"Afspelen voorstellen" verscheen alleen bij embeds === true, en voor een ward
op een andere server is die waarde onbekend, dus null, dus geen knop. Onbekend
is niet uit.

Drie reparaties, een per klacht.

Een: de lus sluit. De server van het kind beantwoordt de Offer die de
beslissing opende, terug naar de voorsteller: Accept als hij settelde op het
voorgestelde, Reject bij het tegendeel. Alleen de stem van het kind-account
telt als uitkomst; een vreemde die onze boeken wil sluiten wordt genegeerd.
Zonder dit kon het scherm van de voorsteller alleen maar eeuwig "wacht"
zeggen, wat er ook gebeurd was: de telling is het prive-grootboek van de
server van het kind.

Twee: de voorsteller houdt een eigen boek bij (ap_gated_sent) en het paneel
toont per ward de stand: wacht, aangenomen, afgewezen, of eerlijk verlopen als
het venster leegliep. Stilte na het venster is geen "loopt nog".

Drie: voor een ward op een andere server toont het paneel nu wel wie de
guardians zijn. Het lidmaatschap is publiek op het actordocument
(shaer:guardians, 2.1); de beschikbaarheid is en blijft het prive-grootboek
van hun server (3.6.1) en wordt alleen benoemd, niet getoond.

Changed files:
src/config/database.js

  • tabel ap_gated_sent (het boek van de voorsteller)
  • kolom proposer op ap_gated_offers, voor het antwoord naar huis

src/services/guardianship/gated.js

  • recordSent/recallSent/settleSent/listSent en sentStatus (puur, getest)
  • rememberGatedOffer onthoudt de voorsteller

src/services/guardianship/handshake.js

  • answerGatedProposer: het settle-antwoord naar de voorsteller
  • de inbox herkent dat antwoord en settelt het eigen boek; alleen het kind-account mag dat

src/routes/guardian.js

  • proposeGated schrijft het boek; dashboardState serveert per ward de voorstellen met status
  • GET /wards/guardians: lokaal met beschikbaarheid, remote de publieke lijst van hun actordocument

src/assets/js/guardian.js

  • de afspeel-knop verschijnt ook bij onbekende embeds-stand (de bug)
  • statusregels onder de instellingen-knoppen
  • remote guardians opgehaald bij het openen van het paneel

src/assets/css/guardian.css

  • g-prop-kleuren: de staat spreekt voor de woorden uit

src/services/i18n.js

  • prop_*- en panel_guards_far-strings, NL/EN/DE

test/gated-settings.test.js

  • de lus sluit: de voorsteller krijgt het antwoord, van alleen het kind
  • het boek: open, aangenomen, afgewezen, verlopen

remarks: 334 tests groen, server start op een schone database. De guardian-kant
(sound-fabrics) en de ward-kant (beta) hebben allebei deze commit nodig: de
knop en de status leven bij de guardian, het antwoord bij het kind.

-robo
Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 8.8 KB
Line 
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;
8 --line: #2c3646;
9 --accent: #ff6b35;
10 --ok: #4caf7d;
11 --danger: #e05a5a; /* alleen voor onomkeerbare stappen, zoals een ward loslaten */
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;
19 padding-bottom: 48px;
20}
21.g-head {
22 display: flex;
23 align-items: center;
24 gap: 12px;
25 padding: 16px;
26 background: var(--card);
27 border-bottom: 1px solid var(--line);
28 position: sticky;
29 top: 0;
30 z-index: 2;
31}
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; }
37#site-picker {
38 background: var(--bg); color: var(--ink);
39 border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px;
40}
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; }
54.g-msg.err { color: #ff7a7a; }
55.g-list { display: flex; flex-direction: column; gap: 8px; }
56
57.g-card { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; }
58.g-card.help { border-left: 3px solid var(--accent); }
59.g-card .row { display: flex; align-items: center; gap: 10px; }
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); }
70.tag.co { background: #2a1f3a; color: #c39bff; }
71
72#adopt-form { display: flex; gap: 8px; }
73#adopt-form input {
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;
77}
78button {
79 background: var(--accent); color: #fff; border: 0;
80 border-radius: 10px; padding: 11px 18px; font-weight: 600; cursor: pointer;
81}
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; }
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; }
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; }
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); }
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); }
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; }
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); }
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; }
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; }
Note: See TracBrowser for help on using the repository browser.